We're introducing a new Grid utility to enhance your experience when working with CSS Grid.
It supports all standard grid properties, such as row and column templates, template areas, individual column sizes, and auto-flow values.
All these properties natively support responsive value syntax.
functionDemo(){const[left, setLeft]=React.useState(50);const flyoutRef =React.useRef();const containerRef =React.useRef(null);React.useEffect(()=>{ flyoutRef.current?.updatePosition();},[left]);return(<><Viewdirection="row"gap={2}position="absolute"insetTop={2}insetStart={2}zIndex={10}align="center"><ButtononClick={()=>setLeft((prev)=> prev -10)}>Left</Button><ButtononClick={()=>setLeft((prev)=> prev +10)}>Right</Button><Textvariant="caption-1"weight="medium"color="neutral-faded">Try mobile viewport size<br/>to see position fallbacks</Text></View><Viewheight={50}width={100}attributes={{ref: containerRef }}><Popoverposition="bottom"disableCloseOnOutsideClickinstanceRef={flyoutRef}containerRef={containerRef}><Popover.Trigger>{(attributes)=>(<divstyle={{position:"absolute",left:`${left}%`,top:'50%',whiteSpace:'nowrap'}}><divstyle={{transform:'translate(-50%, -50%)'}}><Buttoncolor="primary"attributes={attributes}> Show content</Button></div></div>)}</Popover.Trigger><Popover.Content><Placeholder/></Popover.Content></Popover></View></>);}
In our previous release, we introduced numerous improvements to the Tooltip, Popover, Autocomplete, and DropdownMenu components.
This time, we're adding even more enhancements, focusing on their dynamic behavior, shadow DOM support, and performance.
All changes listed under Flyout apply to all four components:
Flyout: Improved position calculation for triggers that transform on click.
Flyout: Switched to using vanilla event listeners for triggers, allowing you to pass additional custom event handlers without needing to manually merge them.
Flyout: Fixed the blur event for content-menuhover flyouts that contain no focusable elements.
Flyout: Added automatic shadow DOM detection instead of relying on containerRef.
Flyout, trapFocus: Added shadow DOM support for keyboard navigation.
Flyout: Improved position fallback order when content doesn't fit into the viewport, based on the position default value.
Flyout: Added a fallbackPositions property to manually select available fallback positions. The forcePosition property is now deprecated.
Flyout: Introduced a history for the last used fallback to prevent content from reverting to the default position when none of the fallbacks fit the viewport.
Flyout: Fixed an edge case where controlled flyouts were blocked from closing after being set to inactive.
Flyout: Optimized the internal resize observer to be active only when rendered.
Popover: Added initialFocusRef to focus an element when the popover content is opened.
We have added new functionality to existing components.
Here are a few highlights, with more improvements listed in the next section.
<Loadersize="large"/>
Added a large size option for the Loader component, intended for use in larger page areas instead of the Skeleton.
<Viewwidth="280px"><TextFieldname="food"placeholder="Pick your favorite food"startSlot={[<Badge>Cinnamon bun</Badge>,<Badge>Pasta</Badge>,<Badge>Ice-cream</Badge>,<Badge>Pizza</Badge>]}defaultValue="Pineapple"multiline/></View>
Introduced a multiline flag for the TextField and Autocomplete components to display selected values.
<Viewwidth="300px"><Divider>or use one of these options</Divider></View>
The Divider component now supports children and contentPosition properties for displaying contextual labels or components.
We've introduced a new Resizable utility for managing layouts with dynamically sized panels.
It supports both row and column orientations, accommodates any number of panels and nested layouts, and allows you to customize drag handles to fit your product's requirements.
In response to numerous requests, we've expanded our handling of additional edge cases and composition scenarios for all flyout components: Popover, Tooltip, Autocomplete, and DropdownMenu.
These enhancements also apply to any custom components you've built on top of these primitives.
Here's a quick demo showcasing how some of the new features work together, followed by a full list of improvements:
<Viewdirection="row"gap={2}><Tooltipposition="top"text="Hello">{(tooltipAttributes)=>(<Popoverposition="bottom"width="300px"><Popover.Trigger>{(attributes)=>(<Buttonattributes={{...tooltipAttributes,...attributes }}> Tooltip with popover</Button>)}</Popover.Trigger><Popover.Content><Viewgap={2}align="center"direction="row"justify="space-between"> Popover content<Popoverposition="bottom"width="300px"><Popover.Trigger>{(attributes)=><Buttonattributes={attributes}>Open</Button>}</Popover.Trigger><Popover.Content><Popover.Dismissiblealign="center"> Another popover content</Popover.Dismissible></Popover.Content></Popover></View></Popover.Content></Popover>)}</Tooltip><Tooltipposition="top"text="Hello">{(tooltipAttributes)=>(<Buttonattributes={tooltipAttributes}> Just a tooltip</Button>)}</Tooltip></View>
Flyout: Enhanced attribute and event handler resolution for multiple flyout components using the same trigger.
Flyout: Improved position calculations for fixed containers not rendered at top: 0.
Flyout: Added automatic resolution for triggers rendered inside shadow DOM.
Tooltip, Popover, DropdownMenu: Enhanced position calculations for composition edge cases.
Tooltip: Tooltips now display instantly when moving between triggers within a global cooldown timeout.
Tooltip: Introduced a disabled flag to hide the tooltip when a Popover on the same trigger becomes active.
Tooltip, Popover, DropdownMenu: Added a containerRef property to control where content is rendered in the DOM.
Popover, DropdownMenu: Added an updatePosition method to instanceRef to dynamically adjust content based on trigger position or size.
Tooltip, Popover: Introduced a disableContentHover option to hide content when the mouse moves into the content area.
Tooltip, Popover: Ensured focus events are triggered only when keyboard mode is active.
Popover, DropdownMenu: Introduced new Popover.Dismissible and DropdownMenu.Dismissible compound components that automatically connect to component state.
Popover: Fixed nesting edge cases when using Popover inside a Tooltip.
Popover, DropdownMenu: Added a disableCloseOnOutsideClick flag.
We have added a verticalorientation for the Slider component, enabling new use cases like volume controls.
It pairs well with the new renderValue={false} option, which disables the native value tooltips, allowing you to render the value elsewhere.
Over the past three months, we focused on adopting the latest Figma features in our design library.
We improved our theming workflows in both Figma and React.
Additionally, we made major overall improvements to the design system.
Look for the ⚡ emoji in the changelog.
These changes update the API of components and features and might require attention for your product.
Don't forget to regenerate themes in React and Figma after updating to v3.
With the latest release of Figma typography variables, we have completed our theming migration to Figma variables.
With the new approach to theming, we now distribute a single file with components, styles, and variables.
This means you no longer have to manually link theme and component libraries together after they are published in your team.
Everything is linked correctly within a single file right after you import it.
With the help of Figma variables, we support up to 4 themes for team licenses and up to 40 themes for enterprise licenses.
Each theme supports light and dark mode and allows dynamic mode switching using Figma variable modes.
With full native variables support, we are also deprecating our Figma plugin theming functionality.
If you are using more than 4 themes and don't have an enterprise Figma license, we suggest using plugins like Swap variables to apply additional modes to your product mockups.
You can learn more about our setup from our recent post, try it yourself in our Figma library, and read more in the documentation.
While we were quite happy with our default theme, we decided that the Slate theme needed better alignment with the color palette of modern productivity tools.
In 3.0, we updated our theming generation algorithm and used it to generate the Slate theme.
You will notice that its colors are now smoother and more ambient in dark mode.
All generated themes are now also closer to the Slate theme since its neutral colors don't rely on additional hues.
functionDemo(){const{ setTheme, theme }=useTheme();return<ButtononClick={()=>setTheme(theme ==='reshaped'?'slate':'reshaped')}>Switch to {theme ==='reshaped'?'Slate':'Reshaped'}</Button>}
Additionally, we have made multiple improvements to the overall design tokens structure and naming:
Made raised shadows more subtle to better work for elevated cards.
Neutral border and background faded colors are now semi-transparent by default to work better across all backgrounds.
⚡ rs-color-rgb-border tokens have been removed since they now include alpha by default. Migration: In case you have an edge case where you need to apply opacity to your border, you can use css color-mix, mixing the border color with transparent.
The generateColors utility now supports passing dark mode values instead of always relying on them being automatically generated.
⚡ --rs-unit-radius variables were renamed to --rs-radius. Migration: Mass replace old variable names when migrating.
⚡ The unit.radius fields in the reshaped.config.js was renamed to radius. Migration: Move radius tokens tokens (e.g. unit.radiusSmall) in the config to the radius group (e.g. radius.small)
⚡ The heavy font weight in the theme configuration was renamed to extrabold. Migration: Rename the font in the theme cofiguration
⚡ highlighted color tokens were removed and are now resolved on the component level.
Migration: In case you were using highlighted color tokens before, use css color-mix or apply opacity to a separate layer with black / white background.
The useTheme hook now also exposes rootTheme and setRootTheme for more granular control of the app when using scoped theming.
reshaped.config.js now supports manually passing onBackground colors.
We have migrated our font-size and line-height CSS variables to rem.
This means that whenever users change browser font-size accessibility settings, all components will adjust accordingly.
All related decorative elements and icons will also align their size and position with the used typography sizes.
To improve the experience of working with iconography, we have switched from a single icon asset component with variants to individual components.
All component properties for picking an icon have been updated to swap instance properties.
This change makes it much easier to add custom icons to the library when building your product.
You will now also see visual previews when selecting an icon for your components.
Migration: In the Reshaped component instances using icons, pick the correct icon to be used using the new swap instance properties.
In case you have your own components exposing icons as a property, update them to also use instance swapping.
⚡ General: Switched to using the exports field in package.json instead of moving the build output to the root repository folder.
Migration: Depending on your bundler / framework setup, you will likely need to switch your tsconfig.jsonmoduleResolution to Bundler.
Types: Improved attributes typing to better work as a subset of React.HTMLAttributes
Slot, Figma: Added new Slot components supporting auto layout wrapping.
Actionable: Migrated the focus ring implementation to :focus-visible instead of a custom JS solution.
Alert: Increased the gap before actions when using the inline layout.
Badge: Relaxed the types to support passing dismissAriaLabel while onDismiss is undefined.
Badge: Added ref support for integration with routing libraries.
Badge: Fixed onClick triggering together with onDismiss.
⚡ Button: Merged black and white colors into a single media color. Migration:: Rename black and white colors to media.
⚡ Button: neutral faded button design was moved to neutral outline for better design alignment. Migration:: Switch color="neutral" variant="faded" buttons to color="neutral variant="outline". If you need it to have a background, you can add an elevated` flag to it.
Button: Improved the media color disabled state.
Button: Updated highlighted style values.
Card, Figma: Improved content clipping.
Container: Added align, justify, height, and maxHeight property support from View for better control over its content.
DropdownMenu: Added automatic position handling inside position: sticky.
Icon, Figma: Added on-background variants to avoid manual color overrides.
Icon, Figma: Fixed color overrides edge cases.
⚡ Hidden: Switched implementation to display: contents. Removed displayStyle property and render props children format since they're no longer required. Migration: Remove displayStyle properties used.
Switch from render props to regular children approach.
Link: Added warning color support.
MenuItem: Aligned the medium size border radius with other components.
MenuItem: Updated highlighted and selected style values.
Modal: Added full-screen position support.
Modal: Added a way to disable auto-focusing on the first element inside the content area and focus on the whole modal instead.
Modal: Added ariaLabel support.
Modal: Added onOpen handler for custom focus management.
Overlay: Added onOpen handler for custom focus management.
PinField: Fixed the first interaction with the field when all values are pre-filled on mount.
Popover: Added automatic position handling inside position: sticky.
⚡ Progress: Renamed white color to media. Migration: Replace white color with media
ScrollArea: Fixed thumb opacity for hover display style.
Slider: Updated thumbs positioning to not cause parent container overflow when there is no space on the sides.
Slider: Fixed horizontal scrollbar appearing in Safari for sliders with long tooltip values.
Text, Figma: Added white color variant.
TextArea: Fixed the field stretching too wide when it has a multiline value without spaces.
TextField: Removed focus ring in the headless variant.
Tooltip: Text prop is now optional and tooltip won't be triggered if text is not passed.
Tooltip: Added automatic position handling inside position: sticky.
useHotkeys: Added support for triggering callbacks while holding the shortcut pressed.