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.
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.
<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)
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?
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