Upgrades

Welcome UI V5 focuses on the rework of our foundations and moving from reakit to ariakit (reakit v2).

Upgrade steps

1. Update your dependencies

Make sure you update all @welcome-ui packages and styled-components packages:

{
"dependencies": {
"@welcome-ui/YOUR_PACKAGE": "^5.0.0",
"@xstyled/styled-components": "^3.7.3",
"react": "^18.0.0",
"styled-components": "^5.3.9"
}
}

2. Migrate foundations

We reworked our theme's colors, spacing, typography, and many other properties. Use the migration script to migrate easily to V5 on a welcome-ui project.

yarn migrate "../yourProject/src/**/**.**(tsx|ts|js)"

3. Migrate Reakit to Ariakit

We also migrated to the new Ariakit library (reakit v2) on some of our components. To migrate easily, you can find components migration below.

To resume:

  • We now pass on a store property the component's state and remove "State" from the hook name.
- const drawerState = useDrawerState()
+ const drawer = useDrawer()
- <Drawer {...useDrawerState}>
+ <Drawer store={drawer}>
  • visible is now replaced by the open property
  • To force open a component, use now the defaultOpen property
- const drawerState = useDrawerState({ open: true })
+ const drawer = useDrawer({ defaultOpen: true })
  • Access the actual component's state with useState:
- const drawerState = useDrawerState()
- const isOpen = drawerState.visible
+ const drawer = useDrawer()
+ const isOpen = drawer.useState('open')

Theme

Colors

We changed our colors dark and light to be fully compatible with the coming dark mode (in beta). Now dark are black rgba with transparency, and light white rgba with transparency.

We also had to rework our colors naming for typescript compatibility reasons:

  • Before: colors.dark.900
  • After: colors['dark-900']

We rework some colors:

  • v4 compare to v5
  • [success/danger/warning/info].500 <-> [success/danger/warning/info]-300
  • [success/danger/warning/info].700 <-> [success/danger/warning/info]-400
  • new color [success/danger/warning/info]-500
  • nude.400 <-> nude-500
  • nude.500 <-> nude-400
  • nude.700 <-> nude-600
  • nude.800 <-> nude-700
  • ** the light colors are all white with opacity, you need to replace the old light color for text with new black color **
    • light.800 <-> dark-100
    • light.700 <-> dark-200
    • light.500 <-> dark-400
    • light.200 <-> dark-400
    • light.100 <-> dark-500
    • now the light colors variants are 100, 200, 400, 500, 700, 900(without opacity)
  • ** the dark colors are all black with opacity, it's also used for text color **
    • dark.100 <-> dark-500
    • dark.200 <-> dark-700
    • dark.500 <-> dark.900
    • dark.700 <-> dark.900
    • dark.800 <-> dark.900
    • now the dark colors variants are 100, 200, 400, 500, 700, 900(without opacity)
  • new color white (get the light.900 for dark mode)
  • new color black (get the dark.900 for dark mode)
  • the color for html is now dark-500

Spacing

We rework our spacing:

  • v5 compare to v4
  • xxs (2px) <-> new size (before it was 6px)
  • xs (4px) <-> new size (before it was 8px)
  • sm (8px) <-> xs
  • md (12px) <-> same size
  • lg (16px) <-> lg (15px)
  • xl (24px) <-> xxl
  • xxl (32px) <-> 3xl (30px)
  • 3xl (48px) <-> 5xl (50px)
  • 4xl (64px) <-> 6xl
  • 5xl (96px) -> new size
  • 6xl (128px) -> new size
  • 7xl (192px) -> new size

Typography

We change the name of variants to xs s m lg and remove useless variants.

  • meta1 and meta2 has been removed and replaced by sm and xs
  • body1 become lg
  • body2 become md
  • body3 become sm
  • body4 become xs
  • subtitle1 become subtitle-md
  • subtitle2 become subtitle-sm

Components

Accordion

We migrated to Ariakit and added an useAccordion hook to play with the component's store.

+ const accordion = useAccordion()
- <Accordion title="accordion">
+ <Accordion store={accordion} title="accordion">
= ...
= </Accordion>

Alert / Toast / Growl

  • All components

    • We have adjusted colors and spacing.
    • Position top has been replaced with top-center and position bottom has been replaced with bottom-center.
    • We removed the property closeButtonDataTestId. Now we add -close-button after your dataTestId property.
  • Alert

    • The props icon is now given to the Alert component and not to Alert.Title.
    • You must use the cta prop instead of pass the Alert.Button as a Children
    • You must use the isFullWidth prop to have an alert with a 100% max width
  • Toast

    • In order to use Toast component, you must add the Notifications component in your project root.
    • The useToast hook is deprecated. Instead, you can directly use toast function.
    • The props icon is now given to Toast.Growl / Toast.Snackbar component and not to Toast.Title.

Badges

Buttons

  • We have adjusted colors and spacing.
  • The xl size has been removed.
  • The ternary-negative has been removed.
  • The quaternary variant is now named ghost.
  • The icon size now adjusts to the size of the button.

Drawer

We migrated to Ariakit. We now pass the component's state from useDrawer to the store property:

- const drawerState = useDrawerState()
+ const drawer = useDrawer()
- <Drawer {...drawerState}>
+ <Drawer store={drawer}>
= ...
= </Drawer>

We replace props by:

  • hideOnClickOutside become hideOnInteractOutside
  • <Drawer.Backdrop> is removed and replace by a property withBackdrop. You can personalize your backdrop with the backdrop property.

We migrated to Ariakit. Now we pass the component's state from useDropdownMenu to the store property:

- const dropdownMenuState = useDropdownMenuState()
+ const dropdownMenu = useDropdownMenu()
- <DropdownMenu.Trigger {...dropdownMenuState}>
+ <DropdownMenu.Trigger store{dropdownMenu}>
= ...
= </DropdownMenu.Trigger>
- <DropdownMenu {...dropdownMenuState}>
+ <DropdownMenu store={dropdownMenu}>
- <DropdownMenu.Item {...dropdownMenuState}>
+ <DropdownMenu.Item store={dropdownMenu}>
= ...
= </DropdownMenu.Item>
= ...
= </DropdownMenu>

If you want to not close DropdownMenu item on click please add a hideOnClose={false} on DropdownMenu.Item:

<DropdownMenu.Item hideOnClose={false} store={dropdownMenu}>
...
</DropdownMenu.Item>

EmojiPicker

We migrated to Ariakit. Now we pass the component's state from useEmojiPicker on the store property:

- const emojiPickerState = useEmojiPicker()
+ const emojiPicker = useEmojiPicker()
- <EmojiPicker.Trigger {...emojiPickerState}>
+ <EmojiPicker.Trigger store{useEmojiPicker}>
= ...
= </EmojiPicker.Trigger>
- <EmojiPicker.Trigger {...emojiPickerState} />
+ <EmojiPicker.Trigger store={useEmojiPicker} />

and defaultTabState becomes defaultTabStore

FileDrop

accept property changed on v14 of react-dropzone:

  • Before: accept: "image/*"
  • After: accept: { "image/*": [] }

See more about showOpenFilePicker and media type.

Icons

We rework our icon size:

  • v5 compare to v4
  • This size has been removed <-> xxs (7px)
  • xs (12px) <-> xs (10px)
  • sm (16px) <-> sm (12px)
  • md (24px) <-> md (15px)
  • lg (32px) <-> lg (20px)
  • xl (48px) <-> xl (27.574px)
  • xxl (64px) <-> new size

We remove all @welcome-ui/icons.* packages (except icons.font). There is now two packages available:

We renamed some icons:

  • <GetIcon> become <DownloadIcon>
  • <EyeIcon> become <ShowIcon>
  • <ThumbupIcon> become <ThumbUpIcon>
  • <ThumbdownIcon> become <ThumbDownIcon>
  • <FlagFillIcon> become <FlagIcon>
  • <FlagIcon> become <FlagOutlineIcon>
  • <ChevronIcon> become <CodeIcon>
  • <DuplicateIcon> become <CopyIcon>
  • <TagsIcon> become <TagIcon>
  • <SalaryIcon> become <EuroCurrencyIcon>
  • new <SalaryIcon> icon
  • the isExternalLink become isExternal
  • We have adjusted colors and spacing.
  • Modal.Title is now named Modal.Header and has props title (mandatory) and subtitle (optional).
  • To ensure good spacing between modal's sub-components, they must be wrapped with Modal.Content.
  • Modal.Body is now the content box for Modal.
  • Modal.Cover has been removed.
  • We migrated to Ariakit and added an useModal hook to play with the component store.
- const modalState = useModalState()
+ const modal = useModal()
- <Modal {...modalState}>
- <Modal.Content>
...
- </Modal.Content>
+ <Modal store={modal}>
+ <Modal.Content store={modal}>
+ <Modal.Body>
...
+ </Modal.Body>
+ </Modal.Content>
= ...
= </Modal>

Popover

  • We migrated to Ariakit and added a usePopover hook to play with the component store.
- const popoverState = usePopoverState()
+ const popover = usePopover()
- <Popover.Trigger {...popoverState}>
+ <Popover.Trigger store={popover}>
= ...
= </Popover.Trigger>
- <Popover {...popoverState}>
+ <Popover store={popover}>
= ...
= </Popover>

RadioGroup

We removed the check icon on radio input and changed the style of it. We also reworked accessibility.

Tabs

We migrated to Ariakit. Now we pass the component state from useTab on the store property:

- const tabState = useTabState()
+ const tab = useTab()
- <Tab.List {...tabState}>
+ <Tab.List store={tab}>
- <Tab {...tabState}>
+ <Tab store={tab}>
= ...
= </Tab>
= </Tab.List>
- <Tab.Panel {...tabState}>
+ <Tab.Panel store={tab}>
= ...
= </Tab.Panel>

and selectedId become defaultSelectedId

Tag

  • We have adjusted colors and spacing.
  • The lg size has been removed.
  • The shape prop has been removed.
  • The icon size now adjusts to the size of the tag.

Tooltip

We added a div around the Children of the tooltip when the children has a disabled prop otherwise the tooltip does not trigger. We removed popper.js and only use Ariakit for fixed or not fixed tooltip.

Swiper

We rework the swiper component:

  • <Swiper.Slide> has been removed, you can embed and style your slides as you want
  • slidesToShow option become slidesPerView and now takes an object to define the number of slides per device { mobile: 1, tablet: 1, desktop: 1 }
  • renderPaginationItem, nextButton, prevButton and slidesToSwipe options have been removed

Now we pass the component state from useSwiper on the store property:

- const state = useSwiperState()
+ const swiper = useSwiper()
- <Swiper state={state}>
+ <Swiper store={swiper}>
= ...
= </Swiper>