Cedar 15

Introducing smarter building blocks to create more consistent customer experiences at scale
package nameversion
@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
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.

NamePresetFluid 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

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

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, use fit instead
  • Removed crop prop, use position 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 CSS border-radius property.
  • Changed ratio prop. This property now passes directly to the CSS aspect-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 CSS object-position property.
  • Added fit prop. This property directly passes to the CSS object-fit property. So you will replace cover="true" with fit="cover".
  • Added srcset and sizes 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 underlying label element.
  • Added an inputContainerClass prop. This prop can be used in the same way that labelClass used to work. It passes a class to the parent element of an input (i.e. the cdr-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. Your data-ui attribute will pass to the role="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