Oct 15, 2024
  • Stack, Inline: Consumers need to render li elements

    When setting component to ul or ol on Stack or Inline, consumers need to ensure they render children as li elements. Previously Braid owned an intermediate HTML element, ensuring it was an li when required. Moving to CSS gap means child elements are no longer being wrapped, requiring consumers to update their child elements to the correct HTML element, e.g. li.

    MIGRATION GUIDE:

     <Stack component="ul">
    -  <Text>Item 1</Text>
    +  <Text component="li">Item 1</Text>
    -  <Text>Item 2</Text>
    +  <Text component="li">Item 2</Text>
     </Stack>
  • Stack, Tiles: Remove divider support

    As part of migrating our layout components to leverage flex gap, the Stack & Tiles components no longer iterate over their children, making dividers no longer feasible to implement centrally.

    While we could have exposed an API to apply this behaviour conditionally, there are edge cases that cannot be handled correctly without consumer-side rendering logic, such as when child components render nothing or a hidden element.

    MIGRATION GUIDE:

    For Stacks with static children you can manually interleave Divider components:

    -<Stack space="..." dividers>
    +<Stack space="...">
       <Component />
    +  <Divider />
       <Component />
    +  <Divider />
       <Component />
     </Stack>

    Or for conditionally rendering children you can return a [React Fragment], including the Divider and child:

    -<Stack space="..." dividers>
    +<Stack space="...">
       <Component />
       {condition ? (
    -    <Component />
    +    <>
    +      <Divider />
    +      <Component />
    +    </>
       ) : null}
     </Stack>

    For Stacks with iterable children you can return a [React Fragment] and conditionally render the Divider component as the first child, before each item (except the first):

    -<Stack space="..." dividers>
    +<Stack space="...">
      {items.map((item, index) => (
    -    <Component>{item}</Component>
    +    <Fragment key={...}>
    +      {index > 0 ? <Divider /> : null}
    +      <Component>{item}</Component>
    +    </Fragment>
      ))}
    </Stack>

    For Tiles the dividers prop was only applied when showing a single column.

    For this you can conditionally render the Divider in a Stack with the same spacing as specified on the Tiles instance, and hide it on breakpoints showing more than one column.

    Here is an example of this with static children:

    -<Tiles space="..." columns={{mobile: 1, tablet: 2}} dividers>
    +<Tiles space="..." columns={{mobile: 1, tablet: 2}}>
        <Component>{item}</Component>
    +   <Stack space="...">
    +     <Hidden above="mobile">
    +       <Divider />
    +     </Hidden>
          <Component>{item}</Component>
    +   </Stack>
    +   <Stack space="...">
    +     <Hidden above="mobile">
    +       <Divider />
    +     </Hidden>
          <Component>{item}</Component>
    +   </Stack>
    </Tiles>

    Here is an example of this with iterable children:

    -<Tiles space="..." columns={{mobile: 1, tablet: 2}} dividers>
    +<Tiles space="..." columns={{mobile: 1, tablet: 2}}>
      {items.map((item, index) => (
    -    <Component>{item}</Component>
    +    <Stack space="..." key={...}>
    +      {index > 0 ? (
    +        <Hidden above="mobile">
    +          <Divider />
    +        </Hidden>
    +      ) : null}
           <Component>{item}</Component>
    +    </Stack>
      ))}
    </Tiles>
  • Stack: Set default text alignment based on align

    As a convenience, the align prop sets the text alignment for the container, meaning any nested Text or Heading components will inherit this alignment by default.

    This can be overridden by setting the alignment explicitly on the relevant Text or Heading component.

  • Stack, Inline, Columns: Widen component support

    With Stack, Columns and Inline no longer adding intermediary elements, the component prop can now accept a wider range of elements. Valid options are kept to a white list of elements relevant to Stack that do not require other HTML attributes, keeping in mind that props are not blindly spread in Braid.

  • Migrate to CSS gap internally.

    With the browser support policy now enabling adoption of CSS gap, Braid’s layout components are now able to lean into the platform directly for its declarative, parent-driven approach to white space management.

    Previously to enable gap-like behaviour, layout components iterated over their children wrapping them in container elements that applied padding. The trade off of this technique was increased number of DOM elements and the introduction of unwanted space if the child element was hidden or returned null, requiring developers to hoist logic to the parent component.

Sep 16, 2024
  • Stack, Tiles: Deprecate dividers prop

    In preparation for migrating Braid layout components to use CSS gap, the dividers prop has been deprecated on Stack and Tiles.

    Consumers are encouraged to migrate now in advance of its removal in v33.

    Migration Guide

    See migration guide for details on how to migrate off the dividers prop.

Mar 31, 2023
  • Add xxxlarge to the space scale

    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;
Nov 9, 2022
  • Support data attribute boolean values

    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" />
Feb 14, 2022
  • Stack: Add support for span elements

    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>
Jul 8, 2021
  • Add wide breakpoint of 1200px

    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
      }
Jun 21, 2021
  • Support object notation for responsive props

    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' }
May 19, 2021
  • Add support for data attribute maps on all components.

    EXAMPLE USAGE:

    <Alert
      data={{
        testId: 'message'
      }}
    />
    
    // => <div data-testId="message" />
May 14, 2020
  • Stack: Add support for Hidden stack items

    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>
May 11, 2020
  • Stack, Inline, Tiles: Flatten fragments when provided as direct children

    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>