There were a lot of questions about if it's possible and if it's a good idea to use Tailwind CSS together with Reshaped. We've always thought that it's a great idea and lets our users use css utilities when they need to get outside the Reshaped scope and build something custom.
Today, we're making it much easier to do this. Starting with v1.14, you can import a theme config for Tailwind CSS right from our package and get access to the same design tokens you had access in your CSS.
const { getTheme } = require("reshaped/tailwind");module.exports = {...theme: getTheme(),};
What makes it special is that you won't need the dark: variant to implement the dark mode. All colors resolve automatically, same as when you're using our components.
If you purchase multiple seats for your license, you can now let others create individual accounts with their own credentials attached to your Reshaped license. As an admin, you can choose when invites are enabled for the license, see everyone using the license and remove their access if needed.
We're getting closer to the v2.0 alpha build with Figma library moving to the test phase. All the components have been reviewed and updated from the ground up to work better with auto layout edge cases, support better composition and use the most out of the component properties.
We now start to work on the React implementation of the same change and you can expect a beta version ship for both design and code in May. At that point we'll be waiting for the Figma Config announcements before we release a stable 2.0 release.
Documentation:
Other:
We've added a new hook that supports the same responsive syntax as other components do for layout styles. It uses the matchMedia browser API to resolve the value of the currently used viewport size.
Since we browser viewport size is available only on the client-side, we're also providing a way to pick a default fallback value during the server-side rendering. It can be used either for the most used viewport size or together with user-agent detection.
function Example() {const backgroundColor = useResponsiveClientValue({s: "neutral",l: "primary",});return (<ViewbackgroundColor={backgroundColor}height={10}width={10}borderRadius="medium"/>);}
To reduce the amount of nested components and solve edge cases of using AspectRatio``, we've exposed the aspectRatioprop directly onView. Alongside with that, we're deprecating the AspectRatio` utility. It's staying in the package for now and will be removed in the next major release.
<ViewbackgroundColor="neutral-faded"aspectRatio={16 / 9}width="200px"borderRadius="medium"/>
Framework and bundlers integrations
We've added a new useHotkeys hook for handling application shortcuts and general keyboard interaction. Since we already have Reshaped provider for working with the global application state, we use it to optimize event handling.
We handle a lot of small edge cases regarding how keyboard events work and how pressed keys combination are handled natively, so we recommend using this hook every time you want to add keyboard navigation to your components or product features.
function Example() {const { checkHotkeyState } = useHotkeys({"shift + b + n": null,});const active = checkHotkeyState("shift + b + n");const shiftActive = checkHotkeyState("shift");const bActive = checkHotkeyState("b");const nActive = checkHotkeyState("n");return (<Viewanimatedgap={2}direction="row"backgroundColor={active ? "positive-faded" : undefined}padding={2}borderRadius="small"><ViewpaddingInline={4}paddingBlock={2}borderRadius="small"borderColor="neutral-faded"animatedbackgroundColor={shiftActive ? "neutral-faded": "base"}shadow={shiftActive ? undefined : "base"}>Shift</View><ViewpaddingInline={4}paddingBlock={2}borderRadius="small"borderColor="neutral-faded"animatedbackgroundColor={bActive ? "neutral-faded" : "base"}shadow={bActive ? undefined : "base"}>b</View><ViewpaddingInline={4}paddingBlock={2}borderRadius="small"borderColor="neutral-faded"animatedbackgroundColor={nActive ? "neutral-faded" : "base"}shadow={nActive ? undefined : "base"}>n</View></View>);}
With the new direction property you can now decide to stack tab items vertically. It works great when you want to switch page content and display menu items in a sidebar.
<Tabs direction="column"><View width="150px"><Tabs.List><Tabs.Item value="1" icon={IconZap}>Item 1</Tabs.Item><Tabs.Item value="2" icon={IconZap}>Long item 2</Tabs.Item><Tabs.Item value="3" icon={IconZap}>Very long item 3</Tabs.Item></Tabs.List></View></Tabs>
Figma:
Documentation:
We've shipped a new Timeline component for displaying lists of data in chronological order. It's built using compound components in code and consists of composable items in Figma, to let you easily build and maintain them in your product.
<View width="400px" maxWidth="100%"><Timeline><View backgroundColor="neutral-faded" height={10} /><View backgroundColor="neutral-faded" height={10} /></Timeline></View>
We've added dynamic resolving for different types of properties setting width and height of the elements. Before this release, you could see that some of the component properties, like padding or gap were using values as unit design tokens. For example, padding={4} would resolve to 16px in the default theme. width and height properties were outliers working with literal values, in order to support values like 100% or 50vh.
In this release we're adding number support for the properties defining the size of an element. It means that you can use still use it as before, but you can also pass a number value to automatically resolve it to a unit design token. This is especially helpful for smaller elements, where you wouldn't want to hardcode a specific px value.
This approach still works with the responsive syntax and it lets you use unit values for one viewport and literal values for another.
<Viewheight={25}width={{ s: "100%", l: 25 }}backgroundColor="neutral-faded"/>
View received support for working with its positioning without writing custom CSS. We've added new position and zIndex properties to handle how components are rendered relatively to each other, as well as a set of inset properties to control their coordinates.
Inset is the name of the vanilla CSS property when working with logical CSS properties, that helps you work with positioning for both LTR and RTL languages
<Viewposition="relative"backgroundColor="neutral-faded"height="100px"borderRadius="medium"><View position="absolute" insetTop={2} insetEnd={2}><Button icon={IconHeart} /></View></View>
Website
Source code
We've shipped a new Skeleton component for displaying animated content placeholder while data is still loading. It's built to be easily composed with other components and achieve layouts of any complexity. Additionally, its documentation comes with multiple examples of how skeletons can be used in the products.
<View width="400px" maxWidth="100%"><Card padding={0}><View aspectRatio={16 / 9}><Skeleton borderRadius="none" /></View><View padding={4} gap={2}><Text variant="body-strong-1"><Skeleton width="40%" /></Text><Skeleton /><Skeleton height="36px" width="120px" /></View></Card></View>
Reshaped semantic tokens are aiming to provide a limited number of tokens that should cover most of the use cases for building interfaces. However, there will always be edge cases where semantic tokens might feel limiting. For example, imagine you're building a chart component. You need a few custom colors for it but you also want to make sure they support dark mode the same way all Reshaped components do.
To address this, we've added support for adding custom design tokens to the theme definitions:
const config = {themes: {productTheme: {color: {foregroundNeutral: { hex: "#1a1a1a", hexDark: "#fff" },chartTomato: { hex: "#ff6347", hexDark: "#b8412c" }},},},};
<View width="340px" maxWidth="100%" direction="row" gap={4}><View.Item grow><TextField size="large" placeholder="Enter your e-mail" /></View.Item><Button color="primary" size="large">Subscribe</Button></View>
TextField, TextArea and Select components now support large and xlarge sizes and Button component has also received supported for xlarge size. With these additional values, you're now more flexible when building landing pages or other marketing material without overriding any of the components styles.
All these properties support responsive syntax, which means you can change these components sizes based on the device viewport.
We've shipped a new Accordion utility for toggling visibility of the content areas with automatic support of its height animation. It supports any type as content as well as it lets you use any component as a trigger.
<View height="120px" width="300px" maxWidth="100%"><Accordion><Accordion.Trigger><View backgroundColor="neutral-faded" height={10} /></Accordion.Trigger><Accordion.Content><View paddingTop={4}><View backgroundColor="neutral-faded" height={10} /></View></Accordion.Content></Accordion></View>
Components documentation have received an update with updated demo sections. Instead of showing static examples of how components look like, documentation now includes interactive knobs for trying out different combination of component properties values. That should help you see how component behaves without reading the whole article.
Check out the components documentation to see it in action. For example, you can start with a Button component as an example of component with many different visual properties.
With the v13 being released now, Next.js supports a new way to build routes with the app directory. One of the changes relevant for UI development that happened there was introduction of global css imports support inside node_modules folder. That means that Reshaped now works with Next without any webpack config customisations or additional plugins.
In this release, we've added a few improvements to align with the changes introduced in the latest Next.js major and have published a new starter example for Next.js 13, as well as we have updated its integration docs.
<View width="200px" maxWidth="100%" gap={2}><View direction="row" gap={2} align="center"><Viewwidth="32px"height="32px"borderRadius="medium"backgroundColor="primary"/><View.Item grow><View height="12px" backgroundColor="neutral" borderRadius="medium" /></View.Item></View><View direction="row" gap={2} align="center"><Viewwidth="32px"height="32px"borderRadius="medium"backgroundColor="primary"/><View.Item grow><View height="12px" backgroundColor="neutral" borderRadius="medium" /></View.Item></View></View>
Looking at the different ways of how Stack and Frame utilities can be used, we have noticed that in many cases both of them are used together. Stack is solving the layout challenges, while Frame allows us to easily access design tokens for typical styles. Additionaly, they both have overlaps in terms of what they provide from the flex api.
To avoid producing more markup than needed and simplify the structure of the codebases using Reshaped, we are introducing a new utility, called View. It supports functionality from both Stack and Frame, and provides more flexibility for how its properties can be combined, including full responsive syntax support for its layout properties. Additionally, we've madded some improvements to the View API:
Being the most low-level utility component, View is probaly going to be the most used component in your interfaces when using Reshaped. You can find information about the View API on its documentation page.
Stack and Frame utilities are still available in the library and are now using View under the hood. They're going to be dropped in the next major release.
We are on a path to make our documentation even more interactive and contextual. With this release, we have revamped structure of all our component pages:
We've shipped a new Toast component for displaying notification messages or other pieces of information above the page content. As always, we're focusing on the quality of the component and how flexible it is when comes to building custom layouts. Try out the following preview to see how it works or check its documentation to see all the supported features.
function Preview() {const toast = useToast();return (<ButtononClick={() => toast.show({ text: 'Account created', icon: IconZap })}>Create an account</Button>)}
We've gone through all components and added support for responsive properties for the layout properties that were not supported before. With the new properties, you can now make every single piece of layout responsive without writing any additional wrapper components.
For example, you can make a responsive action bar with buttons changing their direction and size for mobile screens. Try resizing your browser to see how it changes its layout as you switch to movile viewport size:
<View direction={{ s: "column", m: "row" }} justify="end" gap={2}><Buttonsize={{ s: "large", m: "medium" }}color="primary"fullWidth={{ s: true, m: false }}>Confirm</Button><Button size={{ s: "large", m: "medium" }} fullWidth={{ s: true, m: false }}>Cancel</Button></View>
The full list of newly added responsives properties includes:
We want to make our pricing more accessible for small and medium-sized companies, as well as to cause less confusion when it comes to deciding on the purchase of Reshaped. Therefore, we've decided to simplify our Pro license pricing and make it a one-time payment, similar to the regular license.
Purchasing a Pro license will give you lifetime access to the source code, testing, and Storybook setup, as well as unlimited seats for the library. All companies, who've purchased the Pro license using the previous pricing model, get automatically migrated to the new lifetime access with this release.
We've shipped a new Breadcrumbs component for displaying top-level product navigation. Components like breadcrumbs have a specific product purpose, so to still keep it white-label and not make any product decisions, it supports rendering any component as a child and lets you control how its collapsing should work.
<Breadcrumbs defaultVisibleItems={2} color="primary"><Breadcrumbs.Item onClick={() => {}}>Catalog</Breadcrumbs.Item><Breadcrumbs.Item onClick={() => {}}>Shoes</Breadcrumbs.Item><Breadcrumbs.Item onClick={() => {}}>Running</Breadcrumbs.Item><Breadcrumbs.Item>Ultraboost</Breadcrumbs.Item></Breadcrumbs>
We've launched a new umbrella website for our design system studio called Formaat. Our website is a place that connects all of our products together and we also want to use it as a platform to help teams working on design system grow. We start with a series of design system interviews with the industry experts to help you learn about how design systems are built and maintained at scale.
To help you work with Reshaped React components, we've added a new Core concepts article, explaining ideas that apply to the whole system. We cover topics like, responsive component properties, accessibility, utility components and other concepts that turn a component library into the design system.
// Pass conditional as a className without handling it outside<View className={foo && 'foo'} />// Pass arrays of classNames and we will resolve them for you<View className={['foo', bar && 'bar']} />
We've shipped a new Carousel component for displaying scollable areas with grouped content. It works with any type of content, properly handles RTL and supports responsive layouts.
<View padding={2}><Carousel visibleItems={{ s: 2, l: 3 }}><View aspectRatio={16 / 9}><div style={{ position: 'absolute', top: 8, right: 8 }}><Button icon={IconHeart} color="white" elevated rounded /></div><Image src="/img/examples/architecture-1.webp" alt="Archirecture design" borderRadius="medium" /></View><View aspectRatio={16 / 9}><div style={{ position: 'absolute', top: 8, right: 8 }}><Button icon={IconHeart} color="white" elevated rounded /></div><Image src="/img/examples/architecture-2.webp" alt="Archirecture design" borderRadius="medium" /></View><View aspectRatio={16 / 9}><div style={{ position: 'absolute', top: 8, right: 8 }}><Button icon={IconHeart} color="white" elevated rounded /></div><Image src="/img/examples/architecture-3.webp" alt="Archirecture design" borderRadius="medium" /></View><View aspectRatio={16 / 9}><div style={{ position: 'absolute', top: 8, right: 8 }}><Button icon={IconHeart} color="white" elevated rounded /></div><Image src="/img/examples/architecture-4.webp" alt="Archirecture design" borderRadius="medium" /></View><View aspectRatio={16 / 9}><div style={{ position: 'absolute', top: 8, right: 8 }}><Button icon={IconHeart} color="white" elevated rounded /></div><Image src="/img/examples/architecture-5.webp" alt="Archirecture design" borderRadius="medium" /></View></Carousel></View>
☝️ In case you have custom themes built with Reshaped, you'll have to run their build script once to make sure the typography fixes are applied.
We've built a Figma plugin that can add themes & switch to dark mode. It works locally and does it blazingly fast. It supports theming for color, text, and effects.
Our internal Storybook is finally public for everyone and is now featured in Storybook Encyclopedia. It might give you a better understanding of our internal development setup in case you're looking to purchase our Pro license.
<View direction="row" gap={3}><Image width={{ s: "100px", m: "150px" }} height={{ s: "100px", m: "150px" }} src="/img/examples/image-retina.webp" borderRadius="medium" /><Image width={{ s: "100px", m: "150px" }} height={{ s: "100px", m: "150px" }} src="/wrong.png" borderRadius="medium" fallback={<Icon svg={IconZap} size={8} />} /></View>
We've shipped a new Image utility for displaying images and controlling their behavior. It supports rendering image assets based on the screen pixel density and provides multiple fallback options when image asset is not available or was not loaded correctly.
<View width="200px" gap={2}><Text variant="title-3">Documentation</Text><MenuItem.Aligner><View gap={1}><MenuItem selected size="small" roundedCorners>Overview</MenuItem><MenuItem size="small" roundedCorners>Installation</MenuItem></View></MenuItem.Aligner></View>
Displaying a title for a menu section is such a common case and we don't want anyone to count the pixels they need for the negative margins. Because of that, we've implemented a utility that is similar to Button.Aligner. It aligns the contents of the MenuItem with the content used around it, no matter which size you use them with.
One of the core documentation parts missing before was a place to have all available components at glance. People had to literally go through every single page in the docs to see what we have in the library. In 1.2 we're finally addressing this with a revamped overview page that has previews of every single component in the library and structured access to utilities and hooks from the same page.
Figma:
React:
Website:
<View width="400px" maxWidth="100%"><Alertcolor="primary"title="New version is available"icon={IconZap}actionsSlot={<Link variant="plain">View now</Link>}>Find out which new features are available in the upcoming Reshaped release</Alert></View>
We've shipped a new Alert component that can be used for displaying prominent messages related to the whole page or a specific area. It comes in 4 different colors, supports horizontal layout direction and works with any type of content.
☝️ In case you have custom themes built with Reshaped, don't forget to run the generation script for them to get these new tokens available in your theme.
<View gap={3} direction="row"><ViewbackgroundColor="primary-faded"borderColor="primary-faded"borderRadius="medium"width="60px"height="60px"/><ViewbackgroundColor="positive-faded"borderColor="positive-faded"borderRadius="medium"width="60px"height="60px"/><ViewbackgroundColor="critical-faded"borderColor="critical-faded"borderRadius="medium"width="60px"height="60px"/></View>
We have added three new color tokens for faded borders. They work perfectly for decorative elements that don't need to meet 4.5 to 1 contrast ratio requirements. For example, we use these tokens ourselves in the newly released Alert component.
We've adopted the latest features that Figma announced during Config 2022: individual strokes, instance swap for icons, slot selection, text properties, boolean properties and more. This brings more control for library users as well as better alignment with code. In some cases though connection to the master component may be lost: please read through the bullet points marked with ☝️ before updating your mockups.
Action bar
Alert
Avatar
Card
Badge
Button
Checkbox
Radio
Link
Modal
Overlay
Popover
Input-select
Tabs
Text area
Text field
Tooltip
Text utility
Icon utility
Dependencies
After two years of active development, we've finally reached an important milestone. Today we're releasing the 1.0 version of Reshaped for React and Figma and we're live on Product Hunt.
With this release, we're starting to follow our release strategy with no more breaking changes for the following year. It means that the library has reached a stable state, and you can update to any upcoming minor release in a matter of minutes.
Until June 10, we're keeping early-bird prices to celebrate the release, and we hope you enjoy using Reshaped as much as we do ourselves.
☝️ In case you have custom themes built with Reshaped, don't forget to run the generation script for them to get these new tokens available in your theme.
☝️ In case you have custom themes built with Reshaped, don't forget to run the generation script for them to get these new tokens available in your theme.
<Button color="positive">Complete registration</Button>
We've made a few improvements to our available color tokens to make theming support even more customisation cases:
We've gone through the whole library and tested everything for React 18 compatibility. To confirm that it's all working in external environments, we've also migrated this website to React 18.
React 18 was added to our package peer dependencies and you can start your project migration. However, make sure all other dependencies you use are compatible with React 18, there are a few Typescript changes that a lot of packages are catching up with.
We have updated property tables for all components and utilities to make them more scannable. They also now contain icon indicators for responsive and required properties.
We're adding support for installing Reshaped by access tokens. Since we're not publishing the library on the public NPM, this should help 3rd party tools to easier integrate with our design system and install it as a dependency without manually downloading the system. In the future we might also explore this approach as our default way for installing the library in any codebase.
Meanwhile, if this is something you would like to see working in your tool or you want to be able to install Reshaped in your codebase - send us a message.
React:
Figma:
During the past two months we've been working on updating our brand and our brand assets. There are still a few things we're going to roll-out before 1.0 gets released but today we're shipping our renamed library and the new landing page.
We're renaming to Reshaped, which means there are a few things that are renamed in the code:
We're changing our theming approach just a bit to make it work with NextJS server-side rendering. Theme definitions now rely on the data-rs-theme attribute which means you can assign it in the _document.jsx file without importing .css files.
<body data-rs-theme="reshaped-light">
We've updated framework integrations guidelines and moved them to a separate documentation section on the website. All example projects have been updated with the latest dependencies and their setup has been simplified.
In addition to that, we have added Gatsby starter example and documentation. Check its documentation in the Integrations sections in our docs.
In this release, we've updated the way you can add custom themes. Instead of working with createTheme and createThemeFragment functions, themes are created from an reshaped.config.js file. You can store in the root level of the repository or provide a custom path to our theming CLI.
This release is the first one to include Reshaped Figma library which is available for both regular and source code licenses. Library consists of 3 files that include:
With the help of Figma Themer plugin, you'll be able to design your product just once and switching to dark mode will happen automatically without any manual customisation. This works not only with Reshaped components but also with any custom component you create yourself.
Along with Figma release, we're also updating our pricing tiers.
First of all, even though we're adding Figma library to the list, we're keeping our single seat license to $79 while we're getting closer to v1.0 release of Reshaped. Shortly after the release its price is going to raise to $99.
Team licenses now scale based on the amount of seats you purchase with increasing discounts which means now you get a better deal for 2-3 people teams.
On top of that we're adding two new tiers:
In this release, we've updated the way we generate output of the theming engine and the way themes are used in the code. We've moved away from theme components and ColorMode utility to a single Theme component that works with both, scoped themes and color modes. This allowed us to avoid additional rerenders of the app when a theme changes and reduced the complexity of theming in general.
import { Reshaped, Theme } from "reshaped";import reshapedTheme from "reshaped/themes/reshaped.module.css";import productTheme from "themes/product.module.css";const Application = () => (<Reshaped theme={reshapedTheme}>Reshaped theme is used here<Theme name={productTheme}>Product theme is used here</Theme></Reshaped>);
For the cases where using our ESM build output is not possible, we're now additionally providing Reshaped JS and CSS bundles. This will disable regular tree-shaking of the modules but makes it possible to use the library in environments that currently don't support CSS imports from within node_modules. However this shouldn't affect the performance much considering that current library total size is lest than 40kb including both CSS and JS.
To use the bundles, you can import them directly from the package. Note that you will need to import styles just once.
import { Button } from "reshaped";import "reshaped.css";
After 3 months of design work we're finalising our Figma library with all the components moving into testing phase. All components are designed with variants, auto-layout and paying incredible attention to handling composition of components the same way you would do that in code. Both React and Figma libraries are perfectly aligned so anything you can design with Reshaped Figma library - you can immediately implement in code with no problems.
<View gap={3} direction="row" align="center"><divstyle={{background: "var(--rs-color-background-primary)",borderRadius: "var(--rs-unit-radius-small)",width: 24,height: 24,}}/><Text variant="body-2-2" color="neutral-faded">--rs-color-background-primary</Text></View>
We have revamped our design tokens documentation and added visual examples for all Reshaped tokens. Every token type now has a separate page, going through their values and guidelines on how to use them.
<Button color="primary" icon={IconZap}>Instant delivery</Button>
We've made an major update to our documentation layout to let you discover the information you're looking for faster. Some of the highlights are:
During the past two weeks we have been improving the Reshaped onboarding experience for some of the most popular front-end frameworks and bundles. So far we have prepared 4 starter examples for Parcel, Webpack, NextJS and Create React App as well as few demos with more advanced examples.
We have passed 50% of our Figma library progress with 12 components and design token library ready. Everything is already built with theming/dark mode support, using auto-layout and providing variants for every component.
If you want to track the progress, you can do that in our project board.
When using colors as variables in CSS, you would usually hit a wall when you want to apply custom opacity values to them. The only way to combine a color variable with opacity is to use it with rgba() color function in CSS.
In order to support this case, we've added auto-generation for rgb values of the background color tokens. They use similar names to background token names with an additional rgb prefix:
var(--rs-color-rgb-background-neutral) /* 223, 226, 234 */
Note that the variable stores only the rgb values themselves but doesn't wrap it with a function. This means you can now use it together with rgba() color function in your css:
background: rgba(var(--rs-color-rgb-background-neutral), 0.5);
On the hompage, we now have a video demo for those who want to take a look of how the development process looks like. In the demo we are building a social media card with some common layouts and interactive behavior that you would usually see in your day-to-day job. Additionally, we show how theming and dark mode work with no extra effort or requirements to write custom styling logic on your side.
While building interfaces we have to implement complex behaviors like modal being opened from a dropdown. Both of these components should trap the focus and return it back to the trigger element when closed. Starting with this release with support chained trap focus. It will return the focus back to the correct trigger even if some of the trigger elements are no longer rendered on the screen.
For example, try going through the whole flow using your keyboard in the following example. Once you close the modal, focus will return to the "Open menu" button.
Hint: Click near the button first and press Tab, to focus on the button using keyboard.
function ChainTrapFocus() {const { active, activate, deactivate } = useToggle(false);return (<><DropdownMenu><DropdownMenu.Trigger>{(attributes) => <Button attributes={attributes}>Open menu</Button>}</DropdownMenu.Trigger><DropdownMenu.Content><DropdownMenu.Item onClick={activate}>Open modal</DropdownMenu.Item><DropdownMenu.Item>Second menu item</DropdownMenu.Item></DropdownMenu.Content></DropdownMenu><Modal active={active} onClose={deactivate}><View gap={3}><Dismissible onClose={deactivate} closeAriaLabel="Close modal"><Modal.Title>Modal title</Modal.Title><Modal.Subtitle>Modal subtitle</Modal.Subtitle></Dismissible>Dialogs present a distinct choice to users through their title, content, and actions.<Button onClick={deactivate}>Got it</Button></View></Modal></>);}
Our homepage has been completely revamped to put emphasize on the newly released features, including our recent theming engine. You can try applying one of the 3 demo themes to our whole website, including their light and dark modes.
Stack is the core of any layout you build, and we want it to be as flexible as possible. Starting with 0.9.0 we are using CSS variables to work with responsive styles, and we've started with Stack component integration. Till now, we've only supported a limited number of values that you could use as gap property because its styles have been predefined in CSS. With the new responsive CSS variables, we're changing gap property to support any numerical value as a multiplier of the base unit token.
This change includes both, regular and responsive properties, which means you can pass any number you want for every viewport size:
<View gap={{ s: 2, l: 10 }} />
With this new approach, we're shipping a couple more features for the Stack component:
We've moved away from supporting RTL during build step with a PostCSS plugin and are using CSS logical properties now instead. This takes us one step closer to moving away from CSS build step and using completely native CSS. Additionally, this update helped us improve a handful components and how they render in RTL mode.
We have added size-limit integration to our merge requests which lets us track all the bundle size changes as one of our main metrics. For example, even after introducing all these new features and responsive styles, we have actually reduced our total bundle size by 2kb down to 41kb.
We're finally releasing out theming engine, including completely typed JS API and CLI to build themes using Reshaped design tokens. Writing your theme definition once will build a React component for you that's ready to be imported into your application. Among other features its main highlights are:
For this release we've built our first demo of a page using Reshaped. It's aiming to provide a publicly available example of a project setup as well as giving a hint about how building interfaces with Reshaped looks like.
We've started supporting more scenarios for responsive development. In this release we're adding another viewport support to differentiate between portrait and landscape tablet modes. This means that our viewport media queries names have been updated accordingly:
@media (--rs-viewport-s) @media (--rs-viewport-m) @media (--rs-viewport-l) @media (--rs-viewport-xl);
To make the components easier to use with 4 viewports available, we're also switching from array notation to an object notation for the responsive properties. Since we use mobile-first approach, you don't have to define values for every viewport manually. For example, you can set the Stack gap to be x2 by default and change to x4 starting with large viewport size.
<View gap={{ s: 2, l: 4 }}>
<View gap={2}><View backgroundColor="neutral-faded" height={10} /><View direction="row" gap={2}><View backgroundColor="neutral-faded" height={10} /><View.Item grow><View backgroundColor="neutral-faded" height={10} /></View.Item><View backgroundColor="neutral-faded" height={10} /></View><View direction="row" gap={2}><View width="200px"><View backgroundColor="neutral-faded" height={10} /></View><View.Item grow><View backgroundColor="neutral-faded" height={10} /></View.Item></View></View>
We've completely rebuilt our Stack component from ground up to cover a huge number of new edge cases. Most of our focus went into improving nested stacks, edge cases for specific components and reducing the number of elements rendered per every stack:
We've also tried using the new gap API for flexbox which turned out not so well, due to the limited Safari support and some webkit bugs that have to be fixed first. Once the state of the API becomes more stable, we will immediately migrate to it.
<Tabs variant="pills"><Tabs.List><Tabs.Item id="0">Item 1</Tabs.Item><Tabs.Item id="1">Long item 2</Tabs.Item><Tabs.Item id="2">Very long item 3</Tabs.Item></Tabs.List></Tabs>
Tabs get 2 new variants to support new UI scenarios. borderless is helpful when it's used with parent component that provides its own border already. pills variant is used for less prominent secondary navigation.
<View width="300px" maxWidth="100%" gap={3}><Progress value={25} color="primary" /><Progress value={50} color="critical" /><Progress value={75} color="positive" /></View>
We release Progress component to the progress status for a task that takes a long time or consists of several steps. In some cases it can be used for other types of context, like displaying the score values etc.
<View borderRadius="medium" overflow="hidden" width="300px" maxWidth="100%"><Overlayposition="bottom"backgroundSlot={<View aspectRatio={16 / 9}><img src="/img/examples/architecture-1.webp" alt="Example" /></View>}><Text variant="body-strong-2">Architecture photos</Text></Overlay></View>
We're adding Overlay component to let you build nice-looking media cards and display text content on top of them. You can find which position values it supports in the documentation.
<Tabs defaultActiveId="1"><Tabs.List><Tabs.Item value="0">Components</Tabs.Item><Tabs.Item value="1" icon={IconZap}>Utilities</Tabs.Item><Tabs.Item value="2">Hooks</Tabs.Item></Tabs.List><Tabs.Panel value="0"><View padding={4}>Components tab</View></Tabs.Panel><Tabs.Panel value="1"><View padding={4}>Utilities tab</View></Tabs.Panel><Tabs.Panel value="2"><View padding={4}>Hooks tab</View></Tabs.Panel></Tabs>
We release Tabs component to let you organise navigation between multiple pages or content sections. Its compound components approach lets you easily build custom tab panels or add animation to them, and it's responsive out-of-the-box. Read more about it in its documentation.
<DropdownMenu><DropdownMenu.Trigger>{(attributes) => <Button attributes={attributes}>Open</Button>}</DropdownMenu.Trigger><DropdownMenu.Content><DropdownMenu.Item>Action 1</DropdownMenu.Item><DropdownMenu.Item>Action 2</DropdownMenu.Item></DropdownMenu.Content></DropdownMenu>
We're adding a DropdownMenu component built on top of Popover to simplify the process of building action menus. It works with a similar API as Popover does, however it encapsulates some of its logic, which means you don't have to pass all the right props and aria attributes to Popover manually. Read more about it in its documentation.
We have published and documented 6 hooks provided by the library. Together with our utility components they should close the gaps and let you build custom components using the Reshaped context data:
After a year in the making, the first release of the Reshaped is now available for everyone to use. We're starting by releasing v0.1.0 with 31 components, utilities and their documentation. If you're just starting with the library, start with the Overview page from the menu on the left. We hope you enjoy using Reshaped and are already looking forward to get the next release out of the door! 🕹️