alouette
Version:
A modern, customizable design system built on top of NativeWind v5 with configurable defaults
126 lines (101 loc) • 3.9 kB
Markdown
# alouette 24
Breaking changes of 24.0.0, then what changed within 24.x without breaking.
## To 24.0.0
### FormItem: `render` takes an object, and the input shows the error
`FormItem`'s `render` prop received the label id as a string. It now receives
`FormItemRenderParams`, `{ labelId, describedBy, invalid, required }`, so the
input can carry the state the label and the message around it already show.
`FormField`'s `render` params gain the same fields beside `field` and `labelId`.
Wire all four onto the input. `InputText`, `TextArea`, `Select` and
`InputTextAutocomplete` take `invalid` (the danger border, through the
`interactive-outlined-*` tokens, plus `aria-invalid`), `aria-describedby` and
`aria-required`:
```tsx
// Before
<FormItem
label="Email"
render={(labelId) => <InputText aria-labelledby={labelId} />}
/>
// After
<FormItem
label="Email"
render={({ labelId, describedBy, invalid, required }) => (
<InputText
aria-labelledby={labelId}
aria-describedby={describedBy}
aria-required={required}
invalid={invalid}
/>
)}
/>
```
A `FormField` input adds the same three props next to `ref={field.ref}` and
`aria-labelledby={labelId}`. `describedBy` holds the ids of `details` and
`error`, whichever are rendered, and is `undefined` without either. The three
ARIA attributes are web only in effect: React Native has no equivalent and
ignores them.
### alouette-icons: one module per glyph
`alouette-icons` 12.0.0 has one module per Phosphor glyph instead of one per
weight. Each glyph module exports the regular, duotone and fill weights. The
export names are unchanged; only the import path changes. Upgrade `alouette-icons`
together with `alouette`.
```tsx
// Before
import { HouseDuotoneIcon } from "alouette-icons/phosphor-icons/HouseDuotoneIcon";
import { HouseRegularIcon } from "alouette-icons/phosphor-icons/HouseRegularIcon";
// After
import {
HouseDuotoneIcon,
HouseRegularIcon,
} from "alouette-icons/phosphor-icons/House";
```
Rewrite the paths from the app root:
```sh
perl -pi -e 's#(alouette-icons/phosphor-icons/)(\w+?)(?:Regular|Duotone|Fill)Icon"#$1$2"#g' $(git grep -l alouette-icons/phosphor-icons)
```
This leaves one import per weight from the same module. Merge them with
`eslint --fix` and the `import-x/no-duplicates` rule (or `import/no-duplicates`),
then run your formatter.
A bundler that tree-shakes keeps only the weights you import. Metro keeps the
whole glyph module, which is three small components.
The fill weight (`HouseFillIcon`), previously generated for `Star` only, now
exists for every glyph.
## Within 24.x — recommended: DecisionBar for action rows
Not breaking: `Modal`'s `footer` still takes any content. A row of buttons
ending a decision — a `Modal` footer, an inline form's Cancel and Save — moves
to `DecisionBar`, which owns its alignment and order (dismiss, `alternative`,
`primary`) instead of each call site picking its own. The dismiss action is
rendered by the bar, as the neutral `soft` button.
```tsx
// Before
<View className="flex-row gap-xs">
<ActionButton text="Save" onPress={save} errorToMessage={toMessage} />
<Button accent="neutral" variant="soft" text="Cancel" onPress={close} />
</View>
<Modal
footer={
<>
<Button accent="neutral" variant="soft" text="Discard" onPress={discard} />
<Button text="Save" onPress={save} />
</>
}
/>
// After
<DecisionBar
dismissText="Cancel"
onDismiss={close}
primary={<ActionButton text="Save" onPress={save} errorToMessage={toMessage} />}
/>
<Modal
footer={
<DecisionBar
dismissText="Discard"
onDismiss={discard}
primary={<Button text="Save" onPress={save} />}
/>
}
/>
```
A second way to commit ("Save draft" beside "Publish") is `alternative`; a
Cancel carrying the weight (neutral `filled`, beside a `soft` primary) is
`emphasis="dismiss"`.