Dialog
or Drawer
component. (#1665)MenuRenderer: Ensure menu is visible, even when its trigger element is inside a container with overflow hidden. (#1658)
MenuRenderer, OverflowMenu: Provide improved scroll affordance (#1661)
Introduce scroll affordance to menus, providing a visual cue that there are more items overflowing vertically.
OverflowMenu: Simplify internal layout. (#1658)
Refactor the internal layout of OverflowMenu
to improve the alignment of the menu with the button.
IconCoverLetter
IconChecklist
IconDisallow
IconBluetooth
IconQR
Update the following icon assets: (#1655)
IconNote
IconResume
IconDocument
IconDocumentBroken
IconHeart
Button, ButtonLink: Ensure label is vertically centered (#1656)
Fixes a bug where a ButtonLink
label would not be vertically centered inside containers that stretch elements to fill the available space, such as Tiles
.
While the issue did not affect Button
, the fix was applied to both components to ensure there is no reliance on browser default styling.
Autosuggest: Ensure content is left aligned (#1642)
Applies left alignment to Autosuggest
dropdown content to ensure consistent alignment, even when inside centered layout containers.
Standardise icon slot spacing (#1638)
Normalise the space between the icon
slot and component content across the system.
Rating: Simplify internal layout (#1638)
Simplify the internal HTML and layout of the Rating
component.
This change should not affect the appearance or behavior of the component.
Remove lodash dependency (#1639)
useToast: Ensure content is left aligned (#1630)
Applies left alignment to Toast
content to ensure intended alignment, regardless of other styles applied.
IconRocket: Update design (#1636)
Update the design asset for IconRocket
This release is a huge milestone for Braid with upgrades occurring across a number of key areas:
With SEEKs Browser Support Policy now enabling adoption of CSS gap, Braid's layout components are now able to lean into the platform directly for its declarative, parent-driven approach to white space management.
The result is on average our experiences receive around a 20% reduction in DOM elements, more performant rendering, better composability without the introduction of intermediary elements and a better debug experience in dev tools.
The key tradeoff is the removal of dividers
functionality which is explained further here.
gutter
size in seekJobs
themeThe size of the gutter
token on the seekJobs
theme has been reduced from large
(i.e. 32px), to medium
(i.e. 24px).
This is a semantic token that runs through many system components, and consumer should perform a visual design audit to ensure experiences are laid out as intended.
See full changelog below 👇
Stack, Inline: Consumers need to render li
elements (#1626)
When setting component
to ul
or ol
on Stack
or Inline
, consumers need to ensure they render children as li
elements.
Previously Braid owned an intermediate HTML element, ensuring it was an li
when required.
Moving to CSS gap means child elements are no longer being wrapped, requiring consumers to update their child elements to the correct HTML element, e.g. li
.
MIGRATION GUIDE:
<Stack component="ul"> - <Text>Item 1</Text> + <Text component="li">Item 1</Text> - <Text>Item 2</Text> + <Text component="li">Item 2</Text> </Stack>
Autosuggest: Remove deprecated message syntax from suggestions
prop (#1626)
Remove the deprecated message syntax from the suggestions
prop in favour of the noSuggestionsMessage
prop.
<Autosuggest ... - suggestions={{ message: 'No results found' }} + suggestions={[]} + noSuggestionsMessage="No results found" />
Text, Heading: Remove deprecated truncate
prop (#1626)
Remove the deprecated truncate
prop in favour of the maxLines
prop which accepts a number of lines to truncate the text to.
<Text - truncate + maxLines={1} />
Stack, Tiles: Remove divider
support (#1626)
As part of migrating our layout components to leverage flex gap, the Stack
& Tiles
components no longer iterate over their children, making dividers
no longer feasible to implement centrally.
While we could have exposed an API to apply this behaviour conditionally, there are edge cases that cannot be handled correctly without consumer-side rendering logic, such as when child components render nothing or a hidden element.
For Stack
s with static children you can manually interleave Divider
components:
-<Stack space="..." dividers> +<Stack space="..."> <Component /> + <Divider /> <Component /> + <Divider /> <Component /> </Stack>
Or for conditionally rendering children you can return a [React Fragment], including the Divider
and child:
-<Stack space="..." dividers> +<Stack space="..."> <Component /> {condition ? ( - <Component /> + <> + <Divider /> + <Component /> + </> ) : null} </Stack>
For Stack
s with iterable children you can return a [React Fragment] and conditionally render the Divider
component as the first child, before each item (except the first):
-<Stack space="..." dividers> +<Stack space="..."> {items.map((item, index) => ( - <Component>{item}</Component> + <Fragment key={...}> + {index > 0 ? <Divider /> : null} + <Component>{item}</Component> + </Fragment> ))} </Stack>
For Tiles
the dividers
prop was only applied when showing a single column.
For this you can conditionally render the Divider
in a Stack
with the same spacing as specified on the Tiles
instance, and hide it on breakpoints showing more than one column.
Here is an example of this with static children:
-<Tiles space="..." columns={{mobile: 1, tablet: 2}} dividers> +<Tiles space="..." columns={{mobile: 1, tablet: 2}}> <Component>{item}</Component> + <Stack space="..."> + <Hidden above="mobile"> + <Divider /> + </Hidden> <Component>{item}</Component> + </Stack> + <Stack space="..."> + <Hidden above="mobile"> + <Divider /> + </Hidden> <Component>{item}</Component> + </Stack> </Tiles>
Here is an example of this with iterable children:
-<Tiles space="..." columns={{mobile: 1, tablet: 2}} dividers> +<Tiles space="..." columns={{mobile: 1, tablet: 2}}> {items.map((item, index) => ( - <Component>{item}</Component> + <Stack space="..." key={...}> + {index > 0 ? ( + <Hidden above="mobile"> + <Divider /> + </Hidden> + ) : null} <Component>{item}</Component> + </Stack> ))} </Tiles>
Drop support for React 17.x (#1626)
To enable Braid to leverage newer React APIs, we are no longer providing support for React v17.x. React 18 was released in March 2022 and consumers were encouraged to upgrade to this as part of the Braid v32 release in Feb 2023 (which dropped React 16 support).
Removing support for React 17 allows us to simplify and streamline a lot of our component APIs, which will have downstream improvements on consumer codebases.
Consumers still on v17 should follow the How to Upgrade to React 18 guide.
For sku consumers who upgraded to Braid v32 and added the "jsx-runtime
workaround for ESM incompatibility", this can now be safely removed from their webpack configuration once updated to React 18:
// sku.config.ts { dangerouslySetWebpackConfig: (config) => webpackMerge(config, { - resolve: { - fallback: { - 'react/jsx-runtime': require.resolve('react/jsx-runtime'), - }, - }, }), }
Button, ButtonLink: Remove deprecated bleedY
prop (#1626)
Remove the deprecated bleedY
prop from the Button
and ButtonLink
components.
Consumers should use the bleed
prop instead, which bleeds based on the selected variant
.
<Button - bleedY + bleed {...} > Button </Button>
Radio: Remove deprecated component (#1626)
Remove deprecated Radio
component in favour of RadioGroup
with RadioItem
children.
- <Radio checked={checked} onChange={handleOnChange} label="Option" /> + <RadioGroup + value={value} + onChange={handleOnChange} + label="Options" + > + <RadioItem value="1">Option</RadioItem> + </RadioGroup>
Column: Prevent growing when content
width specified (#1626)
Ensure that when a column width
is specified, the column does not grow or shrink.
Only a column with no width
specified will fluidly adapt to the available space.
Fixes a bug when all Column
components have a defined width
, a column specifying content
width would incorrectly grow to consume the available space.
Hidden: Hide content by default. (#1626)
Hidden
will now hide content if no hidden conditions are specified, i.e. if no above
, below
, or print
props are provided.
Consumers should review usage of the component without these props to ensure Hidden
behaves as expected.
ButtonIcon: Remove deprecated secondary
tone (#1626)
Remove the deprecated secondary
tone from ButtonIcon
in favour of providing the tone
directly to the Icon
itself.
<ButtonIcon - tone="secondary" - icon={<IconAdd />} + icon={<IconAdd tone="secondary" />} />
useColor: Align background
tokens with Box
and vars
(#1626)
Align the available background
tokens between Box
, vars
, and the useColor
Hook.
Removes the surfaceDark
and bodyDark
tokens that were mistakenly exposed in the useColor
Hook.
useBreakpoint: Remove deprecated Hook (#1626)
This Hook has been deprecated since v30.1.0 in favour of useResponsiveValue
, to prevent consumers from inadvertently coupling themselves to the current set of breakpoints, making it risky for us to introduce new breakpoints.
See the migration guide for more information.
Rating: Remove deprecated showTextRating
prop (#1626)
Remove the deprecated showTextRating
prop in favour of variant="starsOnly"
.
<Rating rating={3.7} - showTextRating={false} + variant="starsOnly" />
Stack: Set default text alignment based on align
(#1626)
As a convenience, the align
prop sets the text alignment for the container, meaning any nested Text
or Heading
components will inherit this alignment by default.
This can be overridden by setting the alignment explicitly on the relevant Text
or Heading
component.
Columns, Inline: Only respect reverse
in combination with collapseBelow
(#1626)
The reverse
prop is only respected in combination with collapseBelow
.
This ensures the content is reversed on the same row, but follows the document order when collapsed.
If content needs to be reversed without collapseBelow
then it should be reversed in the document/source order directly.
Spread: Narrow component
options to valid layout elements (#1626)
Not all HTML elements make sense to be a layout container, e.g. input
, so scoping the component
prop to only surface relevant element types.
Migrate to CSS gap
internally. (#1626)
With the browser support policy now enabling adoption of CSS gap, Braid’s layout components are now able to lean into the platform directly for its declarative, parent-driven approach to white space management.
Previously to enable gap-like behaviour, layout components iterated over their children wrapping them in container elements that applied padding.
The trade off of this technique was increased number of DOM elements and the introduction of unwanted space if the child element was hidden or returned null
, requiring developers to hoist logic to the parent component.
Toggle: Enable bleedY
by default, and deprecate bleedY
prop. (#1626)
Deprecate the bleedY
prop on Toggle
component, and enable bleedY
by default.
Consumers should remove use of the bleedY
prop, and if previously not setting bleedY
to true, should update their layout accordingly.
- <Toggle bleedY /> + <Toggle />
List: Reduce default space between list items (#1626)
Reduce the default space between list items from medium
to small
or xsmall
if the size
prop is set to either small
or xsmall
.
Column: Add component
support (#1626)
With Columns
no longer adding intermediary elements, consumers are free to control the underlying HTML element of the Column
themselves via the component
prop.
Valid options are kept to a white list of elements relevant to Column
that do not require other HTML attributes, keeping in mind that props are not blindly spread in Braid.
EXAMPLE USAGE:
<Columns component="ul"> <Column component="li">...</Column> <Column component="li">...</Column> </Columns>
seekJobs: Reduce size of gutter
token (#1626)
The size of the gutter
token on the seekJobs
theme will be reduced from large
(i.e. 32px), to medium
(i.e. 24px).
This is a semantic token that runs through many system components, and consumers are encouraged to perform a visual design audit to ensure experiences are laid out as intended.
Box, atoms: Add content
to maxWidth
(#1626)
Add the content
option to the maxWidth
property on the styling atoms.
This will ensure an element is only as wide as its content.
EXAMPLE USAGE:
<Box maxWidth="content" />
import { atoms } from 'braid-design-system/css'; atoms({ maxWidth: 'content', });
IconSocialTwitter: Remove deprecated icon. (#1626)
Remove the deprecated IconSocialTwitter
icon.
Consumers should use the IconSocialX
icon instead.
- <IconSocialTwitter /> + <IconSocialX />
PageBlock, Drawer: Increase screen gutter on mobile (#1626)
Increase the horizontal screen gutter from xsmall
(i.e. 12px) to small
(i.e. 16px) on mobile devices.
Hidden: Deprecate screen
prop. (#1626)
Deprecate screen
prop.
To provide content to screen readers without rendering it to the screen, consumers should use HiddenVisually
instead.
- <Hidden screen> + <Hidden>
Stack, Inline, Columns: Widen component
support (#1626)
With Stack
, Columns
and Inline
no longer adding intermediary elements, the component
prop can now accept a wider range of elements.
Valid options are kept to a white list of elements relevant to Stack
that do not require other HTML attributes, keeping in mind that props are not blindly spread in Braid.
Box, atoms: Add responsive gap
support (#1626)
Add the gap
property to the available styling atoms, inclusive of responsive spacing values.
EXAMPLE USAGE:
<Box gap="small" />
import { atoms } from 'braid-design-system/css'; atoms({ gap: 'small' });
Ensure content is left aligned by default (#1626)
Applies left alignment to content, to ensure consistent alignment even when inside centered layout containers.
Apply max width to all inline components (#1626)
Apply a maxWidth
of content
to ensure component widths are controlled by their content — not growing to the size of their container.
BraidTestProvider: Provide scrollIntoView
stub function for jsdom (#1590)
Fixes an issue where scrollIntoView
is not defined in jsdom, causing tests to fail with the following error:
Error: Uncaught [TypeError: highlightedItem?.scrollIntoView is not a function]
Autosuggest: Update suggestion group heading design (#1581)
Updating the design of the suggestion group headings, moving from formAccent
to secondary
tone, from all caps to provided casing, and from xsmall
to small
size.
Text, Heading: Ensure maxLines
truncates correctly when used as the direct child of a flex container. (#1580)
Validate accessible field labels in development (#1591)
Introduce development-time validation for the label
prop on form fields to guard against blank values and guide towards the alternative labelling options that are available.
This validation helps ensure that all fields are accessible to screen readers and other assistive technologies.
Spread: Apply content width to children (#1583)
Align the behaviour of children in Spread
to be the same as Inline
children.
This makes their behaviour more predicatable when spreading full width elements, while also ensuring child elements are not stretched vertically.
Icons: Support rendering inline as child of a flex container (#1585)
Stack, Tiles: Deprecate dividers
prop (#1574)
In preparation for migrating Braid layout components to use CSS gap, the dividers
prop has been deprecated on Stack
and Tiles
.
Consumers are encouraged to migrate now in advance of its removal in v33.
See migration guide for details on how to migrate off the dividers
prop.
Autosuggest: Improve handling of suggestionHighlight
prop when set to remaining
(#1572)
Fixes a bug in Autosuggest
when using suggestionHighlight
prop set to remaining
.
If the input contained multiple words, the highlighted portion would be appended to the end of matching suggestions.
Divider: Ensure full width in flex container (#1574)
Ensures the Divider
component remains full width when used as a flex child inside a flex container.
RadioItem: Improve checked
visual affordance when disabled
(#1564)
Improve the visual affordance of the checked
state when disabled
across all themes and colour modes.
MenuRenderer, OverflowMenu: Limit the menu height (#1567)
Limit the menu to show a maximum of around 10 items before scrolling (a little less so it's evident there is more to scroll to).
TextLink: Default to weak inside secondary tone (#1561)
Align the secondary
tone with other non-neutral text tones, making the foreground color of links inherit the tone of the wrapping Text
component.
EXAMPLE USAGE:
In the following example the TextLink
will now follow the secondary
tone from the wrapping Text
component:
<Text tone="secondary"> <TextLink href="#">Link</TextLink> </Text>
Previously this would have retained the default link colour from the theme.
Standardise disabled
& critical
state across form fields (#1564)
Improves the consistency of form fields when combining both disabled
and critical
tone, which includes:
critical
bordersmessage
and not reserving space for it unless explicitly providing the reserveMessageSpace
prop.Spread: Add component
prop support (#1559)
Enable support for changing the underlying HTML element of the Spread
component.
EXAMPLE USAGE:
<Spread component="span">...</Spread>
Column: Add support for hide above/below breakpoint (#1553)
Introduce new hideAbove
and hideBelow
props on column for responsively hiding columns across breakpoint.
These props can be used either separately or in combination to optimise content display across different screen sizes.
EXAMPLE USAGE:
<Columns space="small"> <Column> <Placeholder height={60} label="Always visible" /> </Column> <Column hideBelow="tablet"> <Placeholder height={60} label="Tablet and above" /> </Column> <Column hideAbove="mobile"> <Placeholder height={60} label="Mobile Only" /> </Column> </Columns>
Badge: Enable usage inside typographic components (#1547)
A Badge
can now be nested inside typographic components, e.g. Text
and Heading
, as an inline element alongside text.
Previously a Badge
had to be aligned against text using an Inline
component, which would result in the Badge
dropping below the text when the copy wrapped.
EXAMPLE USAGE:
<Text> Lorem ipsum velit in <Badge>amet</Badge>. </Text>
Tabs: Add size
support (#1550)
Introduces the ability to customise the size
of the Tab
components in the tab list.
Available sizes are standard
(default) and small
.
EXAMPLE USAGE:
<Tabs size="small"> <Tab>First tab</Tab> <Tab>Second tab</Tab> <Tab>Third tab</Tab> </Tabs>
Spread: Add new layout component (#1554)
Introduce a new layout component, Spread
, used to justify content with both an equally distributed and a specified minimum amount of space in between each child.
EXAMPLE USAGE:
The Spread
component works horizontally by default:
<Spread space="small" alignY="center"> <Heading level="4">Heading</Heading> <OverflowMenu label="Options"> <MenuItem>First</MenuItem> <MenuItem>Second</MenuItem> </OverflowMenu> </Spread>
But can be switched to vertical
via the direction
prop:
<Spread space="large" direction="vertical"> <Stack space="small"> <Heading level="4">Heading</Heading> <Text>Text</Text> </Stack> <Text size="small" tone="secondary"> Date </Text> </Spread>
Move badge
slot inside label (#1547)
Relocate the badge
slot inside the label
slot enabling the Badge
to sit alongside the last word in wrapping lines of text.
Improve internal form field spacing (#1541)
Refined the spacing between internal elements of form fields to align with the latest spacing guidelines.
This change impacts the Stack
spacing between label
and description
, the form field itself and the message
slots.
Autosuggest: Add suggestionHighlight
prop (#1536)
Introduces the suggestionHighlight
prop, which uses the input value to automatically highlight either the matching
or remaining
portion of each suggestion.
EXAMPLE USAGE:
<Autosuggest suggestionHighlight="matching">
Refine the Checkbox, Radio, Toggle & MenuItemCheckbox size (#1541)
Refines the size of the inline field elements including the RadioItem
, Checkbox
, Toggle
and MenuItemCheckbox
components.
Primarily impacts consumers of the seekJobs
theme, seeing a reduction across all sizes.
Ensure no space above field with undefined
label (#1541)
Fixes an issue where passing undefined
as the label
to a form field would result in an unwanted space above the field.
Badge: Ensure label follows correct tone (#1544)
Ensure that the foreground text of a Badge
always follows the correct tone for the background colour.
Fixes a bug where using a Badge
in a List
that overrides the default tone would result in the Badge
text following the List
tone instead of the Badge
tone.
Fix warning in React 18.3.0 when using useToast. (#1534)
MonthPicker: Reduce space between month and year fields (#1541)
Reducing the space between month and year fields to improve correlation between the two fields within the greater context of a form.
Toggle: Add togglePosition
prop (#1509)
Introduces the togglePosition
prop, enabling the toggle to either be leading
or trailing
its label text.
EXAMPLE USAGE:
<Toggle togglePosition="trailing" label="Label" />
Toggle: Add bleedY
prop (#1519)
Introduces the bleedY
prop, enabling vertical bleed for the Toggle
component. This removes excess vertical space created by the Toggle
input.
EXAMPLE USAGE:
<Toggle label="Label" bleedY />
MIGRATION GUIDE:
Vertical bleed will become standard for the Toggle
component in a future version. Please use the bleedY
prop with a value of true
and update your layout accordingly.
Tag: Introduce "addable" support (#1521)
Tag actions have been extended to now support being “added”.
A Tag
will include a small add icon button when both an onAdd
handler and addLabel
prop are provided.
EXAMPLE USAGE:
<Tag onAdd={() => {...}} addLabel="Add Tag" />
seekJobs: Use Tahoma for Thai fallback font (#1527)
Currently in the seekJobs
theme, the fallback font for the Thai character set resolves to the default system font which differs by operating system.
By choosing a deterministic fallback that is available across operating systems, we can use Capsize to improve the alignment with the SEEK Sans web font, and reduce Cumulative Layout Shift for experiences that use Thai.
Additionally, adding sans-serif
as an ultimate fallback in the event that we ever fall all the way through the stack on an obscure operating system.
Tag: Add missing click event parameter to onClear
prop type (#1516)
Toggle: Improve label text vertical alignment at small
size (#1518)
Toggle: Remove tick icon & fix antialias haze when selected (#1525)
Simplying the selected state design by removing the tick icon from the toggle thumb.
Also fixes the antialias haze that appears around the thumb when selected.
Move secondary ButtonIcon tone to icons (#1512)
Following the deprecation of the secondary
tone of ButtonIcon
, this updates all internal usages to apply the secondary
tone directly to the icon.
PageBlock: Add small
and full
width options (#1504)
Add small
to available width
options of PageBlock
to support narrower max width for page content.
Also introducing full
as a width
option to enable full width content, while still maintaining consistent screen gutters.
EXAMPLE USAGE:
<PageBlock width="small">...</PageBlock>
ContentBlock: Add support for left alignment (#1507)
Introduces horizontal alignment support for ContentBlock
, enabling content to be constrained to a max width and aligned to the left.
Useful inside of larger PageBlock
or ContentBlock
elements when constraining the content for readability or length of form fields.
EXAMPLE USAGE:
<ContentBlock align="left">...</ContentBlock>
ButtonIcon: Add formAccent
tone (#1508)
Introduces support for the formAccent
tone on ButtonIcon
.
The new tone sits alongside the existing neutral
tone, while the secondary
tone is now deprecated and will be removed in a future version (see Migration Guide below).
EXAMPLE USAGE:
<ButtonIcon tone="formAccent" icon={<IconAdd />} />
MIGRATION GUIDE:
For consumers of the now deprecated secondary
tone, you can pro-actively migrate away from it by moving the tone
to the icon itself:
<ButtonIcon - tone="secondary" - icon={<IconAdd />} + icon={<IconAdd tone="secondary" />}
dedent
: ^1.5.1
clsx
: ^2.1.1
is-mobile
: ^4.0.0
IconPromote: Update semantic icon from sparkles to a megaphone (#1500)
With the introduction of IconAI
recently adopting the sparkles artwork (aligning with the industry trend), the IconPromote
semantic is now updated to use a megaphone instead of sparkles.
This change will run through all semantic usages, for example Alert
, Notice
, etc.
ButtonIcon: Add small
size (#1496)
Introduce a new small
size for ButtonIcon
component.
This size sits alongside the existing standard
and large
sizes.
EXAMPLE USAGE:
<ButtonIcon size="small" icon={<IconEdit />} label="Small size" />
Add exit animation to Dialog
which mirrors the existing entrance animation. (#1489)
Tag: Add small
size (#1497)
Introduce a new small
size for Tag
component.
This size sits alongside the existing standard
size, which is the default.
EXAMPLE USAGE:
<Tag size="small">Tag</Tag>
Ensure all paths through AutoSuggest
state updates are handled. (#1486)
Fix minor bug which prevented the Drawer
exit animation from occurring. (#1489)
Update Capsize dependencies (#1484)
Adopt small
sized ButtonIcon
for field actions (#1496)
Switch over to small
(previously standard
) sized ButtonIcon
for field actions such as clear field, or toggle password visibility.
Update Crackle CLI dependency (#1480)
Improve virtual touch target positioning for narrow elements (#1493)
To maintain accessibility for smaller interactive elements, Braid uses a virtual touch target to maintain the minimum hit area. This change ensures that the virtual element is always centered to the visual target, in particular when the width of the visual target is narrower than the minimum hit area.
Update semantic icon assets. (#1481)
IconCritical
: Move from circle to diamond outline. Increase the visual distinction from IconInfo
.
IconLanguage
: Move from globe to characters. Better represents the concept of language. Previous asset available as IconGlobe
.
MIGRATION GUIDE
As the above are updates to semantics icons, consumers are unaffected if their usage follows the icon's semantic intent. For those choosing the icon based on its visual appearance, please review the usage and consider decoupling from the semantic system icon for safer upgrades.
Add new icons to the library (#1481)
Update Capsize dependencies (#1456)
Text, Heading: Fix maxLines
cropping of decending characters (#1451)
Fixes a bug when using -webkit-box, where the descender on the last line of text could be cropped based on the combination of line height and font size.
Tab: Remove cropping of the icon slot (#1447)
Previously the icon
slot on a Tab
was cropped on the left to improve alignment with the active tab indicator.
For most icons in a Tab
, this was subtle polish, but for others it had the undesirable side effect of clipping the side of the icon.
Removing the cropping until we have a better solution for trimming whitespace around icons.
Badge: Allow Badge
to take arrays of values (#1443)
Previously, Badge
only accepted a string
as children, to prevent the use of other components inside a Badge
.
However, when a variable is included with text inside the Badge
, the children property is interpreted as an array. This prevents a very reasonable use case from being allowed:
<Badge>{jobs.length} Jobs</Badge> // Error: Type '{ children: string[]; }' is not assignable to type 'BadgeProps'.
This change allows Badge
to accept a string, number, or array thereof.
Fix circular dependencies (#1444)
IconSocialX: Add new icon (#1438)
Add the new IconSocialX
component to the suite of social icons, enabling teams to migrate across from IconSocialTwitter
which has now been marked as deprecated.
EXAMPLE USAGE:
<IconSocialX />
MIGRATION GUIDE:
Teams should migrate from IconSocialTwitter
to IconSocialX
at their earliest convenience. The IconSocialTwitter
component will be removed in a future release.
-<IconSocialTwitter /> +<IconSocialX />
react-focus-lock
to avoid build warnings in Rollup and Vite (#1433)Rating: Add weight
support (#1430)
Provide a weight
prop to customise the weight of the text rating alongside the stars.
EXAMPLE USAGE:
<Rating rating={3} weight="strong" />
Autosuggest: Fix aria-label and aria-labelledby features (#1420)
Fixes an issue where the aria-label
and aria-labelledby
props provided by a consumer were being overidden internally by the Autosuggest
component.
TooltipRenderer: Fix useLayoutEffect
warnings during SSR (#1407)
Tabs: Improve positioning of the active underline (#1407)
Fixes a bug where the reset module mistakenly included all the tokens for all the themes. (#1405)
Additionally, this includes significant compilation improvements to ensure that only styles for the components being used are included — speeding up build times and reducing the overall CSS bundle size.
Add optional tooltipPlacement
prop to ButtonIcon
(#1390)
The tooltipPlacement
prop allows you to specify the placement of the tooltip to either top
or bottom
.
The default value is top
.
EXAMPLE USAGE:
<ButtonIcon tooltipPlacement="bottom" />
seekJobs: Update formAccent
colour (#1387)
The formAccent
tone, used through our form fields and buttons, is being updated to a derivative of the SEEK brand blue.
As this update only relates to the seekJobs
theme, consumers of other themes will not be affected.
The Braid Provider contains some code to check that it's running in a browser context (otherwise a BraidTestProvider should be used). (#1382)
Part of this check was looking to see if there was a navigator
object, which was not available in Node.
If there were, it would check the userAgent
to determine if it was inside jsdom.
Node 21 has a navigator
object, but it doesn't have a userAgent
property, so this check was failing (cannot read property 'indexOf' of undefined).
The "are we in JSDom" check in the BraidProvider has now been reworked slightly to account for the potentially existing but empty navigator
object.
TextLink, TextLinkButton: Ensure consistent underline thickness on weak links (#1380)
A subtle bug affecting weak links was resulting in a change in underline thickness on hover. This bug has been fixed such that weak links now always have the same underline thickness regardless of hover state.
TooltipRenderer: Re-evaluate position when trigger
or children
changes (#1374)
Fixes an issue where the tooltip would not re-evaluate its position when the trigger
or children
prop changed while the tooltip was already open.
When animating an SVG circle, it seems that the width changes slightly, which on Loader was causing the right-most one to push off the boundaries of the SVG View Box. (#1370)
This has been fixed so clipping should no longer occur.
Button, ButtonLink: Default to neutral ghost in non-legacy themes (#1363)
By default, a button now has a neutral
tone and uses the ghost
variant, allowing the visual prominence to be increased or decreased as required, enabling colour to be applied as accents and with purpose, rather than by default.
<Button /> // => tone="neutral" & variant="ghost"
To compliment this, when a tone
is purposefully applied, the default variant becomes solid
to maximise its impact — allowing the visual prominence to be reduced as needed.
<Button tone="brandAccent" /> // => tone="brandAccent" & variant="solid"
apac
and seekBusiness
consumersGiven the fundamental change in approach to colour and usage of such a core component, this change has been isolated to newer themes and does not impact apac
and seekBusiness
consumers.
These themes will continue to have a tone of formAccent
and a solid
variant by default, allowing consumers to adopt this new approach as part of the design uplift when migrating to an updated theme, e.g. seekJobs
.
Button, ButtonLink: Provide formAccent
as the name for undefined tone (#1359)
Formalise the name of the undefined
tone as formAccent
, making it more discoverable as an accent available for increased prominence.
Note: Consumers should only apply this tone where an action should be emphasized explicitly. The undefined
value is still valid for buttons that should follow the default button style of the theme.
EXAMPLE USAGE:
<Button tone="formAccent">...</Button>
seekJobs: Change link colour to neutral (#1347)
Changing the foregroundColor
token for link
on the seekJobs
theme to align with neutral text.
Our different approach to using colour has seen links dialled back to compete less with other messaging and CTAs.
This affects the following usages across the system:
vars.foregroundColor.link
Text
(using tone="link"
)TextLink
and (TextLinkButton
)TextLink, TextLinkButton: Underline regular links in non-legacy themes (#1347)
To improve affordance beyond primarily being colour, a TextLink
(and TextLinkButton
) will now always be underlined, in line with best practice accessibility guidelines.
Given this has not been the case previously, this decision has been applied to non-legacy themes only, as such only affecting consumers of seekJobs
, docs
and wireframe
.
TextLink, TextLinkButton: Apply themed focus outline (#1347)
Apply a focus outline using the relevant focus attributes from the theme, bringing TextLink
(and TextLinkButton
) into line with the focus treatment applied to rest of the system.
TextLink, TextLinkButton: Reduce weak
links to regular
font weight (#1347)
The font weight of a weak
link is now reduced to regular
weight, reducing the link's visual prominence in addition to following the neutral text colour.
docs: Lighten soft background tokens (#1347)
Lighten the brandAccentSoft
and formAccentSoft
background tokens for the docs
theme.
Dialog, Drawer: Adapt max height to available viewport space (#1352)
Make use of the new dynamic viewport units for applying a max height to modal elements such as Dialog
and Drawer
. These new units take into account dynamic browser toolbars that expand and contract as the user scrolls, ensuring the browser interface never obscures the web site content.
Fix also incorporates fallback for older browsers to use regular viewport units.
Drawer: Prevent close button protruding in left position (#1351)
Fixes an issue where the close button could protrude from a Drawer
.
This was only visible when setting position
to left
and between a small range of screen widths — above 660px (small
content width) and below 768px (tablet
breakpoint).
RadioGroup: Ensure reserveMessageSpace
prevents layout shift correctly (#1349)
Consider the reserveMessageSpace
prop as well as message
when conditionally applying internal padding between radio list and field message.
Page: Add component (#1343)
The new Page
component establishes a consistent page-level layout by managing the relationship between the footer and the main content.
By default, for pages with limited content the footer
will at a minimum be placed at the bottom of the screen, pushed beyond as the page content grows.
For pages with dynamic content, it is recommended to place the footer out of view by setting the footerPosition
prop to belowFold
to prevent the footer from popping in and out of view when the page content changes, e.g. toggling between a loading indicator and content.
EXAMPLE USAGE:
<Page footer={<Footer />}> <Header /> {/* page content... */} </Page>
TabPanel: Align focus outline radius to scale (#1345)
Increase the radius of the focus outline to better align to the scale. A TabPanel
is typically a "large" element containing entire sections of UI, so using the large
radius to better align to the radius scale.
apac, seekBusiness: Increase medium
font weight (#1331)
The unicode range of Thai characters is not satisfied by the preferred fonts specified for the apac
theme, resulting in these characters falling through and being rendered by sans-serif
— which applies a platform-specific font.
These system fonts do not have support for the semi-bold weight chosen for medium
, resulting in the visual weight of medium
text being rounded down to regular
— providing no differentiation relative to other text in the UI.
In addition, due to both Helvetica
and Arial
not having a medium
weight, these fallbacks also have the same problem, even for Latin characters.
By increasing the value of medium
, it will now round to strong
when the rendered font cannot satisfy medium
— preventing the loss of hierarchy.
This only affects apac-based themes, namely apac
and seekBusiness
.
Drawer, Dialog: Increase gutter around close button (#1328)
Fix for a regression where the gutter around the close button was reduced — resulting in visually clashing with the content when scrolling.
seekJobs: Update visited link colour tokens (#1323)
Darken the visited link colour tokens within the seekjobs
theme.
IconEnlarge: Add new component (#1320)
EXAMPLE USAGE:
<IconEnlarge />
The active
prop can be used to toggle the icon into the "reduce" state:
<IconEnlarge active={true} />
Drawer, Dialog: Support validation blocking closure of modal (#1318)
To prevent a Dialog
or Drawer
from closing, e.g. due to validation, the onClose
function can now return false.
EXAMPLE USAGE:
<Drawer open={open} onClose={() => { const valid = runValidation(); if (!valid) { return false; } setOpen(false); }} />
TooltipRenderer: Fix arrow overlapping tooltip corner radius (#1316)
Fix for an edge case where the arrow on a small tooltip could the overlap the corner radius of the tooltip.
Drawer: Darken backdrop in dark mode (#1316)
Increase the weight of the backdrop in dark mode to ensure the content is suffiently obscured.
Drawer: Fix entrance animation from left
position (#1316)
Apply the entrance animation correctly for a Drawer
using the left
position.
Also reduced the horizontal overshoot for the transition for a smoother feel.
Drawer: Increase space between title
and description
on tablet (#1316)
Drawer: Align horizontal gutters with PageBlock (#1316)
Given a Drawer
is full width on a mobile device, applying the same horizontal gutter rules as PageBlock
makes sense.
This ensures content on a mobile will have the same available space whether its in the page, or inside a Drawer
.
PageBlock: Add new component (#1307)
Provides a top-level page container, constraining the content width (using ContentBlock
) while establishing common screen gutters on smaller devices.
EXAMPLE USAGE:
<PageBlock width="large">...</PageBlock>
Button, TextLinkButton: Add aria-label
support (#1304)
Provide support for aria-label
, enabling additional context to be given to assistive technologies where context is typically visual.
EXAMPLE USAGE:
<Button aria-label="Save job">Save</Button>
Hide field borders in dark containers (#1294)
Reduce visual noise when a form field is displayed in a dark container by hiding the default border. As fields are light on light backgrounds, the border is used to delineate its bounds against the container, which is not relevant in a dark container.
Add seekJobs
theme (#1281)
The seekJobs
theme encapsulates the system changes necessary to apply and deliver the updated visual design language for SEEK Jobs.
Through the development of this theme, we have been able improve the fidelity of the various scales in our tokens, while also ensuring that the tokens themselves are consumed and applied more consistently throughout the system itself.
EXAMPLE USAGE:
import seekJobs from 'braid-design-system/themes/seekJobs'; <BraidProvider theme={seekJobs}>...</BraidProvider>;
MIGRATION
Consumers of the apac
theme are not recommended to migrate independently. The seekJobs
theme represents an uplifted visual identity that is part of a wider visual uplift.
Instead, we’ll be guiding the initial teams through a staged migration in coordination with the centralised team process.
There are some differences in how certain concepts are applied, whether it's the space scale, or Card
usage, etc., and we will be documenting these in due course.
If you would like to talk about migrating, please reach out to us in our #braid-support channel on slack.
Text, Heading: Only show truncate deprecation message when true (#1289)
Only show the truncate deprecation message when truncate
is provided and set to true
TextLink, TextLinkButton: Improve underline position for wrapping text (#1290)
Refine the underline position to be consistent across the whole typographic hierarchy, ensuring it does not interfere with wrapping lines of text.
Text, Heading: Add maxLines
support (#1286)
Provide support for limiting the number of lines shown by a Text
or Heading
component.
EXAMPLE USAGE:
<Text maxLines={3}>...</Text>
MIGRATION:
With the addition of this feature, the truncate
prop is now deprecated and will be removed in a future release.
Existing consumers should start migrating as below:
<Text - truncate + maxLines={1} />
Card: Add full height support (#1285)
Provide support for making a Card
use all available vertical space.
This is useful when laying out rows of Card
elements and having them all be equal height.
EXAMPLE USAGE:
<Card height="full">...</Card>
TextLink, TextLinkButton: Update underline design (#1288)
Uplift the design of the the text underline used on TextLink
and TextLinkButton
components.
Column: Support full height content (#1285)
Provide support for full height content by growing all Column
elements to be uniform in height.
This will have no effect on the content itself, but enables consumers to create designs of uniform content, such as rows of Card
elements.
RadioItem, Checkbox: Fix stacking context behaviour (#1284)
A RadioItem
and Checkbox
previously created a new stacking context with an elevated z-index
applied on hover, resulting in their labels overlaying other elements in an unpredictable ways — most noticable when toggling nested content.
For example, toggling nested content containing an Autosuggest
, would see the list of suggestions list would be overlayed by the next RadioItem
on hover.
To fix this, the z-index
is no longer elevated on hover, and additionally the nested content container applies an elevated index when the field is checked.
Textarea: Adjust highlightRange
background to support different line heights (#1279)
Remove the vertical padding on the highlight element to prevent the background colour overlapping the wavy underline in themes with tighter line heights.
MenuItemCheckbox: Align checkbox size with a small
Checkbox (#1276)
Align the size of a MenuItemCheckbox
with a small
sized Checkbox
.
Checkbox, RadioItem: Fix alignment with updated Badge layout (#1280)
Improve layout to work with updated Badge layout which is no longer driven by line height.
MonthPicker: Reduce space between fields (#1277)
Reduce the space between the month and year fields.
Box, atoms: Add borderBrandAccent
variants to available boxShadows (#1274)
Add borderBrandAccent
and borderBrandAccentLight
to the available boxShadows, combining the brandAccent
and brandAccentLight
border colours with the standard
border width token.
Previously, brandAccent
was only available with the large
border width.
EXAMPLE USAGE:
<Box boxShadow="borderBrandAccent" />; { /* or */ } <Box boxShadow="borderBrandAccentLight" />;
import { atoms } from 'braid-design-system/css'; atoms({ boxShadow: 'borderBrandAccent' }); atoms({ boxShadow: 'borderBrandAccentLight' });
useToast: Design uplift with increased page contrast (#1269)
As a means to increase constrast against page content, the design has been updated to be presented on inverted backgrounds based on the color mode.
The design has also be refined to remove the sidebar/keyline (consistent with Alert
), while also applying the tone
to the provided message
.
Textarea: Add support for disabling built-in spell checker (#1272)
Provide support for disabling the built-in browser spell checker using the native HTML attribute spellCheck
.
When highlighting ranges you may choose to turn spell check off to prevent colliding highlights. This can be done be setting spellCheck
to false
.
EXAMPLE USAGE:
<Textarea spellCheck={false} />
Add support for caution
tone to form fields (#1271)
Provide support for applying a caution
tone to form fields.
Specifying this tone
will show the IconCaution
alongside the provided message
.
EXAMPLE USAGE:
<TextField tone="caution" message="Caution message" />
Textarea: Add support for caution
highlightRanges (#1272)
Providing a tone
of caution
along with a set of highlightRanges
will now apply the caution
tone to the text being highlighted.
To complement this feature, the design has been uplifted to work consistently across both the critical
and caution
tones.
EXAMPLE USAGE:
<Textarea tone="caution" message="Caution message" highlightRanges={...} />
Alert: Design uplift (#1269)
Refine the design to use consistent horizontal container inset, aligning content with elements like Card
, as well as simplifying the design by removing the sidebar/keyline (consistent with useToast
).
Button, ButtonLink: Align ghost
border width with field border width (#1274)
Align the border width of ghost
variants with the border width of fields.
This is the final re-alignment piece to ensure all components use theme scales consistently, improving the ability of Braid themes to deliver cohesive design uplift.
Stepper: Reduce size of Step
indicators (#1275)
Refine the design of Step
indicators by reducing their size.
TooltipRenderer: Remove custom background (#1268)
Use the correct semantic token for the background of tooltips. While there is no visual change, this is just a clean up to ensure the palette usage remains consistent.
Box, atoms, vars: Add small
to border radius scale (#1253)
Extends the border radius scale to include small
as a step below standard
.
This addition is to support an upcoming design uplift that requires greater fidelity in the scale.
Note, the new value is also available as a responsive property.
EXAMPLE USAGE:
<Box borderRadius="small" />; { /* Or responsively: */ } <Box borderRadius={{ mobile: 'small', tablet: 'standard' }} />;
import { atoms } from 'braid-design-system/css'; atoms({ borderRadius: 'small' });
import { vars } from 'braid-design-system/css'; const radius = vars.borderRadius.small;
theme: Add support for defining line heights with lineGap (#1267)
Provide support for themes to define their typographic line heights via lineGap
.
This allows us to reason about the white space between wrapping lines of text in the same way we think about Stack
spacing.
For a visual preview of this mental model head over to the Capsize website.
Add xxxlarge
to the space scale (#1262)
Extends the range of the space scale to include xxxlarge
.
This addition is to support an upcoming design uplift that requires greater fidelity in the scale.
Note, the new value is also available as a responsive property.
EXAMPLE USAGE:
<Stack space="xxxlarge">...</Stack>; { /* Or responsively: */ } <Stack space={{ mobile: 'large', tablet: 'xxxlarge' }}>...</Stack>;
import { atoms } from 'braid-design-system/css'; atoms({ paddingY: 'xxxlarge' });
import { vars } from 'braid-design-system/css'; const space = vars.space.xxxlarge;
theme: Add support for webfonts beyond Google Fonts (#1255)
Previously the webFont
on the theme was the familyName
and was being used to construct a link tag to a Google Fonts stylesheet and provide to consumers via a runtime token.
To enable fonts beyond Google Fonts, we are changing webFont
to be a URL.
This does not impact existing themes (as there are no themes currently with a web font), and the contract of the runtime token (a constructed link tag) remains unchanged.
MenuRenderer: Hide overflow on menu (#1264)
Fixes a bug where the selection/highlight for a MenuItem
could extend outside of the menu itself.
Badge: Adjust height to support different typographic scales (#1257)
Adjusts the height of Badge
to be driven by the capHeight of xsmall
text plus vertical padding, rather than xsmall
line height.
This enables different typographic scales across themes, while ensuring the Badge
height is relative.
RadioItem, Toggle: Use formAccent border when selected (#1251)
Switch to using the formAccent
border colour, rather than the field
border color, when in the selected state (e.g. checked
for RadioItem
, on
for Toggle
).
Fix error reading standard
of undefined (#1256)
The use of dynamic property access left some styles exposed to being marked as unused and tree shaken away.
Refactoring these styles to be explicitly referenced to ensure this will not be the case.
TooltipRenderer: Refine padding to complement radius scale (#1263)
Removes the custom padding on tooltips in favour of using the space scale. Previously, a custom value was used to complement the over sized radius which has now be reduced.
Button, ButtonLink: Improve support for different typographic scales (#1259)
Ensure the height of a small
sized Button
is not reliant on the text line height.
This enables different typographic scales across themes, while ensuring the Button
height is relative.
Alert, Card, useToast: Decouple keyline width from space scale (#1266)
Previously the keyline width on the left determined its width using the space scale. Re-aligning this to use the grid unit to enable themes with larger space scales.
Improve consistency of border radius usage across components (#1253)
Over time, individual components have reached for a larger radius in the scale, rather than increasing the scale at a theme level. This resulted in inconsistent use across the system, preventing uplift of the scale.
Re-aligning all components to use the scale consistently enables themes to apply very different radius scales — enabling an upcoming design uplift theme.
Dialog, Drawer: Reduce space between title and description (#1265)
Reducing the space between title
and description
to small
to improve association of the header block content
Prevent wrong entry point paths from appearing as suggestions in VS Code. (#1247)
For example, wanting to use Braid's CSS variables (vars
) VS Code would suggest braid-design-system/dist/css
instead of braid-design-system/css
.
Disclosure: Add weight
support (#1240)
Provides support for reducing the visual weight of the Disclosure's call to action. Follows the same contextual styling rules as TextLink
.
EXAMPLE USAGE:
<Disclosure weight="weak">...</Disclosure>
Disclosure: Add inline content support (#1240)
Provides support for using a Disclosure within a sentence by allowing it to be nested within a typographic component, i.e. Text
.
All size and weight properties will inherit from the parent component.
EXAMPLE USAGE:
<Text> Preceding text content that is followed by a Disclosure. <Disclosure expandLabel="Read more">...</Disclosure> </Text>
Button, ButtonLink, TextLink, TextLinkButton: Add support for trailing icons (#1242)
Provide support for choosing the position of the icon
slot within a Button
or TextLink
.
By default, the iconPosition
will be leading
the label, but optionally, can be set to trailing
.
EXAMPLE USAGE:
<Button icon={<IconArrow direction="right" />} iconPosition="trailing"> Next </Button>
Show description
on form fields when no label
provided (#1239)
Previously, a FieldLabel
without a label
would return nothing. However, now that form fields can opt for indirect or hidden labels (via aria-label
or aria-labelledby
), the description
should still be shown if provided.
Note: The secondaryLabel
and tertiaryLabel
remain conditional based on the presence of a label
. This is due to their location in the layout being anchored off the label
.
EXAMPLE USAGE:
<FieldLabel description="Description now visible without label" />
TextLink, TextLinkButton: Increase text weight of weak links (#1237)
Increases the text weight of weak
links to medium
, increasing the affordance against standard text.
As a result, this makes the weight of all text links consistent.
Disclosure: Ensure chevron does not wrap alone (#1240)
Fixes the scenario where based on copy length and container size, the chevron could wrap independently of the rest of the label. By using a zero-width, non-breaking space, the chevron will now wrap together with the last word of the label.
The is a huge enablement release that sees the removal of legacy themes and treat our previous styling solution, as well as a migration to our new build tool Crackle.
By moving to Crackle, Braid will now be published as a pre-compiled artefact, no longer requiring TypeScript to be transpiled by consumers. This should see faster build times and clearer boundaries between Braid and consuming applications.
Outside of the removal of treat
and the legacy themes, there is no impact on the public API of Braid. However, if a consuming web app is reaching into Braid internals, this will no longer work and require code changes.
For these cases, to support teams in upgrading we have provided a Compiled Braid Migration Guide based on patterns observed in code bases.
For more detail on the specific changes in this release, please read on.
Drop support for React 16. (#1229)
To support the pre-compilation of Braid, it is now a requirement that consumers are on React 17 or later. Originally the plan was to drop React 17 as well, however the team has been able to maintain support for a little longer — but there is a catch (see migration guide below).
MIGRATION GUIDE:
As this version is no longer supported it is a requirement that consumers upgrade. For more information on the differences between v16 and v17, see the React blog. We strongly encourage teams to take this opportunity to upgrade to v18 as well.
The way React 17 exposes the jsx-runtime
is not compatible with ESM, which means the bundler will need instructions on how to resolve the import.
This can be done by adding a fallback module resolve rule to the webpack configuration.
For sku consumers, this can be done as follows:
// sku.config.ts { dangerouslySetWebpackConfig: (config) => webpackMerge(config, { resolve: { fallback: { 'react/jsx-runtime': require.resolve('react/jsx-runtime'), }, }, }), }
We recommend using webpack-merge to ensure both configurations are deep merged correctly.
Note: This rule can be removed after upgrading to React 18, which has ESM support.
No action required.
Playroom imports are now formalised entrypoints rather than path imports, and as such no longer require the file path extensions to be provided. (#1229)
EXAMPLE USAGE:
// playroom.config.js module.exports = { frameComponent: require.resolve( 'braid-design-system/playroom/FrameComponent', ), components: require.resolve('braid-design-system/playroom/components'), snippets: require.resolve('braid-design-system/playroom/snippets'), scope: require.resolve('braid-design-system/playroom/scope'), };
Remove legacy themes: catho
, occ
and seekAnz
(#1229)
The seekAnz
theme facilitated consumers migrating like-for-like from seek-style-guide
, while the catho
and occ
themes intended to enable a specific use case that never eventuated.
Removing these themes allows us to move faster with upcoming theme uplift work.
MIGRATION GUIDE:
Any remaining consumers of the catho
, occ
or seekAnz
themes should migrate to the apac
theme like so:
-import seekAnz from 'braid-design-system/themes/seekAnz'; +import apac from 'braid-design-system/themes/apac';
Remove treat support (#1229)
Treat has been deprecated for nearly 2 years, superseded by vanilla-extract.
.treat.ts
files can no longer be used for styling and should be converted to .css.ts
(vanilla-extract) stylesheets.
Remove experimental color-mode check script (#1229)
The experimental script for checking which color mode to render has been formalised to an entrypoint specific to the mechanism that is being used — in this case the query parameter. In the future we may add other mechanisms, such as local storage for example, but for now all existing consumers should have been migrated to the query-param check.
MIGRATION GUIDE:
- import { __experimentalDarkMode__ } from 'braid-design-system/color-mode' + import { colorModeQueryParamCheck } from 'braid-design-system/color-mode/query-param'
Use theme tokens for shape of font metrics (#1214)
Internally some theme utilities were using Capsize’s FontMetrics
as their expected payload, rather than correctly using the shape of the theme tokens.
This makes Braid compatible with Capsize v3.x.
Whitelist only the required FontMetrics for theme tokens (#1212)
The latest version of FontMetrics
type in Capsize adds more properties, and we only populate the properties we require on the theme. Whitelisting the required properties to keep the themes explicit.
Accordion, AccordionItem: Add weight
support (#1211)
Add support for customising the weight
of AccordionItem
s.
This can be either at an Accordion
level or on a standalone AccordionItem
based on design requirements.
Note, in order to maintain visual consistency, the weight
prop can only be specified on an AccordionItem
when outside of an Accordion
.
EXAMPLE USAGE:
<Accordion weight="strong"> <AccordionItem /> ... </Accordion>
or
<AccordionItem weight="strong" />
CheckboxStandalone: Enable alignment with Text (#1209)
Enables CheckboxStandalone
to be wrapped in a Text
component, ensuring it only occupies the same layout as text.
This is useful for visually aligning checkboxes in a custom layout alongside other text-based components, e.g. AccordionItem
.
EXAMPLE USAGE:
<Columns> <Column> <Text> <CheckboxStandalone /> </Text> </Column> <Column> <AccordionItem /> </Column> </Columns>
color-mode: Add query-param entry (#1205)
Add new query-param
entry, providing a script for resolving the color mode preference from query string, as well as a utility function for retrieving the preference for constructing subsequent links.
Tab, Tabs: Updated visual design (#1180)
The appearance of a Tab
has been updated. Changes include:
regular
text weightneutral
tone instead of underlineminimal
divider under Tabs
underlines content only, without the horizontal gutterThe braid-upgrade
command now tries to preserve newlines as best as possible (#1194)
Expose Playroom config (#1190)
This allows consuming packages (e.g. Metropolis) to enhance the Playroom experience by leveraging Braid's internal Playroom configuration.
EXAMPLE USAGE:
// playroom.config.js module.exports = { frameComponent: require.resolve( 'braid-design-system/playroom/FrameComponent.tsx', ), components: require.resolve('braid-design-system/playroom/components.ts'), snippets: require.resolve('braid-design-system/playroom/snippets.ts'), scope: require.resolve('braid-design-system/playroom/scope.ts'), };
TextLink, TextLinkButton: Add icon
support (#1184)
Provides a designed slot for adding an icon
to a TextLink
or TextLinkButton
.
This solves for the problem of underlining the space between the icon and text.
EXAMPLE USAGE:
<Text> <TextLink icon={<IconLink />}>...</TextLink> </Text>
IconRenderer: Support the sizing and alignment of custom icons (#1185)
Provides support for sizing and aligning custom icons with Braid’s typographic components. The new IconRenderer
component supports being used within Text
and Heading
components as well as inside icon
slots of other components.
Uses the render prop pattern to provide the required classes to style and align a custom icon.
EXAMPLE USAGE:
<Heading level="1"> <IconRenderer> {({ className }) => <svg className={className}>...</svg>} </IconRenderer> </Heading>
Link: Support custom data
prop format for attributes (#1182)
While Link
already supports the native HTML syntax for data attributes, e.g. data-testid="123"
, it now supports the data
prop too. This allows data attributes to be provided consistently to all components.
EXAMPLE USAGE:
<Link + data={{ testId: 'myComponent' }} />
The above example results in the following HTML attribute being set on the element: data-testId="myComponent"
.
Support data attribute boolean values (#1182)
The data
attribute map now supports boolean values. This provides an improvement for the developer experience, no longer having to convert values to strings explicitly.
EXAMPLE USAGE:
<Component data={{ 'custom-attribute': true, }} /> // => <div data-custom-attribute="true" />
TextLink: Allow native data attributes with anchor api (#1182)
Disables the validation against the use of data attributes on TextLink
. Given it exposes the full native anchor tag api, it is not invalid
to use the native syntax.
TextField: Add inputMode
and step
support (#1174)
Provide support for the native inputMode
and step
attributes.
The inputMode
will also be defaulted based on the specified type
. For example: <TextField type="number" />
will default the inputMode
to numeric
.
EXAMPLE USAGE:
<TextField inputMode="numeric" step=".01" />
Rating: Only fill star for scores .75 and above (#1176)
A star is only filled
when the score is .75 and above. Fixes an issue where all scores .5 or above are shown as half filled stars.
EXAMPLE USAGE: Now when a rating reaches .75 it will round up to a full star.
<Rating rating={3.75} /> // 4 filled
ButtonLink: Allow native data attributes with anchor api (#1178)
Disables the validation against the use of data attributes on ButtonLink
. Given it exposes the full native anchor tag api, it is not invalid to use the native syntax.
Box, atoms: Remove native buttons on number input field (#1174)
Extends the CSS reset behaviour of HTML input fields where type="number"
to remove the native increment and decrement buttons.
EXAMPLE USAGE:
The following will now render a HTML input of type number
without native buttons:
<Box component="input" type="number" />
Additionally, if using the atoms
function to build styles, when resetting an input
field, the native buttons will also be removed.
const customClasses = atoms({ reset: 'input', ... });
Button, ButtonLink: Improve alignment of transparent buttons with icons against Text with icons (#1170)
To improve optical balance of a Button
with an icon
, the icon container is bled to the left to balance against the larger horizontal inset of a standard
button.
This alignment correction is now only applied on standard
sized buttons that are not using the transparent
variant.
Isolating this alignment correction enables transparent buttons to better align with other components with icon
slots, for example:
<Stack space="small"> <Text icon={<IconSend />}>Text</Text> <Button icon={<IconSend />} variant="transparent" bleed> Button </Button> </Stack>
Icons and text will now be perfectly aligned between Button components and others icon slots with the same text size.
Box: Support custom data
prop format for attributes (#1168)
While Box
already supports the native HTML syntax for data attributes, e.g. data-testid="123"
, it now supports the data prop too. This allows data attributes to be provided consistently to all components.
EXAMPLE USAGE:
<Box + data={{ testId: 'myComponent' }} />
The above example results in the following HTML attribute being set on the element:
data-testId="myComponent"
.
Text, Heading: Add icon slots (#1160)
Provides a designed slot for adding an icon to Text
and Heading
components
EXAMPLE USAGE:
<Text icon={<IconPromote />}>{...}</Text>
or with a Heading
:
<Heading level="3" icon={<IconPromote />}>{...}</Heading>
useToast: Add data
attribute support (#1168)
Support applying custom data attributes to Toast elements.
EXAMPLE USAGE:
export const Component = () => { const showToast = useToast(); return ( <Button onClick={() => showToast({ + data: { testId: 'myToastMessage' }, ... }) }> Show </Button> ); }
The above example results in the following HTML attribute being set on the toast element:
data-testId="myToastMessage"
.
Provide dev time validation/warnings when the native data attribute format is provided to components that do not support it. (#1168) This is required as TypeScript does not validate kebab cased properties, and Braid components do not spread abritrary props.
This validation will prevent silent failures where attributes are seemingly provided, but not applied.
For example:
<Card data-testid={123} /> // => Would not be applied and TypeScript would not error.
However, now the following console warning will guide users to use the data
prop:
Braid components do not support the native data attribute format. Use the “data” prop instead. <Component - data-testid={123} + data={{ + testid: 123, + }} /> For more details, see the “Data Attributes” documentation: https://seek-oss.github.io/braid-design-system/components/Box#data-attributes
Pagination: Increase chevron spacing on prev/next links (#1160)
Increases the space between the "Previous" and "Next" text and their chevron icons to balance with the larger icon size.
MenuItemCheckbox: Align with increased icon size (#1160)
Ensure menu item text has uniform spacing to the checkbox of MenuItemCheckbox
and the icon
slot of MenuItem
.
Text, Heading: Increase icon size inside typographic elements (#1160)
The size of icons has been increased by 20% when used inside of Text
and Heading
components. There is no layout impact expected for consumers, with only the visual ratio of icon to text size changing.
This applies to icons using the new icon
slots, as well as inline icons within the text content.
Icons used outside of typographic elements are not affected by this change.
ButtonIcon: Increase standard icon size (#1160)
Adopt the increased standard icon size.
Note this does not affect overall dimensions of ButtonIcon
, or the layout of surrounding components.
Removes custom icon sizing and layout in favour of new typography icon sizes and layout. (#1162)
Update @vanilla-extract/css
dependency (#1158)
This fixes a type error that was occurring with typescript versions >=4.5.0
Heading: Nested icons inherit text colour (#1153)
When using icons inside of a Heading
, the default tone
was always neutral
, rather than inheriting the colour of the nearest component.
For example, when an icon was used inside of a TextLink
within a Heading
:
<Heading level="1"> Title with{' '} <TextLink> link <IconArrow /> </TextLink> </Heading> // => Previously, IconArrow was the heading text colour // `neutral`, now inherits the `link` colour.
or equally, when an icon was used inside of a Secondary
component within a Heading
:
<Heading level="1"> Title with{' '} <Secondary> secondary <IconArrow /> </Secondary> </Heading> // => Previously, IconArrow was the heading text colour // `neutral`, now inherits the `secondary` colour.
Autosuggest: Add configurable message for no suggestions (#1140)
Provides consumers a way to give the user more context when no suggestions are available. The noSuggestionsMessage
prop accepts a simple message by providing a single piece of text. Alternatively, a more structured prompt can be shown by providing an object containing title and description.
This message is only displayed when there are no available suggestions provided.
EXAMPLE USAGE: For the simple case:
<Autosuggest ... suggestions={[]} noSuggestionsMessage="No results found" />
Or, for more a structured prompt:
<Autosuggest ... suggestions={[]} noSuggestionsMessage={{ title: "No results found", description: "Try searching for something else", }} />
MIGRATION GUIDE:
In addition, the old mechanism allowing consumers to pass an object to suggestions
containing a message
has been deprecated. This will continue to work for now but will be removed in a future release.
It is recommended to migrate to the noSuggestionsMessage
prop.
<Autosuggest ... - suggestions={{ message: 'No results found' }} + noSuggestionsMessage="No results found" />
useToast: Add neutral tone support (#1141)
Add support for neutral
tone. When using a neutral
tone, an icon may optionally be provided. For consistency, the tone of the icon is set to secondary and cannot be customised.
EXAMPLE USAGE:
import { useToast } from 'braid-design-system'; export const DemoButton = () => { const showToast = useToast(); return ( <Button onClick={() => showToast({ tone: 'neutral', icon: <IconBookmark />, message: 'Neutral with icon', }) } > Show Toast </Button> ); };
react-dom
as a peer dependency (#1136)vars: Expose shadow palette (#1133)
Provide access to the themed shadow
scale on the vars
object
EXAMPLE USAGE:
import { vars } from 'braid-design-system/css'; export const dropShadow = style({ boxShadow: vars.shadow.small, });
IconArrow: Add component (#1130)
Add new IconArrow
component. The orientation of the arrow can be controlled using the direction
prop.
EXAMPLE USAGE:
<IconArrow direction="left" />
Stepper: Add align prop (#1126)
Provide the align
prop which now includes support for left
alignment.
EXAMPLE USAGE:
<Stepper align="left">...</Stepper>
RadioGroup: Remove surrounding white space with no visual label (#1129)
Removes additional white space applied above the RadioItem
s when no visible label
is provided, i.e. when labelling via aria-label
or aria-labelledby
.
Stepper: Fix clipping of step name in Safari (#1126)
Fixes issue where the descenders in Step labels were being clipped only in Safari.
Rating: Add variant
prop and deprecate showTextRating
(#1123)
Provide the variant
prop to allow customising the appearance. This supports the new minimal
appearance, which presents a single star alongside the text rating.
Also adding the starsOnly
variant as a replacement for the now deprecated showTextRating={false}
.
EXAMPLE USAGE:
<Rating rating={3.7} variant="minimal" />
MIGRATION GUIDE:
The showTextRating
prop is now deprecated. If you were using this previously, please migrate to the new variant
prop using starsOnly
.
<Rating rating={3.7} - showTextRating={false} + variant="starsOnly" />
IconPlatformAndroid, IconPlatformApple, IconSocialYouTube: Add new icons (#1121)
Add icons for the Apple and Android mobile platforms as well as YouTube
EXAMPLE USAGE:
<IconPlatformAndroid /> <IconPlatformApple /> <IconSocialYouTube />
apac
and seekBusiness
themes: Update colour palette (#1104)
The colours used in these themes have been updated to the latest design standards as they were subtly off due to coming from an incorrect source.
MenuRenderer, OverflowMenu: Provide context data to onClose (#1115)
The onClose
handler now receives data to allow consumers to discern why the menu closed — either by exiting or selecting an action. See the documentation for more details.
EXAMPLE USAGE:
<MenuRenderer onClose={(closeReason) => { // ... }} />
RadioItem: Add disabled
support (#1108)
Provide support for disabling individual RadioItem
s within a RadioGroup
.
EXAMPLE USAGE:
<RadioGroup> <RadioItem label="One" value="1" /> <RadioItem label="Two" value="2" /> <RadioItem label="Three" value="3" disabled={true} /> </RadioGroup>
Button, ButtonLink: Ensure bleedY
is backwards compatibile for transparent
variant (#1106)
Ensure that bleedY
applies bleed only vertically on transparent
variant, isolating the new horizontal bleed to the new bleed
prop exclusively.
Button, ButtonLink: Improve Button bleed
(#1103)
Previously the bleedY
prop allowed the background of Button
to bleed vertically into the surrounding layout. This worked well for all variants except transparent
, which needed to bleed horizontally as well.
To support this we have introduced the bleed
prop which will apply the bleed based on the variant
. We have also deprecated bleedY
which will be removed in a future release.
EXAMPLE USAGE:
<Button - bleedY + bleed {...} > Button </Button>
MIGRATION GUIDE
Migration from bleedY
to bleed
can be automated by running the Braid upgrade command, passing the v31.11
version. You must provide a glob to target your project’s source files. For example:
yarn braid-upgrade v31.11 "**/*.{ts,tsx}"
It is recommended to visually review the any Button
usage with the transparent
variant, to ensure the layout is as expected.
Bleed: Support using span elements via component prop (#1094)
Setting the component
prop to span
will now ensure all elements controlled by Bleed
are span
s. This is useful when using layout components inside dom elements that should not contain div
s from a HTML validation perspective.
EXAMPLE USAGE:
<Bleed space="medium" component="span"> ... </Bleed>
Dialog, Drawer: Prevent sticky close button container from blocking content (#1097)
Fix regression introduced when migrating the close action to use ButtonIcon
. The close action container was blocking the content of the Dialog
/Drawer
, and when scrolling could prevent a user from interacting with the content as it went behind the container.
Additionally, re-introduced the surface coloured background behind the button to prevent the button from visually colliding with content when scrolling.
Tab: Add icon support (#1089)
Provides a designed slot for adding an icon to a Tab
EXAMPLE USAGE:
<Tab icon={<IconPromote />}>{...}</Tab>
AccordionItem: Add icon support (#1086)
Provides a designed slot for adding an icon to an AccordionItem
EXAMPLE USAGE:
<AccordionItem icon={<IconPromote />} {...} />
Tag: Add id
support (#1081)
Button, ButtonLink: Add icon support (#1090)
Provides a designed slot for adding an icon to a Button
or ButtonLink
EXAMPLE USAGE:
<Button icon={<IconSend />}>{...}</Button>
Tag: Add icon support (#1087)
Provides a designed slot for adding an icon to a Tag
EXAMPLE USAGE:
<Tag icon={<IconPromote />} {...} />
OverflowMenu: Add id
support (#1081)
ButtonIcon: Add component (#1084)
See documentation for full feature set.
EXAMPLE USAGE:
<ButtonIcon icon={<IconShare/>} label="Share" id="share" onClick={...} />
Divider: Use span element (#1089)
As the Divider
component is not used as a container element, we now use a span
. This allows it to be used inside button
elements, such as a Tab
, without producing invalid html.
Badge: Use span element (#1086)
As the Badge
component is not used as a container element, we now use a span
. This allows it to be used inside button
elements, such as an AccordionItem
, without producing invalid html.
TooltipRenderer: Ignore pointer events on tip container (#1082)
Fix for the container of the tooltip interferring with pointer events of the tooltip trigger itself.
MenuRenderer, OverflowMenu: Guard against open/close handlers firing incorrectly (#1088)
Add guard to ensure open and close handlers are not re-fired when handler instances are updated.
Autosuggest, PasswordField, TextField, useToast: Add id
to internal close/clear buttons (#1081)
Autosuggest, Dialog, Drawer, OverflowMenu, Tag, TextField, useToast: Migrate to use ButtonIcon (#1084)
Adopt new ButtonIcon
for clear/close actions in favour of custom internal buttons.
useToast: Add closeLabel
prop (#1079)
To support translations, the close button can now be customised using the closeLabel
prop.
EXAMPLE USAGE:
<Button onClick={() => showToast({ closeLabel: 'Close', // ... }) } />
Autosuggest, TextField: Add clearLabel
prop (#1079)
To support translations, the clear button in the field can now be customised using the clearLabel
prop.
EXAMPLE USAGE:
<Autosuggest clearLabel="Clear" // ... />
Loader: Apply WAI-ARIA alert pattern (#1079)
To improve the feedback of the Loader
provided to screen readers, we now apply the WAI-ARIA Alert Pattern using an assertive level of importance.
IconThumb: Update artwork (#1080)
MenuRenderer, OverflowMenu: Mouse leave no longer affects focus state (#1077)
Previously, moving the mouse from hovering a menu item to outside of the menu would shift focus the to the menu trigger. This is not a requirement for accessibility and introduces undesired behaviour when the trigger is used in conjunction with TooltipRenderer.
Note: As per the menu accessibility guidelines, focus will still be returned to the trigger when clicking outside the menu, selecting a menu item or pressing the escape key.
MenuRenderer, OverflowMenu: Add menu width
and placement
support (#1075)
Provides a set of width
s to control how wide the menu is, where content
is the default. The available widths are ratioed off the contentWidth
s specified on the theme.
Additionally the placement
of the menu can choose from either top
or bottom
where the latter remains the default.
EXAMPLE USAGE:
<MenuRenderer // ... width="small" placement="top" > ... </MenuRenderer>
MenuItem, MenuItemLink, MenuRenderer, OverflowMenu: Add icon
support (#1075)
Provides a designed slot for adding an icon to MenuItem
and MenuItemLink
. To compliment this we have introduced reserveIconSpace
on both MenuRenderer
and OverflowMenu
so the labels in menu items without icons align with the labels of menu items with an icon.
EXAMPLE USAGE:
<MenuRenderer reserveIconSpace> <MenuItem // ... icon={<IconBookmark />} > Menu Item </MenuItem> </MenuRenderer>
MenuItem, MenuItemLink, MenuItemChecklist: Add badge
support (#1075)
Provides a designed slot for adding a Badge
to all the variants of a menu item.
EXAMPLE USAGE:
<MenuRenderer> <MenuItem // ... badge={<Badge>Badge</Badge>} > Menu Item </MenuItem> </MenuRenderer>
Button: Support using as menu trigger (#1075)
Allow a Button
to receive all of the required props for a menu trigger. As a result a Button
now accepts onKeyUp
, onKeyDown
and aria-haspopup
.
EXAMPLE USAGE:
<MenuRenderer trigger={(triggerProps) => <Button {...triggerProps}>Button</Button>} > ... </MenuRenderer>
Column: Enure inner element honours component
prop (#1075)
Bleed: Add component (#1066)
Introduce Bleed
layout component that allows content to bleed out into the parent layout by a specified amount, useful when a content needs to negate the indent provided by a parent component.
See the documentation and layout guide for more information.
EXAMPLE USAGE:
<Card> <Stack space="gutter"> + <Bleed horizontal="gutter" top="gutter"> <Placeholder height={200} label="Header Image" /> + </Bleed> <Heading level="3">Heading</Heading> <Text>Text content</Text> </Stack> </Card>
Box, BoxRenderer, atoms: Add support for inset
shorthand (#1069)
Introduces the inset
shorthand as a convenience for applying top
, bottom
, left
and right
properties.
EXAMPLE USAGE:
<Box position="absolute" inset={0} />
or
atoms({ position: 'absolute', inset: 0, });
Pagination: Add pageLimit
support (#1070)
Add support for configuring the number of pages displayed using the pageLimit
prop. The default is still set to 7, but consumers can now reduce this, useful when Pagination
is used inside column layouts.
In addition, the layout has been stabilised, preventing the links moving when the next/prev actions are shown/hidden.
EXAMPLE USAGE:
<Pagination ... pageLimit={3} />
Columns: Support using span elements via component prop (#1064)
Setting the component
prop to span
will now ensure all elements controlled by Columns
are span
s. This is useful when using layout components inside dom elements that should not contain div
s from a HTML validation perspective.
EXAMPLE USAGE:
<Columns space="medium" component="span"> ... </Columns>
Drawer: Support positioning on the left (#1067)
A Drawer
can now enter from and be positioned on the left. The default remains unchanged and will enter from and be docked to the right.
EXAMPLE USAGE:
<Drawer ... position="left" />
Inline: Support using span elements via component prop (#1068)
Setting the component
prop to span
will now ensure all elements controlled by Inline
are span
s. This is useful when using layout components inside dom elements that should not contain div
s from a HTML validation perspective.
EXAMPLE USAGE:
<Inline space="medium" component="span"> ... </Inline>
Stack: Add support for span elements (#1060)
Stack now supports using span
elements for it's markup, this is useful when using layout components inside elements that should not contain a div
element, e.g. button
.
EXAMPLE USAGE:
<Stack component="span" space="medium"> ... </Stack>
Stepper: Add component (#1060)
See documentation for full feature set and usage details.
EXAMPLE USAGE:
<Stepper label="Linear steps" progress={3}> <Step>1. First step</Step> <Step>2. Second step</Step> <Step>3. Third step</Step> <Step>4. Forth step</Step> </Stepper>
AccordionItem: Add badge support (#1057)
The AccordionItem
now has support for the badge
prop.
EXAMPLE USAGE:
<AccordionItem label="Label" badge={<Badge>New</Badge>}> ... </AccordionItem>
Autosuggest: Scroll list into view (#1058)
The suggestions list will now be scrolled into view (on tablet and above) if it extends beyond the bottom of the window. This prevents suggestions (particularly those loaded asynchronously) from being obscured by the edge of the window.
MenuRenderer, OverflowMenu: Ensure layout of the trigger is controlled by the parent (#1055)
Fixes an issue where the trigger container did not adhere to the parent layout, preventing consumers from providing triggers that take up the full width of their available space. This goes against one of Braid's key layout principles which says spacing between elements is owned entirely by layout components.
contentWidth
theme tokens (#1052)backgroundColor
to html node when styleBody
is set (defaults to true
) (#1047)vars: Add light variant foreground colors (#1042)
New foregrounds
The following foregrounds are now available on the vars.foregroundColor
theme object:
cautionLight
infoLight
linkLight
linkLightVisited
positiveLight
promoteLight
Text: Improve contrast of caution
, positive
, info
, promote
and link
tones (#1042)
When using any of the above tones in a dark container, a lighter colour will be used to improve the text contrast against the background.
OverflowMenu: Use neutral
tone button style (#1042)
Alert, Card, Toast: Improve highlight keyline (#1042)
Ensures that components using a highlight keyline have the correct border radius and mask their overflow correctly.
Alert, Autosuggest, Tag, TextField: Use neutral
tone button style for clear action (#1042)
Box: Reset background color on input
and select
elements (#1042)
When specifying a component
of input
or select
the background color was not being reset, falling through to the user agent styles. Reseting it to transparent
to ensure predicatble styles across browsers and colour modes.
MenuItem, MenuItemLink, MenuItemCheckbox: Use span
elements internally for more valid HTML. (#1042)
Loader: Use current text color (#1042)
BraidTestProvider: Move to separate entry (#1031)
By moving BraidTestProvider
to it’s own entry, we can prevent importing all the themes at dev-time. This improves the developer experience when debugging the stylesheet that is output by the development server.
MIGRATION GUIDE
Migration can largely be automated by running the Braid upgrade command. You must provide a glob to target your project’s source files. For example:
yarn braid-upgrade v31 "**/*.{ts,tsx}"
It may be necessary to manually migrate code in some cases, here are the affected use cases:
- import { BraidTestProvider } from 'braid-design-system'; + import { BraidTestProvider } from 'braid-design-system/test';
BackgroundProvider Removed in favour of setting a background
of customDark
/customLight
directly on the Box
that has the custom background color. (#1031)
MIGRATION GUIDE
-<Box style={{ backgroundColor: 'purple' }}> +<Box background="customDark" style={{ backgroundColor: 'purple' }}> - <BackgroundProvider value="UNKNOWN_DARK"> <Text>Inverted text given dark context</Text> - </BackgroundProvider> </Box>
Remove previously deprecated ButtonRenderer
component in favour of Button
and ButtonLink
. (#1031)
MIGRATION GUIDE
If you were using this to render an a
element that visually looks like a button, you should be using ButtonLink
- <ButtonRenderer> - {(ButtonChildren, buttonProps) => ( - <a to="#" {...buttonProps}> - Visually a button - </a> - )} - </ButtonRenderer> + <ButtonLink> + Visually a button + </ButtonLink>
Button, ButtonLink: Add neutral
tone (#1031)
Introduces a neutral
tone for cases where actions need to be de-emphasised. As a result, there is a breaking change to the contextual design rules that invert buttons in dark containers.
BREAKING CHANGE:
A Button
with a variant
of ghost
, soft
, or transparent
and no specified tone
would previously invert when inside a dark container. Now, instead of inverting the foreground colour, these cases will use a lighter version of the default tone, i.e. formAccent
.
MIGRATION GUIDE:
To maintain previous behaviour, consumers should opt into the neutral
tone.
<Box background="brand" padding="gutter"> - <Button variant="ghost">Click</Button> + <Button variant="ghost" tone="neutral">Click</Button> </Box>
Remove legacy seekAsia themes (#1031)
Since the rebrand went live earlier this year, all consumers of jobsDb
, jobStreet
, jobStreetClassic
and seekUnifiedBeta
themes should now be using the apac
theme in production.
MIGRATION GUIDE
-import jobStreet from 'braid-design-system/themes/jobStreet'; +import apac from 'braid-design-system/themes/apac'; -<BraidProvider theme={jobStreet}> +<BraidProvider theme={apac}> ... </BraidProvider>
BulletList Remove deprecated component (#1031)
MIGRATION GUIDE
-<BulletList> - <Bullet large>Bullet</Bullet> - <Bullet large>Bullet</Bullet> - <Bullet large>Bullet</Bullet> -</BulletList> +<List size="large"> + <Text>Bullet</Text> + <Text>Bullet</Text> + <Text>Bullet</Text> +</List>
Remove previously deprecated TextLinkRenderer
component in favour of TextLink
and TextLinkButton
. (#1031)
MIGRATION GUIDE
If you were using this to render a button
element that visually looks like a link, you should be using TextLinkButton
<Text> - <TextLinkRenderer reset={false}> - {(textLinkProps) => ( - <Box component="button" {...textLinkProps}> - Visually a link - </Box> - )} - </TextLinkRenderer> + <TextLinkButton> + Visually a link + </TextLinkButton> , rendered as a button. </Text>
If you were using this to render an a
element or using a client side router link component you should ensure you have configured the linkComponent on BraidProvider
in your app. Once handled, migrating to TextLink
should be straight forward.
<Text> - <TextLinkRenderer reset={false}> - {(textLinkProps) => ( - <Link {...textLinkProps}> - ... - </Link> - )} - </TextLinkRenderer> + <TextLink> + ... + </TextLink> </Text>
TextLink, TextLinkButton: Remove support inside Actions
component (#1031)
Removing support for TextLink
and TextLinkButton
components inside of Actions
. This was previously deprecated back in v29.26.0 in favour of using the transparent
variant
of ButtonLink
.
MIGRATION GUIDE
<Actions> <Button>...</Button> - <TextLink href="...">...</TextLink> + <ButtonLink href="..." variant="transparent">...</ButtonLink> </Actions>
Remove BraidLoadableProvider
(#1031)
As most Apps should run the apac
theme across all brands, it no longer makes sense to centralise a loadable version of the BraidProvider
. This should simplify builds across the board and may result in a small build-speed increase.
MIGRATION GUIDE
If you are only using a single theme, then you should migrate your BraidLoadableProvider
usage to BraidProvider
.
+import apac from 'braid-design-system/themes/apac'; +import { BraidProvider } from 'braid-design-system'; -import { BraidLoadableProvider } from 'braid-design-system'; export const App = () => ( - <BraidLoadableProvider themeName="apac"> + <BraidProvider theme={apac}> ... - </BraidLoadableProvider> + </BraidProvider> );
If your app still needs to render different themes then you can replicate the BraidLoadableProvider
functionality locally using the loadable.lib
API.
import { BraidProvider } from 'braid-design-system'; import React, { ReactNode } from 'react'; import loadable from 'sku/@loadable/component'; type ThemeName = 'apac' | 'catho'; const BraidTheme = loadable.lib( (props: { themeName: ThemeName }) => import(`braid-design-system/themes/${props.themeName}`), ); interface AppProps { themeName: ThemeName; children: ReactNode; } export const App = ({ themeName, children }: AppProps) => ( <BraidTheme themeName={themeName}> {({ default: theme }) => ( <BraidProvider theme={theme}>{children}</BraidProvider> )} </BraidTheme> );
Box, atoms, vars: Update theme colour tokens with improved semantics. (#1031)
Simplifies the semantics of the colour-based tokens to support upcoming colour mode work. Changes to the property values on backgroundColor
and borderColor
has flow on affects to the apis on Box
and atoms
.
TOKEN CHANGES
New
surface
, neutralSoft
neutral
, neutralInverted
, neutralLight
Removed
card
, formAccentDisabled
, input
, inputDisabled
, selection
formHover
, standard
, standardInverted
MIGRATION GUIDE
Migration can largely be automated by running the Braid upgrade command. You must provide a glob to target your project’s source files. For example:
yarn braid-upgrade v31 "**/*.{ts,tsx}"
It may be necessary to manually migrate code in some cases, here are the affected use cases:
Box
backgrounds
- <Box background="card" /> + <Box background="surface" /> - <Box background="formAccentDisabled" /> + <Box background="neutralLight" /> - <Box background="input" /> + <Box background="surface" /> - <Box background="inputDisabled" /> + <Box background="neutralSoft" /> - <Box background="selection" /> + <Box background="formAccentSoft" />
Box
boxShadows
- <Box boxShadow="borderStandard" /> + <Box boxShadow="borderNeutralLight" /> - <Box boxShadow="borderStandardInverted" /> + <Box boxShadow="borderNeutralInverted" /> - <Box boxShadow="borderStandardInvertedLarge" /> + <Box boxShadow="borderNeutralInvertedLarge" /> - <Box boxShadow="borderFormHover" /> + <Box boxShadow="borderFormAccent" />
vars
- vars.borderColor.standard + vars.borderColor.neutralLight - vars.borderColor.standardInverted + vars.borderColor.neutralInverted - vars.borderColor.formHover + vars.borderColor.formAccent
atoms
atoms({ - boxShadow: 'borderStandard', + boxShadow: 'borderNeutralLight', }); atoms({ - boxShadow: 'borderStandardInverted', + boxShadow: 'borderNeutralInverted', }); atoms({ - boxShadow: 'borderStandardInvertedLarge', + boxShadow: 'borderNeutralInvertedLarge', }); atoms({ - boxShadow: 'borderFormHover', + boxShadow: 'borderFormAccent', });
Box: Add neutral background variants and new boxShadow border variants (#1031)
New backgrounds The following backgrounds are now available:
neutralActive
neutralHover
neutralSoftActive
neutralSoftHover
New boxShadows The following box shadows are now available:
borderBrandAccentLightLarge
borderCriticalLightLarge
borderFormAccentLight
borderFormAccentLightLarge
atoms: Add boxShadow border variants (#1031)
New boxShadows The following box shadows are now available:
borderBrandAccentLightLarge
borderCriticalLightLarge
borderFormAccentLight
borderFormAccentLightLarge
vars: Darken neutral background for the occ
theme. (#1031)
A neutral
background should be able to hold tone-based text. Moving from grey700
to grey800
as per the Atomic Design System color palette
vars: Add new backgrounds and light variant border colors (#1031)
New backgrounds
The following backgrounds are now available on the vars.backgroundColor
theme object:
neutralActive
neutralHover
neutralSoftActive
neutralSoftHover
New borderColors
The following border colors are now available on the vars.borderColor
theme object:
brandAccentLight
criticalLight
formAccentLight
vars: Darken neutral background for the seekAnz
theme. (#1031)
A neutral
background should be able to hold tone-based text. Moving from sk-mid-gray-dark
to sk-charcoal
as per the Seek Style Guide color palette
Text: Improve contrast of brandAccent
, critical
and formAccent
tones (#1031)
When using any of the above tones in a dark container, a lighter colour will be used to improve the text contrast against the background.
tabIndex
(#1025)Move @types/react
to devDependencies (#1023)
Braid requires consumers to provide React, therefore they should also provide the appropriate version of @types/react
rather than rely on the version installed in Braid.
disabled
(#1019)Autosuggest, Dropdown, MonthPicker, PasswordField, TextField, Textarea: Hide placeholder
text when field is disabled
(#1019)
Autosuggest, Checkbox, CheckboxStandalone, Dropdown, MonthPicker, TextField, Textarea, Radio, RadioGroup: Dim the field value and label when field is disabled
(#1019)
Autosuggest, TextField: Hide clear button when field is disabled
. (#1019)
apac
and seekBusiness
themes: Update colour palette (#983)
The colours used in these themes have been updated to the latest design standards.
A design review is highly recommended to ensure any custom design elements in your application still look correct when combined with these new colours.
Box: Add new background and border colours (#983)
New background
values:
brandAccentSoft
brandAccentSoftActive
brandAccentSoftHover
criticalSoft
criticalSoftActive
criticalSoftHover
formAccentSoft
formAccentSoftActive
formAccentSoftHover
New boxShadow
values:
borderCautionLight
borderCriticalLight
borderInfoLight
borderPositiveLight
borderPromoteLight
atoms: Add new boxShadow
values: (#983)
borderCautionLight
borderCriticalLight
borderInfoLight
borderPositiveLight
borderPromoteLight
vars: Add new background and border colours (#983)
New backgroundColor
values:
brandAccentSoft
brandAccentSoftActive
brandAccentSoftHover
criticalSoft
criticalSoftActive
criticalSoftHover
formAccentSoft
formAccentSoftActive
formAccentSoftHover
New borderColor
values:
cautionLight
criticalLight
infoLight
positiveLight
promoteLight
Button, ButtonLink, ButtonRenderer: The soft
variant now has a solid background colour rather than an opacity. You may need to review any usage on top of coloured backgrounds. (#983)
Box, atoms, vars: Add large
and xlarge
to borderRadius
scale (#983)
apac
and seekBusiness
themes: Increase size of focus ring (accessed via the boxShadow
value of "outlineFocus"
) and use updated colour palette. (#983)
Display formAccent
outline on form elements when focused (#983)
IconThumb, IconFlag: Add new icons (#980)
Autosuggest, Dropdown, MonthPicker, PasswordField, Textarea, TextField: Add aria-label & aria-labelledby support (#979)
In some cases it may be necessary for a field to be labelled by another element or even not to have a visual label. Instead of providing a label either aria-label or aria-labelledby can be provided.
EXAMPLE USAGE:
// Standard field label <TextField label="My field" /> // Hidden field label <TextField aria-label="My field" /> // Labelled by another element <Heading id="title">Title</Heading> <TextField aria-labelledby="title" />
Checkbox, RadioGroup, Radio: Use atoms for label cursor styles (#973)
Since the disabled state of a checkbox can only be changed via JavaScript, cursor styles can be toggled via Box
props rather than generating additional CSS.
While this is an improvement in and of itself, this change is being made to work around a third-party testing bug where our use of :disabled
in a complex CSS selector is causing an exception to be thrown.
TextField: Add characterLimit
prop (#963)
You can now provide a characterLimit
that will communicate when the input text approaches or exceeds the specified limit.
To prevent loss of information, exceeding the limit is permitted, however the count will be presented in a critical tone.
Add wide
breakpoint of 1200px (#960)
This adds support for wide
to the following touchpoints:
{ mobile: 'small', wide: 'large' }
<Columns collapseBelow="wide" space={{ mobile: 'small', wide: 'large' }}>
responsiveStyle
function, e.g.export const className = style(responsiveStyle({ wide: '...' }));
breakpoints
object, which now exposes the number 1200
via breakpoints.wide
, i.e.{ mobile: 0, tablet: 740, desktop: 940, wide: 1200 }
Add useResponsiveValue
Hook (#960)
This Hook will return the resolved value based on the breakpoint the browser viewport currently falls within (mobile
, tablet
, desktop
or wide
). As this can only be calculated in the browser, the value will also be null
when rendering server-side or statically rendering.
Note that this Hook returns a function so that it can be called anywhere within your component.
EXAMPLE USAGE
const responsiveValue = useResponsiveValue(); const screenSize = responsiveValue({ mobile: 'Small', desktop: 'Large', });
You can also resolve to boolean values for breakpoint detection.
const responsiveValue = useResponsiveValue(); const isMobile = responsiveValue({ mobile: true, tablet: false, }); const isDesktopOrAbove = responsiveValue({ mobile: false, desktop: true, });
Dialog, Drawer: Support nested Dialogs & Drawers (#959)
Remove restriction preventing the nesting of modal components, e.g. Dialog
and Drawer
. While it is still discouraged to keep experiences simple, there is no longer a technical guard against it.
Deprecate useBreakpoint
(#960)
This Hook has been deprecated in favour of the new useResponsiveValue
Hook.
This is because useBreakpoint
leads consumers to inadvertently couple themselves to the current set of breakpoints, making it risky for us to introduce new breakpoints.
For example, you may have chosen to detect large screens by checking that the user is on the (current) largest breakpoint (e.g. const isDesktop = useBreakpoint() === "desktop"
), but this logic would break if we introduced an even larger breakpoint and the Hook started returning other values.
To maintain backwards compatibility, useBreakpoint
will continue to return "desktop"
when the user is technically on larger breakpoints.
MIGRATION GUIDE
Note that the useResponsiveValue
Hook returns a responsiveValue
function, so in these cases we're double-calling the function.
-const isMobile = useBreakpoint() === 'mobile'; +const isMobile = useResponsiveValue()({ + mobile: true, + tablet: false +});
-const isTablet = useBreakpoint() === 'tablet'; +const isTablet = useResponsiveValue()({ + mobile: false, + tablet: true, + desktop: false, +});
-const isDesktop = useBreakpoint() === 'desktop'; +const isDesktop = useResponsiveValue()({ + mobile: false, + desktop: true +});
Narrow fontWeight
token type from string | number
to the expected values (#952)
Textarea: Fix "Received NaN for the rows
attribute." warning. (#950)
Fixes the warning in node testing environments where updating the rows
attribute was failing due to line-height
being normal
. Now falling back to the predefined lines
prop when the dynamic grow
size is not valid.
Box: Remove transform="touchable"
in favour of transform={{ active: 'touchable' }}
(#947)
MIGRATION GUIDE
-<Box transform="touchable"> +<Box transform={{ active: 'touchable' }}>
Updated minimum browser requirement to browsers that support CSS variables (#947)
For the major browsers this includes:
Update minimum required sku version to 10.13.1
(#947)
BREAKING CHANGE
Ensure your version of sku is at least 10.13.1
. This is required as Braid now uses vanilla-extract for styling.
Standardise breakpoints across all themes (#947)
All themes now use the following breakpoints:
0px
740px
992px
BREAKING CHANGE
This is a change for the following themes:
jobStreet, jobStreetClassic, jobsDb, occ, wireframe
768px
→ 740px
catho
600px
→ 740px
1024px
→ 992px
docs
768px
→ 740px
1136px
→ 992px
Migrate to vanilla-extract (#947)
Braid now uses vanilla-extract rather than treat to power its theme-based styling.
Since they use different file extensions (.css.ts
vs .treat.ts
), we're able to ease the migration by supporting both approaches simultaneously in the same project.
While we encourage you to write new CSS with vanilla-extract files and slowly migrate your existing treat files over time, the goal is to eventually remove treat entirely to enable further improvements to build tooling.
We've written a treat to vanilla-extract migration guide to make it easier when opting to migrate a treat file. If you have any questions or concerns, or if you need assistance with implementation or migration work, please reach out to us in the #braid-support
channel.
BREAKING CHANGE
React Portals containing Braid components/styles must use the new BraidPortal
component
CSS-based theming doesn't automatically cascade through React portals. The new BraidPortal
component handles this for you by forwarding Braid's CSS variables through the portal.
-import { createPortal } from 'react-dom'; +import { BraidPortal } from 'braid-design-system'; // ... -return open ? createPortal(<SomeComponent />) : null; +return open ? ( + <BraidPortal> + <SomeComponent /> + </BraidPortal> +) : null;
TextLinkRenderer: Allow custom CSS reset via the reset
prop, and allow it to be disabled by setting the prop to false
. (#947)
Support object notation for responsive props (#947)
Responsive prop values can now be written as objects with named breakpoints, which is now the recommended notation.
{ mobile: 'small', tablet: 'medium', desktop: 'large' }
This also means that breakpoints can be skipped.
{ mobile: 'small', desktop: 'large' }
Add breakpoints object for accessing standard breakpoint values (#947)
The breakpoints object provides a named set of screen sizes that form the basis of all responsive rules in Braid, available in the following format:
{ mobile: 0, tablet: 740, desktop: 992 }
Add globalTextStyle and globalHeadingStyle functions for applying standard text styles to foreign markup in vanilla-extract stylesheets (#947)
Note: These utilities should only be used when you have no control over the HTML.
EXAMPLE USAGE
// styles.css.ts import { style, globalStyle } from '@vanilla-extract/css'; import { globalHeadingStyle, globalTextStyle } from 'braid-design-system/css'; export const root = style({}); // Target all <h2> elements within the root class globalStyle( `${root} h2`, globalHeadingStyle({ level: '2', }), ); // Target all <p> elements within the root class globalStyle( `${root} p`, globalTextStyle({ size: 'standard', weight: 'regular', }), );
Add atoms function for accessing re-usable atomic classes within vanilla-extract stylesheets (#947)
Braid's re-usable atomic classes were previously only available via Box
, but they are now accessible via the new atoms
function.
// styles.css.ts import { atoms } from 'braid-design-system/css'; export const className = atoms({ paddingTop: 'small', });
This allows you to co-locate custom styles with Braid's atomic classes in your stylesheets.
// styles.css.ts import { style, composeStyles } from '@vanilla-extract/css'; import { atoms } from 'braid-design-system/css'; export const className = composeStyles( atoms({ position: 'absolute' }), style({ top: 300 }), );
Add responsiveStyle function for creating custom mobile-first styles within vanilla-extract stylesheets (#947)
EXAMPLE USAGE
// styles.css.ts import { style } from '@vanilla-extract/css'; import { vars, responsiveStyle } from 'braid-design-system/css'; export const className = style( responsiveStyle({ mobile: { flexBasis: vars.space.small, }, tablet: { flexBasis: vars.space.medium, }, desktop: { flexBasis: vars.space.large, }, }), ); // is equivalent to import { style } from '@vanilla-extract/css'; import { vars, breakpoints } from 'braid-design-system/css'; export const className = style({ flexBasis: vars.space.small, '@media': { [`screen and (min-width: ${breakpoints.tablet}px)`]: { flexBasis: vars.space.medium, }, [`screen and (min-width: ${breakpoints.desktop}px)`]: { flexBasis: vars.space.large, }, }, });
Add vars object for accessing themed CSS variables within vanilla-extract stylesheets and runtime files. (#947)
Theming is now achieved natively with CSS variables rather than generating separate styles for each theme. CSS variables are exposed via the braid-design-system/css
import.
// styles.css.ts import { style } from '@vanilla-extract/css'; import { vars } from 'braid-design-system/css'; export const className = style({ paddingTop: vars.space.small, });
CheckboxStandalone:: Add component (#935)
Adds support for cases where a Checkbox needs to be used without a form field style label.
To maintain accessibility, it is required to provide either a aria-label or aria-labelledby property, to describe the field's intent.
Given there is no visual label, the following features from a standard Checkbox cannot be supported:
EXAMPLE USAGE:
<CheckboxStandalone id={...} checked={...} onChange={...} aria-label="Label" />
Add support for data attribute maps on all components. (#934)
EXAMPLE USAGE:
<Alert data={{ testId: 'message', }} /> // => <div data-testId="message" />
Checkbox,RadioGroup,Toggle: Add size
support to Checkbox, RadioGroup & Toggle (#928)
Adds support for adjusting the size
of a Checkbox
, the RadioItems within a RadioGroup
or a Toggle
. Setting the size adjusts both the visual control and the text size of the label.
EXAMPLE USAGE:
<Checkbox size="small" label="Label" />
<RadioGroup size="small" label="Label"> ... </RadioGroup>
<Toggle size="small" label="Label" />
Pagination: Add keyline to improve active page indicator contrast (#926)
Improves the contrast of the active page indicator by adding a keyline when Pagination
is used outside of a Card
.
Accordion, AccordionItem: Allow customisation of size, tone, space and dividers. (#925)
Note that, to ensure adequate space for touch targets, the space
prop only accepts values of "medium"
, "large"
and "xlarge"
.
EXAMPLE USAGE
<Accordion size="standard" tone="secondary" space="xlarge" dividers={false}> <AccordionItem label="Accordion item 1">...</AccordionItem> <AccordionItem label="Accordion item 2">...</AccordionItem> <AccordionItem label="Accordion item 3">...</AccordionItem> </Accordion>
characterLimit
is provided (#919)Text
elements (#912)Box: Support responsive borderRadius
(#910)
Adds support for responsive values to borderRadius
.
EXAMPLE USAGE:
<Box borderRadius={['none', 'standard']}>...</Box>
Button: Add support for ref
and tabIndex
props (#905)
Card: Add component
support (#910)
The HTML tag can be customised to ensure the underlying document semantics are meaningful. This can be done using the component prop and supports div
(default), article
, aside
, details
, main
and section
.
EXAMPLE USAGE:
<Card component="article">...</Card>
Badge: Add support for ref
, tabIndex
and aria-describedby
props (#905)
Card: Add tone
support (#910)
Specifying a tone
will now add a keyline down the left hand side of the container. The supported tones are promote
and formAccent
.
As a result, Cards are now position relative containers.
EXAMPLE USAGE:
<Card tone="formAccent">...</Card>
TextLink, ButtonLink: Add support for ref
prop (#905)
Card: Add rounded
and roundedAbove
support (#910)
Card corners can be rounded by providing the rounded
prop.
Alternatively, rounding may be applied responsively using the roundedAbove
prop, and providing either mobile
or tablet
. This enables card edges to be softened on larger screens, but squared off if it runs full bleed on smaller devices.
EXAMPLE USAGE:
<Card rounded>...</Card>
or
<Card roundedAbove="mobile">...</Card>
TooltipRenderer: Add placement
prop, support top
and bottom
. Set default placement to top
. (#901)
EXAMPLE USAGE
<TooltipRenderer id={id} tooltip={<Text>This is a tooltip!</Text>} placement="bottom" > {({ triggerProps }) => ( <Box aria-label="Help" {...triggerProps}> <IconHelp /> </Box> )} </TooltipRenderer>
Button, ButtonLink, ButtonRenderer: Add bleedY
prop (#900)
You can now choose to allow the button’s background colour to bleed out into the surrounding layout, making it easier to align with other elements.
For example, we can align a button to a Heading element using an Inline, even though the button is actually taller than the heading. If we didn’t use the bleedY prop in this case, the button would introduce unwanted space above and below the heading.
EXAMPLE USAGE:
<Inline space="small" alignY="center"> <Heading level="4">Heading</Heading> <Button bleedY>Button</Button> <Button bleedY size="small"> Button </Button> </Inline>
Add TooltipRenderer component (#897)
Tooltips appear on mouse hover, tap and keyboard focus, and are hidden when scrolling and clicking/tapping/focusing on other elements.
Tooltips cannot contain interactive elements like links, buttons or form elements.
Note: The trigger element must support ref
, tabIndex
and aria-describedby
props.
EXAMPLE USAGE
<TooltipRenderer id={id} tooltip={<Text>This is a tooltip!</Text>}> {({ triggerProps }) => ( <Box aria-label="Help" {...triggerProps}> <IconHelp /> </Box> )} </TooltipRenderer>
Box: Add borderBrandAccentLarge
to boxShadow
prop (#893)
Text, Icons: Add brandAccent tone to Text and Icons (#893)
EXAMPLE USAGE:
<Text tone="brandAccent">...</Text>
Button,ButtonLink: Add variant to Button and deprecate weight (#893)
Introduces a new variant
prop to Button
/ButtonLink
giving consumers a single prop to use for selecting the visual style of the button. Choose from solid
(default), ghost
, soft
or transparent
. The colour of the button is now consistently controlled via the tone
prop, with supported values being "brandAccent"
, "critical"
or undefined
.
As a result the weight
prop is now deprecated. See the migration guide below.
EXAMPLE USAGE:
<Inline space="small" collapseBelow="desktop"> <Button>Solid</Button> <Button variant="ghost">Ghost</Button> <Button variant="soft">Soft</Button> <Button variant="transparent">Transparent</Button> </Inline>
MIGRATION GUIDE:
The weight
prop is now deprecated. If you are not specifying a weight
there is no change required.
If you are, each weight can be migrated as follows:
Can be replicated with a variant
of solid
(default).
-<Button weight="regular">...</Button> +<Button variant="solid">...</Button>
Given it is the default variant
, you could also choose to simply remove the weight
prop.
-<Button weight="regular">...</Button> +<Button>...</Button>
Can be replicated with a variant
of solid
(default), with a tone
of brandAccent
.
-<Button weight="strong">...</Button> +<Button tone="brandAccent">...</Button>
Can be replicated with a variant
of ghost
.
-<Button weight="weak">...</Button> +<Button variant="ghost">...</Button>
TextLink,TextLinkButton: Deprecate inside of Actions in favour of transparent Button (#893)
Usage of TextLink
or TextLinkButton
inside of an Actions
container should now use a Button
with a variant
of transparent
.
Previously when a TextLink
or TextLinkButton
was placed inside of an Actions
container, it would be given a custom layout to align with the Button
elements. We are deprecating this behaviour.
MIGRATION GUIDE:
Going forward Actions
should only contain Button
elements. To migrate towards this, both TextLink
and TextLinkButton
should now use either a ButtonLink
or Button
respectively, with a variant
or transparent
.
<Actions> <Button>...</Button> - <TextLink href="...">...</TextLink> + <ButtonLink href="..." variant="transparent">...</ButtonLink> </Actions>
<Actions> <Button>...</Button> - <TextLinkButton onClick={...}>...</TextLinkButton> + <Button onClick={...} variant="transparent">...</Button> </Actions>
Button, ButtonLink: Remove all interactive styles when loading (#895)
No longer applies hover and cursor pointer styles when a Button
is set to loading
.
null
/undefined
as children in Tabs
and TabPanels
(#889)Hidden: Add component
support (#880)
You can now customise the DOM element rendered when using Hidden
. If no component
is specified, it will fall back to the current behaviour — a div
by default, or a span
when setting inline
to true
.
EXAMPLE USAGE:
<Hidden component="li">...</Hidden>
Pagination: Add component (#880)
EXAMPLE USAGE:
<Pagination label="Search results pagination" page={1} total={20} linkProps={({ page }) => ({ href: `/results?page=${page}`, })} />
Button, ButtonLink, ButtonRenderer, Actions: Add size
prop, support small
size (#879)
You can now render smaller variants of button/action elements by setting the size
prop to small
.
EXAMPLE USAGE
Small Button
<Button size="small">Small Button</Button>
Small Actions
<Actions size="small"> <Button>Regular Button</Button> <Button weight="weak">Weak Button</Button> <TextLink href="#">TextLink</TextLink> </Actions>
standard
size from gutter
to medium
(#879)Tabs: Add divider
prop, support full
and none
(#875)
You can now customise the width of the divider line underneath the tab strip. The default value is minimal
, but you can now set it to full
or none
.
EXAMPLE USAGE
<TabsProvider id="id"> <Tabs label="Label" divider="full"> <Tab>The first tab</Tab> <Tab>The second tab</Tab> </Tabs> <TabPanels> <TabPanel>...</TabPanel> <TabPanel>...</TabPanel> </TabPanels> </TabsProvider>
Use JSDoc comments to flag deprecated components (#860)
You will now receive in-editor warnings and migration guidance when using deprecated components.
Autosuggest: Fix bug where async suggestions may not be visible (#862)
This fixes a bug where suggestions wouldn't become visible if the suggestions
prop was initially empty and then populated asynchronously, only becoming visible on the next user interaction, e.g. typing in the field.
MenuItem, MenuItemLink: Add support for critical
tone (#855)
For destructive actions (e.g. "Delete") you can now provide a tone
prop with a value of "critical"
.
EXAMPLE USAGE
<OverflowMenu label="Options"> <MenuItem tone="critical" onClick={() => {}}> Delete </MenuItem> </OverflowMenu>
Box: Add "criticalActive"
and "criticalHover"
to background
prop (#851)
Button, ButtonLink, ButtonRenderer: Add support for critical
tone (#851)
For destructive actions (e.g. "Delete") you can now provide a tone
prop with a value of "critical"
.
EXAMPLE USAGE
<Button tone="critical"> <IconDelete /> Delete </Button>
Box: Add "borderCriticalLarge"
to boxShadow
prop (#851)
Autosuggest: Add support for custom messages when no suggestions are present (#847)
If no suggestions are available and you'd like to provide an explanation to the user, you can now pass an object with a messages
property to the suggestions
prop.
EXAMPLE USAGE
<Autosuggest suggestions={{ message: 'No suggestions available.' }} {...restProps} />
Checkbox: Support inferring of tri-state checked value (#843)
To simplify the use of tri-state checkboxes, the checked prop now supports resolving the tri-state value from an array of checked values.
EXAMPLE USAGE:
<Checkbox label="Select all" checked={[true, false, false]} // Will resolve to "mixed" />
Dropdown: Only show a blank option in the list when the value
prop is blank and a placeholder isn't present (#846)
PasswordField: Ensure disabled is handled correctly (#845)
Fixes a bug where the disabled prop was hiding the visibility toggle but leaving the field enabled.
Autosuggest: Add filterSuggestions
function, allow suggestions
prop to be a function (#831)
The logic for filtering suggestions typically lives on the server rather than the client because it’s impractical to send all possible suggestions over the network. However, when prototyping in Playroom or working with smaller datasets, you may want to perform this filtering on the client instead. For this case, we now provide a filterSuggestions
function to make this as painless as possible.
To better support this behaviour, you can now pass a function to the suggestions
prop. When executed, this function will be passed the current value
of the field.
EXAMPLE USAGE
import { Autosuggest, filterSuggestions } from 'braid-design-system'; <Autosuggest suggestions={filterSuggestions([ { text: 'Apples', value: 1 }, { text: 'Bananas', value: 2 }, ])} {...restProps} />;
Checkbox: Add support for mixed state (#822)
A checkbox can now accept a boolean or mixed
as the checked
property. When mixed
, the checkbox is marked as being in an indeterminate
state and announced as mixed
to a screen reader.
EXAMPLE USAGE:
<Checkbox checked="mixed" onChange={handler} label="Label" />
Autosuggest: Support custom label text for suggestions (#821)
You can now optionally provide different suggestion text from the value that gets inserted into the text field.
EXAMPLE USAGE
<Autosuggest suggestions={[{ text: 'apples', label: 'Add "apples"' }]} {...restProps} />
ref
prop to input element (#819)Checkbox,RadioGroup,Radio: Fix element type passed to onChange event (#814)
Fixes a bug where the onChange
event previously received the change event for a form
element rather than an input
element.
List: Add support for icons (#810)
Provides a way to use an icon for all the items in a list. When using type="icon"
you must also provide the icon
prop. See example below:
EXAMPLE USAGE:
<List type="icon" icon={<IconTick tone="positive" />}> <Text>This is a list item.</Text> <Text>This is a list item.</Text> <Text>This is a list item.</Text> </List>
RadioGroup,RadioItem: Add RadioGroup & RadioItem components (#807)
The RadioGroup provides an accessible way to group and control a set of RadioItem components. The RadioGroup is responsible for handling the value, tone, message, and disabled state—determining the presentation and selection of the items in the list.
EXAMPLE USAGE:
<RadioGroup id="experience" label="Experience" value="" onChange={() => {}}> <RadioItem label="Less than one year" value="0" /> <RadioItem label="1 year" value="1" /> <RadioItem label="2 years" value="2" /> <RadioItem label="3+ years " value="3" /> </RadioGroup>
Tabs: Only scroll tabs when necessary on large screens (#806)
Previously, when there were enough tabs to require horizontal scrolling, we would always scroll the active tab to the left-hand side of the scroll container (with a slight offset). This was primarily designed as a mobile interaction, and in practice was found to be a bit unexpected on large screens.
Instead, when the tabs are scrollable on large screens, we now only scroll the active tab into view if it's partially off-screen or positioned too close to the edge of the scroll container. This ensures that automatic scrolling only occurs when absolutely necessary.
TextField,Dropdown,PasswordField,MonthPicker,Textarea: Apply aria-describedby to form elements only when needed (#798)
Only apply aria-describedby
to form elements when needed, e.g. either a message
, description
, or an explicit aria-describedby
is passed.
MonthPicker: Announce semantic grouping of fields and improved translation support. (#798)
When not on a native device, the MonthPicker uses a fieldset
containing two dropdowns. This change ensures that the grouping is announced correctly. From a translations perspective the labels for the dropdowns are no longer a concatenation of the label
and monthLabel
/yearLabel
, supporting translation of the entire phrase.
Autosuggest: Add hideSuggestionsOnSelection
prop (#792)
Typically we hide the suggestion list when a selection is made, assuming that the field is now populated with the desired value. However, if the surrounding application clears the text field when a selection is made, this clashes with the user expectation that the field has been reverted back to its initial state with suggestions visible. To cater for this, we now allow you to opt out of this behaviour via the hideSuggestionsOnSelection
boolean prop.
EXAMPLE USAGE
<Autosuggest hideSuggestionsOnSelection={false} {...rest} />
List: Add support for Roman numerals (#788)
EXAMPLE USAGE
<List type="roman"> <Text>This is a Roman list item.</Text> <Text>This is a Roman list item.</Text> <Text>This is a Roman list item.</Text> </List>
Radio,Checkbox: Add description and badge support (#786)
Allows a way to provide more detail about a Radio
or Checkbox
item using description
, bringing these fields into line with the rest of the form fields in Braid. Also allows a badge
to be provided to be placed alongside the label
.
EXAMPLE USAGE:
<Radio label="Option" description="This option is your favourite" badge={ <Badge tone="positive" weight="strong"> New </Badge> } />
or
<Checkbox label="Option" description="This option is your favourite" badge={ <Badge tone="positive" weight="strong"> New </Badge> } />
Add Drawer component (#775)
You can now open a modal panel on the right-hand side of the screen, following the WAI Aria Dialog (Modal) Pattern.
See the documentation for more details and interactive examples.
Box: Add maxWidth
prop (#775)
The sizes from ContentBlock are now available at a lower level for more primitive-based layouts.
EXAMPLE USAGE:
<Box maxWidth="large">...</Box>
FieldLabel: Add descriptionId prop (#766)
EXAMPLE USAGE:
<FieldLabel htmlFor="id" label="This is a field label" description="Extra info about the field" descriptionId="id-description" />
Autosuggest: Improve screen reader experience (#757)
Add description informing user that suggestions will appear below field. Also, notify users about how many suggestions are available, and about automatic selections.
TextField, PasswordField, Textarea, Dropdown: Add support for multiple field descriptions (#757)
Previously, if a custom aria-describedby
prop was passed, it would take precedence over the message
prop, which also uses aria-describedby
. Both descriptions can now be applied at the same time.
Add MenuItemDivider component (#751)
You can now place visual separators between groups of menu items when using OverflowMenu/MenuRenderer.
EXAMPLE USAGE
<OverflowMenu label="Options"> <MenuItem onClick={() => {}}>Button</MenuItem> <MenuItemLink href="#">Link</MenuItemLink> <MenuItemDivider /> <MenuItem onClick={() => {}}>Another button</MenuItem> </OverflowMenu>
Add MenuItemCheckbox component (#751)
You can now render checkboxes within OverflowMenu/MenuRenderer elements.
EXAMPLE USAGE
<OverflowMenu label="Checklist"> <MenuItemCheckbox checked={true} onChange={() => {}}> Checkbox 1 </MenuItemCheckbox> <MenuItemCheckbox checked={false} onChange={() => {}}> Checkbox 2 </MenuItemCheckbox> <MenuItemCheckbox checked={false} onChange={() => {}}> Checkbox 3 </MenuItemCheckbox> </OverflowMenu>
Loader: Add support for aria-label
(#752)
Provides a mechanism for consumers to better communicate to assistive technologies what is happening.
EXAMPLE USAGE:
<Loader aria-label="Loading search results" />
Badge: Add bleedY
prop (#743)
You can now choose to allow the badge’s background colour to bleed out into the surrounding layout, making it easier to align with other elements.
For example, we can align a badge to a Heading element using an Inline, even though the badge is actually taller than the heading. If we didn’t use the bleedY
prop in this case, the badge would introduce unwanted space above and below the heading.
<Inline alignY="center" space="xsmall"> <Heading level="4">Heading</Heading> <Badge bleedY tone="positive"> New </Badge> </Inline>
Add Dialog
component (#746)
Follows the WAI Aria Dialog (Modal) Pattern.
EXAMPLE USAGE:
<Fragment> <Actions> <Button onClick={() => setOpen(true)}>Open dialog</Button> </Actions> <Dialog title="Dialog Example" id={id} open={open} onClose={setOpen}> <Placeholder height={100} width="100%" /> </Dialog> </Fragment>
See the documentation for an exhaustive list of features.
List, BulletList: Ensure list items are full width (#745)
Fixes an issue where list content was unable to stretch to the edge of its container. To allow this, we now set the list item container itself to be full width so that content is no longer constrained.
ContentBlock: Ensure block is full width (#746)
Fixes an issue where ContentBlock
s inside of flex containers would not grow to their defined max-width
.
Badge: Allow custom title text (#738)
EXAMPLE USAGE
<Badge tone="positive" title="3 new jobs"> 3 </Badge>
Improved server rendering of Tabs (#737)
Previously, Tab
and TabPanel
components only showed their content and active states after the first render, which meant server rendering was not ideal. Active Tabs and TabPanel content can now be server rendered. Uncontrolled usages of Tabs should just work.
For controlled Tabs using the selectedItem
prop, you now need to pass the item
prop (already on Tab
) to TabPanel
as well.
<TabsProvider id="id" selectedItem="second"> <Tabs label="Test tabs"> <Tab item="first">The first tab</Tab> <Tab item="second">The second tab</Tab> <Tab item="third">The third tab</Tab> </Tabs> <TabPanels> - <TabPanel> + <TabPanel item="first"> <Placeholder height={200} label="Panel 1" /> </TabPanel> - <TabPanel> + <TabPanel item="second"> <Placeholder height={200} label="Panel 2" /> </TabPanel> - <TabPanel> + <TabPanel item="third"> <Placeholder height={200} label="Panel 3" /> </TabPanel> </TabPanels> </TabsProvider>
ContentBlock: Add support for xsmall & small widths (#735)
EXAMPLE USAGE
<ContentBlock width="small">...</ContentBlock>
OverflowMenu, MenuRenderer: Assert that all child nodes are valid menu items (#731)
In order to maintain accessibility, we now throw assertion errors in development if any child node within an OverflowMenu or MenuRenderer component is not a MenuItem/MenuItemLink.
Box: Added zIndex
prop (#726)
The following z-index palette is now available on Box
:
Local stacking
0
1
2
Global stacking
"dropdownBackdrop"
"dropdown"
"sticky"
"modalBackdrop"
"modal"
"notification"
EXAMPLE USAGE
<Box position="fixed" zIndex="sticky"> ... </Box>
TabPanels: Add renderInactivePanels
prop (#722)
By default, the children of TabPanel
components are only rendered when they are selected. However, in cases where you want to preserve local component state when switching tabs, this behaviour is undesirable. Setting renderInactivePanels
will cause the TabPanel
children to be rendered even when visually hidden.
Note: This is not a visual change, the panels will still be hidden from the user.
e.g.
<TabsProvider selectedItem={0}> <Tabs> <Tab>First</Tab> <Tab>Second</Tab> </Tabs> <TabPanels renderInactivePanels> <TabPanel> <Text>Tab 1</Text> </TabPanel> <TabPanel> {/* This TabPanel is hidden but still in the DOM */} <Text>Tab 2</Text> </TabPanel> </TabPanels> </TabsProvider>
Forwarding refs is necessary for certain accessibility patterns (e.g. managing focus states), but the Link
component wasn't doing this correctly.
Please note that, if you're passing a custom linkComponent
implementation to BraidProvider, you'll need to ensure that you're using the new makeLinkComponent
helper function to forward refs, otherwise any attempt to pass a ref to Link
will throw an error.
MIGRATION GUIDE
-import { BraidProvider, LinkComponent } from 'braid-design-system'; +import { BraidProvider, makeLinkComponent } from 'braid-design-system'; -const CustomLink: LinkComponent = ({ href, ...restProps }) => +const CustomLink = makeLinkComponent({ href, ...restProps }, ref) => href[0] === '/' ? ( - <ReactRouterLink to={href} {...restProps} /> + <ReactRouterLink to={href} {...restProps} ref={ref} /> ) : ( - <a href={href} {...restProps} /> + <a href={href} {...restProps} ref={ref} /> ); export const App = () => ( <BraidProvider linkComponent={CustomLink} {...rest}> ... </BraidProvider> );
Link: Fixed types for className
prop to support the full classnames API (#725)
You can now pass arrays and objects to the className
prop on Link
without type errors.
For example:
<Link href="#" className={[ 'someClass', ['anotherClass', 'yetAnotherClass'], { someConditionalClass: someBoolean }, ]} > ... </Link>
Added MenuItemLink component (#725)
You can now render semantic links within menu components, e.g. OverflowMenu, MenuRenderer
For example:
<OverflowMenu label="Options"> <MenuItem onClick={() => {}}>Button</MenuItem> <MenuItemLink href="...">Link</MenuItemLink> </OverflowMenu>
Note that links are rendered internally using Link. If you want to customise the rendering of these links, you need to provide a custom linkComponent
implementation to BraidProvider.
Add List
component (#710)
List
serves as a replacement for the BulletList
and Bullet
components which adds the following improvements:
Note: The BulletList
and Bullet
components have been marked as deprecated and will be removed in an upcoming major release.
MIGRATION GUIDE
If you want to migrate from BulletList
to List
, you can simply replace BulletList
with List
, and Bullet
with Text
:
-<BulletList> - <Bullet>...</Bullet> - <Bullet>...</Bullet> - <Bullet>...</Bullet> -</BulletList> +<List> + <Text>...</Text> + <Text>...</Text> + <Text>...</Text> +</List>
TextLink, TextLinkButton, TextLinkRenderer: Default weight
prop to "regular"
when nested inside secondary text (#714)
As of v28.13.0, TextLink
components that were nested inside secondary text would be "weak"
by default, i.e. the same tone as the surrounding text and underlined. In practice, this turned out to be somewhat unpredictable behaviour for consumers. We've now reverted this to the previous behaviour of being "regular"
weight by default, i.e. blue and medium font weight.
Note that, if needed, you can still use the weaker link treatment within secondary text via an explicit prop override:
<Text tone="secondary"> The TextLink in this sentence is{' '} <TextLink href="..." weight="weak"> weak. </TextLink> </Text>
Improved trimming of white space around text (#696)
Migrated from our custom Basekick implementation to 🛶 Capsize to more accurately trim the white space around text. This will have subtle white space changes throughout the UI, but will largely just be improvements to the balance of space around text.
BREAKING CHANGES
Heading/Text: Removed LEGACY_SPACE
The _LEGACY_SPACE_
prop was provided to support consumers migrating to v14
when the white space cropping and layout components were originally introduced. This has now been removed to allow us to further improve on our approach.
Migrating off this prop will require consumers to perform the following steps:
_LEGACY_SPACE_
on a componentStack
, to define/control the reintroduction of the desired space.Any issues, please reach out to the team as we are happy to help support consumers in migrating.
Theme Tokens: Text and Heading definitions
There have been strutural theme changes for heading
and text
definitions to support the defining of capHeight
in the system. Previously a definition contained size
that was the specified font size inclusive of surrounding white space.
A definition now has capHeight
which is representative of the visual height, supporting improved alignment with other elements like, icons etc.
{ text: { standard: { mobile: { - size: 16, + capHeight: 11.43, rows: 6 } } } }
This is not likely to affect consumers, unless these theme values are used explicitly in custom treat files.
Theme Tokens: Descender and Cap Height scales
Instead of the calculated values of capHeightScale
and decenderHeightScale
, a theme now accepts fontMetrics
—a structure that represents the metadata from the font itself.
-const capHeight = 24 * theme.typography.capHeightScale; +const capHeight = 24 * (theme.typography.fontMetrics.capHeight / theme.typography.fontMetrics.unitsPerEm);
-const descender = 24 * theme.typography.decenderHeightScale; +const descender = 24 * (Math.abs(theme.typography.fontMetrics.descent) / theme.typography.fontMetrics.unitsPerEm);
Add Notification icon (#702)
Add useBreakpoint (#700)
useBreakpoint
will return the breakpoint the browser viewport currently falls within (mobile, tablet or desktop). As this can only be calculated in the browser, the value may also be null. Window resizing is supported.
Note: Avoid use of this hook where possible. Responsive properties and media queries are a better option in most cases.
TextLink, TextLinkButton: Add weight
prop, add weak
weight variant (#697)
You can now render links that are underlined while inheriting the tone and weight of its surrounding text.
EXAMPLE USAGE
<Text> This sentence contains a{' '} <TextLink href="..." weight="weak"> weak TextLink. </TextLink> </Text>
seekBusiness
theme: Inherit from new apac
theme rather than the deprecated seekAnz
theme (#694)
Just like the migration from seekAnz
to apac
, the visual changes are as follows:
#eeeeee
to #f5f6f8
.48px
to 44px
.2px
to 4px
.It's possible that your application has custom design elements that depend on these older values in order to look correct. It's also possible that your application is part of a broader user journey that makes use of these older design standards. As a result, a design review is highly recommended.
TextLinkButton: Pass click event object to onClick
handler (#688)
The onClick
handler was previously called without any arguments. We now pass the click event object through as expected.
Button: Add aria-controls
and aria-expanded
props (#686)
Add Disclosure
component (#686)
This component serves as a replacement for ToggleContent
from SEEK Style Guide.
SEEK STYLE GUIDE MIGRATION GUIDE
ToggleContent
has been renamed to Disclosure
.onShowMore
prop has been renamed to onToggle
.-<ToggleContent onShowMore={(expanded) => { ... }} {...rest}> +<Disclosure onToggle={(expanded) => { ... }} {...rest}>
TextLinkButton: Add aria-controls
, aria-describedby
and aria-expanded
props (#686)
Add TextLinkButton
component (#683)
Allows you to render a semantic button that looks like a TextLink
.
This component renders a native span
element with an ARIA role of button
so that, unlike a standard button element, text can wrap across multiple lines.
Introduce apac
theme (#676)
The seekAnz
theme has always been held back by the need to maintain visual consistency with SEEK Style Guide.
In order to provide a path forwards, this release introduces a new apac
theme, giving teams the opportunity to adopt newer design standards while still providing the seekAnz
theme as a backwards compatibility layer.
Consumers of the seekAnz
theme are under no immediate pressure to migrate and both themes will be provided for the forseeable future. For now, this theme is aimed at those teams that are explicitly wanting to adopt newer design standards.
The visual changes to seekAnz
are as follows:
#eeeeee
to #f5f6f8
.It's possible that your application has custom design elements that depend on these older values in order to look correct. It's also possible that your application is part of a broader user journey that makes use of these older design standards. As a result, a design review is highly recommended.
This release also signifies that the seekUnifiedBeta
theme is coming out of beta. Any references to this theme should be replaced with apac
. As with seekAnz
, both themes will be provided for the timebeing to give you an opportunity to migrate.
EXAMPLE USAGE
import apac from 'braid-design-system/themes/apac'; <BraidProvider theme={apac}>
<BraidLoadableProvider themeName="apac">
Box: Add body
background (#677)
You can now use the theme's body background on arbitrary elements within the page.
EXAMPLE USAGE
<Box background="body">...</Box>
MonthPicker: Support custom month and year labels (#672)
To support internationalisation, you can now pass the following props to MonthPicker
:
string
)string
)string[]
)Expose docs theme (#670)
In order to support internal documentation sites that leverage Braid, we're now exposing a docs
theme.
import docsTheme from 'braid-design-system/themes/docs';
Add Tabs component (#666)
Follows the WAI Aria Tabs Pattern.
EXAMPLE USAGE:
<TabsProvider id="id"> <Stack space="medium"> <Tabs label="Label"> <Tab>The first tab</Tab> <Tab>The second tab</Tab> <Tab badge={<Badge tone="positive">New</Badge>}>The third tab</Tab> </Tabs> <TabPanels> <TabPanel>...</TabPanel> <TabPanel>...</TabPanel> <TabPanel>...</TabPanel> </TabPanels> </Stack> </TabsProvider>
Autosuggest: Fix suggestion double tap bug on iOS (#668)
Tapping a suggestion on iOS triggers the hover state rather than a selection, forcing users to tap a second time to select the suggestion.
This is due to the way that iOS simulates mouse events in a touch environment. If the document is updated during a mouseover
, mouseenter
or mousemove
event, the subsequent click
event is never fired. While it may seem counterintuitive, this ensures that touch users are able to see hover effects that make changes to the page.
To fix this, we now trigger our suggestion hover logic on touchstart
so that the document doesn't change during mouse events, which then allows the click
event to fire uninterrupted.
Fix CSS ordering issue in production mode (#664)
Files within the top-level themes
directory were not correctly marked as side effects which meant that, when importing from braid-design-system/themes/*
, the CSS order could differ between development and production.
useToast: Add deduplication of toasts (#662)
Passing key
when creating new toasts will now remove existing Toasts on screen with the same key
before adding the new Toast. This is useful when a toast is created as part of a repeatable process that happens frequently.
const showToast = useToast(); showToast({ message: 'There can only be one of me', tone: 'positive', key: 'deduped', });
Inline: Add support for semantic list elements (#654)
As already featured on Stack
, when rendering <Inline component="ul|ol">
, its children will be rendered as li
elements.
Hide icons from screen readers that have no title (#656)
Icons are mostly used for decorative purposes and as such are now hidden from screen readers unless providing a title
. In this case, an Icon is identified as an image.
Alert, Notice: Support rich content (#647)
BREAKING CHANGE
Since Alert
and Notice
no longer render a Text
component for you, you'll need to ensure that you're providing an enclosing Text
element as a direct child.
Alert:
<Alert tone="positive"> - Success! + <Text>Success!</Text> </Alert>
Notice:
<Notice tone="positive"> - Success! + <Text>Success!</Text> </Notice>
WHY?
The Alert and Notice components were originally designed to render a single paragraph of text, but in practice we've found that there's a lot of demand for richer content, e.g. multiple paragraphs, bullet lists, etc.
In order to support this level of flexibility, Alert
and Notice
no longer render an enclosing Text
component for you. While this means you'll need a bit more boilerplate in simple cases, it also means you now have much more fine-grained control over the layout.
For example, if you wanted to render an Alert
using both Text
and BulletList
with "medium"
space between them:
<Alert tone="positive"> <Stack space="medium"> <Text>The quick brown fox jumps over the lazy dog.</Text> <BulletList space="small"> <Bullet>Bullet 1</Bullet> <Bullet>Bullet 2</Bullet> </BulletList> </Stack> </Alert>
This same pattern applies to Notice
:
<Notice tone="positive"> <Stack space="medium"> <Text>The quick brown fox jumps over the lazy dog.</Text> <BulletList space="small"> <Bullet>Bullet 1</Bullet> <Bullet>Bullet 2</Bullet> </BulletList> </Stack> </Notice>
MonthPicker: Fix internal <Hidden screen>
deprecation warning (#650)
The MonthPicker
component was mistakenly using <Hidden screen>
to provide labels to screen readers rather than the new HiddenVisually
component. As a result, deprecation warnings were being logged in the console during development.
Please ensure you are on sku v10.3.0 or higher so that these assertions are removed in production. This ensures that these checks don't have a negative performance impact on users.
The main driver for this change is to ensure that runtime design validation occurs within the Braid Playroom.
Playroom is built in production mode to maximise performance, but this means that our custom development-time validation code isn't being executed. As a result, it's becoming increasingly common for prototypes to contain invalid code that only throws an error when transposed into a proper development environment. This change ensures that invalid designs are caught as early as possible.
Improve field border contrast ratio (#638)
To improve accessibility, field borders have been darkened for the following themes:
seekAnz
seekBusiness
seekUnifiedBeta
catho
(based on referencing Quantum)Since this is a noticeable visual change that may introduce inconsistincies with custom design elements, design review is recommended.
Toggle: Hide border on dark backgrounds (#638)
In order to reduce visual noise, similar to other fields, we now hide the border on Toggle
elements when rendered on dark backgrounds.
Dropdown: Lighten chevron when disabled (#638)
The visual prominence of the chevron icon is now lower when disabled
is set to true
.
Autosuggest: Apply darker background when disabled (#638)
When disabled, Autosuggest
elements didn't have the same dark background as other disabled fields. This has now been fixed.
Add HiddenVisually
component (#643)
You can now easily provide content to assistive technologies while hiding it from the screen.
<Text> This content is available to everyone. <HiddenVisually> This content is only available to screen readers. </HiddenVisually> </Text>
Hidden: Infer inline
prop when nested inside Text or Heading (#643)
Currently, if you want to hide content using the Hidden
component in an inline context (e.g. hiding part of a sentence), you need to remember to set the inline
boolean prop.
Since most usages of this feature are within text, we now infer this for you automatically within the context of a Text
or Heading
component.
MIGRATION GUIDE
This change is not strictly required, but you can now clean up your code like this:
-<Text>The end of this sentence is... <Hidden inline below="tablet">hidden on mobile.</Hidden> +<Text>The end of this sentence is... <Hidden below="tablet">hidden on mobile.</Hidden>
MonthPicker: Preserve touchable height on iOS (#641)
Fix for the native variant of MonthPicker
having a reduced height on iOS when no value is provided.
Stack: Add support for Hidden stack items (#632)
You can now responsively hide stack items using the Hidden
component while maintaining the correct spacing between all visible elements.
For example, if you wanted to hide a stack item on mobile:
<Stack space="small"> <Text>...</Text> <Hidden below="tablet"> <Text>...</Text> </Hidden> <Text>...</Text> </Stack>
seekAnz, seekBusiness, seekUnifiedBeta: Change critical colour to red (#634)
As part of the colour uplift work, this updates the critical
colour in the seekAnz
(and subsequently seekBusiness
and seekUnifiedBeta
) theme from pink to red. This brings the theme into line with our colour usage guide documented under Tones on the website.
BREAKING CHANGE
While not technically a breaking change, you may want to review usage of the critical
tone in your application, particularly in custom scenarios, for example:
background
props on Box
<Box background="critical">...</Box>
or
<Box background="criticalLight">...</Box>
tone
props on Icon
or Text
<Icon tone="critical">...</Icon>
or
<Text tone="critical">...</Text>
Stack, Inline, Tiles: Flatten fragments when provided as direct children (#626)
The following patterns should now work as you might have previously expected:
<Stack space="small"> <React.Fragment> <Text>...</Text> <Text>...</Text> </React.Fragment> <Text>...</Text> </Stack>
<Inline space="small"> <React.Fragment> <Badge>...</Badge> <Badge>...</Badge> </React.Fragment> <Badge>...</Badge> </Inline>
<Tiles space="small" columns={3}> <React.Fragment> <Card>...</Card> <Card>...</Card> </React.Fragment> <Card>...</Card> </Tiles>
BREAKING CHANGE
While highly unlikely, if you were using a fragment to group unspaced sibling nodes within a Stack
, Inline
or Tiles
element, you'll need to replace it with a Box
, for example:
<Stack space="small"> ... - <React.Fragment> + <Box> <Box>...</Box> <Box>...</Box> - <React.Fragment> + </Box> ... </Stack>
<Inline space="small"> ... - <React.Fragment> + <Box> <Box>...</Box> <Box>...</Box> - <React.Fragment> + </Box> ... </Inline>
<Tiles space="small" columns={3}> ... - <React.Fragment> + <Box> <Box>...</Box> <Box>...</Box> - <React.Fragment> + </Box> ... </Tiles>
TextField, Autosuggest, PasswordField: Improved support for field buttons with browser extensions. (#625)
The implementation of internal spacing within fields has been adjusted to better support browser extensions for password managers.
Affects the following components:
Textarea: Fix border radius on dark backgrounds (#625)
When rendering a Textarea
on a background other than white, the field background extended out beyond the field's border radius.
TextField, Autosuggest, PasswordField: Prevent field buttons firing on right click (#625)
Field buttons, such as clear and password visibility toggle, fire on mouse down to ensure focus is retained on the relevant field. We now ensure that the button only recognises left mouse button clicks.
Affects the following components:
Autosuggest: Support suggestion descriptions (#613)
You can now provide a description
as part of each suggestion item, e.g.:
<Autosuggest suggestions={[ { text: 'Apples', value: 123, description: 'Juicy and delicious', }, ]} {...rest} />
AccordionItem: Support onToggle
prop without expanded
to allow tracking in uncontrolled mode (#605)
For example:
<AccordionItem id="id" label="Label" onToggle={(expanded) => trackSomething(expanded)} > ... </AccordionItem>
automaticSelection
prop, we now prevent automatic selection from ocurring if the input value hasn't changed since focusing the field (#601)Inline: Add collapseBelow
and reverse
props. (#593)
Similar to Columns, you can now responsively collapse an Inline
into a vertical stack on mobile with the collapseBelow
prop.
For example, if you want items to stack vertically below tablet:
<Inline space="small" collapseBelow="tablet"> ... </Inline>
Also similar to Columns
, you can now reverse the order of items horizontally. This is particularly useful when combined with align="right"
.
For example, if you're rendering buttons and you want your primary action on the right on desktop, but at the top on mobile:
<Inline space="small" collapseBelow="tablet" align="right" reverse> <Button>Primary action</Button> <Button weight="weak">Secondary action</Button> </Inline>
Columns: Add align
prop (#593)
When collapsing columns into a vertical stack on smaller screens, you can now control the alignment.
For example, if you want your columns to be horizontally centred on mobile:
<Columns space="small" collapseBelow="tablet" align="center"> <Column>...<Column> <Column>...<Column> <Column>...<Column> </Columns>
As a side effect, this also means that you can control the alignment of columns when the total width doesn't reach 100%.
For example:
<Columns space="small" align="center"> <Column width="1/3">...<Column> <Column width="1/3">...<Column> </Columns>
Add TextDropdown component (#594)
An inline dropdown that can be used as part of a sentence or as an
alternative to Dropdown
, outside of a more structured form.
Inherits its styling from the parent typographic component, and as such
must be used nested within either a Text
or Heading
component.
Example usage:
const [jobTitle, setJobTitle] = useState('Developer'); <Text> <TextDropdown id="jobTitle" label="Job Title" value={jobTitle} onChange={setJobTitle} options={['Developer', 'Designer', 'Product Manager']} /> </Text>;
Theme: Introduce the Catho theme (#550)
Adds support to build product for the Catho market. This theme is an adaption of the Quantum Design System.
Add Accordion
and AccordionItem
components (#587)
Example usage:
<Accordion> <AccordionItem id="item_1" label="Accordion item 1"> <Text>Accordion item content</Text> </AccordionItem> <AccordionItem id="item_2" label="Accordion item 2"> <Text>Accordion item content</Text> </AccordionItem> <AccordionItem id="item_3" label="Accordion item 3"> <Text>Accordion item content</Text> </AccordionItem> </Accordion>
Accordions manage their own state internally by default. If you'd like to take control of them yourself, you can pass an expanded
prop to AccordionItem
as well as an onToggle
callback.
const [expanded, setExpanded] = useState(false); <AccordionItem id="id" label="Accordion item" expanded={expanded} onToggle={setExpanded} > <Text>Accordion item content</Text> </AccordionItem>;
Box: Add support for outline="none"
(#587)
Drop lodash usage to decrease bundle size. (#585)
This directly affects MonthPicker
and any components using the data
prop:
Add ButtonLink component (#581)
You can now easily render semantic links that look like Button elements without needing to use the lower level ButtonRenderer.
This component renders a native a
element by default, but this can be customised via the linkComponent
prop on BraidProvider.
Example usage:
<ButtonLink href="#" weight="strong"> Submit </ButtonLink>
BraidProvider: Add linkComponent
prop to customise link rendering. (#574)
If you'd like to customise the technical implementation of all Link
and TextLink
components from Braid, you can now pass a custom component to the linkComponent
prop on BraidProvider
. For example, if you wanted to ensure that all relative links are React Router links:
import React from 'react'; import { Link as ReactRouterLink } from 'react-router-dom'; import { BraidProvider, LinkComponent } from 'braid-design-system'; import wireframe from 'braid-design-system/themes/wireframe'; // First create the custom link implementation: const CustomLink: LinkComponent = ({ href, ...restProps }) => href[0] === '/' ? ( <ReactRouterLink to={href} {...restProps} /> ) : ( <a href={href} {...restProps} /> ); // Then pass it to BraidProvider: export const App = () => ( <BraidProvider theme={wireframe} linkComponent={CustomLink}> ... </BraidProvider> );
In order to make your custom link component available for any type of link (not just usages of TextLink
), this release introduces a new Link
component which renders an unstyled a
tag by default.
BREAKING CHANGES
TextLink
now requires an href
prop. Even though this is unlikely to affect anyone (a TextLink
without an href
isn't terribly useful), this is still technically a breaking change.
However, if you find an instance of TextLink
that you think shouldn't have an href
, this is a sign that it's not actually a link and you should use a TextLinkRenderer
instead. Unfortunately, because there's no way for us to know the semantics of your usage ahead of time, we're unable to provide a migration guide, so you'll need to be mindful of how this might impact accessibility.
The props for TextLink
now extend React's AnchorHTMLAttributes<HTMLAnchorElement>
type rather than AllHTMLAttributes<HTMLAnchorElement>
. While highly unlikely, this may cause type errors if you've passed props to TextLink
that aren't considered to be valid anchor props.
Themes: Fix OCC theme export (#576)
The braid-design-system/themes/occ
theme export is now exposed correctly.
Divider: Add strong weight variant, e.g. <Divider weight="strong">
. (#569)
Note that this also affects the dividers
prop on both Stack
and Tiles
, e.g. <Stack space="medium" dividers="strong">
. You can still pass a boolean prop if you want to render the default divider styling, e.g. <Stack space="medium" dividers>
, so this change is backwards compatible.
Theme: Introduce the OCC theme (#547)
Adds support to build product for the OCC market. This theme is an adaption of the Atomic Design System.
Inline: Support vertical alignment (#562)
Inline
Vertical alignment is now supported via the alignY
prop, e.g. <Inline space="small" alignY="center">
.
This also supports responsive values, e.g. <Inline space="small" alignY={['center', 'top']}>
Box: Add userSelect="none"
. (#556)
Box
You can now set userSelect
to "none"
directly on Box
.
Since the default value of user-select
in CSS is "auto"
, you can make this value dynamic by conditionally setting it to undefined
, e.g. <Box userSelect={selectable ? undefined : 'none'}
.
Textarea: Fix trailing new line highlight issue (#555)
BUG FIXES
Textarea
Fix for highlightRanges
, where the highlights could get out of sync with the field value, if the value contained trailing new lines.
Checkbox & Radio: Only add aria-describedby when a message is provided (#542)
BUG FIXES
Checkbox
& Radio
Both of these inputs were previously always adding the aria-describedby
attribute, while conditionally rendering the message
only when provided. This meant that elements without a message
would be indicating that they are described by an element that does not exist.
Tiles: Honour column width for non-breaking content. (#537)
BUG FIXES
Tiles
The column width of a tile was not being honoured when its child elements contained non-wrapping/breaking content.
MenuRenderer: Add support for configuring the menu offset from the trigger (#532)
FEATURES
MenuRenderer
Configure the offset distance between the menu trigger and menu using the offsetSpace
prop. As with all space values in the system, this accepts a responsive prop.
<MenuRenderer + offsetSpace="small" trigger={(triggerProps, { open }) => ( <button {...triggerProps}>Menu</button> )} > <MenuItem onClick={...}>Option</MenuItem> </MenuRenderer>
Add customisable MenuRenderer
component (#514)
BREAKING CHANGES
OverflowMenuItem
to MenuItem
.type="link"
from OverflowMenuItem
due to an accessibility issue with the approach (based on review of consumer usage, it did not seem to be used).FEATURES
MenuRenderer
Encapsulates all the behaviours of an accessible menu button, allowing consumers to define a custom trigger
to open the menu. The trigger function receives two arguments:
open
state.<MenuRenderer trigger={(triggerProps, { open }) => ( <button {...triggerProps}>Menu</button> )} > <MenuItem onClick={...}>Option</MenuItem> </MenuRenderer>
MIGRATION GUIDE
OverflowMenuItem
Rename OverflowMenuItem
to MenuItem
.
<OverflowMenu label="Overflow"> - <OverflowMenuItem onClick={...}>Option</OverflowMenuItem> + <MenuItem onClick={...}>Option</MenuItem> </OverflowMenu>
Changing the type
is no longer supported due to an accessibility issue with the previous implementation. Please get in contact via Slack if you depended on this.
<OverflowMenu label="Overflow"> - <OverflowMenuItem type="link" onClick={...}>Option</OverflowMenuItem> + <MenuItem onClick={...}>Option</MenuItem> </OverflowMenu>
Add BraidTestProvider component. (#529)
This is an alternative to BraidProvider
for unit test environments. Note that, as the name implies, this should not be used in production code.
MIGRATION GUIDE
In your unit tests, you can replace usage of BraidProvider
with BraidTestProvider
, omitting the theme.
-<BraidProvider theme={wireframe}> +<BraidTestProvider>
If for whatever reason your tests are relying on the presence of a specific theme, you can pass the name of the desired theme.
-<BraidProvider theme={seekAnz}> +<BraidTestProvider themeName="seekAnz">
Only show focus rings on buttons for keyboard navigation. (#526)
This impacts the following components:
Button
ButtonRenderer
OverflowMenu
Browsers automatically show focus rings on buttons when clicking on them, even though (for our purposes, at least) they're undesirable from a visual design perspective and redudant from a UX perspective.
We now automatically hide these focus rings if the user has moved their mouse, indicating that they're not navigating via the keyboard. However, to maintain keyboard accessibility, we reinstate these focus rings whenever the keyboard is used. Most typically, this ensures that you'll see focus rings when tabbing around the UI, even if you've previously used the mouse.
MIGRATION GUIDE
No public APIs are affected by this, but you may find that this causes unit test failues that look like this:
Warning: An update to X inside a test was not wrapped in act(...).
If this is the case, you should replace BraidProvider
in your tests with BraidTestProvider
.
-<BraidProvider theme={wireframe}> +<BraidTestProvider>
33139c8: Clone seekAnz theme to seekUnifiedBeta
BREAKING CHANGE
jobsDbRebrand
theme has been removed