15 April 2024
<FormControl>
  <FormControl.Label>Pin code</FormControl.Label>
  <PinField name="pin" defaultValue="2543" />
</FormControl>

We've added a new PinField component for handling one-time passwords and other numeric or alphabetic codes. It works based on a native input element, supports controlled/uncontrolled modes and has an extensive keyboard support for managing the input focus and selection.

Based on the community request, we have added Toast rendering boundaries. Anywhere in your application, you can wrap an area with a separate ToastProvider to make notifications render based on that area boundaries.

function Boundary() {
  const ChildComponent = () => {
    const toast = useToast();

    return (
      <Button
        onClick={() => {
          toast.show({
            text: "Notification sent",
          });
        }}
      >
        Show notification
      </Button>
    );
  };

  return (
    <View backgroundColor="neutral-faded" padding={10} width="600px" maxWidth="100%" borderRadius="medium">
      <ToastProvider>
        <ChildComponent />
      </ToastProvider>
    </View>
  );
}
  • Updated Commitlint, Storybook and Chromatic to the latest major versions
  • Fixed a build error caused the FormControl files naming when working with Vite
  • Updated Vite integration guide #238
  • Actionable: improved the form submission logic for the submit type buttons with a custom onClick
  • Breadcrumbs: added a disabledExpand property to render static breadcrumbs inside other clickable elements #227
  • Calendar: fixed edge cases of assigning the correct tabIndex to the day cells
  • Card: improved the padding logic to include the border width into its calculations
  • DropdownMenu: simplified the handling of keyboard and mouse click events combination
  • Modal: added overlayClassName property #229
  • Modal: improved the scrollable content handling when using swipe-to-close functionality #242
  • Pagination: added tabular number styles to avoid the page button size changes during navigation
  • Slider: added tabular number styles to avoid the tooltip size changes
  • Slider: added float values rounding #228
  • Table: removed content wrapping for the cells using the auto width
  • Tabs: added smooth transition for the Tab list fades whenever it doesn't fit into the viewport
  • Tabs: improved the selection element transition
  • Tabs: updated the triggers font-weight to medium to match other clickable elements
  • TextField: removed focus-within styles from the root elements whenever a button is focused in one of its slots
  • View: fixed dividers rendering incorrectly when nested inside React.Fragment #226
  • View: improved the padding logic to include the border width into its calculations
  • useHotkeys: added a disabled option to control the hotkeys availability based on your local state
  • useHotkeys: added a preventDefault option to automatically prevent the default behavior of the binded hotkeys
  • useHotkeys: improved the cleanup of the triggered hotkeys when pressing the meta key
4 March 2024

We've added a new component to help users navigate across multiple pages of content. It automatically truncates the pages, handles accessility including focus management and provides controlled as well as uncontrolled behavior to make sure you can connect it to your custom application logic.

<Pagination total={10} previousAriaLabel="Back" nextAriaLabel="Forward" />

While we have aligned components and design tokens implementations in Figma and in React, syncing custom themes across both platforms was always a manual process. With the introduction of theming generation, we've automated a part of the theming process and in this release we're adding the missing piece.

We've released a new version of our Figma plugin that now lets you upload the json output from your theme in code and generate a Figma style and variables library automatically. We're planning to keep evolving this functionality with the upcoming improvements for the Figma variables support and general announcements that will happen during the Figma Config this summer.

Ever wanted to start your own development blog but then you find yourself spending weeks to build a front-end application for that? We've created a new blog example using Reshaped but this time we've also published it as an NPM package and open-sourced it.

Besides checking how Reshaped can be used in your own project, you can use it for your own MDX and Next.js powered blog. It gives you an amazing layout inspired by Brian Lovin's personal website, which is built using Reshaped, supports light and dark mode, completely accessible and responsive.

  • With the last few components css changes, we were able to switch Reshaped NPM package to use sideEffects: false by default which improves tree-shaking for the bundlers relying on this flag. This means that you will get full tree-shaking support for even more frameworks, including the CSS tree-shaking for components you don't use in your application.
  • Updated all internal dependencies for the source code setup
  • Updated Create React App guidelines with more details on how to enable custom media queries support
  • Added json file output during theme generation
  • Actionable: Moved css reset to a css @layer with lower priority, making sure that css order gets resolved correctly during tree-shaking
  • Accordion: Fixed an error which caused product code calling Accordion to inlcude use client directive in RSC supporting frameworks
  • Accordion: Migrated height animation to CSS transitions without and JS calculations involved
  • BadgeContainer: Added pointer-events: none to the Badge used in BadgeContainer to avoid it blocking the trigger clicks
  • Button, Figma: Added min-width support for the text buttons
  • Button: Added as property support for nesting multiple clickable elements within each other
  • FormControl: Fixed an error which caused product code calling Accordion to inlcude use client directive in RSC supporting frameworks
  • MenuItem: Added as property support for nesting multiple clickable elements within each other
  • ScrollArea: Added overflow hidden to root element to prevent scrollbar thumb travelling outside the scrollable area in Safari
  • Slider: Added dynamic Tooltip positioning to always keep it inside the viewport and avoid causing page to scroll horizontally for tooltips with long labels
  • Table: Added cell verticalAlign support
  • Table: Removed border-radius in borderless tables for better composition with other components
  • Table: Fixed duplicated cell padding in borderless tables
  • Text: Added balance wrap support
29 January 2024

We're introducing a new ScrollArea utility which aligns the scrollbar styling across all platforms, while still relying on the native scrolling behavior. It supports multiple display modes and supports both horizontal and vertical directions.

Besides the general style alignment, it can be useful for non-standard scrolling areas where displaying a native scrollbar can be too distractive on some platforms. For example, it's perfect for navigation menus or smaller components with scrollable areas.

In this example, we're rendering it inside the Card with scrollbars shown on the area hover and scrolling in both directions:

<View width="300px">
  <Card height="200px" padding={0}>
    <ScrollArea scrollbarDisplay="hover">
      <View height="300px" width="150%" align="center" justify="center">
        Text content
      </View>
    </ScrollArea>
  </Card>
</View>

Based on the community request, we've improved out Storybook setup with the new addons:

  • Each story now display its source code with a storysource plugin
  • Most of the components now have an additional tab displaying auto-generated prop tables based on the current version of the source code you're using
  • In case you need more context about the component without leaving Storybook, we're also display each component latest documentation in an iframe

Together, these changes are aiming to improve the developer experience of teams working with our Storybook environment and provide additional contextual information about components in case they're staying on one of the previous versions of Reshaped.

  • Switched the TypeScript jsx build mode to react-jsx
  • Added support for radio inputs arrow navigation inside the areas with trapped focus
  • Added the page color background to <html> in addition to <body>
  • TextArea: Fixed placeholder color misalignment with TextFIeld
3 January 2024
<View gap={2}>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-brand)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-brand
      </Text>
    </View.Item>
  </View>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-foreground-warning)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-foreground-warning
      </Text>
    </View.Item>
  </View>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-background-warning)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-background-warning
      </Text>
    </View.Item>
  </View>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-background-warning-faded)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-background-warning-faded
      </Text>
    </View.Item>
  </View>

  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-border-warning)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-border-warning
      </Text>
    </View.Item>
  </View>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-border-warning-faded)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-border-warning-faded
      </Text>
    </View.Item>
  </View>
  <View gap={3} direction="row" align="center">
    <div
      style={{
        background: "var(--rs-color-on-background-warning)",
        borderRadius: "var(--rs-radius-small)",
        width: 24,
        height: 24,
      }}
    />

    <View.Item grow>
      <Text color="neutral-faded">
        --rs-color-on-background-warning
      </Text>
    </View.Item>
  </View>
</View>

We are adding new color tokens: warning and brand. Warning colors are used as a new role in between critical and positive colors, while brand colors can be used for brand assets as a standalone color different from primary colors. With the new colors support we have introduced new colors for component like Badge and Progress.

If you're using your own themes, make sure to generate them again to include new color tokens in the builders. If you're using a custom theme in Figma, update its definition in the theming plugin you're using.

We have added a new example of the whole application screen built with Reshaped and its design is included in our Design license. It features the whole page layout relying completely on the Reshaped components utilities, including its responsive behaviour and interactive components, like DropdownMenu or Toast.

  • PostCSS: Added getConfig() function to support viewport breakpoints theming
  • Badge, Figma: Exposed icon properties in Figma
  • Button: Added flex layout support for the button children
  • Button: Reduced the vertical padding to work with larger slots without stretching the button
  • Button, Figma: Extracted .button-content into a separate cmponent to improve the library performance and maintenance experience
  • Button, Figma: Added slot support
  • Icon: Fixed svg rendering error happening for icon components using prop-types
  • Icon: Added linear logo to the iconset in Figma
  • MenuItem: Fixed Tailwind CSS reset overriding button styles
  • Overlay: Fixed Tailwind CSS cursor override
  • Slot, Figma: Fixed slot overriding styles of the swapped components
  • Timeline, Figma: Fixed the content slot auto layout
  • View: added minWidth and minHeight support
  • View: added overflow auto support
12 December 2023
<View width="320px">
  <Calendar />
</View>

We're adding a new Calendar component to work with single and range date selection. It supports controlled / uncontrolled behavior, full keyboard navigation, localization, separate month selection and much more.

Like with every other component, we pay additional attention to how it can be composed with other components and we provide examples of how you can build a form input for the date selection.

We've introduced a new swipe behavior for Modal components on touch devices. All Modals besides the center-positioned ones can now be closed with touch events and you can try it for yourself if you're on mobile device or simulate it in your dev tools:

function Example() {
  const { active, activate, deactivate } = useToggle(false);

  return (
    <>
      <Button onClick={activate}>Open modal</Button>
      <Modal active={active} onClose={deactivate} position="start">
        Modal content
      </Modal>
    </>
  );
}
  • Source code: Added GitHub actions setup
  • Themes: Updated on color generation algorithm to be more precise according to the wcag requirements
  • Themes: Added rgb variants for the border color tokens
  • Themes: Updated contrast edge cases to be handled based on the APCA formulas
  • Autocomplete: Fixed inputAttributes not applying correctly
  • Link: Fixed inherit color value for the iOS Safari edge cases
  • Modal: Improved the open/close transition effect
  • Overlay: Added number values support for the transparent property to manually control its progress
  • Slider: Removed the touch highlighting on mobile devices
  • Text: Updated maxLines to apply word-break when truncating a single line
  • Toast: Added className support
  • View: Updated documented to refer to the updated paddingInline and paddingBlock properties
19 November 2023
<View width="300px" maxWidth="100%">
  <FileUpload name="file">
    <View gap={2}>
      <Icon svg={IconMic} size={6} />
      <View.Item>
        Drop files to attach, or{" "}
        <FileUpload.Trigger>
          <Link variant="plain">browse</Link>
        </FileUpload.Trigger>
      </View.Item>
    </View>
  </FileUpload>
</View>

The new FileUpload component we're introducing is a flexible and easy-to-use tool for handling file attachments in forms. It's designed to be lightweight, leveraging our standard composition approach and give you complete control over the component's layout and appearance.

One of the key aspects of the FileUpload component is its compatibility with third-party libraries. For instance, integrating with react-dropzone is straightforward, enabling you to tap into its advanced file upload capabilities. This ensures that while the component itself remains simple and unopinionated, it doesn't limit your ability to implement more complex functionalities.

The component supports both click and drag events for file selection, making it user-friendly and adaptable to various user interactions. This approach aligns with our goal of providing components that are both powerful and easy to use, without imposing strict design or functional constraints.

  • Themes: added a way control individual "on" colors resolutions. Read more in the documentation.
  • Themes: improved baseThemeDefiniion typings
  • Breadcrumbs: fixed breadcrumbs rendering when used in React Server Components
  • Popover: fixed default render styles and updated transition effect for trigger width
  • Popover, DropdownMenu: added support for positioning inside the position: fixed parent
  • Select: fixed custom trigger start padding when used without slots
  • TextArea: added support for passing rows to inputAttributes
  • TextArea, TextField: updated onFocus and onBlur typings to use correct html element reference
23 October 2023
function Demo() {
  const colors = ["#5a58f2", "#2563eb", "#0891b2", "#34d399", "#facc15", "#d97706", "#be185d"];
  const [hex, setHex] = React.useState(colors[0]);

  const css = getThemeCSS("myTheme", {
    color: generateThemeColors({ primary: hex }),
  });

  return (
    <>
      {css && <style>{css}</style>}
      <Theme name="myTheme">
        <View gap={4}>
          <View gap={4} direction="row">
            {colors.map(color => (
              <Actionable key={color} onClick={() => setHex(color)}>
                <View
                  width={5}
                  height={5}
                  borderRadius="circular"
                  attributes={{
                    style: {
                      transition: `box-shadow var(--rs-duration-fast) var(--rs-easing-standard)`,
                      background: color,
                      boxShadow:
                        color === hex
                          ? `0 0 0 3px var(--rs-color-background-elevation-base), 0 0 0 5px ${color}`
                          : undefined,
                    },
                  }}
                />
              </Actionable>
            ))}
          </View>
          <View gap={4} direction="row">
            <Button color="primary">Primary button</Button>
            <Button color="primary" variant="faded">Faded button</Button>
          </View>
        </View>
      </Theme>
    </>
  );
}

Last time, we've introduced support for the runtime theming to let you create new themes right in your browser environment. However, creating themes manually would mean that you still have to go through a long process of manually picking the values for all design tokens.

Finding right colors is definitely the hardest step in the process, so in v2.5 we're adding a new theme generation feature. Now you can pass just your primary brand color and we'll generate a full set of color tokens required for theming, including dark mode values. In case you want more granular control over certain colors, you still can pick different base colors for the critical, positive and neutral hues or even override individual token values.

To make sure your generated themes don't stay aligned with our default theme, we've updated some of the Reshaped theme values. In case you're relying on the default Reshaped theme value, make sure to re-sync it in Figma.

<View width="500px" maxWidth="100%" gap={2}>
  <Stepper labelDisplay={{ s: "hidden", m: "inline" }} activeId={1}>
    <Stepper.Item completed title="Pick your plan" subtitle="Pro or hobby" />
    <Stepper.Item title="Contact info" />
    <Stepper.Item title="Payment" />
  </Stepper>
  <Hidden hide={{ s: false, m: true }}>
    <View direction="row" gap={4} justify="space-between">
      <Text weight="medium">Contact info</Text>
      <Text weight="medium">Step 2 of 3</Text>
    </View>
  </Hidden>
</View>

One of the requests we had was a component to control a multi-step process navigation, so we're introducing a new Stepper component in this release. It includes support for row and column direction, as well as responsive visibility of the labels. With all supported properties, you can easily compose and control the Stepper component according to the unique business logic of your product.

  • Figma: Fixed foreground-critical color style reference used in the colors preview
  • Theming: Added 0 value support for the shadow attributes
  • Theming: Fixed transitions staying disabled after setting the color mode to an already applied one

Accordion

  • Improved overflow handling on the accordion state change

Button

  • Renamed Button.Aligner position property to side. position is deprecated now but both properties will work until the next major release.

DropdownMenu

  • Added support for opening nested submenus with Enter and Space keys
  • Updated open and close transition effects

MenuItem

  • Added side support for the MenuItem.Aligner

Popover

  • Updated open and close transition effects

TextArea

  • Added TextField.Aligner utility for aligning the field value with other content on the page #180

TextField

  • Fixed width calculation bug in Safari that was causing field to grow on focus when it was centered #178
  • Fixed positioning of the native Chrome autocomplete #183
  • Added TextField.Aligner utility for aligning the field value with other content on the page #180

Tooltip

  • Updated open and close transition effects

View

  • Added static position support
  • Added automatic switching to the flexbox layout if any of the direct children are using grow property #185
22 September 2023
<View width="280px" maxWidth="100%">
  <Table border>
    <Table.Row highlighted>
      <Table.Heading>Product</Table.Heading>
      <Table.Heading align="end" width="auto">
        Price
      </Table.Heading>
    </Table.Row>
    <Table.Row>
      <Table.Cell>Coffee</Table.Cell>
      <Table.Cell align="end">$4</Table.Cell>
    </Table.Row>
    <Table.Row>
      <Table.Cell>Sandwich</Table.Cell>
      <Table.Cell align="end">$6.50</Table.Cell>
    </Table.Row>
  </Table>
</View>

We're adding a new Table component that provides common compound components for rendering individual table elements and gives you a lot of flexibility through composition. This approach allows teams to build both, simple table with text content and rich tables with interactive content that are integrated with libraries like TanStack Table.

With the recent theming improvements, we're adding a new website page for previewing theme values on a real component examples. This is a first step towards making it easier to create new themes. In the upcoming releases, we're planning to expand its functionality with user interface for the runtime theme editing and theme values auto-generation.

  • Documentation: Updated website performance
  • Documentation: Added examples of working with theming settings based on user preferences and local storage before the React hydration

Button

  • Fixed margin value for the Button.Aligner used with ghost buttons

Card

  • Added selection transition

Checkbox

  • Added transition for the indeterminate state

Tabs

  • Added auto-scrolling when selecting items if Tabs.List is scrollable

View

  • Added space-between value for the justify property
11 September 2023
function Demo() {
  const [customTheme, setCustomTheme] = React.useState(false);

  const css =
    customTheme &&
    getThemeCSS("myTheme", {
      color: {
        backgroundPrimary: { hex: "#1abc9c", hexDark: "#16a085" },
        backgroundPrimaryHighlighted: { hex: "#16a085", hexDark: "#1abc9c" },
      },
    });

  return (
    <>
      {css && <style>{css}</style>}
      <Theme name={customTheme ? "myTheme" : "reshaped"}>
        <View gap={4} align="start">
          <FormControl>
            <View direction="row" gap={2}>
              <Switch
                name="theme"
                onChange={() => setCustomTheme((prev) => !prev)}
              />
              <FormControl.Label>Toggle custom theme</FormControl.Label>
            </View>
          </FormControl>
          <Button color="primary">Primary button</Button>
        </View>
      </Theme>
    </>
  );
}

We have added a new way to work with themes without building them using our CLI ahead of time. With the new runtime theming feature, you can create new themes directly in the browser and insert them as a style tag, or create themes dynamically in Node.js and return css file contents.

<View gap={4} align="start">
  <Button.Group>
    <Button variant="faded">File</Button>
    <Button variant="faded">Edit</Button>
    <Button variant="faded">View</Button>
  </Button.Group>

  <Button.Group>
    <Button>Save changes</Button>
    <DropdownMenu>
      <DropdownMenu.Trigger>
        {(attributes) => <Button icon={IconDown} attributes={attributes} />}
      </DropdownMenu.Trigger>
      <DropdownMenu.Content>
        <DropdownMenu.Item>Copy link</DropdownMenu.Item>
        <DropdownMenu.Item>Update permissions</DropdownMenu.Item>
        <DropdownMenu.Item>Save to folder</DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu>
  </Button.Group>
</View>

We're adding a new compound component for Button – Button.Group, which lets you wrap any number of buttons to colocate multiple actions together. It leverages the composition approach, which means you can combine items with other components like DropdownMenu.

  • Figma: Updated component style relations to improve the experience of switching color modes. Original issue is reported to the Figma team but let us know if you see any styles left that might be not respecting the mode without refreshing the page so we can patch those individual components.

Actionable

  • Fixed cases when onClick was triggered multiple times on Enter key press

Autocomplete

  • Added correct positioning support inside scrollable areas
  • Added trapFocus support for the dynamically rendered content

Checkbox

  • Removed default browser tap highlight on mobile devices

DropdownMenu

  • Added correct positioning support inside scrollable areas
  • Added trapFocus support for the dynamically rendered content

Popover

  • Added correct positioning support inside scrollable areas
  • Added trapFocus support for the dynamically rendered content

Radio

  • Removed default browser tap highlight on mobile devices

Select

  • Fixed the color of the chevron icon when using the disabled state

Switch

  • Removed default browser tap highlight on mobile devices

Tabs

  • Added support for wrapping Tabs.Item with framework router link components and other custom wrappers
  • Added href support for Tabs.Item
  • Added attributes support for Tabs.Item

Toast

  • Fixed an edge case when toast.hide is called immediately after toast was triggered
28 August 2023

Haven't used Reshaped before and interested in trying out our NPM package for the first time? Check our standalone release announcement covering core Reshaped principles.

Don't forget to resync the theme in Figma in case you're using the default theme or copy line-height variables into your custom theme from the Reshaped theme file.

<Card padding={6}>
  <Text color="primary" variant="body-1" weight="medium" attributes={{ style: { fontFamily: 'monospace' } }}>
    npm install reshaped
  </Text>
</Card>

Since the very beginning of Reshaped, we wanted to find more ways to give back to the community and it was very challenging to do without sacrificing our whole business model and keeping the development sustainable. In the past few months, we've started switching the focus of our paid assets and services more towards companies creating their design systems and we can finally start giving more of our content for free to let individual developers try our Reshaped.

In v2.2 we've published our React package to npm and it's now available to everyone for free. We hope this could help more indie hackers in building their new projects, as well as for everyone who has been asking us about how to use Reshaped in their open-source projects – you finally can.

For teams considering buying the Pro version with the library source code, free npm access could help with making the decision without having to pay for the individual licenses.

We're very excited to see more people using Reshaped and get more feedback to see what we can improve further on 🚀

function DemoFiltering() {
  const [value, setValue] = React.useState("");
  const options = ["Pizza", "Pie", "Ice-cream"];

  const handleChange = (args) => setValue(args.value);

  return (
    <View width="300px" maxWidth="100%">
      <Autocomplete
        name="fruit"
        placeholder="Pick your food"
        value={value}
        onChange={handleChange}
      >
        {options.map((option) => {
          if (!option.toLowerCase().includes(value.toLowerCase())) return;
          if (option === value) return;

          return (
            <Autocomplete.Item key={option} value={option}>
              {option}
            </Autocomplete.Item>
          );
        })}
      </Autocomplete>
    </View>
  );
}

We're extending our form fields collection with a new Autocomplete component that comes with full accessibility support and keyboard navigation. Like in many other components, we're following our composition approach here so you would see its primitives are built using TextField and DropdownMenu and let you control its internal composition and state based on your own requirements.

<View paddingBlock={4} maxWidth="100%" width="300px">
  <Slider
    range
    name="slider"
    defaultMinValue={20}
    defaultMaxValue={60}
    renderValue={(args) => `$${args.value}`}
  />
</View>

One of the requests we had was a component to pick a range of values, so we're adding support for the Slider component. It comes with built-in accessibility and keybord navigation, works for individual values and value ranges, as well as it supports all typical form states and can be combined with the FormControl utility.

  • Theming: Increased body-1 line-height to work better when used in multiline paragraphs
  • Theming: Removed Segoe UI fallback font from the default theme definition
  • Documentation website: Migrated to the Next.js app directory and has improved web vitals

Button

  • Updated xlarge size to use body-2 font to better align with the form fields

Checkbox

  • Added css transition for the selection state change

DropdownMenu

  • Added new selection-menu value for the trapFocusMode property
  • Added new focus value for the triggerType property
  • Added new disableHideAnimation property
  • Added attributes support for the DropdownMenu.Content

MenuItem

  • Added box-shadow css transition to align its focus state with the Button component

Popover

  • Added new selection-menu value for the trapFocusMode property
  • Added new focus value for the triggerType property
  • Added new disableHideAnimation property

Radio

  • Added css transition for the selection state change
12 July 2023

Don't forget to resync the theme in Figma in case you're using the default theme or copy line-height variables into your custom theme from the Reshaped theme file.

function Demo() {
  const [theme, setTheme] = React.useState('reshaped');

  return (
    <>
      <View position="absolute" insetTop={4} insetStart={4}>
        <Select
          options={[
            { label: 'Reshaped', value: 'reshaped' },
            { label: 'Slate', value: 'slate' },
            { label: 'Figma', value: 'figma' }
          ]}
          onChange={({ value }) => setTheme(value)}
        />
      </View>
      <Theme name={theme}>
        <View width="300px">
          <Card elevated>
            <View gap={3}>
              <FormControl>
                <FormControl.Label>Your name</FormControl.Label>
                <TextField name="name" placeholder="Paul" />
              </FormControl>
              <FormControl hasError>
                <FormControl.Label>Your email</FormControl.Label>
                <TextField name="name" value="hello@reshaped" />
                <FormControl.Error>
                  Invalid email address
                </FormControl.Error>
              </FormControl>
              <Button color="primary" fullWidth>Submit</Button>
            </View>
          </Card>
        </View>
      </Theme>
    </>
  )
}

In this release, we are introducing two new themes. One of the themes is called Slate, which features a color palette inspired by productivity applications and developer tools. It primarily utilizes shades of gray that are closer to monochrome values.

Second theme is a theme based on the Figma interface and can help with building Figma plugins with a familiar set of components.

<View gap={2} direction="row">
  <Badge size="large" onDismiss={() => {}} color="positive">
    In progress
  </Badge>
  <Badge icon={IconHeart} color="primary" variant="faded" size="large" onClick={() => {}}>
    Locals favorite
  </Badge>
</View>

Badge has been enhanced with the following additional properties, expanding its versatility and usage in various scenarios:

  • large size: Make badges more prominent on the page, ideal for marketing pages where emphasis is important.
  • icon support: Illustrate the badge text with icons to enhance content recognition and visual appeal.
  • onDismiss and dismissAriaLabel: Utilize badges for displaying selected items, such as filters, and easily subscribe to their dismiss events.
  • onClick and href: Transform badges into actionable elements, allowing user navigation or general user interaction. Clicking or tapping on the badge triggers the defined action or navigation.

These additional properties empower you to leverage badges creatively in new scenarios, providing flexibility and enhancing the user experience.

  • Figma: Updated the color pallete preview layout with built-in contrast ratio checking for background color
  • Figma: Added new line-height variables that can be applied as elements width and height balues. This lets you create themes with different typography sizes and make components size scale alongside your typography.
  • Updated Button, TextField, Select, Checkbox and Radio to calculate their dimensions based on the typography values.
  • Theming config: Added support for semibold weight.
  • Theming: Added typography styles for scoped theming.

Button

  • Fixed black and white button colors not applying border color changes on hover

Card

  • Figma: Fixed theming of the border-radius variables

FormControl

  • Reduced the font-size for helper and error to better align with the typography theming

MenuItem

  • Figma: Exposed icon props to the main component

View

  • Fixed the divider visibility when one of the items has background color applied
3 July 2023

We're excited to announce our v2.0 release today 🎉

For the past 6 months, we've been working hard rethinking every single piece of Reshaped and what should be our next steps. It led us to rebuilding our Figma library from ground-up, increasing all components reliability, helping you compose them together without unexpected layout issues and adopting the latest features features, like Figma Variables.

With more teams purchasing Reshaped Pro license, we've spent additional time making sure we can provide the best experience for those teams starting with their design systems. What they value the most is how fast they can start building their custom features without spending any time on the setup. To support them, we have completely revamped our Pro license development environment to cover all technical requirements for a modern design system.

Look for âš¡ emoji in the changelog. These changes update the API of components and features and might require attention on your product.

Don't forget to regenerate themes in React and Figma after updating to v2.

We've updated our source code structured and moved it away from an internal monorepo. This way we can ensure that our development environment works without any manual adjustments for other teams and dependency resolutions. At the same time you can still include it into your own monorepo and store all components right next to your product.

While working on this, we've also improved the overall setup of the source code. We've switched from Webpack to vite for bundling the library and storybook, added stylelint and git hooks for running automatic linting on commit. With all the changes in place – making a full library build now takes ~10-15 seconds.

âš¡ Figma gives us a lot of new features to improve the quality of design system assets. We've been using component variants and properties in Reshaped for quite some time, but there were parts of the library we could only change after the major release.

In 2.0, we've revamped the whole library to be even more aligned with code and use these features to their full potential, as well as be ready for the new features Figma will announce on Figma Config this year:

  • Moved theme library to Figma variables, which now allows for theming unit and radius tokens
  • Many component variants have been reviewed and switched to component properties. It means there is less room for mistakes when we're shipping new releases but also a better experience for you if you start customizing our components.
  • All components follow the same layer structure best practices now and won't break because of the auto-layout styles of their parent layers.
  • All components that allow content customization are now integrated with the new Slot utility, which lets you create custom layouts within components without detaching components.
  • Figma page structure has been updated with a new layout. In addition, every component and utility includes helpful tips and a playground to test how the component works.

âš¡ We have updated our font design tokens structure to reduce the complexity of working with the design tokens in Figma and reduce the size of the theme CSS file by almost 60%.

  • Typography doesn't have responsiveness built-in now in favor of manually picking the correct token based on the product context. This change gives you more control over how typography is used across the product while keeping it consistent.
  • Weight is now a separate style modifier you can apply to the fonts below title to apply text formatting.
  • There are four new tokens that you can use directly now to improve the flexibly of the typography you can use.

Here is a mapping of the old typography values to the new ones:

// Before          After

display-1          title-1
...                title-2 [new]
display-2          title-3
...                title-4 [new]
display-3          title-5
...                title-6 [new]

title-1            featured-1, weight: bold
title-2            featured-2, weight: bold
title-3            featured-3, weight: bold

featured-1         featured-1
featured-2         featured-2
featured-3         featured-3

...                body-1 [new]
body-1             body-2
body-2             body-3
body-medium-1      body-2, weight: medium
body-medium-2      body-3, weight: medium
body-strong-1      body-2, weight: bold
body-strong-2      body-3, weight: bold

caption-1          caption-1
caption-2          caption-2
<View direction="row" gap={4}>
  <Theme colorMode="light">
    <View backgroundColor="neutral-faded" padding={8} borderRadius="large" direction="row" gap={3}>
    <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-base)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
        }}
      />
      <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-raised)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
          boxShadow: "var(--rs-shadow-raised)",
        }}
      />
      <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-overlay)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
          boxShadow: "var(--rs-shadow-overlay)",
        }}
      />
    </View>
  </Theme>
  <Theme colorMode="dark">
    <View backgroundColor="neutral-faded" padding={8} borderRadius="large" direction="row" gap={3}>
      <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-base)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
        }}
      />
      <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-raised)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
          boxShadow: "var(--rs-shadow-raised)",
        }}
      />
      <div
        style={{
          backgroundColor: "var(--rs-color-background-elevation-overlay)",
          border: "1px solid var(--rs-color-border-neutral-faded)",
          borderRadius: "var(--rs-radius-medium)",
          width: 60,
          height: 60,
          boxShadow: "var(--rs-shadow-overlay)",
        }}
      />
    </View>
  </Theme>
</View>

âš¡ We've slightly updated our elevation system with the design token name changes and a new color token to align color and shadow tokens completely. This change is inspired by Atlassian Design System's work on its foundations.

// Before                     After

shadow-base                   shadow-raised
shadow-elevated               shadow-overlay

...                           color-background-elevation-base [new]
color-background-base         color-background-elevation-raised
color-background-elevated     color-background-elevation-overlay

We have reviewed our color palette to work better across various edge cases, especially in the dark mode:

  • Dark mode background-faded colors now stand out less than before and better align with other dark mode color tokens.
  • All neutral colors have been updated to ensure enough contrast ratio to keep them visible on top of each other. For example, you can now clearly see the elements using a neutral-faded background on top of elevation-overlay.
<View gap={3}>
  <View gap={3} direction="row" align="center">
    <Button onClick={() => {}}>
      Solid button
    </Button>
    <Button variant="faded" onClick={() => {}}>
      Faded button
    </Button>
    <Button variant="outline" onClick={() => {}}>
      Outline button
    </Button>
    <Button variant="ghost" onClick={() => {}}>
      Ghost button
    </Button>
  </View>
  <View gap={3} direction="row" align="center">
    <Button color="primary" onClick={() => {}}>
      Solid button
    </Button>
    <Button color="primary" variant="faded" onClick={() => {}}>
      Faded button
    </Button>
    <Button color="primary" variant="outline" onClick={() => {}}>
      Outline button
    </Button>
    <Button color="primary" variant="ghost" onClick={() => {}}>
      Ghost button
    </Button>
  </View>
</View>

The button is the component every design system usually starts with, and there are so many different use cases we need them for in our products. In this release, we're adding a new faded variant to the Button component and have slightly updated the existing variants' styles to ensure we cover as many typical use cases as possible.

You can find more information about the available variants in the documentation:

We've added support for more complicated menus with nesting. To achieve that, we have introduced two new componenets inside DropdownMenu: DropdownMenu.SubMenu and DropdownMenu.SubTrigger. By using them together with previously available parts of the DropdownMenu, you will automatically get trap focus support for multiple levels of menus and new hotkeys for working with submenus.

<DropdownMenu>
  <DropdownMenu.Trigger>
    {(attributes) => <Button attributes={attributes}>Open</Button>}
  </DropdownMenu.Trigger>
  <DropdownMenu.Content>
    <DropdownMenu.Item onClick={() => {}}>Item 1</DropdownMenu.Item>
    <DropdownMenu.SubMenu>
      <DropdownMenu.SubTrigger>Item 2</DropdownMenu.SubTrigger>
      <DropdownMenu.Content>
        <DropdownMenu.Item onClick={() => {}}>SubItem 1</DropdownMenu.Item>
        <DropdownMenu.Item onClick={() => {}}>SubItem 2</DropdownMenu.Item>
      </DropdownMenu.Content>
    </DropdownMenu.SubMenu>
    <DropdownMenu.Item onClick={() => {}}>Item 3</DropdownMenu.Item>
  </DropdownMenu.Content>
</DropdownMenu>
  • âš¡ Dependencies: Minimum React version has been updated to 18.0.0
  • Figma: Added keywords to all components for better components discoverability
  • Theming: Added support for 8-digit hex colors
  • Theming: Increased the default motion duration values
  • Theming: Added themeOptions.generateOnColorsFor option to generate foreground colors for custom background color tokens
  • Theming: Updated on colors resolving based on your black and white color tokens
  • âš¡ PostCSS integration: Updated import path from reshaped/postcss to reshaped/config/postcss
  • Tailwind integration: Added support for black and white color tokens for text, bg and border
  • Tailwind integration: Added support for 0 spacing value
  • âš¡ Tailwind integration: Updated import path from reshaped/tailwind to reshaped/config/tailwind
  • Added a custom internal postcss plugin to simplify css source code and optimise the reponsive styles output
  • âš¡ Deleted deprecated utilities: Stack, Frame and AspectRatio. View can be used instead to achieve the same functionality.
  • âš¡ Deleted useElementId hook in favor of React.useId which can guarantee more stable identifier generation.

useHotkeys

  • Improved support for edge cases when using multi-key shortcuts using Meta key
  • Added support for passing an existing ref to the hook options
  • Added support for a cross-platform mod key

Actionable

  • Added support for passing both onClick and attributes.onClick simultaneously

Dismissible

  • Added as a utility in Figma

Icon

  • Added disabled color

Reshaped provider

  • âš¡ Moved all global attributes from <body> to <html> to ensure dark mode affects native elements, like the page scrollbar color
  • âš¡ Split data-rs-theme="reshaped-light" into data-rs-theme="reshaped" and data-rs-color-mode="light". It gives us more granular access to the theming updates.

Text

  • Figma: Updated available variants based on the new tokens structure
  • Figma: Added fill property to control the text max-width
  • Figma: Added color property for easier usage of color design tokens

Theme provider

  • âš¡ Renamed to Theme from ThemeProvider
  • âš¡ theme property has been renamed to name

View

  • âš¡ Replaced padding tuple value [y, x] with paddingBlock={y} paddingInline={x}
  • Added support for passing custom inline styles to View.Item
  • Added grow property support directly on View for nested Views

ActionBar

  • âš¡ Removed size property in favor of padding which gives you more control over the content spacing

Alert

  • Figma: Updated links in the positive Alert to positive color
  • Figma: Added support for slot composition

Avatar

  • Figma: Added additional sizes to align with other components dimensions
  • âš¡ Moved faded colors to a variant property to align API across components
  • Added correct color definitions for the neutral and faded avatars for the cases when color is defined by its parent

Badge

  • Updated spacing in the small Badge size

Card

  • Added height property support
  • Figma: Added bleed support for elevated cards
  • Figma: Added support for changing the container padding with auto layout

Carousel

  • Figma: Added slots support
  • Figma: Improved mobile scaling

Checkbox

  • Figma: Added missing variants
  • Figma: Added support for preserving property values when swapping with Radio and Switch

Divider

  • âš¡ Figma: Renamed direction property to a vertical boolean

DropdownMenu

  • Added contentGap property to control distance between the trigger and the content
  • Added instanceRef property to access imperative methods: open, close
  • Added support for trigger width to align popover width with the trigger width

Overlay

  • Added as a utility in Figma

Radio

  • Figma: Added missing variants
  • Figma: Added support for preserving property values when swapping with Checkbox and Switch

Link

  • Added positive color support

MenuItem

  • Aligned MenuItem size and icon size values with the Button sizes
  • Added neutral color support
  • Figma: Aligned selection styles with React
  • âš¡ Figma: Removed built-in child component variants in favor of composition

Modal

  • âš¡ Renamed transparentBackdrop to transparentOverlay for the component naming alignment

Popover

  • Added start-top, start-bottom, end-top and end-bottom position support
  • Added contentGap property to control distance between the trigger and the content
  • Added instanceRef property to access imperative methods: open, close
  • Added support for trigger width to align popover width with the trigger width

Scrim

  • âš¡ Renamed Overlay to Scrim
  • Figma: Aligned gradient styles
  • Figma: Added background slot support

Select

  • Figma: Aligned placeholder color value with React
  • Added faded and unstyled variant
  • Updated the chevron icon
  • Added support for using Select as a custom trigger without passing options

Switch

  • Added new small size
  • Added text label support
  • Added new reversed flag to control the display of the label
  • Updated disabled variant styles
  • Figma: Added support for preserving property values when swapping with Radio and Checkbox

Tabs

  • Added new large size

TextField

  • âš¡ Figma: Removed success state
  • Figma: Aligned placeholder color value with React
  • Added faded and unstyled variant
  • Added prefix and suffix properties for rendering text affixes

TextArea

  • Figma: Aligned the default field height with the code implementation
  • Figma: Aligned placeholder color value with React
  • Added faded and unstyled variant