@ahrowe/ui 0.50.0 → 0.52.0
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/CHANGELOG.md +24 -0
- package/README.md +2 -1
- package/dist/cjs-types/common/actionIcon/actionIcon.types.d.ts +10 -6
- package/dist/cjs-types/common/ahroweProvider/ahroweProvider.d.ts +1 -1
- package/dist/cjs-types/common/button/button.types.d.ts +25 -8
- package/dist/cjs-types/common/chatMessageList/chatMessageList.types.d.ts +1 -1
- package/dist/cjs-types/common/configProvider/configProvider.d.ts +2 -1
- package/dist/cjs-types/common/configProvider/configProvider.types.d.ts +8 -0
- package/dist/cjs-types/common/copyButton/copyButton.types.d.ts +4 -1
- package/dist/cjs-types/common/dropdown/dropdown.types.d.ts +3 -2
- package/dist/cjs-types/common/infiniteBlock/useInfiniteScroll.d.ts +1 -1
- package/dist/cjs-types/common/listItem/index.d.ts +2 -0
- package/dist/cjs-types/common/listItem/listItem.d.ts +4 -0
- package/dist/cjs-types/common/listItem/listItem.types.d.ts +33 -0
- package/dist/cjs-types/common/menu/menu.types.d.ts +2 -2
- package/dist/cjs-types/common/menu/menuItem.d.ts +5 -2
- package/dist/cjs-types/common/themeProvider/theme.types.d.ts +4 -0
- package/dist/cjs-types/common/utils/navigation.d.ts +12 -0
- package/dist/cjs-types/index.d.ts +2 -0
- package/dist/esm/common/ahroweProvider/ahroweProvider.mjs +1 -1
- package/dist/esm/common/ahroweProvider/ahroweProvider.mjs.map +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
- package/dist/esm/common/button/button.mjs +1 -1
- package/dist/esm/common/button/button.mjs.map +1 -1
- package/dist/esm/common/button/button.module.mjs +1 -1
- package/dist/esm/common/button/button.module.mjs.map +1 -1
- package/dist/esm/common/button/button.types.mjs.map +1 -1
- package/dist/esm/common/chatMessageList/chatMessageList.mjs +1 -1
- package/dist/esm/common/chatMessageList/chatMessageList.mjs.map +1 -1
- package/dist/esm/common/commandPalette/commandPalette.mjs +1 -1
- package/dist/esm/common/commandPalette/commandPalette.mjs.map +1 -1
- package/dist/esm/common/configProvider/configProvider.mjs +1 -1
- package/dist/esm/common/configProvider/configProvider.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.mjs.map +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs +1 -1
- package/dist/esm/common/dropdown/dropdown.module.mjs.map +1 -1
- package/dist/esm/common/infiniteBlock/useInfiniteScroll.mjs +1 -1
- package/dist/esm/common/infiniteBlock/useInfiniteScroll.mjs.map +1 -1
- package/dist/esm/common/listItem/listItem.mjs +2 -0
- package/dist/esm/common/listItem/listItem.mjs.map +1 -0
- package/dist/esm/common/listItem/listItem.module.mjs +2 -0
- package/dist/esm/common/listItem/listItem.module.mjs.map +1 -0
- package/dist/esm/common/loader/loader.module.mjs.map +1 -1
- package/dist/esm/common/menu/menu.mjs +1 -1
- package/dist/esm/common/menu/menu.mjs.map +1 -1
- package/dist/esm/common/menu/menu.types.mjs.map +1 -1
- package/dist/esm/common/menu/menuItem.mjs +1 -1
- package/dist/esm/common/menu/menuItem.mjs.map +1 -1
- package/dist/esm/common/utils/navigation.mjs +2 -0
- package/dist/esm/common/utils/navigation.mjs.map +1 -0
- package/dist/esm/index.mjs +1 -1
- package/dist/index.cjs +5 -5
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/common/actionIcon/actionIcon.types.d.ts +10 -6
- package/dist/types/common/ahroweProvider/ahroweProvider.d.ts +1 -1
- package/dist/types/common/button/button.types.d.ts +25 -8
- package/dist/types/common/chatMessageList/chatMessageList.types.d.ts +1 -1
- package/dist/types/common/configProvider/configProvider.d.ts +2 -1
- package/dist/types/common/configProvider/configProvider.types.d.ts +8 -0
- package/dist/types/common/copyButton/copyButton.types.d.ts +4 -1
- package/dist/types/common/dropdown/dropdown.types.d.ts +3 -2
- package/dist/types/common/infiniteBlock/useInfiniteScroll.d.ts +1 -1
- package/dist/types/common/listItem/index.d.ts +2 -0
- package/dist/types/common/listItem/listItem.d.ts +4 -0
- package/dist/types/common/listItem/listItem.types.d.ts +33 -0
- package/dist/types/common/menu/menu.types.d.ts +2 -2
- package/dist/types/common/menu/menuItem.d.ts +5 -2
- package/dist/types/common/themeProvider/theme.types.d.ts +4 -0
- package/dist/types/common/utils/navigation.d.ts +12 -0
- package/dist/types/index.d.ts +2 -0
- package/docs/ActionIcon.md +7 -3
- package/docs/AhroweProvider.md +2 -1
- package/docs/Breadcrumb.md +4 -24
- package/docs/Button.md +44 -9
- package/docs/CLAUDE.md +4 -0
- package/docs/ChatMessageList.md +5 -5
- package/docs/CommandPalette.md +1 -1
- package/docs/ConfigProvider.md +34 -1
- package/docs/Dropdown.md +17 -3
- package/docs/ListItem.md +97 -0
- package/docs/Menu.md +2 -2
- package/docs/ScrollbarProvider.md +1 -1
- package/package.json +1 -1
package/docs/ListItem.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# ListItem
|
|
2
|
+
|
|
3
|
+
**When to use:** One row of a list that stands for a record: a customer, an invoice, a delivery note. It shows a title, a second line and a status, can hold actions of its own, and can open the record from the whole row. For hundreds of rows use [VirtualList](VirtualList.md); for actions hanging off a trigger, [Menu](Menu.md).
|
|
4
|
+
|
|
5
|
+
**Keywords:** row, list row, cell, entry, record, item, drill-down, detail link, settings row
|
|
6
|
+
|
|
7
|
+
**Import:** `import { ListItem } from '@ahrowe/ui'`
|
|
8
|
+
**Types:** `import type { ListItemProps } from '@ahrowe/ui'`
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { ActionIcon, Chip, ListItem, ThemeColor } from '@ahrowe/ui';
|
|
12
|
+
import { faFileInvoice, faPen } from '@fortawesome/free-solid-svg-icons';
|
|
13
|
+
|
|
14
|
+
// Shows a record
|
|
15
|
+
<ListItem title="Created" endContent="12 Oct 2026" />
|
|
16
|
+
|
|
17
|
+
// Opens it: the whole row is the link, with a chevron
|
|
18
|
+
<ListItem
|
|
19
|
+
icon={faFileInvoice}
|
|
20
|
+
title="Invoice 2026-0042"
|
|
21
|
+
subtitle="Müller GmbH, due 1 Nov"
|
|
22
|
+
endContent={<Chip text="Open" color={ThemeColor.Warn} />}
|
|
23
|
+
href="/invoices/42"
|
|
24
|
+
/>
|
|
25
|
+
|
|
26
|
+
// Opens it and has an action: the edit button stays its own
|
|
27
|
+
<ListItem
|
|
28
|
+
title="Müller GmbH"
|
|
29
|
+
subtitle="3 projects"
|
|
30
|
+
href="/clients/7"
|
|
31
|
+
endContent={<ActionIcon icon={faPen} aria-label="Edit" onClick={editClient} />}
|
|
32
|
+
/>
|
|
33
|
+
|
|
34
|
+
// Opens it from a button instead of a link: no chevron, which promises a page
|
|
35
|
+
<ListItem title="Add a contact" onClick={openContactModal} />
|
|
36
|
+
|
|
37
|
+
// The one that is open, beside its detail view
|
|
38
|
+
<ListItem title="Müller GmbH" href="/clients/7" selected={clientId === 7} />
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Opening a record
|
|
42
|
+
|
|
43
|
+
With `href` the title is a link, and with `onClick` a button. Either one stretches over the whole
|
|
44
|
+
row, so a click anywhere on it opens the record, and with a link a middle click and a long press
|
|
45
|
+
too. Controls in the row stay their own: a button, a link, an input or anything with a `tabindex`
|
|
46
|
+
sits above the stretched area. Text around them still opens the row, so a click on a status `Chip`
|
|
47
|
+
opens the record.
|
|
48
|
+
|
|
49
|
+
A plain click on a page of the app goes through `ConfigProvider`'s `navigate` when it is set, see
|
|
50
|
+
[ConfigProvider.md](ConfigProvider.md). A screen reader hears the title as the link's name and the
|
|
51
|
+
subtitle, and a text `endContent`, as its description, rather than the whole row run together.
|
|
52
|
+
|
|
53
|
+
Because the link covers the row, its text cannot be selected with the mouse. A row that is only
|
|
54
|
+
read, with neither `href` nor `onClick`, selects as usual.
|
|
55
|
+
|
|
56
|
+
The rows sit in whatever holds them, a `Card` or a `<ul>` of your own. ListItem draws no dividers
|
|
57
|
+
and no list semantics of its own: it is a `<div>`, so in a `<ul>` give each one an `<li>`.
|
|
58
|
+
|
|
59
|
+
**Dividers.** Between groups of rows, a [Divider](Divider.md): it has no margin, so it adds the line
|
|
60
|
+
and nothing else. Between every row, a border from the container instead, because a screen reader
|
|
61
|
+
announces each `Divider` as a separator. The same rule works on `<div>`s and on `<li>`s:
|
|
62
|
+
|
|
63
|
+
```css
|
|
64
|
+
.clients > * + * {
|
|
65
|
+
border-top: 1px solid var(--border-color);
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Key props:**
|
|
70
|
+
|
|
71
|
+
| Prop | Type | Description |
|
|
72
|
+
|------|------|-------------|
|
|
73
|
+
| `title` | `ReactNode` | The main line, cut off with an ellipsis where it does not fit (required) |
|
|
74
|
+
| `subtitle` | `ReactNode` | A smaller line under it, cut off after two lines |
|
|
75
|
+
| `icon` | `IconDefinition \| ReactElement` | Before the title: a FontAwesome icon or any element, such as an `Avatar` |
|
|
76
|
+
| `endContent` | `ReactNode` | The trailing edge: a status, a date, an amount, and controls of its own |
|
|
77
|
+
| `href` | `string` | Opens the record from the whole row, as a link. `target`, `rel` and `download` apply to it |
|
|
78
|
+
| `onClick` | `MouseEventHandler<HTMLElement>` | Opens the record from the whole row, as a button. With `href` too, runs first, and `preventDefault()` keeps the link from being followed |
|
|
79
|
+
| `selected` | `boolean` | The row whose record is open: tinted in `--list-item-selected-background`, and `aria-current="page"` on its link |
|
|
80
|
+
| `chevron` | `boolean` | The chevron at the end. On by default for a row with an `href`, off for one with only `onClick`, which opens a dialog or runs an action rather than going somewhere |
|
|
81
|
+
|
|
82
|
+
Every native attribute passes through to the root `<div>`. A long title shrinks before
|
|
83
|
+
`endContent` and the chevron do, so they never leave the row. `endContent` itself never shrinks:
|
|
84
|
+
a value longer than a date or an amount belongs in the `subtitle`.
|
|
85
|
+
|
|
86
|
+
**Theming:**
|
|
87
|
+
|
|
88
|
+
| Variable | Default |
|
|
89
|
+
|----------|---------|
|
|
90
|
+
| `--list-item-min-height` | `48px`, the smallest comfortable touch target |
|
|
91
|
+
| `--list-item-selected-background` | a 12% tint of `--primary-color` |
|
|
92
|
+
|
|
93
|
+
Set it once in the theme rather than on each row: `'--list-item-min-height': '64px'`. Hover and
|
|
94
|
+
press tint the row in its own text colour, so they show on any surface; the keyboard focus ring
|
|
95
|
+
goes around the whole row, inside its edge, in `--focus-border-color`.
|
|
96
|
+
|
|
97
|
+
**Slots:** `root` `icon` `labels` `trigger` (the link or button, which draws the hover and focus ring in its `::after`) `title` `subtitle` `endContent` `chevron`
|
package/docs/Menu.md
CHANGED
|
@@ -54,7 +54,7 @@ useHotkeys(menuHotkeys(items, run));
|
|
|
54
54
|
useHotkeys(menuHotkeys(items, run), { enabled: isOpen });
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
It runs each entry the way clicking it does, its own `onClick` then `onAction` then its `href`, and leaves out a `disabled` entry and any entry with no `shortcut`. Bind them yourself instead if the actions already live in a keymap of your own; the menu does not mind either way.
|
|
57
|
+
It runs each entry the way clicking it does, its own `onClick` then `onAction` then its `href`, and leaves out a `disabled` entry and any entry with no `shortcut`. It runs outside React, so it cannot reach `ConfigProvider`'s `navigate`: an `href` run from a shortcut loads the page. Bind them yourself instead if the actions already live in a keymap of your own; the menu does not mind either way.
|
|
58
58
|
|
|
59
59
|
An action runs its own `onClick` first, then `onAction` on the menu, then the menu closes. Use whichever of the two fits: a handler per entry when they are unrelated, `onAction` when they funnel into one place.
|
|
60
60
|
|
|
@@ -120,7 +120,7 @@ Separators and headings are never focused. The trigger is given `aria-haspopup`,
|
|
|
120
120
|
| `shortcut` | `string` | A combo in `useHotkeys` spelling, e.g. `'mod+k'`. Shown on the trailing edge, written for the platform. Binding it is yours, see `menuHotkeys` |
|
|
121
121
|
| `disabled` | `boolean` | Not clickable, and skipped by the arrow keys |
|
|
122
122
|
| `danger` | `boolean` | Renders in the destructive colour |
|
|
123
|
-
| `href` | `string` | Makes the entry a real `<a>`, so Ctrl/⌘-click and a middle click open it in a new tab. A click runs `onClick` and `onAction` first, a middle click neither
|
|
123
|
+
| `href` | `string` | Makes the entry a real `<a>`, so Ctrl/⌘-click and a middle click open it in a new tab. A click runs `onClick` and `onAction` first, a middle click neither, then follows the link through `ConfigProvider`'s `navigate` when it is set, see [ConfigProvider.md](ConfigProvider.md). A `disabled` entry stays a button |
|
|
124
124
|
| `onClick` | `() => void` | Runs before `onAction` |
|
|
125
125
|
|
|
126
126
|
**Slots:** `root` `trigger` `menu` `item` `itemIcon` `itemLabel` `itemShortcut` `separator` `heading`
|