Group

Arranges inline elements horizontally with consistent spacing and wrapping.

import { ... } from '@corndev/ui'

HTML

No JavaScript required — these classes are the whole component.

<div class="corn-group" data-gap="sm" data-align="center">
  <button class="corn-button">Cancel</button>
  <button class="corn-button" data-level="primary">Save</button>
</div>

Classes

Class
.corn-group

Attributes

AttributeValues
data-nowrappresent or absent
data-gapxs|sm|md|lg|xl
data-alignstart|center|end|baseline
data-justifystart|center|end|between|around
data-growpresent or absent

Vanilla JS

Optional. createGroup only adds and removes the classes and attributes above, so the HTML is equivalent. Reach for it when you need to change options at runtime.

import { createGroup } from '@corndev/ui';
import '@corndev/ui/theme';

const el = document.querySelector('#target');
const instance = createGroup(el, { /* options */ });

Options

OptionTypeDefaultDescription
gap'xs'|'sm'|'md'|'lg'|'xl''sm'
align'start'|'center'|'end'|'baseline''center'
justify'start'|'center'|'end'|'between'|'around''start'
wrapbooleantrue
growbooleanfalseEvery child takes an equal share of the row, whatever it contains. A child’s own flex always wins — the rule is 0-0-0, so even a single class like .no-grow { flex: none } keeps that child at its natural width. With wrap, a child that no longer fits moves to the next line and fills it; with wrap={false} the children shrink instead.

React

Group — from @corndev/ui-react.

The props are the same as the options above, plus className.

Default

<Group>
  <Button size="sm">Save</Button>
  <Button size="sm" level="ghost">Cancel</Button>
</Group>

Gap sizes

<Group gap="xs">...</Group>
<Group gap="sm">...</Group>
<Group gap="md">...</Group>
<Group gap="lg">...</Group>

Justify

<Group justify="start">...</Group>
<Group justify="center">...</Group>
<Group justify="between">...</Group>
<Group justify="end">...</Group>

No wrap

<Group wrap={false}>...</Group>

Sharing the row

grow gives every child an equal share of the row, whatever each one contains — a pair of buttons dividing the space, a label beside a field:

<Group grow>
  <Button emphasis="outline">Cancel</Button>
  <Button>Save</Button>
</Group>

justify cannot say this: it spreads the free space between children, it does not make the children themselves wider.

Keeping one child at its natural width

The rule behind grow has a specificity of 0-0-0 — it is written as :where(.corn-group[data-grow]) > * — so any rule of your own on a child wins, even a single class:

.no-grow { flex: none; }
<Group grow>
  <Input aria-label="Search" />
  <Button className="no-grow">Go</Button>
</Group>

Had it been written .corn-group[data-grow] > * it would weigh 0-2-0, and that one-class opt-out would lose without a word.

When the row is too narrow

With wrap (the default), a child that can no longer fit its content moves to the next line — and fills it, so a lone last item spans the full width. With wrap={false} the children shrink to share the row instead of wrapping.