Releases

Patch Changes

  • Fix bug where patch-package attempts to run for consumers when installing (#975)

Patch Changes

  • 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.

Minor Changes

  • 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.

Minor Changes

  • Add wide breakpoint of 1200px (#960)

    This adds support for wide to the following touchpoints:

    • Responsive values, e.g.
      { mobile: 'small', wide: 'large' }
    • Responsive range props, e.g.
      <Columns collapseBelow="wide" space={{ mobile: 'small', wide: 'large' }}>
    • The responsiveStyle function, e.g.
      export const className = style(responsiveStyle({ wide: '...' }));
    • The 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.

Patch Changes

  • 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
    +});

Patch Changes

  • Ensure atoms are always lowest specificity (#955)

Patch Changes

Patch Changes

  • 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.

Major Changes

  • 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:

    • Chrome 49+
    • iOS 9.3+
    • Safari 9.1+
    • Microsoft Edge 16+
    • Firefox 31+
    • Samsung 5+
  • 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:

    • Mobile: 0px
    • Tablet: 740px
    • Desktop: 992px

    BREAKING CHANGE

    This is a change for the following themes:

    jobStreet, jobStreetClassic, jobsDb, occ, wireframe

    • Tablet: 768px740px

    catho

    • Tablet: 600px740px
    • Desktop: 1024px992px

    docs

    • Tablet: 768px740px
    • Desktop: 1136px992px
  • 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;

Minor Changes

  • 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,
    });

Patch Changes

  • Loader: Adjust size to better match text (#947)

  • Badge: Use correct text size for bleedY positioning (#947)

  • Box, Tag, Toggle: Make borderRadius="full" always circular (#947)

    Fixes circular border radius bug where non-square elements would result in an ellipse.

Patch Changes

  • MenuItem: Prevent click events from bubbling (#939)

  • Autosuggest: Fix missing/invalid group headings in some cases (#937)

Minor Changes

  • 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:

    • description
    • message
    • badge
    • children (nested content)

    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" />

Patch Changes

  • Sku dependencies update (#924)

Minor Changes

  • 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" />

Patch Changes

  • 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.

Minor Changes

  • 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>

Patch Changes

  • Update capsize dependency (#921)

Patch Changes

  • Textarea: Highlight excess characters when characterLimit is provided (#919)

Patch Changes

  • Fix type errors in TypeScript v4.2.2 (#915)

Patch Changes

  • TooltipRenderer: Support usage within Text elements (#912)

Minor Changes

  • 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>

Patch Changes

  • Badge: Ensure ref, title, tabIndex and aria-describedby props are applied to the visual badge element, not its container element (#908)

  • TooltipRenderer: Add arrow to tooltip (#908)

Patch Changes

  • TextLink, TextLinkButton, TextLinkRenderer: Scope deprecation warning to only be in Actions context. (#903)

Minor Changes

  • Box: Support value of default on cursor prop (#901)

    EXAMPLE USAGE

    <Box cursor="default">...</Box>
  • 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>

Minor Changes

  • 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>

Minor Changes

  • 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:

    Regular

    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>

    Strong

    Can be replicated with a variant of solid (default), with a tone of brandAccent.

    -<Button weight="strong">...</Button>
    +<Button tone="brandAccent">...</Button>

    Weak

    Can be replicated with a variant of ghost.

    -<Button weight="weak">...</Button>
    +<Button variant="ghost">...</Button>

Patch Changes

  • 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.

    TextLink

    <Actions>
      <Button>...</Button>
    - <TextLink href="...">...</TextLink>
    + <ButtonLink href="..." variant="transparent">...</ButtonLink>
    </Actions>

    TextLinkButton

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

Minor Changes

  • Tabs: Support fragments and null/undefined as children in Tabs and TabPanels (#889)

Patch Changes

  • Add space between page and navigation controls above mobile to improve affordance between the current page and the hover state of surrounding buttons. (#888)

Minor Changes

  • 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}`,
      })}
    />

Patch Changes

  • Update dependencies (#883)

Minor Changes

  • 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>

Patch Changes

  • Button, ButtonLink, ButtonRenderer: Reduce horizontal padding of standard size from gutter to medium (#879)

Minor Changes

  • 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>

Patch Changes

  • Autosuggest: Ensure input occupies the full width of its container (#872)

Minor Changes

  • Add IconMobile and IconDesktop icons. (#867)

  • TextField: Add prefix prop (#866)

    The prefix prop allows you to prepend read-only content on the left-hand side of the field. This is typically used for currency symbols, country codes, etc.

    EXAMPLE USAGE

    <TextField prefix="+61" {...rest} />

Patch Changes

  • 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.

Minor Changes

  • 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>

Patch Changes

  • OverflowMenu, MenuRenderer, MenuItemDivider: Remove horizontal padding (#855)

Minor Changes

  • 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)

Minor Changes

  • 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}
    />

Patch Changes

  • 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.

Patch Changes

  • Fix type definitions for Stack and scroll components (#841)

Patch Changes

  • Toggle: Fix layout issue when label text wraps to multiple lines (#838)

Minor Changes

  • 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}
    />;

Minor Changes

  • 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" />

Minor Changes

  • 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}
    />

Minor Changes

  • Autosuggest: Forward ref prop to input element (#819)

Patch Changes

  • 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.

Minor Changes

  • 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>

Minor Changes

  • 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>

Patch Changes

  • 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.

Patch Changes

  • Radio,Checkbox: Apply aria-describedby only when needed (#802)

    Only apply aria-describedby when needed, e.g. either a message or description is passed.

  • IconVisibility: Simplify visibility icon (#804)

Patch Changes

  • 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.

Minor Changes

  • 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} />

Minor Changes

  • 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>

Minor Changes

  • 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>
      }
    />

Patch Changes

  • Loader, Button, ButtonLink, ButtonRenderer: Improve performance of loading animations (#784)

    Adjust animations properties and values to reduce CPU recalculation overheads.

  • Toggle: Ensure there is a minimum amount of space between the label and the toggle when using justified alignment (#782)

Minor Changes

  • 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>

Patch Changes

  • Dialog: Fix close button to the corner of the dialog when scrolling (#775)

  • Autosuggest, Dialog: Lighten backdrop opacity from 0.7 to 0.4 (#775)

Minor Changes

  • 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"
    />

Patch Changes

  • TextField, PasswordField, Textarea, Autosuggest, Dropdown, MonthPicker: Add decription to aria-describedby (#766)

Minor Changes

  • HiddenVisually: Add support for passing IDs (#757)

    This is useful when mapping a HiddenVisually component to aria-describedby

    EXAMPLE USAGE:

    <HiddenVisually id="my-hidden-desciption">Hidden desciption</HiddenVisually>
  • Autosuggest: Add translations prop to enable internationalisation (#757)

Patch Changes

  • 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.

Patch Changes

  • MenuRenderer, OverflowMenu: Fix circular dependency issue (#761)

Minor Changes

  • 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" />

Patch Changes

  • Autosuggest: Update to ARIA 1.2 combobox spec (#754)

Minor Changes

  • Badge: Add bleedY prop (#743)

    You can now choose to allow the badge’s background colour to bleed out into the surrounding layout, making it easier to align with other elements.

    For example, we can align a badge to a Heading element using an Inline, even though the badge is actually taller than the heading. If we didn’t use the bleedY prop in this case, the badge would introduce unwanted space above and below the heading.

    <Inline alignY="center" space="xsmall">
      <Heading level="4">Heading</Heading>
      <Badge bleedY tone="positive">
        New
      </Badge>
    </Inline>
  • Add Dialog component (#746)

    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.

Patch Changes

  • 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 ContentBlocks inside of flex containers would not grow to their defined max-width.

Minor Changes

  • 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>

Patch Changes

  • 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.

Patch Changes

  • Loader: Fix rendering issues due to browser rounding errors (#728)

Minor Changes

  • 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>
  • Added support for refs on Link (#725)

    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.

Patch Changes

  • Change SEEK Business formAccent token to match Seek ANZ (#718)

Patch Changes

  • List, BulletList: Limit width to 100% of parent (#715)

Minor Changes

  • Add List component (#710)

    List serves as a replacement for the BulletList and Bullet components which adds the following improvements:

    • Support for numbers and alpha characters as bullets
    • Support for custom start positions in number/alpha lists
    • Rich content support, e.g. list items with multiple paragraphs, nested lists, etc.

    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>

Patch Changes

  • AccordionItem: Prevent Safari from clipping label text (#712)

Patch Changes

  • Throw meaningful error when using 'BraidProvider' in unit tests (#707)

Major Changes

  • Improved trimming of white space around text (#696)

    Migrated from our custom Basekick implementation to 🛶 Capsize to more accurately trim the white space around text. This will have subtle white space changes throughout the UI, but will largely just be improvements to the balance of space around text.

    BREAKING CHANGES

    Heading/Text: Removed LEGACY_SPACE

    The _LEGACY_SPACE_ prop was provided to support consumers migrating to v14 when the white space cropping and layout components were originally introduced. This has now been removed to allow us to further improve on our approach.

    Migrating off this prop will require consumers to perform the following steps:

    • Remove the usage of _LEGACY_SPACE_ on a component
    • Conduct a visual review of the impact (component will appear closer to neighbouring elements)
    • Use existing layout components, e.g. Stack, 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);

Patch Changes

  • Fix type error in Textarea formatRanges (#706)

Minor Changes

  • 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.

Minor Changes

  • 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>

Minor Changes

  • 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:

    • The body background has changed from #eeeeee to #f5f6f8.
    • All grey colours now have a hint of blue.
    • Buttons and form fields have decreased in height from 48px to 44px.
    • Border radiuses have increased from 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.

Patch Changes

  • Inline: Prevent overlapping of preceding interactive components (#692)

Minor Changes

  • 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.

Minor Changes

  • 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.
    • The onShowMore prop has been renamed to onToggle.
    • The spacing around the button has changed to follow Braid's layout guidelines. Design review is recommeded.
    -<ToggleContent onShowMore={(expanded) => { ... }} {...rest}>
    +<Disclosure onToggle={(expanded) => { ... }} {...rest}>
  • TextLinkButton: Add aria-controls, aria-describedby and aria-expanded props (#686)

Minor Changes

  • 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.

Minor Changes

  • Add IconLanguage (#680)

Minor Changes

  • 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:

    • The body background has changed from #eeeeee to #f5f6f8.
    • All grey colours now have a hint of blue.
    • Buttons and form fields have decreased in height from 48px to 44px.
    • Border radiuses have increased from 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.

    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">

Minor Changes

  • 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>

Minor Changes

  • MonthPicker: Support custom month and year labels (#672)

    To support internationalisation, you can now pass the following props to MonthPicker:

    • monthLabel (string)
    • yearLabel (string)
    • monthNames (string[])

Minor Changes

  • 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';

Minor Changes

  • Add Tabs component (#666)

    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>

Patch Changes

  • 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.

Patch Changes

  • 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.

Minor Changes

  • 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',
    });

Minor Changes

  • 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.

Patch Changes

  • 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.

Major Changes

  • Alert, Notice: Support rich content (#647)

    BREAKING CHANGE

    Since Alert and Notice no longer render a Text component for you, you'll need to ensure that you're providing an enclosing Text element as a direct child.

    Alert:

    <Alert tone="positive">
    -  Success!
    +  <Text>Success!</Text>
    </Alert>

    Notice:

    <Notice tone="positive">
    -  Success!
    +  <Text>Success!</Text>
    </Notice>
    
    

    WHY?

    The Alert and Notice components were originally designed to render a single paragraph of text, but in practice we've found that there's a lot of demand for richer content, e.g. multiple paragraphs, bullet lists, etc.

    In order to support this level of flexibility, Alert and Notice no longer render an enclosing Text component for you. While this means you'll need a bit more boilerplate in simple cases, it also means you now have much more fine-grained control over the layout.

    For example, if you wanted to render an Alert using both Text and BulletList with "medium" space between them:

    <Alert tone="positive">
      <Stack space="medium">
        <Text>The quick brown fox jumps over the lazy dog.</Text>
        <BulletList space="small">
          <Bullet>Bullet 1</Bullet>
          <Bullet>Bullet 2</Bullet>
        </BulletList>
      </Stack>
    </Alert>

    This same pattern applies to Notice:

    <Notice tone="positive">
      <Stack space="medium">
        <Text>The quick brown fox jumps over the lazy dog.</Text>
        <BulletList space="small">
          <Bullet>Bullet 1</Bullet>
          <Bullet>Bullet 2</Bullet>
        </BulletList>
      </Stack>
    </Notice>

Patch Changes

  • 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.

Patch Changes

  • Use assert for runtime assertions during development (#624)

    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.

Minor Changes

  • 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.

Patch Changes

  • 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.

Minor Changes

  • 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>

Patch Changes

  • 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>

Patch Changes

  • 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.

Minor Changes

  • 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>

Major Changes

  • 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:

    Usage of background props on Box

    <Box background="critical">...</Box>

    or

    <Box background="criticalLight">...</Box>

    Usage of tone props on Icon or Text

    <Icon tone="critical">...</Icon>

    or

    <Text tone="critical">...</Text>

Major Changes

  • 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>

Patch Changes

  • 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:

    • PasswordField: visibility toggle button
    • TextField: clear button
    • Autosuggest: clear button
  • 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:

    • PasswordField: visibility toggle button
    • TextField: clear button
    • Autosuggest: clear button

Minor Changes

  • Add zero opacity to Box (#621)

    Provide zero opacity on Box as an optimisation.

    Example usage:

    <Box opacity={0}>...</Box>
  • Add PasswordField component (#620)

    Provides a password field complete with visibility toggle to switch between a masked and unmasked field value.

Minor Changes

  • 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}
    />

Patch Changes

  • Autosuggest: Don't select suggestions onBlur when using automaticSelection and suggestions are closed (#609)

Minor Changes

  • 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>

Patch Changes

  • Autosuggest: When using the automaticSelection prop, we now prevent automatic selection from ocurring if the input value hasn't changed since focusing the field (#601)

Minor Changes

  • Text: Add data attribute support (#596)

  • Heading: Add data attribute support (#596)

Minor Changes

  • 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>;

Patch Changes

  • Hide native focus rings on Box elements during mouse interactions (#589)

Minor Changes

  • 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)

Patch Changes

  • Drop lodash usage to decrease bundle size. (#585)

    This directly affects MonthPicker and any components using the data prop:

    • All field components
    • OverflowMenu
    • MenuRenderer
    • Button

Minor Changes

  • 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>

Major Changes

  • 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.

Patch Changes

  • Themes: Fix OCC theme export (#576)

    The braid-design-system/themes/occ theme export is now exposed correctly.

Patch Changes

  • Divider: Rename 'standard' weight to 'regular'. (#572)

Minor Changes

  • 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.

Patch Changes

  • Update deprecated treat imports (#566)

Minor Changes

  • 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.

Minor Changes

  • 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'}.

Patch Changes

  • 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.

Patch Changes

  • 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.

Patch Changes

  • 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.

Minor Changes

  • 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>

Major Changes

  • Add customisable MenuRenderer component (#514)

    BREAKING CHANGES

    • Rename OverflowMenuItem to MenuItem.
    • Removed 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:

    • Props required for accessibility, including mouse/keyboard interactions
    • Menu state object containing the 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>

Minor Changes

  • 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>

Patch Changes

  • 273ed8a: seekUnifiedBeta: Decrease touchable height to 44px

Patch Changes

  • 9890660: Hide webkit native clear field on search type inputs

Patch Changes

  • eae3496: Fix release of v23.0.0

Major Changes

  • 33139c8: Clone seekAnz theme to seekUnifiedBeta

    BREAKING CHANGE

    • jobsDbRebrand theme has been removed