Cedar 15
Introducing smarter building blocks to create more consistent customer experiences at scalepackage name | version |
---|---|
@rei/cedar | ^15.x.x |
@rei/cdr-tokens | ^12.x.x |
@rei/cdr-component-variables | ^9.x.x |
If your project depends on any external modules that also use Cedar, make sure to update those to the same version as your project. As a reminder, external modules using Cedar should list it as a peerDependency so that your main application can resolve it.
For consumers at REI, now is a great time to ensure you are on the latest version of our base front end configuration as well.
Object overlay: Flexible content positioning
The new CdrObjectOverlay
component provides a flexible way to position content relative to a container element. This component is perfect for creating overlays on images, positioning captions, or adding interactive elements at specific locations within a container.
Key features:
- Flexible positioning: Position content in 9 different locations (top-left, top-center, top-right, center-left, center-center, center-right, bottom-left, bottom-center, bottom-right)
- Responsive behavior: Define different positions, margins, and gradients for different breakpoints
- Gradient support: Apply gradients to enhance visibility of overlaid content
- Spacing control: Adjust margin and padding around positioned content
Learn more about Object Overlay.
Surface navigation: Enhanced interactive containers
Building on our Surface component system introduced in v15.2.0, we're adding CdrSurfaceNavigation
, a specialized variant designed for navigational elements. Surface Navigation provides comprehensive state management for different interaction states (rest, hover, active, focused, and disabled), allowing for fine-grained control over the component's appearance.
Key features:
- State management: Built-in styles for rest, hover, active, focused, and disabled states
- Flexibility: Can be used to create cards, navigation tiles, and other interactive elements
Surface Navigation is perfect for building navigational containers that direct users to other pages or sections, and can be used to create card-like components with consistent interaction patterns.
Learn more about Surface Navigation.
Tokens updates
For info on the latest major token updates, see Cedar Tokens v12.
Introducing Pressura font in both regular and bold weight. This font is specifically intended for Membership campaign support.
Landing page showcase
We've added a new landing page showcase page to demonstrate how our layout components work together in a full-page context. This first showcase illustrates how to compose heroes, banners, and card layouts to create responsive landing pages. Now you can visualize our new fluid layout capabilities in action.
Layout and Media object: Dynamic layout capabilities
These components build upon our fluid container system released earlier this year, providing the flexible foundation needed for our 2025 initiatives. We're adding these components to Cedar to eliminate redundant development work across teams while providing the dynamic layout capabilities needed for our DXP solution and personalization initiatives. These patterns will be essential building blocks for distributed publishing and content flexibility in the coming year.
Layout component
A layout tool that helps you organize content in rows and columns that automatically adjust to fit different screen sizes. Learn more about layout.
Key features:
- Dynamic column/row configuration
- Grid layout options
- Easy responsive configuration based on Cedar breakpoints
- Consistent CdrGrid spacing
Used for: Category grids, product tiles, card collections, story components, and flexible page layouts
Media object component
A component that pairs images or videos with related text in a consistent way, like a product photo next to its description. Learn more about media object.
Key features:
- Flexible media positioning
- Decoupled content/display patterns
- Responsive design works well across device types and screen sizes
- Works with Surface containers to build content-rich components like cards and banners
Used for: Product tiles, story banners, article cards, and content previews
Miscellaneous updates
- Fixed padding within CdrBanner
- Minor tokens updated to match designs
- Minor changes to Surface tokens
- SurfaceSelection and FulfillmentTile have been updated to use the new layout component
v15.3.1, v15.3.2 patch updates
- Fixed a Modal issue on older versions of Chrome that caused content to be incorrectly aligned
- Refinements to make Media object easier to use with content which incorporates container queries or units
Membership palettes
Membership palettes are now available and are being distributed in a new global css asset from Cedar,
@import 'path/to/cedar/cdr-palette.css';
For a full guide on implementing palettes view our palettes documentation within the guidelines section of this site.
Surface: Introducing a new way to represent elevation
Surface elevates elements above a base layer to create a sense of depth and structure. It’s a flexible container for grouping content and interactive elements.
What makes this different?
On REI.com today, the page and its content rest on a single base layer where UI elements, including text, icons, backgrounds, and borders, are placed. Cedar has a rudimentary concept of elevation, but its lack of consistency makes it difficult to understand the hierarchical structure of UI elements.
As a foundation, surface introduces new criteria around elevation, stacking, hierarchy, shadows and light, and fixed and flexible sizes.
New surface container, variants, and components
Surface is a base container that acts as a starting point for constructing more specific container components such as cards, tiles, and action-driven elements.
Surface has a wide range of customization options, but we’ve created specialized variants for specific use cases. You can always use surface as a fallback, but first make sure if Cedar has an available variant that suits your purpose before customizing.
These specialized variants are building blocks with more built-in design opinions on behaviors and style, helping to keep things consistent and save you time. They are specialized to meet a specific user intent, like selection or navigation. These variants can then be consumed by components that align with that intent, like fulfillment tiles for selection behaviors and cards for navigation.
Surface
This is a generic, flexible layout container for grouping content and interaction elements. It handles visual elevation and spatial organization, providing a broad set of styling and layout options for customization. It also enables palette options by applying a background surface for components to lay on.
Learn more about surface.
Surface selection
Surface selection is a base variant for user selections that have a checked state. It’s a variation of a checkbox/radio that provides additional details about one or more radio button options within a large and well-defined tap target.
This root pattern is used by fulfillment tiles (new) and is planned for use with color swatches and size selection. It could also be extended to other existing user selection components, such as toggle, switch, and chip.
Learn more about surface selection.
Fulfillment tile
The fulfillment tile component displays a button with an optional icon in the header. It shows a checked state with descriptive content. This is an extension of the surface selection variant, providing a set of features intended for product, checkout, and search pages.
Fulfilment tile comes with styles for checked, disabled, loading, and active states. It also provides:
- A layout for inner elements
- A content component for styling text below the header
- An icon component that can be used in the header
- A header component
Learn more about fulfillment tile.
Be on the lookout for more surface variants and components in the near future, including surface navigation and surface controls.
Fluid space: Enhancing layout flexibility
Added fluid space to the design system. Just like fluid typography fluid space dynamically adjusts based on screen size, ensuring consistent and proportional spacing across different devices.
How it works
Fluid space uses the clamp()
function in CSS, allowing for responsive spacing without the need for media queries. This approach ensures our design maintains its integrity and aesthetics, regardless of the screen size.
CSS for our fluid space scale:
--cdr-space-scale-0: clamp(0.2rem, 0.2rem + 0.11cqi, 0.3rem);
--cdr-space-scale-1: clamp(0.3rem, 0.3rem + 0.11cqi, 0.4rem);
--cdr-space-scale-2: clamp(0.4rem, 0.4rem + 0.11cqi, 0.5rem);
--cdr-space-scale-3: clamp(0.8rem, 0.7rem + 0.22cqi, 1rem);
--cdr-space-scale-4: clamp(1.2rem, 1.1rem + 0.33cqi, 1.5rem);
--cdr-space-scale-5: clamp(1.6rem, 1.5rem + 0.44cqi, 2rem);
--cdr-space-scale-6: clamp(2.4rem, 2.2rem + 0.66cqi, 3rem);
--cdr-space-scale-7: clamp(3.2rem, 2.9rem + 0.88cqi, 4rem);
--cdr-space-scale-8: clamp(4.8rem, 4.4rem + 1.31cqi, 6rem);
/* One-up pairs */
--cdr-space-scale-0--1: clamp(0.2rem, 0.1rem + 0.223cqi, 0.4rem);
--cdr-space-scale-3--4: clamp(0.4rem, 0.2rem + 0.66cqi, 1rem);
--cdr-space-scale-3--5: clamp(0.8rem, 0.1404rem + 1.21cqi, 1.6rem);
Integrating fluid space and fluid typography
Fluid space and fluid typography work together to create a seamless, responsive design experience. By using container query units (cqi), our spacing and typography adapt to the size of their containing elements, not just the viewport. This ensures a more consistent and flexible design, particularly in complex layouts.
For example:
body {
font-size: var(--cdr-type-scale-0);
margin: var(--cdr-space-scale-2);
}
h1 {
font-size: var(--cdr-type-scale-4);
margin-bottom: var(--cdr-space-scale-3);
}
p {
font-size: var(--cdr-type-scale-1);
margin-bottom: var(--cdr-space-scale-2);
}
Current limitations and future improvements
While the browser support for cqw
units is improving, it's not yet universal. That’s why we're releasing this feature under the @supports
query to ensure backward compatibility. This way, if a browser doesn't support cqw
, it will fall back to using vw
.
Performance update
Added a low-Cumulative Layout Shift (CLS) fallback font to improve the page loading experience. Action needed: update to Cedar v15.1 and to the latest tokens version 12.2.0.
Fluid typography
With a twist
Fluid typography is not a new concept, but it's only recently the browser support has gotten to a place where we feel can release it. At its core, it's simple math, but it's incredibly powerful in what it unlocks.
Fluid typography is based on the slope of a line between two points (remember your y = mx + b
from geometry?). In this case, our points are the minimum and maximum font-size of our type. Calculating the slope of the line when accounting for screen sizes is a little tricky, but here's a great article from Smashing Magazine that goes through the math.
Using the CSS clamp() function, we pass the minimum font-size, preferred font-size (the slope), and maximum font-size and the function handles the rest.
font-size: clamp(
[minimum-font-size],
[preferred-font-size],
[maximum-font-size]
);
We can then assemble a set of scales to cover the various font "sizes" we need to support.
For Cedar, after doing all the math, our scale looks like this:
--cdr-type-scale--1: clamp(1.33rem, 0.29vw + 1.24rem, 1.6rem);
--cdr-type-scale-0: clamp(1.6rem, 0.44vw + 1.46rem, 2rem);
--cdr-type-scale-1: clamp(1.92rem, 0.64vw + 1.72rem, 2.5rem);
--cdr-type-scale-2: clamp(2.3rem, 0.9vw + 2.02rem, 3.13rem);
--cdr-type-scale-3: clamp(2.76rem, 1.25vw + 2.36rem, 3.91rem);
--cdr-type-scale-4: clamp(3.32rem, 1.72vw + 2.77rem, 4.88rem);
--cdr-type-scale-5: clamp(3.98rem, 2.33vw + 3.24rem, 6.1rem);
--cdr-type-scale-6: clamp(4.78rem, 3.13vw + 3.78rem, 7.63rem);
--cdr-type-scale-7: clamp(5.73rem, 4.17vw + 4.4rem, 9.54rem);
Where scale-0
is the baseline (think body copy) all the way up to scale-7
(think giant display headings). We've also added a negative scale for text treatments that might be intentionally smaller than body copy (eyebrows, kickers, etc). We plan to adjust this scale as needed to ensure it's meeting the needs of our consumers ... in other words, our fluid scale, will be fluid.
Note we wrapped "sizes" in quotation marks up above. That's because this technique represents a departure in how we think about font-sizes across screens. There is no longer an explicit size for anything between desktop and mobile, the type will fluidly scale between its upper and lower bound without any media queries. That's right, I'll say that again, using this technique it's not necessary to write media queries to handle scaling your type across breakpoints. Your body copy is your body copy and the fluid scale will handle how it responds to different devices and screen sizes.
The twist
That's right, this is fluid typography with a twist. Traditionally, the fluid slope is created using vw
units in order to respond across screen sizes, but we've taken this a step further with container query units. Specifically, we're using the cqw
unit in place of vw
so that if your fluid type is within a container
, it will respond to the container's width instead. If no container is present, cqw
becomes the equivalent of vw
.
This unlocks some really amazing patterns, which we'll learn about further on.
Unfortunately, there's a "but"
The browser support isn't quite where we need it to be for full adoption. It's close, but for time-being this twist is being released under the @supports
query so that it will back to the traditional vw
for browsers that were late to catch on (cough Safari cough). There's still some cool stuff we can do with it, but those really amazing patterns are being released under a preview
flag.
Fluid text presets
For easy implementation, we've created these preset components for applying our various font styles across the fluid scale. These components share the <CdrText>
API, but extend it, allowing you to select scale and weight where applicable.
Name | Preset | Fluid properties |
---|---|---|
Eyebrow | <CdrEyebrow> | - |
Body | <CdrBody> | scale?: '0'|'1' strong?: boolean |
Utility sans | <CdrUtilitySans> | scale?: '-1'|'0'|'1'|'2'|'3' strong?: boolean |
Utility serif | <CdrUtilitySerif> | scale?: '-1'|'0'|'1'|'2'|'3' strong?: boolean |
Subheading sans | <CdrSubheadingSans> | scale?: '0'|'1'|'2' |
Heading sans | <CdrHeadingSans> | scale?: '1'|'2'|'3' strong?: boolean |
Heading serif | <CdrHeadingSerif> | scale?: '1'|'2'|'3'|'4'|'5' strong?: boolean |
Heading display | <CdrHeadingDisplay> | scale?: '2'|'3'|'4'|'5'|'6'|'7' |
See the CdrText article for more information.
Atomic content components Preview Preview features may change or have additional considerations
Using our fluid typography scales and container queries, Cedar has formed an opinion about generic expressions of content. Each of these atomic components have opinions about how type should scale and be styled across the width of their parent container.
This enables an extremely efficient approach to content-driven-design. When a "title" is a "title" no matter where it's placed, we remove design friction and create real efficiencies in the creation of content.
In the following example, we've placed a variable number of cards within an auto-flowing grid. Watch how the card's atomic title adjusts to the number of cards in the grid as well as the size of the viewport.
Nothing fancy is required on the implementation to achieve this. Simply place your <CdrTitle>Atomic title</CdrTitle>
within a element specified as a container.
CdrPicture
We've added a CdrPicture component to enable generating your <picture>
markup using a schema vs. handwriting the HTML. This component consumes the refactored CdrImg
. See the CdrPicture article for more information.
CdrSplitSurface
CdrSplitSurface is a generic container for a split-surface presentation. See the CdrSplitSurface article for more information.
CdrLandingLead Preview Preview features may change or have additional considerations
CdrLandingLead is an opinionated page lead with a simplified API intended for use on static landing pages. See the CdrLandingLead article for more information.
CdrCard
CdrCard is now specified as container-type: inline-size
by default. Classes passed from the parent will have higher specificity if you need to adjust this.
CdrTooltip
CdrTooltip now generates a unique ID if none is provided to help ensure an accessible experience.
CdrImg refactor
CSS has changed a lot since CdrImg was first introduced six years ago and it's time for CdrImg to change as well. CdrImg was using a standard Media Container pattern in order to support image ratios, CSS now has native aspect-ratio support so we've refactored to take advantage. This is a breaking change due to a number of API removals and additions, as well as how drastically the underlying markup has shifted when using image with ratios.
Removals
- Removed
cover
prop, usefit
instead - Removed
crop
prop, useposition
instead - Removed
coverClass
prop, there is no longer a container for this class to be applied to. - Removed
modifier
prop, CdrImg is now always responsive.
Changes
- Changed
radius
prop. This property will accept a shorthand for a Cedar radius token (e.g. CdrRadiusSoft) or a string that represents a valid value for the CSSborder-radius
property. - Changed
ratio
prop. This property now passes directly to the CSSaspect-ratio
property. You can target the underlying CSS custom property (--cdr-img-aspect-ratio
) as well if you need to set different aspect ratios across screen sizes.
Additions
- Added
position
prop. This property directly passes to the CSSobject-position
property. - Added
fit
prop. This property directly passes to the CSSobject-fit
property. So you will replacecover="true"
withfit="cover"
. - Added
srcset
andsizes
props to support using those attributes with CdrImg to craft responsive images.
See the CdrImg article for more information.
CdrInput
CdrInput's "custom class" props were inconsistent in comparison to the other form components, these changes create a more consistent implementation experience.
- Refactored the
labelClass
prop. This prop now applies a custom class to the underlyinglabel
element. - Added an
inputContainerClass
prop. This prop can be used in the same way thatlabelClass
used to work. It passes a class to the parent element of an input (i.e. thecdr-label-standalone
wrapping div).
CdrModal accessibility improvements
Just like Nightcrawler, CdrModal has learned how to teleport.
To fix a long-standing bug where content could be read outside of the modal on specific screen readers (notably, Android Talkback), the modal now teleports to the body
element on mount. Then, on open and close, it applies and removes aria-hidden
from other elements in the body that could contain readable text.
While this doesn't change the implementation details of the modal, it is likely to cause issues with tests.
Examples of what may fail:
- UI Tests that target the modal via the expectation of a parent container. We recommend using
data-ui
attributes on specific modal instances to avoid confusion. Yourdata-ui
attribute will pass to therole="dialog"
element in the modal, for testing content within. - Unit tests that match against snapshots or test against inner contents of a modal. One of the two fixes below may work for this.
const wrapper = mount(MyComponent, {
global: { stubs: { teleport: true } },
...
});
or
import { config } from '@vue/test-utils';
config.global.stubs['Teleport'] = true;
With snapshots, add this first and then update your snapshot to include the stubbed teleport element.
npx vitest -u
This will replace the Teleport element with a stub, but still render the component for testing.
<teleport-stub to="body">
Since this is a significant change to functionality, we expect there may be some edge cases we have not taken into account. If you run into issues, please reach out so we can help troubleshoot.
Special thanks to REI Engineer Harmony Hames for this contribution.
Static assets
We've made a number of changes to our build system in order to optimize the creation of assets. We've also renamed a few things for consistency which will need to be updated in your applications.
CSS reset
reset.css
has been renamed to cdr-reset.css
for consistency.
Full CSS assets
cedar-compiled.css
and cedar-full.css
were deprecated in Cedar 14 and have been removed in this release.
By default, Vite is generating a compiled style asset for us, but we were still doing a lot post-processing to create the cedar-compiled
and cedar-full
css assets.
If you were reliant on these assets, you can use the new cdr-style.css
asset that vite gives us for free in conjunction with the cdr-reset.css
to achieve the same result.
Special thanks to REI Engineer Kurt Medley, for helping us enable this efficiency.
v12.6
Cedar-Tokens update 12.6 provides a new Cedar token:
cdr-font-family-mono-brand-font
Assign this token as an override to font-family properties needing this new display option.
v12.5
Figma and Cedar tokens
Cedar color design tokens are now connected to the Figma Cedar UI toolkit.
This update creates a single source of truth for Cedar colors. Benefits include:
- Consistent design updates across Cedar
- Streamlined collaboration between designers and developers
- Easier design system maintenance because updates to values happen in one central location
- Visual coherence is ensured across different platforms and components
Stay tuned for future token updates for other design elements, such as typography and spacing!
With this work we also took the opportunity to adjust our warm-grey scale within our color options. This work normalizes the scale, reducing transparent additions, ensuring the number of colors in this new color scale will stay consistent across future palettes.
The hover color for our primary button color is adjusted to resolve a discrepancy between code and design.
Empowering designers with a unified design language
The Tokens v12.5 release builds on the Style Dictionary 4 foundation, placing designers at the forefront by seamlessly integrating design tokens into Figma. Now Figma can transform into a single source of truth for designers.
Consistent color values across design tools and code mean improved UI consistency, scalability, and maintainability. And the direct integration with Cedar's UI toolkit opens the door to a future where designers have greater control over design values. Plus it strengthens collaboration with developers.
This update lays the groundwork for future enhancements that will streamline workflows and empower designers to drive Cedar's evolution. Stay tuned for improvements such as automated redlines and dynamic color palettes via Figma variables.
v12.0
Style Dictionary 4
The upgrade from Style Dictionary 3 to 4 brings substantial enhancements to Cedar-Tokens' core functionality. With this latest version we've aligned with W3C specification. This ensures greater compatibility and interoperability with other design systems and tools.
Style Dictionary 4 introduces improved token structure and transformation capabilities, for more flexible and robust token management. This upgrade also features performance optimizations, resulting in faster token processing and build times.
Enhanced platform support and expanded plugin capabilities allow for more complex and customized token workflows. This empowers us to create a more efficient and scalable design token system.
These improvements pave the way for a more streamlined design-to-development process, providing a stronger foundation for future innovation and expansion of Cedar's design language.
- The CJS format of the component library has been deprecated and will be removed in Cedar 16. Vite will no longer support a CJS output in version 6