Skip to main content

Group

Overview​

The Group component lays its children out in a row that wraps, centered on each other, with half of Bulma's block spacing between them.

Reach for it for a row of buttons, tags or avatars beside some text, or a toolbar with its two ends pushed apart. The row wraps when it runs out of room, so it doesn't scroll sideways on a narrow screen, and the children are centered on each other, so a large button and a line of text line up. Their own block margins are zeroed, so a Title or a Field in the row sits on the same line as a button. The default gap is half of Bulma's block spacing, the space Bulma's Level puts between its items.

For a column, use Stack. For buttons joined into one control, with no gap and shared borders, use hasAddons on Buttons or Field instead: that's what Chakra UI and Ant Design call a group.

info

Bulma has no group, so Group brings its own styles, in bestax.css and its variants, or in extras.css next to your own Bulma. The layout is in those styles, so it holds in bestax-no-helpers.css too, where the gap, alignItems, justifyContent and flexWrap props have no helper class to add and the defaults stay.


Import​

import { Group } from '@allxsmith/bestax-bulma';

Usage​

Basic Usage​

Buttons and a line of text in a row, centered on each other.

<Group>
  <Button color="primary">Save</Button>
  <Button>Cancel</Button>
  <Span textColor="grey">Last saved a minute ago</Span>
</Group>

Toolbar​

justifyContent="space-between" pushes the two ends apart, with a Group of actions at one end.

<Group justifyContent="space-between">
  <Title as="h2" size="4">
    Invoices
  </Title>
  <Group gap="1">
    <Button>Export</Button>
    <Button color="primary">New invoice</Button>
  </Group>
</Group>

Wrapping​

The row wraps by default. Set flexWrap="nowrap" to keep it on one line. A gap step replaces the default spacing, which is --bulma-stack-horizontal-gap, half of Bulma's --bulma-block-spacing. Of the two variables below, that's the Group's; the other is Stack's.

<Group gap="1">
  {['React', 'TypeScript', 'Bulma', 'Sass', 'Vite', 'Storybook', 'Vitest'].map(
    name => (
      <Tag key={name} color="link">
        {name}
      </Tag>
    )
  )}
</Group>

Full Width​

isFullwidth gives every child an equal share of the row, as Bulma's is-fullwidth does for tabs.

<Group isFullwidth>
  <Button>Cancel</Button>
  <Button color="primary">Save</Button>
</Group>

Stacking on a Phone​

breakpoint stacks the children below that Bulma breakpoint and sets them in a row from it up: tablet, desktop or widescreen, the breakpoints Container takes. With isFullwidth as well, each child takes the column's full width while stacked. Make the window narrower to see it.

<Group breakpoint="tablet" isFullwidth>
  <Button>Cancel</Button>
  <Button color="primary">Save</Button>
</Group>

The order never changes: stacked, the first child is on top, so the reading order is the same at every width.

As a List​

A row of tags is often a list. With as="ul", give it li children, and it restates role="list", which Safari drops once Bulma's reset hides the markers.

<Group as="ul" gap="1" aria-label="Topics">
  <li>
    <Tag>React</Tag>
  </li>
  <li>
    <Tag>Bulma</Tag>
  </li>
</Group>


Accessibility​

  • No role of its own: a Group adds nothing to the accessibility tree, apart from role="list" on a ul or ol, which Safari otherwise drops once Bulma's reset hides the markers.
  • Order: it's a row in the children's own order, or a column below its breakpoint in the same order, so what's seen, the reading order and the Tab order agree at every width. Right to left, the row runs right to left.
  • Reflow: it wraps by default, so a row of controls doesn't make the page scroll sideways at a width of 320 CSS pixels (WCAG 1.4.10).
  • Grouping controls: a Group of buttons isn't announced as a group. When the buttons belong together and need a name, give it role="group" and an aria-label, or render it as="fieldset" with one.

  • Stack: A column of children.
  • Buttons: Bulma's row of buttons, and with hasAddons, buttons joined into one control.
  • Level: Bulma's bar with items pushed to its two ends, stacked on a phone.
  • Flex: A flex container with CSS's own defaults and every flex property as a prop.
  • Helper Props: Bulma helper props for spacing, color, etc.

Additional Resources​


Props​

PropTypeDefaultDescription
asLayoutElement'div'The element to render. With ul or ol, give it li children: it restates role="list", which Bulma's list reset takes away in Safari.
gapBulmaGapStep—Space between children, a step of Bulma's gap scale. Unset, it's --bulma-stack-horizontal-gap, half of Bulma's block spacing. Needs Bulma's helper classes: under bestax-no-helpers.css the default stays.
alignItems(typeof validAlignItems)[number]'center'How each child sits across the row. While breakpoint stacks them, it's where each sits across the column. Needs Bulma's helper classes: under bestax-no-helpers.css the default stays.
justifyContent(typeof validJustifyContents)[number]—Where the children sit along the row: 'space-between' pushes the ends apart. Needs Bulma's helper classes: under bestax-no-helpers.css the default stays.
flexWrap(typeof validFlexWraps)[number]'wrap'Whether children move to a new row when they don't fit. Needs Bulma's helper classes: under bestax-no-helpers.css the default stays.
isFullwidthbooleanfalseThe children share the row equally, and fill the column while breakpoint stacks them (Bulma's is-fullwidth).
breakpoint'tablet' | 'desktop' | 'widescreen'—Stacks the children below this Bulma breakpoint and sets them in a row from it up, the breakpoints Container's breakpoint takes. Unset, a row at every width. It's the job Columns and Level do with booleans: 'tablet' is where they turn into a row by default, 'desktop' is Columns' isDesktop, and leaving it unset is their isMobile.
classNamestring—Additional CSS classes.
childrenReact.ReactNode—What it lays out. The top and bottom margins Bulma gives them are zeroed, so gap is the only space between them, and a spacing helper such as mt="2" still adds to it. A Columns child keeps its own top and side margins, and takes at the bottom the one Bulma gives the last Columns in a container, the column gap pulled back in (none when gapless), so its columns line up. A Pagination child keeps its negative margins too, so its links line up.
textColorBulma color | 'inherit' | 'current'—Text color helper.
bgColorBulma color | 'inherit' | 'current'—Background color helper.
refPolymorphicRef<LayoutElement>—Ref forwarded to the element as renders.
...Remaining props of the element selected by as and Bulma helper props—See Helper Props

Types:

  • BulmaGapStep: '0' | '0.5' | '1' | '1.5' | '2' | '2.5' | '3' | '3.5' | '4' | '4.5' | '5' | '5.5' | '6' | '6.5' | '7' | '7.5' | '8' | 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 4.5 | 5 | 5.5 | 6 | 6.5 | 7 | 7.5 | 8 — A gap step as gap, columnGap and rowGap take it: a value from validGaps, or the same step written as a number (gap={2}, gap={1.5}). Grid took its gaps as numbers before the gap helpers were shared, so every gap prop still does.
  • LayoutElement: 'div' | 'main' | 'section' | 'article' | 'aside' | 'header' | 'footer' | 'nav' | 'ul' | 'ol' | 'form' | 'fieldset' — The elements Stack, Group, Center and Flex can render as: Container's landmarks and sections, a list, a form or a fieldset.

CSS & Sass Variables​

Group registers these variables on its own .stack element. Override them there (or via className) — a value set on an ancestor is only inherited, and loses to the component-level declaration. See Theme.

CSS VariableSass VariableDefault
--bulma-stack-gap$stack-gapvar(--bulma-block-spacing)
--bulma-stack-horizontal-gap$stack-horizontal-gapcalc(var(--bulma-block-spacing) * 0.5)