@uxelle/skills 0.2.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +58 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +586 -0
- package/index.json +573 -0
- package/package.json +57 -0
- package/skills/uxelle-components/Accordion.md +51 -0
- package/skills/uxelle-components/AccordionGroup.md +39 -0
- package/skills/uxelle-components/Banner.md +73 -0
- package/skills/uxelle-components/BannerAnnouncement.md +63 -0
- package/skills/uxelle-components/Breadcrumb.md +38 -0
- package/skills/uxelle-components/Breadcrumbs.md +32 -0
- package/skills/uxelle-components/Bubble.md +34 -0
- package/skills/uxelle-components/Button.md +54 -0
- package/skills/uxelle-components/ButtonGroup.md +43 -0
- package/skills/uxelle-components/Card.md +35 -0
- package/skills/uxelle-components/Checkbox.md +57 -0
- package/skills/uxelle-components/CheckboxGroup.md +47 -0
- package/skills/uxelle-components/ChoiceChip.md +44 -0
- package/skills/uxelle-components/ChoiceChipGroup.md +50 -0
- package/skills/uxelle-components/DatePicker.md +59 -0
- package/skills/uxelle-components/DatePickerRange.md +73 -0
- package/skills/uxelle-components/Dialog.md +83 -0
- package/skills/uxelle-components/Divider.md +37 -0
- package/skills/uxelle-components/DynamicAngleLine.md +36 -0
- package/skills/uxelle-components/DynamicAngleLineCombo.md +30 -0
- package/skills/uxelle-components/DynamicAngleShape.md +32 -0
- package/skills/uxelle-components/DynamicAngleShapeSurface.md +35 -0
- package/skills/uxelle-components/DynamicAngleTexture.md +29 -0
- package/skills/uxelle-components/DynamicAngleTextureText.md +35 -0
- package/skills/uxelle-components/FieldMessage.md +31 -0
- package/skills/uxelle-components/FileUpload.md +53 -0
- package/skills/uxelle-components/FilterChip.md +35 -0
- package/skills/uxelle-components/FilterChipGroup.md +42 -0
- package/skills/uxelle-components/Footer.md +34 -0
- package/skills/uxelle-components/Hero.md +61 -0
- package/skills/uxelle-components/Icon.md +43 -0
- package/skills/uxelle-components/IconButton.md +44 -0
- package/skills/uxelle-components/Image.md +40 -0
- package/skills/uxelle-components/Label.md +35 -0
- package/skills/uxelle-components/LabelBadge.md +58 -0
- package/skills/uxelle-components/LanguageSelector.md +38 -0
- package/skills/uxelle-components/LanguageSelectorButton.md +34 -0
- package/skills/uxelle-components/Layout.md +81 -0
- package/skills/uxelle-components/LinearProgress.md +53 -0
- package/skills/uxelle-components/Link.md +52 -0
- package/skills/uxelle-components/List.md +35 -0
- package/skills/uxelle-components/ListControls.md +100 -0
- package/skills/uxelle-components/ListItem.md +69 -0
- package/skills/uxelle-components/Lockup.md +50 -0
- package/skills/uxelle-components/Logo.md +39 -0
- package/skills/uxelle-components/Menu.md +48 -0
- package/skills/uxelle-components/MultiSelect.md +54 -0
- package/skills/uxelle-components/NavLink.md +44 -0
- package/skills/uxelle-components/Navigation.md +61 -0
- package/skills/uxelle-components/NavigationSide.md +51 -0
- package/skills/uxelle-components/NavigationSideGroup.md +36 -0
- package/skills/uxelle-components/NavigationSideItem.md +56 -0
- package/skills/uxelle-components/NavigationSideSubItem.md +39 -0
- package/skills/uxelle-components/NotificationBadge.md +62 -0
- package/skills/uxelle-components/Pagination.md +49 -0
- package/skills/uxelle-components/PaginationComplex.md +51 -0
- package/skills/uxelle-components/PaginationSimple.md +44 -0
- package/skills/uxelle-components/ProductCard.md +46 -0
- package/skills/uxelle-components/Quantity.md +45 -0
- package/skills/uxelle-components/Radio.md +55 -0
- package/skills/uxelle-components/RadioGroup.md +49 -0
- package/skills/uxelle-components/SKILL.md +242 -0
- package/skills/uxelle-components/Scrim.md +28 -0
- package/skills/uxelle-components/SegmentedControl.md +118 -0
- package/skills/uxelle-components/Select.md +55 -0
- package/skills/uxelle-components/Sheet.md +31 -0
- package/skills/uxelle-components/Skeleton.md +35 -0
- package/skills/uxelle-components/Spinner.md +33 -0
- package/skills/uxelle-components/StatTile.md +150 -0
- package/skills/uxelle-components/Stepper.md +73 -0
- package/skills/uxelle-components/Switch.md +41 -0
- package/skills/uxelle-components/Tab.md +41 -0
- package/skills/uxelle-components/Table.md +55 -0
- package/skills/uxelle-components/TabsCompact.md +37 -0
- package/skills/uxelle-components/TabsStretch.md +35 -0
- package/skills/uxelle-components/Text.md +56 -0
- package/skills/uxelle-components/Textarea.md +77 -0
- package/skills/uxelle-components/Textfield.md +62 -0
- package/skills/uxelle-components/Tooltip.md +33 -0
- package/skills/uxelle-design-harness/SKILL.md +149 -0
- package/skills/uxelle-design-harness/a2ui.md +73 -0
- package/skills/uxelle-design-harness/how-to-accessibility.md +31 -0
- package/skills/uxelle-design-harness/how-to-color.md +82 -0
- package/skills/uxelle-design-harness/how-to-host.md +108 -0
- package/skills/uxelle-design-harness/how-to-page-layout.md +203 -0
- package/skills/uxelle-design-harness/principles.md +72 -0
- package/skills/uxelle-design-harness/recipe-app-chrome.md +168 -0
- package/skills/uxelle-design-harness/recipe-card-grid.md +104 -0
- package/skills/uxelle-design-harness/recipe-cta-band.md +91 -0
- package/skills/uxelle-design-harness/recipe-dashboard-overview.md +118 -0
- package/skills/uxelle-design-harness/recipe-data-table-page.md +323 -0
- package/skills/uxelle-design-harness/recipe-feature-section.md +96 -0
- package/skills/uxelle-design-harness/recipe-footer.md +156 -0
- package/skills/uxelle-design-harness/recipe-form-section.md +163 -0
- package/skills/uxelle-design-harness/recipe-hero.md +89 -0
- package/skills/uxelle-design-harness/recipe-landing-page.md +94 -0
- package/skills/uxelle-design-harness/recipe-logo-wall.md +80 -0
- package/skills/uxelle-design-harness/recipe-multi-step-flow.md +108 -0
- package/skills/uxelle-design-harness/recipe-page-header.md +102 -0
- package/skills/uxelle-design-harness/recipe-page-shell.md +82 -0
- package/skills/uxelle-design-harness/recipe-pricing.md +83 -0
- package/skills/uxelle-design-harness/recipe-query-bar.md +108 -0
- package/skills/uxelle-design-harness/recipe-record-detail.md +96 -0
- package/skills/uxelle-design-harness/recipe-settings-page.md +170 -0
- package/skills/uxelle-design-harness/recipe-stat-callouts.md +111 -0
- package/skills/uxelle-design-harness/recipe-states.md +119 -0
- package/skills/uxelle-design-harness/recipe-summary-list.md +88 -0
- package/skills/uxelle-design-harness/recipe-template.md +62 -0
- package/skills/uxelle-design-harness/recipe-testimonial.md +73 -0
- package/skills/uxelle-design-harness/spacing-steps.md +57 -0
- package/skills/uxelle-design-harness/tokens.md +101 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Link
|
|
2
|
+
|
|
3
|
+
Import: `import { Link } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Standalone hyperlink for use outside navigation contexts.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| href (required) | `string` | `—` | Destination for the underlying `a` — absolute URL, root-relative path, `mailto:`, or `#fragment`. Triggers a full page navigation; for client-side routing, render your router's link with `className="uxl-link"` instead. |
|
|
14
|
+
| icon | `ReactNode` | `—` | Node rendered after the link text, typically an **Icon** such as `outbound` for external destinations. Its wrapper is `aria-hidden`, so keep the meaning in the link text rather than the icon. |
|
|
15
|
+
| children | `ReactNode` | `—` | Link text. A string or number is wrapped in `Text` `type="Link"`; pass a `Text` node or other custom content when needed. |
|
|
16
|
+
|
|
17
|
+
<!-- prettier-ignore-end -->
|
|
18
|
+
|
|
19
|
+
Extends `React.AnchorHTMLAttributes` — supports standard HTML attributes.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
// Link component with optional icon
|
|
25
|
+
<Link
|
|
26
|
+
href="#"
|
|
27
|
+
icon={<Icon iconName="outbound" variant="sharpUnfilled" aria-hidden />}
|
|
28
|
+
>
|
|
29
|
+
Documentation
|
|
30
|
+
</Link>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
// Bare anchor + Link text style
|
|
35
|
+
<a href="/docs" className="uxl-link">
|
|
36
|
+
<Text type="Link" inline>Documentation</Text>
|
|
37
|
+
</a>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
// Inline link inside body copy (styled via Text.css)
|
|
42
|
+
<Text type="Body Medium">
|
|
43
|
+
<>Email: <a href="mailto:hello@example.com">hello@example.com</a></>
|
|
44
|
+
</Text>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- String children render with `Text` `type="Link"`. Pass custom nodes when needed.
|
|
51
|
+
- **Accessibility**: Uses semantic <a> with proper href. Add rel="noopener noreferrer" for external links.
|
|
52
|
+
- **States**: Underline at rest; thicker underline on hover per design tokens.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# List
|
|
2
|
+
|
|
3
|
+
Import: `import { List } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Vertical stack of `ListItem` children, rendered as a semantic `ul` or `ol`.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| children | `ReactNode` | `—` | `ListItem` elements, each rendering its own `li` row. Any other node is rendered as-is, so wrap raw content in an `li` to keep the list valid. |
|
|
14
|
+
| ordered | `boolean` | `false` | Renders an `ol` instead of a `ul`, so the sequence is announced as ordered. Semantics only — markers stay hidden, so put any visible numbering in the `ListItem` content. |
|
|
15
|
+
| role | `AriaRole` | `—` | Overrides the ARIA role of the list element. Inside a **Menu** the list already falls back to `presentation` so the menu's own semantics apply; set this only to force a different role. |
|
|
16
|
+
|
|
17
|
+
<!-- prettier-ignore-end -->
|
|
18
|
+
|
|
19
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
<List>
|
|
25
|
+
<ListItem centerText="Item" />
|
|
26
|
+
<ListItem interactive centerText="Clickable item" />
|
|
27
|
+
</List>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Notes
|
|
32
|
+
|
|
33
|
+
- **Slot**: Accepts ListItem children (renders as li)
|
|
34
|
+
- **Layout**: Vertical stack
|
|
35
|
+
- **Semantic**: Uses ul/ol for list structure
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# ListControls
|
|
2
|
+
|
|
3
|
+
Import: `import { ListControls } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Settings or choice list: optional **Label**, **List** of interactive **ListItem** rows with an embedded Switch, Checkbox, or Radio in the trailing slot.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| children | `ReactNode` | `—` | Rows of the list — `ListItem` elements marked `interactive` with an `embedded` Switch, Checkbox, or Radio in their `trailing` slot. Activating a row toggles or selects that control. |
|
|
14
|
+
| label | `boolean` | `false` | When true and `labelText` is non-empty, renders a `Label` above the list and names the group with it. When false, name the group with `aria-label` or `aria-labelledby` instead. |
|
|
15
|
+
| labelText | `string` | `""` | Text shown in the visible `Label`. Rendered only when `label` is true and this is non-empty after trimming. |
|
|
16
|
+
| dense | `boolean` | `false` | Applies compact vertical padding to every nested `ListItem`. An individual row can still override it by setting its own `dense`. |
|
|
17
|
+
| controlType | `"switch" \| "checkbox" \| "radio"` | `"switch"` | Control rendered in each row and the selection model it uses: `switch` for independent toggles with no shared value, `checkbox` for multi-select where the value is a `string[]`, `radio` for exclusive single-select where the value is a `string`. The checkbox and radio modes also require `name`. |
|
|
18
|
+
| name (required) | `string` | `—` | Form field name applied to every nested **Checkbox** so the rows submit as one multi-valued field. |
|
|
19
|
+
| value | `readonly string[] \| string` | `—` | Selected option values for controlled use. Pass it with `onChange`; omit it to let the group track selection itself starting from `defaultValue`. |
|
|
20
|
+
| defaultValue | `readonly string[] \| string` | `[] as readonly string[]` | Initial selection for uncontrolled use, read once on mount. Later changes are ignored, so remount with a `key` or switch to controlled `value` to reset the group. |
|
|
21
|
+
| optionValues | `readonly string[]` | `—` | Native `value` for each embedded **Checkbox**, matched to children in **ListItem** order. Omit it to fall back to generated ids, which are not meaningful in submitted data or in `value` / `defaultValue`. |
|
|
22
|
+
| onChange | `(value: string[]) => void \| (value: string, event: ChangeEvent<HTMLInputElement>) => void` | `—` | Called with the complete next selection, not just the row that changed. |
|
|
23
|
+
| fieldMessage | `ReactNode` | `—` | Message rendered below the list. A string or number is wrapped in a **FieldMessage** styled by `fieldMessageType`; any other node renders as-is. |
|
|
24
|
+
| fieldMessageType | `"Info" \| "Danger" \| "Warning" \| "Success"` | `LIST_CONTROLS_DEFAULTS.fieldMessageType` | Tone for a string or number `fieldMessage` below the list (checkbox and radio only). `Danger` also exposes the message as `aria-errormessage` and announces changes politely, while the other tones expose it through `aria-describedby`. |
|
|
25
|
+
| required | `boolean` | `false` | Sets `aria-required` on the group so a selection is announced as mandatory (checkbox and radio only). It does not block form submission. |
|
|
26
|
+
| invalid | `boolean` | `false` | Sets `aria-invalid="true"` on the group unless `aria-invalid` is passed explicitly. Pair it with a `Danger` field message so the reason is visible. |
|
|
27
|
+
| disabled | `boolean` | `false` | Marks the group non-interactive with `aria-disabled` on the radiogroup and its options so they stay readable, and disables the hidden input so no value is submitted. Radio mode only. |
|
|
28
|
+
| "aria-label" | `string` | `""` | Accessible name for the group when no visible label is rendered. Prefer `label` with `labelText` whenever the name belongs on screen. |
|
|
29
|
+
| "aria-labelledby" | `string` | `""` | Space-separated ids of elements that name the group. Appended after the visible `Label` id when `label` is on. |
|
|
30
|
+
| "aria-describedby" | `string` | `""` | Space-separated ids of helper copy for the group. The field message region id is appended automatically for every tone except `Danger`. |
|
|
31
|
+
| "aria-errormessage" | `string` | `""` | Id of the element holding the error text, which defaults to the field message region when `fieldMessageType` is `Danger`. Assistive technology only exposes it while the group is also invalid. |
|
|
32
|
+
| "aria-invalid" | `boolean` | `false` | Explicit invalid state on the group, which takes precedence over `invalid`. Leave it unset to let `invalid` drive the state; a `Danger` field message on its own does not mark the group invalid. |
|
|
33
|
+
| "aria-required" | `boolean` | `false` | Explicit `aria-required` on the group, which takes precedence over `required`. Leave it unset to let `required` drive the value. |
|
|
34
|
+
|
|
35
|
+
<!-- prettier-ignore-end -->
|
|
36
|
+
|
|
37
|
+
## Usage
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
<ListControls controlType="switch" label labelText="Notification Type">
|
|
41
|
+
<ListItem
|
|
42
|
+
interactive
|
|
43
|
+
trailingSlot
|
|
44
|
+
trailing={<Switch embedded defaultChecked aria-label="Direct Messages" />}
|
|
45
|
+
centerText="Direct Messages"
|
|
46
|
+
bottomText="Instant push notifications for new direct messages."
|
|
47
|
+
/>
|
|
48
|
+
</ListControls>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
<ListControls
|
|
53
|
+
controlType="checkbox"
|
|
54
|
+
name="privacy"
|
|
55
|
+
label
|
|
56
|
+
labelText="Privacy Settings"
|
|
57
|
+
defaultValue={["public"]}
|
|
58
|
+
optionValues={["public", "activity"]}
|
|
59
|
+
>
|
|
60
|
+
<ListItem
|
|
61
|
+
interactive
|
|
62
|
+
trailingSlot
|
|
63
|
+
trailing={<Checkbox embedded inputProps={{ "aria-label": "Public Profile" }} />}
|
|
64
|
+
centerText="Public Profile"
|
|
65
|
+
bottomText="Allow others to find and view your profile"
|
|
66
|
+
/>
|
|
67
|
+
</ListControls>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
<ListControls
|
|
72
|
+
controlType="radio"
|
|
73
|
+
name="delivery"
|
|
74
|
+
label
|
|
75
|
+
labelText="Delivery Options"
|
|
76
|
+
defaultValue="standard"
|
|
77
|
+
optionValues={["standard", "express"]}
|
|
78
|
+
>
|
|
79
|
+
<ListItem
|
|
80
|
+
interactive
|
|
81
|
+
trailingSlot
|
|
82
|
+
trailing={<Radio embedded inputProps={{ "aria-label": "Standard" }} />}
|
|
83
|
+
centerText="Standard"
|
|
84
|
+
bottomText="Get in a week"
|
|
85
|
+
/>
|
|
86
|
+
</ListControls>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
## Notes
|
|
91
|
+
|
|
92
|
+
- **`controlType`** selects the row control and selection model:
|
|
93
|
+
- **`switch`** — independent immediate toggles (no shared value).
|
|
94
|
+
- **`checkbox`** — multi-select (**`value`** as **`string[]`**), same model as **CheckboxGroup**.
|
|
95
|
+
- **`radio`** — exclusive single-select, same model as **RadioGroup**.
|
|
96
|
+
- Compose **ListItem** with **`interactive`** and an **`embedded`** control in **`trailing`**. Row activation toggles or selects that control. Use **`centerText`** / **`bottomText`** for the title and optional supporting copy. Set **`dense`** for compact row padding (rows inherit unless they set **`dense`** themselves).
|
|
97
|
+
- **Accessibility (WCAG 2.x AA baseline)**
|
|
98
|
+
- **Group** — Visible **Label** or **`aria-label`** / **`aria-labelledby`**. Radio uses **`role="radiogroup"`**; switch/checkbox use **`role="group"`**. **`aria-describedby`**, **`aria-required`**, **`aria-invalid`**, and **`aria-errormessage`** wire helper/error copy where applicable.
|
|
99
|
+
- **Rows** — Each interactive **ListItem** owns focus and activates its embedded control. Prefer naming the option from the row title (**`aria-label`** / **`aria-labelledby`**).
|
|
100
|
+
- **Keyboard** — **Tab** visits each row; **Space** / **Enter** activate; radio rows also use **Arrow** keys to move selection.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# ListItem
|
|
2
|
+
|
|
3
|
+
Import: `import { ListItem } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Row for **List** with leading, center content, and trailing regions.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| children | `ReactNode` | `—` | Legacy fallback used as the center line when `centerText` is omitted. Prefer `topText` / `centerText` / `bottomText`, which apply the right `Text` type per line. |
|
|
14
|
+
| leading | `ReactNode` | `—` | Node rendered in the leading region at the start of the row, typically an `Icon` or avatar. Needs `leadingSlot`; without it the region falls back to an `Icon` built from `leadingIconName` and `leadingIconVariant`. |
|
|
15
|
+
| trailing | `ReactNode` | `—` | Node rendered in the trailing region at the end of the row — an `Icon`, a badge, or an embedded `Switch` / `Checkbox` / `Radio`. Needs `trailingSlot`; without it the region falls back to an `Icon` built from `trailingIconName` and `trailingIconVariant`. |
|
|
16
|
+
| topContentSlot | `ReactNode` | `—` | Node rendered above the text stack inside the center region, typically a `LabelBadge` or chip. Needs `topSlot`; nothing renders unless both are set. |
|
|
17
|
+
| leadingSlot | `boolean` | `false` | Renders the leading region at the start of the row. Ignored while `reserved` is on, which claims that space for the activation check icon instead. |
|
|
18
|
+
| trailingSlot | `boolean` | `false` | Renders the trailing region at the end of the row, holding `trailing` or the default `trailingIconName` icon. |
|
|
19
|
+
| topSlot | `boolean` | `false` | Renders `topContentSlot` above the text stack. Both this and `topContentSlot` are required for anything to appear. |
|
|
20
|
+
| topText | `ReactNode` | `""` | Eyebrow line above `centerText`, for category or status copy. Strings are wrapped in a Text node with the Overline type; omit or pass an empty string to hide it. |
|
|
21
|
+
| centerText | `ReactNode` | `"List Item"` | Primary line of the row. Strings are wrapped in a Text node with the Body Small Alt type; an empty string hides the line, and omitting it falls back to `children`. |
|
|
22
|
+
| bottomText | `ReactNode` | `"List Item"` | Supporting line below `centerText`, for secondary detail. Strings are wrapped in a Text node with the Condensed type; omit or pass an empty string to hide it. |
|
|
23
|
+
| divider | `boolean` | `false` | Draws a low-emphasis hairline pinned to the bottom edge of the row, separating it from the next one. Set it per row rather than on the list. |
|
|
24
|
+
| interactive | `boolean` | `false` | Makes the row activatable: it renders as a `<button>`, or an `<a>` when `href` is set, and gains hover and pressed styling. Inside ListControls the row stays an `<li>` that owns focus and toggles the embedded control. |
|
|
25
|
+
| href | `string` | `undefined` | Destination for a navigational row. With `interactive`, the row renders as an `<a>` inside the `<li>` and `activated` adds `aria-current="page"`; inside a Menu it also takes `role="menuitem"`. |
|
|
26
|
+
| leadingIconName | `string` | `"outbound"` | Material Symbol drawn in the leading region when `leading` is not supplied. Only reaches the DOM while `leadingSlot` is on and `reserved` is off. |
|
|
27
|
+
| trailingIconName | `string` | `"outbound"` | Material Symbol drawn in the trailing region when `trailing` is not supplied. Only reaches the DOM while `trailingSlot` is on. |
|
|
28
|
+
| leadingIconVariant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Fill style for the default leading icon: `sharpUnfilled` is outlined, `sharpFilled` is solid. No effect when `leading` supplies its own node. |
|
|
29
|
+
| trailingIconVariant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Fill style for the default trailing icon: `sharpUnfilled` is outlined, `sharpFilled` is solid. No effect when `trailing` supplies its own node. |
|
|
30
|
+
| disabled | `boolean` | `false` | Blocks activation and applies disabled styling. Button rows get the native `disabled` attribute; plain, ListControls, and anchor (`href`) rows expose `aria-disabled` instead so they stay readable. |
|
|
31
|
+
| activated | `boolean` | `false` | Marks the row as the current selection: activated background plus `aria-selected`, or `aria-current="page"` on `href` rows. Turns the row interactive on its own, and shows the check icon when paired with `reserved`. |
|
|
32
|
+
| reserved | `boolean` | `false` | Reserves the leading space for the activation check icon so text does not shift as selection changes. Overrides `leadingSlot`, and the check appears only while `activated`. |
|
|
33
|
+
| dense | `boolean` | `false` | Compact vertical padding for denser lists. Inside ListControls, inherits the group’s `dense` when this prop is omitted. |
|
|
34
|
+
|
|
35
|
+
<!-- prettier-ignore-end -->
|
|
36
|
+
|
|
37
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
38
|
+
|
|
39
|
+
## Usage
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
<ListItem centerText={<Text type="Body Small Alt">Item label</Text>} />
|
|
43
|
+
<ListItem dense centerText={<Text type="Body Small Alt">Compact row</Text>} />
|
|
44
|
+
<ListItem divider centerText={<Text type="Body Small Alt">Header</Text>} />
|
|
45
|
+
<ListItem
|
|
46
|
+
interactive
|
|
47
|
+
trailingSlot
|
|
48
|
+
trailingIconName="outbound"
|
|
49
|
+
centerText={<Text type="Body Small Alt">Item with icon</Text>}
|
|
50
|
+
/>
|
|
51
|
+
<ListItem
|
|
52
|
+
topSlot
|
|
53
|
+
topContentSlot={<LabelBadge label="New" />}
|
|
54
|
+
centerText={<Text type="Body Small Alt">Title</Text>}
|
|
55
|
+
bottomText={<Text type="Condensed">Supporting copy</Text>}
|
|
56
|
+
/>
|
|
57
|
+
// Strings also work: <ListItem centerText="Item label" />
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
## Notes
|
|
62
|
+
|
|
63
|
+
- **Center content**: Optional top content slot plus a center text stack driven by `topText`, `centerText`, and `bottomText` (omit or empty string to hide a line). Prefer **Text** nodes (Overline / Body Small Alt / Condensed); plain strings are accepted and wrapped the same way.
|
|
64
|
+
- **Children**: Fallback for `centerText` when that prop is omitted (legacy).
|
|
65
|
+
- **Props**: `leading` / `trailing` for icons; `leadingSlot` / `trailingSlot` / `topSlot` to show/hide
|
|
66
|
+
- **States**: disabled (via disabled prop); interactive items use CSS :hover/:active
|
|
67
|
+
- **Interactive**: When true, renders as button for keyboard/click support
|
|
68
|
+
- **Dense**: Compact vertical padding; inside **ListControls**, inherits group `dense` when omitted
|
|
69
|
+
- **List controls**: Inside **ListControls**, an interactive row owns focus and activates the embedded trailing Switch / Checkbox / Radio (no nested button around the control).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Lockup
|
|
2
|
+
|
|
3
|
+
Import: `import { Lockup } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Stacked eyebrow, heading, and supporting copy used for section and hero intros.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| overline | `ReactNode` | `—` | Eyebrow content above the title, typically a `Text` of type `Overline` or a fragment mixing a `LabelBadge` with that text. Rendered only when `topSlot` is true and this is non-empty. |
|
|
14
|
+
| title | `ReactNode` | `—` | Heading content between `overline` and `body`, rendered as-is. Pass a `Text` with `as="h1"`–`"h6"` for the outline — `Lockup` adds no heading element of its own. This slot replaces the HTML `title` attribute on the root. |
|
|
15
|
+
| body | `ReactNode` | `—` | Supporting copy under the title, typically a `Text` of type `Body Medium`. Omit it and nothing is rendered, so the stack gap collapses. |
|
|
16
|
+
| topSlot | `boolean` | `true` | Gate for the overline region. Set `false` to suppress it even when `overline` has content; `title` and `body` are unaffected. |
|
|
17
|
+
|
|
18
|
+
<!-- prettier-ignore-end -->
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<Lockup
|
|
24
|
+
overline={<Text type="Overline" width={false}>Our mission</Text>}
|
|
25
|
+
title={<Text type="Display Medium" as="h2" width={false}>Health for all, Hunger for none</Text>}
|
|
26
|
+
body={
|
|
27
|
+
<Text type="Body Medium" width={false}>
|
|
28
|
+
Advancing access to health and nutrition worldwide.
|
|
29
|
+
</Text>
|
|
30
|
+
}
|
|
31
|
+
/>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// Badge beside overline text
|
|
36
|
+
<Lockup
|
|
37
|
+
overline={
|
|
38
|
+
<>
|
|
39
|
+
<LabelBadge label="New" />
|
|
40
|
+
<Text type="Overline" width={false}>Our mission</Text>
|
|
41
|
+
</>
|
|
42
|
+
}
|
|
43
|
+
title={<Text type="Display Medium" as="h1" width={false}>Health for all, Hunger for none</Text>}
|
|
44
|
+
/>
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
## Notes
|
|
49
|
+
|
|
50
|
+
- Each region accepts composed content—typically `Text` for typography, or a fragment mixing badges and overline text in `overline`. Empty regions are not rendered. Set `topSlot={false}` to hide the top region. Remaining HTML attributes—including `aria-*`, `id`, and `className`—are forwarded to the root element.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Logo
|
|
2
|
+
|
|
3
|
+
Import: `import { Logo } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Brand logo slot for navigation, footer, and marketing surfaces.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| name | `"generic"` | `"generic"` | Which mark to render from the logo set bundled in this build. It picks the asset file together with `color` and `background`, and fixes the aspect ratio that `width` scales. |
|
|
14
|
+
| background | `"default" \| "onDark"` | `"default"` | Surface the mark sits on. `onDark` swaps in the on-dark full-color asset for the brands that ship one, and only applies while `color` is `fullColor`. |
|
|
15
|
+
| color | `"fullColor" \| "black" \| "white" \| "colorSwitcherIcon"` | `"fullColor"` | Color treatment: `fullColor` for the brand palette, `black` or `white` for the monochrome mark, `colorSwitcherIcon` to tint the black mark with `--uxl-color-switcher-icon` from the nearest color-switcher context. Anything but `fullColor` overrides `background`. |
|
|
16
|
+
| interactive | `boolean` | `false` | Fades the mark to 80% opacity on hover. `Logo` is not a control on its own, so set this only when it sits inside a link or button. |
|
|
17
|
+
| width | `string` | `""` | Width of the logo container. A number or bare numeric string becomes pixels (`56`); any other string passes through as CSS (`100%`, `var(--uxl-logo-size)`). Height follows the brand aspect ratio; omit to use the mark's intrinsic width. |
|
|
18
|
+
| "aria-label" | `string` | `""` | Accessible name for a meaningful (non-decorative) logo, applied as the image `alt`. Ignored while the logo is decorative — that is, when `aria-hidden` is true or when neither this nor `aria-hidden={false}` is set. |
|
|
19
|
+
| "aria-hidden" | `"auto" \| "true" \| "false"` | `undefined` | Forces decorative (`true`, empty `alt`) or announced (`false`) treatment. Omit to derive it: the logo is decorative unless `aria-label` is set. |
|
|
20
|
+
| role | `string` | `""` | ARIA role on the wrapper element. Prefer leaving it unset and naming the mark through the image `alt` or a parent **Link**; `role="img"` on the wrapper while the image already has `alt` can confuse assistive technology. |
|
|
21
|
+
|
|
22
|
+
<!-- prettier-ignore-end -->
|
|
23
|
+
|
|
24
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<Logo>
|
|
30
|
+
{/* Content */}
|
|
31
|
+
</Logo>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Notes
|
|
35
|
+
|
|
36
|
+
- Set `width` (pixels, percentage, or theme variable) so the image scales to the full width of the container; height follows each brand's aspect ratio. Not a control by itself — wrap with **Link** when it should navigate. Set `interactive` for the hover opacity treatment when the mark is inside a control.
|
|
37
|
+
- **Decorative (default)** — Nav with visible site title beside the mark: omit `aria-label`; the logo stays decorative (`aria-hidden`, empty `alt`).
|
|
38
|
+
- **Meaningful** — Home control where the logo is the only visible label: `aria-label="My Company Logo"` (or `aria-hidden={false}` with a label) so `alt` names the logo; put the control name on the parent link (`aria-label` / visible text), not duplicated on both link and image without intent.
|
|
39
|
+
- **Avoid** `role="img"` on the wrapper when the image already has a non-empty `alt` — some assistive technologies expose redundant structure. Prefer `aria-hidden` on the mark beside visible text (see navigation examples).
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Menu
|
|
2
|
+
|
|
3
|
+
Import: `import { Menu } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Popover surface that pairs a trigger with a floating content panel.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| direction | `"Top Right" \| "Top Center" \| "Top Left" \| "Right Top" \| "Right Center" \| "Right Bottom" \| "Bottom Right" \| "Bottom Center" \| "Bottom Left" \| "Left Bottom" \| "Left Center" \| "Left Top"` | `"Top Right"` | Preferred panel position: the first word is the trigger edge the panel sits on, the second is its alignment along that edge. Flips to the opposite edge and shifts back inside the viewport when it would overflow. |
|
|
14
|
+
| disableFlip | `boolean` | `—` | Pins the panel to `direction` exactly, turning off both the edge flip and the viewport clamping. Use it when a predictable position matters more than the panel staying fully visible. |
|
|
15
|
+
| open | `boolean` | `—` | Controlled visibility. Pass it with `onOpenChange` and update it yourself; omit it to let the menu track its own state from `defaultOpen`. |
|
|
16
|
+
| defaultOpen | `boolean` | `false` | Whether the panel starts open on first render. Ignored afterwards, and whenever `open` is passed. |
|
|
17
|
+
| onOpenChange | `(open: boolean) => void` | `—` | Called with the requested visibility on trigger toggle, outside click, page scroll, Escape, or Tab-out. Required when `open` is controlled. |
|
|
18
|
+
| pattern | `MenuPattern` | `"menu"` | `menu` (default): application menu (`role="menu"`, menuitems, arrow keys, Tab dismisses). `disclosure`: popup list of links or buttons. Tab moves through destinations; Tab-out and Escape close and return focus to the trigger. |
|
|
19
|
+
| trigger | `ReactElement` | `—` | Single element that opens the panel, normally a `Button`. It is cloned to receive `onClick`, arrow-key handling, `aria-expanded` / `aria-haspopup` / `aria-controls`, and — in the `menu` pattern — a chevron `trailingIconName`. Without it the menu renders an inert placeholder. |
|
|
20
|
+
| children | `ReactNode` | `—` | Contents of the floating panel, usually a `List` of `ListItem`s. In the `menu` pattern only `menuitem` children join arrow-key navigation; in `disclosure` any links or buttons are walked with Tab. |
|
|
21
|
+
|
|
22
|
+
<!-- prettier-ignore-end -->
|
|
23
|
+
|
|
24
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
<Menu
|
|
30
|
+
direction="Top Right"
|
|
31
|
+
trigger={<Button emphasis="low" size="large" trailingIcon trailingIconName="keyboard_arrow_down">Open Menu</Button>}
|
|
32
|
+
>
|
|
33
|
+
<List>
|
|
34
|
+
<ListItem divider centerText="Header" />
|
|
35
|
+
<ListItem interactive trailingSlot trailingIconName="call_made" centerText="Item" />
|
|
36
|
+
</List>
|
|
37
|
+
</Menu>
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
## Notes
|
|
42
|
+
|
|
43
|
+
- **Trigger**: Pass a Button (required). Clicking toggles the menu open/close.
|
|
44
|
+
- **Children**: Pass List with ListItems or custom content for the menu panel.
|
|
45
|
+
- **Direction**: Twelve placements (Top/Right/Bottom/Left × alignment), matching Tooltip. Flips to the opposite edge when space is tight.
|
|
46
|
+
- While open, the panel tracks the trigger if it moves (e.g. layout or column resize).
|
|
47
|
+
- **pattern**: Default `menu` is an application menu (`role="menu"`, arrow keys, Tab dismisses). Use `disclosure` for a popup list of destinations (side-nav flyout): no menu role, Tab moves through links, Tab-out and Escape close and return focus to the trigger.
|
|
48
|
+
- **Accessibility**: Default `menu` panels use `role="menu"` and are named by the trigger (`aria-labelledby`). Pass `id` on the trigger when you need a stable association. `disclosure` panels stay unnamed (destination list, no menu role).
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# MultiSelect
|
|
2
|
+
|
|
3
|
+
Import: `import { MultiSelect } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Multi-select dropdown with removable chips, label, optional `FieldMessage`, and listbox options.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| label | `boolean` | `true` | When false, the label row is not rendered; pass `aria-label` so the combobox keeps an accessible name. |
|
|
14
|
+
| labelText | `string` | `"Department"` | Visible label text, rendered as Body Medium Alt inside `Label`; ignored when `labelSlot` is set, and an empty string hides the label row. |
|
|
15
|
+
| labelSlot | `ReactNode` | `—` | Replaces `labelText` with custom content inside `Label`, which keeps `htmlFor` and the required asterisk. Reach for it when the label needs a link or badge. |
|
|
16
|
+
| fieldDescription | `string` | `""` | Helper copy rendered under the label and linked to the combobox with `aria-describedby`; only rendered while the label row is visible. |
|
|
17
|
+
| fieldMessage | `boolean` | `false` | Renders a `FieldMessage` row below the control; `validation` set to `error` shows the row as well, so use this flag for neutral helper copy. |
|
|
18
|
+
| fieldMessageContent | `string` | `""` | Content for the `FieldMessage` row; when omitted, the row falls back to built-in copy for the current `validation` state. |
|
|
19
|
+
| validation | `"none" \| "error"` | `"none"` | Validation state: `error` switches the field message to the danger style, sets `aria-invalid`, and forces the message row; `none` leaves the field neutral. |
|
|
20
|
+
| placeholder | `string` | `""` | Text shown in the trigger while nothing is selected; nothing is rendered when it is an empty string. |
|
|
21
|
+
| leadingIcon | `boolean` | `false` | When true, renders the built-in leading `Icon` from `leadingIconName` inside the trigger; `leadingSlot` is the identical alias and `leading` overrides both. |
|
|
22
|
+
| leadingSlot | `boolean` | `false` | Alias of `leadingIcon`: either flag turns the leading region on, matching the Textfield leading-slot naming. |
|
|
23
|
+
| leadingIconName | `string` | `"add"` | Material Symbol rendered in the leading region; used only when `leadingIcon` (or `leadingSlot`) is true and `leading` is unset. An empty string falls back to `add`. |
|
|
24
|
+
| leadingIconVariant | `"sharpFilled" \| "sharpUnfilled"` | `"sharpUnfilled"` | Icon style for the built-in leading icon — `sharpUnfilled` (outlined) or `sharpFilled` (solid); ignored when `leading` supplies its own icon. |
|
|
25
|
+
| leading | `ReactNode` | `—` | Custom node rendered in the leading region instead of the built-in icon, with no need for `leadingIcon`. The wrapper is `aria-hidden`, so keep it decorative. |
|
|
26
|
+
| value | `string[]` | `—` | Selected option values in controlled mode. Pass it with `onChange`; omit it to let the component track the selection itself. |
|
|
27
|
+
| defaultValue | `string[]` | `[] as string[]` | Starting selection for uncontrolled usage; ignored once `value` is set. |
|
|
28
|
+
| onChange | `(value: string[]) => void` | `—` | Called with the complete next array of values each time an option is toggled or a chip is removed. |
|
|
29
|
+
| options | `MultiSelectOption[]` | `MULTI_SELECT_DEFAULT_OPTIONS` | Options rendered as listbox rows, and the lookup that resolves the trigger chip labels — still used when `children` replaces the rows. Omitting it falls back to three placeholder department options. |
|
|
30
|
+
| children | `ReactNode` | `—` | Custom listbox rows (usually `ListItem`) replacing the rows built from `options`; each row must spread `listboxOptionProps()` plus a handler that toggles the value. The trigger still builds its chips from `options`, so keep the two in sync. |
|
|
31
|
+
| open | `boolean` | `—` | Controlled open state of the listbox. Pass it with `onOpenChange`; omit it to let the component manage its own. `disabled` and `readOnly` keep the list closed. |
|
|
32
|
+
| defaultOpen | `boolean` | `false` | Whether the listbox starts open when uncontrolled; ignored once `open` is set. |
|
|
33
|
+
| onOpenChange | `(open: boolean) => void` | `—` | Called with the next open state whenever the listbox opens or closes, including outside clicks, Escape, and Tab. |
|
|
34
|
+
| readOnly | `boolean` | `false` | Shows the selection as comma-separated text instead of chips, blocks opening the listbox, and hides the trailing chevron; the trigger stays focusable. |
|
|
35
|
+
| required | `boolean` | `—` | Adds the asterisk to `Label` and `aria-required` on the trigger. Advisory only — no native constraint validation runs on the hidden inputs. |
|
|
36
|
+
| name | `string` | `—` | Form field name for the hidden inputs that post the selection — one input per selected value, and none at all while nothing is selected. |
|
|
37
|
+
| disabled | `boolean` | `false` | Blocks interaction, collapses chips to comma-separated text, and removes the trigger from the tab order; a `name` hidden input still submits each selected value. |
|
|
38
|
+
|
|
39
|
+
<!-- prettier-ignore-end -->
|
|
40
|
+
|
|
41
|
+
## Usage
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
<MultiSelect>
|
|
45
|
+
{/* Content */}
|
|
46
|
+
</MultiSelect>
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Notes
|
|
50
|
+
|
|
51
|
+
- Chips stay on one row when interactive; overflowed chips collapse to “and N more”. Read-only and disabled states show comma-separated text with truncation.
|
|
52
|
+
- **Accessibility**: Visible label uses `<Label htmlFor>`; selected values render as Filter Chip–styled tags inside the combobox (standard tag-in-input pattern). Remove controls use `tabIndex={-1}` and are omitted from the accessibility tree; toggle selections via the listbox. Overflowed labels are included in a screen-reader-only summary on the combobox. Composable list rows should use `listboxOptionProps()`. `FieldMessage` uses `aria-describedby` (info) or `aria-errormessage` (error). Pass `id` for stable ids; use `aria-label` when `label={false}`.
|
|
53
|
+
- **Focus**: Tab focuses the combobox trigger; **Arrow** keys move the active option while open. **Enter** / **Space** toggle the active option; **Escape** closes the list.
|
|
54
|
+
- **Forms**: With `name`, one hidden input is rendered per selected value.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# NavLink
|
|
2
|
+
|
|
3
|
+
Import: `import { NavLink } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Primary or secondary navigation item with Navigation Link typography.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| label | `string` | `"Nav Link"` | Link text, rendered with Navigation Link typography. It is the control's accessible name — `children` holds the dropdown panel, not the label. |
|
|
14
|
+
| leadingIcon | `boolean` | `false` | Renders `leadingIconName` before the label. |
|
|
15
|
+
| leadingIconName | `string` | `"add"` | Material Symbol name for the leading icon. Ignored when `leadingIcon` is false. |
|
|
16
|
+
| trailingIcon | `boolean` | `false` | Renders `trailingIconName` after the label. Forced on when `withMenu` is true, which supplies its own chevron. |
|
|
17
|
+
| trailingIconName | `string` | `"keyboard_arrow_down"` | Material Symbol name for the trailing icon. Ignored when `trailingIcon` is false, and overridden by the menu chevron when `withMenu` is true. |
|
|
18
|
+
| iconVariant | `"sharpUnfilled" \| "sharpFilled"` | `"sharpUnfilled"` | Fill style shared by both icons: `sharpUnfilled` for the outline glyph, `sharpFilled` for the solid one. |
|
|
19
|
+
| navigationLevel | `"Primary" \| "Secondary"` | `"Primary"` | Which `Navigation` band the link sits in, so its colors match that surface: `Primary` for the main bar, `Secondary` for the sub-navigation bar. |
|
|
20
|
+
| withMenu | `boolean` | `false` | Wraps the link in a `Menu` that opens `children` as a dropdown panel. The trigger stays a button (so `href` is ignored) and always shows a trailing `keyboard_arrow_down` that rotates 180° when open. |
|
|
21
|
+
| href | `string` | `undefined` | Destination URL, which renders the link as an anchor instead of a button. Ignored when `withMenu` is true. |
|
|
22
|
+
| children | `ReactNode` | `undefined` | Dropdown panel content — typically a `List` of `ListItem`s — shown when `withMenu` is true. Ignored otherwise; the visible text comes from `label`. |
|
|
23
|
+
| className | `string` | `—` | |
|
|
24
|
+
|
|
25
|
+
<!-- prettier-ignore-end -->
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
<NavLink label="Products" href="/products" />
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<NavLink label="More" withMenu>
|
|
35
|
+
<List>...</List>
|
|
36
|
+
</NavLink>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
## Notes
|
|
41
|
+
|
|
42
|
+
- Renders as an anchor when `href` is set; otherwise a button.
|
|
43
|
+
- Set `withMenu` and pass panel `children` for dropdown overflow items. `href` is ignored while `withMenu` is true so the trigger stays a button. A trailing `keyboard_arrow_down` icon is shown and rotates 180° when open.
|
|
44
|
+
- Use `navigationLevel="Secondary"` in the secondary nav band so colors follow that surface.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Navigation
|
|
2
|
+
|
|
3
|
+
Import: `import { Navigation } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
Two-tier navigation bar for enterprise applications.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| leadingSlot | `ReactNode \| null` | `undefined` | Start of the primary bar, typically a menu `IconButton`, a **Logo**, and a title lockup. Pass `null` to drop the region; omit to render the built-in placeholder branding. |
|
|
14
|
+
| centerSlot | `ReactNode \| null` | `undefined` | Middle of the primary bar between the leading and trailing regions — typically a row of `NavLink`s. Pass `null` to drop the region; omit to render placeholder links. |
|
|
15
|
+
| trailingSlot | `ReactNode \| null` | `undefined` | End of the primary bar, for utilities such as a search `IconButton`, a `LanguageSelector`, and a log-in `Button`. Pass `null` to drop the region; omit for the built-in utility set. |
|
|
16
|
+
| bottomSlot | `ReactNode \| null` | `undefined` | Contents of the secondary bar below the primary bar, typically `NavLink`s with `navigationLevel="Secondary"`. Pass `null` to drop the secondary bar entirely; omit to render placeholder links. |
|
|
17
|
+
|
|
18
|
+
<!-- prettier-ignore-end -->
|
|
19
|
+
|
|
20
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<Navigation
|
|
26
|
+
leadingSlot={
|
|
27
|
+
<>
|
|
28
|
+
<IconButton emphasis="low" size="medium" iconName="menu" iconVariant="sharpUnfilled" />
|
|
29
|
+
<Logo name="generic" className="uxl-navigation__logo" width={48} aria-hidden />
|
|
30
|
+
<Text type="Condensed Alt" truncation>Votre espace dédié</Text>
|
|
31
|
+
</>
|
|
32
|
+
}
|
|
33
|
+
centerSlot={
|
|
34
|
+
<>
|
|
35
|
+
<NavLink label="Menu Link" href="#" />
|
|
36
|
+
<NavLink label="Menu Link" href="#" />
|
|
37
|
+
</>
|
|
38
|
+
}
|
|
39
|
+
trailingSlot={
|
|
40
|
+
<>
|
|
41
|
+
<IconButton iconName="search" aria-label="Search" emphasis="low" size="small" />
|
|
42
|
+
<LanguageSelector value="EN" />
|
|
43
|
+
<Divider orientation="vertical" emphasis="low" />
|
|
44
|
+
<Button emphasis="low" size="small" trailingIcon trailingIconName="keyboard_arrow_down" trailingIconVariant="sharpUnfilled">Log In</Button>
|
|
45
|
+
</>
|
|
46
|
+
}
|
|
47
|
+
bottomSlot={
|
|
48
|
+
<>
|
|
49
|
+
<NavLink label="Menu Link" href="#" navigationLevel="Secondary" />
|
|
50
|
+
<NavLink label="Menu Link" href="#" navigationLevel="Secondary" />
|
|
51
|
+
</>
|
|
52
|
+
}
|
|
53
|
+
/>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
## Notes
|
|
58
|
+
|
|
59
|
+
- **Primary nav**: Leading, center, and trailing regions. Use slots for branding, main links, and utilities.
|
|
60
|
+
- **Secondary nav**: Optional bottom bar for sub-navigation.
|
|
61
|
+
- **Slots**: Pass `leadingSlot`, `centerSlot`, `trailingSlot`, and `bottomSlot` to customize each region. Omit a slot for the built-in placeholder; pass `null` to drop that region.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# NavigationSide
|
|
2
|
+
|
|
3
|
+
Import: `import { NavigationSide, DefaultLogoSlotContent, DefaultCenterSlotContent, DefaultBottomSlotContent } from "@uxelle/components";`
|
|
4
|
+
|
|
5
|
+
App chrome for a vertical side rail, or a compact top bar on small layouts.
|
|
6
|
+
|
|
7
|
+
## Props
|
|
8
|
+
|
|
9
|
+
<!-- prettier-ignore-start -->
|
|
10
|
+
|
|
11
|
+
| Prop | Type | Default | Description |
|
|
12
|
+
|------|------|---------|-------------|
|
|
13
|
+
| expanded | `boolean` | `—` | Controlled rail width: wide labeled rail when true, icon-only rail when false. Pass with `onExpandedChange`; omit to let `defaultExpanded` and the built-in toggle own the width. Ignored when the mobile layout is shown. |
|
|
14
|
+
| defaultExpanded | `boolean` | `true` | Whether the rail starts wide and labeled (true) or icon-only (false) when `expanded` is omitted. The built-in toggle owns the width after mount. |
|
|
15
|
+
| onExpandedChange | `(expanded: boolean) => void` | `—` | Called with the next width state each time the expand/collapse control is activated. Required to track the width when `expanded` is set. |
|
|
16
|
+
| mobile | `boolean` | `—` | Top-bar chrome when true; side rail when false. SSR hosts must pass `true` or `false` so server and client markup match. Omit only in client-only surfaces to follow the theme mobile range (`--uxl-theme-layout-mobile-screen-width-max`). The menu opens a right sheet with the same center and bottom slots as the rail. |
|
|
17
|
+
| logoSlot | `boolean` | `true` | Renders the logo region on the expanded rail and the mobile top bar. Set `false` to leave it empty; the collapsed rail never shows the logo. |
|
|
18
|
+
| logoSlotContent | `ReactNode` | `undefined` | Content for the logo region, typically a decorative **Logo**. Rendered only when `logoSlot` is true; omit for a neutral placeholder block. |
|
|
19
|
+
| centerSlotContent | `ReactNode` | `undefined` | Main destination region: one or more `NavigationSideGroup` elements, each wrapping `NavigationSideItem` rows. Rendered in the rail and, on the mobile layout, in the menu sheet. Omit for demo groups; pass `false` to leave empty. |
|
|
20
|
+
| bottomSlotContent | `ReactNode` | `undefined` | Trailing region under the destinations, typically an account row built from `List` + `ListItem`. Sits at the bottom of the rail and is pinned to the bottom of the mobile menu sheet. Pass `false` to leave it empty. |
|
|
21
|
+
| menuOpen | `boolean` | `—` | Controlled open state of the mobile menu sheet. Pass with `onMenuOpenChange` (for example to close the sheet after navigation); omit to let `defaultMenuOpen` and the menu control own it. No effect on the side rail. |
|
|
22
|
+
| defaultMenuOpen | `boolean` | `false` | Whether the mobile menu sheet starts open when `menuOpen` is omitted. |
|
|
23
|
+
| onMenuOpenChange | `(open: boolean) => void` | `—` | Called with the next open state whenever the mobile menu sheet opens or closes, including dismissals from inside the sheet. |
|
|
24
|
+
| onMenuClick | `MouseEventHandler<HTMLButtonElement>` | `—` | Click handler on the mobile menu button itself. Fires in addition to the sheet opening — use `onMenuOpenChange` to track sheet state. |
|
|
25
|
+
|
|
26
|
+
<!-- prettier-ignore-end -->
|
|
27
|
+
|
|
28
|
+
Extends `HTMLAttributes` — supports standard HTML attributes.
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<NavigationSide
|
|
34
|
+
expanded
|
|
35
|
+
logoSlotContent={<Logo name="generic" width={48} aria-hidden />}
|
|
36
|
+
centerSlotContent={
|
|
37
|
+
<NavigationSideGroup aria-label="Product">
|
|
38
|
+
<NavigationSideItem label="Overview" href="/overview" leadingIconName="view_quilt" />
|
|
39
|
+
</NavigationSideGroup>
|
|
40
|
+
}
|
|
41
|
+
/>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
## Notes
|
|
46
|
+
|
|
47
|
+
- **Rail**: Logo, expand/collapse control, `centerSlotContent` (`NavigationSideGroup` rows), and `bottomSlotContent`. Renders an `<aside>`. Groups remain named `<nav>` landmarks — do not wrap this chrome in another `nav`.
|
|
48
|
+
- **Width**: Set `expanded` for the labeled rail and `expanded={false}` for the icon-only rail. Hosts own when to pass those values (tablet-and-up). This component does not hard-code those widths.
|
|
49
|
+
- **Mobile**: Pass `mobile` (`true` or `false`) in SSR so the first paint matches hydration. The server snapshot for an omitted `mobile` is always the rail, so a phone viewport would swap to the top bar on the client. Omit `mobile` only in client-only surfaces (for example Storybook) to follow the theme mobile range (`--uxl-theme-layout-mobile-screen-width-max`). When the mobile layout is shown, the menu control opens a right `Sheet` (no visible title, labeled Menu for assistive tech) with the same `centerSlotContent` and `bottomSlotContent` as the rail (labeled rows, not the collapsed icon rail). The logo stays on the top bar. Use `menuOpen` / `onMenuOpenChange` to control the sheet (for example to close it after navigation). `onMenuClick` still fires on the menu control.
|
|
50
|
+
- **Slots**: Omit a slot to fill demo content. Pass `false` to leave a region empty. `logoSlot={false}` hides the logo on the expanded rail and the mobile bar.
|
|
51
|
+
- **Bottom slot**: Typical account rows use `List` + `ListItem`. List item text stays on one line during the rail width transition (same as destination labels) so it is revealed horizontally instead of wrapping.
|