prime-ui-kit 0.11.1 → 0.13.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/README.md +4 -1
- package/dist/chunks/{chunk-WDTSHOTD.js → chunk-E6SQBSDF.js} +140 -30
- package/dist/chunks/{chunk-CUH6DJ57.js → chunk-Z3WKKAS6.js} +6572 -5024
- package/dist/chunks/{chunk-GKX3QAUC.js → chunk-ZSJMNA46.js} +14 -5
- package/dist/color-picker.js +2 -2
- package/dist/components/chat/Chat.d.ts +11 -12
- package/dist/components/chat/chatContext.d.ts +2 -0
- package/dist/components/chat-list/ChatList.d.ts +191 -0
- package/dist/components/chat-list/formatChatTime.d.ts +6 -0
- package/dist/components/command-menu/CommandMenu.d.ts +10 -5
- package/dist/components/composer/Composer.d.ts +3 -10
- package/dist/components/data-table/DataTable.d.ts +16 -2
- package/dist/components/data-table/Row.d.ts +23 -7
- package/dist/components/data-table/StateRows.d.ts +5 -1
- package/dist/components/data-table/reorder.d.ts +3 -1
- package/dist/components/data-table/rows.d.ts +20 -4
- package/dist/components/file-upload/FileUpload.d.ts +7 -0
- package/dist/components/gantt/Gantt.d.ts +19 -1
- package/dist/components/gantt/GanttBar.d.ts +4 -1
- package/dist/components/gantt/GanttRow.d.ts +8 -1
- package/dist/components/index.d.ts +11 -7
- package/dist/components/kanban/Kanban.d.ts +17 -2
- package/dist/components/list/List.d.ts +120 -0
- package/dist/components/message/Message.d.ts +13 -0
- package/dist/components/message/MessageParts.d.ts +2 -0
- package/dist/components/modal/DialogParts.d.ts +5 -1
- package/dist/components/select/Select.d.ts +11 -5
- package/dist/components/select/SelectItem.d.ts +19 -0
- package/dist/components/select/selectContext.d.ts +4 -0
- package/dist/components/sparkline/Sparkline.d.ts +14 -3
- package/dist/components/textarea/Textarea.d.ts +11 -3
- package/dist/hooks/useUploadQueue.d.ts +5 -1
- package/dist/icons/registry.d.ts +2 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +10 -2
- package/dist/internal/VisuallyHidden.d.ts +6 -1
- package/dist/internal/attachmentTile.d.ts +5 -1
- package/dist/internal/richText.d.ts +7 -2
- package/dist/internal/textFormatting.d.ts +52 -0
- package/dist/internal/textFormattingToolbar.d.ts +26 -0
- package/dist/skill/api-contract.md +1 -1
- package/dist/skill/cheatsheet.md +13 -1
- package/dist/skill/choosing.md +9 -4
- package/dist/skill/components.md +7 -5
- package/dist/skill/composition.md +9 -1
- package/dist/skill/layouts.md +4 -1
- package/dist/skill/patterns/app-shell.module.css +18 -0
- package/dist/skill/patterns/app-shell.tsx +301 -0
- package/dist/skill/patterns/chat.module.css +0 -25
- package/dist/skill/patterns/chat.tsx +72 -29
- package/dist/skill/patterns/kanban-board.module.css +28 -0
- package/dist/skill/patterns/kanban-board.tsx +612 -0
- package/dist/skill/patterns/media-library.module.css +66 -0
- package/dist/skill/patterns/media-library.tsx +638 -0
- package/dist/skill/patterns/schedule.module.css +22 -0
- package/dist/skill/patterns/schedule.tsx +722 -0
- package/dist/skill/reference/components/chat/COMPONENT.md +13 -4
- package/dist/skill/reference/components/chat/examples/states.tsx +100 -0
- package/dist/skill/reference/components/chat-list/COMPONENT.md +256 -0
- package/dist/skill/reference/components/chat-list/examples/controlled.tsx +103 -0
- package/dist/skill/reference/components/chat-list/examples/examples.module.css +66 -0
- package/dist/skill/reference/components/chat-list/examples/live.tsx +133 -0
- package/dist/skill/reference/components/chat-list/examples/long-list.tsx +87 -0
- package/dist/skill/reference/components/chat-list/examples/narrow.tsx +88 -0
- package/dist/skill/reference/components/chat-list/examples/overview.tsx +194 -0
- package/dist/skill/reference/components/chat-list/examples/search.tsx +71 -0
- package/dist/skill/reference/components/chat-list/examples/sizes.tsx +61 -0
- package/dist/skill/reference/components/chat-list/examples/states.tsx +107 -0
- package/dist/skill/reference/components/chat-list/examples/structure.tsx +135 -0
- package/dist/skill/reference/components/command-menu/COMPONENT.md +15 -11
- package/dist/skill/reference/components/command-menu/examples/server-search.tsx +11 -9
- package/dist/skill/reference/components/composer/COMPONENT.md +8 -7
- package/dist/skill/reference/components/composer/examples/formatting.tsx +1 -1
- package/dist/skill/reference/components/confirm-dialog/COMPONENT.md +1 -0
- package/dist/skill/reference/components/data-table/COMPONENT.md +21 -6
- package/dist/skill/reference/components/data-table/examples/groups.tsx +2 -1
- package/dist/skill/reference/components/data-table/examples/trend.tsx +85 -0
- package/dist/skill/reference/components/drawer/COMPONENT.md +7 -6
- package/dist/skill/reference/components/drawer/examples/client-card.tsx +50 -0
- package/dist/skill/reference/components/fieldset/COMPONENT.md +1 -0
- package/dist/skill/reference/components/file-upload/COMPONENT.md +12 -8
- package/dist/skill/reference/components/file-upload/examples/overview.tsx +14 -3
- package/dist/skill/reference/components/gantt/COMPONENT.md +15 -5
- package/dist/skill/reference/components/gantt/examples/row-link.tsx +96 -0
- package/dist/skill/reference/components/kanban/COMPONENT.md +12 -4
- package/dist/skill/reference/components/kanban/examples/item-link.tsx +92 -0
- package/dist/skill/reference/components/list/COMPONENT.md +195 -0
- package/dist/skill/reference/components/list/examples/as-link.tsx +37 -0
- package/dist/skill/reference/components/list/examples/examples.module.css +18 -0
- package/dist/skill/reference/components/list/examples/overflow.tsx +46 -0
- package/dist/skill/reference/components/list/examples/overview.tsx +63 -0
- package/dist/skill/reference/components/list/examples/reorder.tsx +48 -0
- package/dist/skill/reference/components/list/examples/sizes.tsx +35 -0
- package/dist/skill/reference/components/list/examples/states.tsx +27 -0
- package/dist/skill/reference/components/list/examples/with-icon.tsx +60 -0
- package/dist/skill/reference/components/message/COMPONENT.md +18 -2
- package/dist/skill/reference/components/message/examples/bot-actions.tsx +51 -0
- package/dist/skill/reference/components/modal/COMPONENT.md +6 -4
- package/dist/skill/reference/components/page-content/COMPONENT.md +2 -2
- package/dist/skill/reference/components/page-content/examples/examples.module.css +5 -12
- package/dist/skill/reference/components/page-content/examples/list-detail.tsx +13 -18
- package/dist/skill/reference/components/select/COMPONENT.md +38 -7
- package/dist/skill/reference/components/select/examples/create-action.tsx +107 -0
- package/dist/skill/reference/components/select/examples/saving.tsx +47 -0
- package/dist/skill/reference/components/sheet/COMPONENT.md +4 -4
- package/dist/skill/reference/components/sparkline/COMPONENT.md +16 -2
- package/dist/skill/reference/components/sparkline/examples/compact.tsx +41 -0
- package/dist/skill/reference/components/sparkline/examples/examples.module.css +12 -0
- package/dist/skill/reference/components/textarea/COMPONENT.md +22 -2
- package/dist/skill/reference/components/textarea/examples/formatting.tsx +20 -0
- package/dist/skill/reference/components/visually-hidden/COMPONENT.md +6 -3
- package/dist/skill/reference/components/visually-hidden/examples/overview.tsx +2 -2
- package/package.json +2 -2
- package/src/components/chat/COMPONENT.md +13 -4
- package/src/components/chat/examples/states.tsx +100 -0
- package/src/components/chat-list/COMPONENT.md +256 -0
- package/src/components/chat-list/examples/controlled.tsx +103 -0
- package/src/components/chat-list/examples/examples.module.css +66 -0
- package/src/components/chat-list/examples/live.tsx +133 -0
- package/src/components/chat-list/examples/long-list.tsx +87 -0
- package/src/components/chat-list/examples/narrow.tsx +88 -0
- package/src/components/chat-list/examples/overview.tsx +194 -0
- package/src/components/chat-list/examples/search.tsx +71 -0
- package/src/components/chat-list/examples/sizes.tsx +61 -0
- package/src/components/chat-list/examples/states.tsx +107 -0
- package/src/components/chat-list/examples/structure.tsx +135 -0
- package/src/components/command-menu/COMPONENT.md +15 -11
- package/src/components/command-menu/examples/server-search.tsx +11 -9
- package/src/components/composer/COMPONENT.md +8 -7
- package/src/components/composer/examples/formatting.tsx +1 -1
- package/src/components/confirm-dialog/COMPONENT.md +1 -0
- package/src/components/data-table/COMPONENT.md +21 -6
- package/src/components/data-table/examples/groups.tsx +2 -1
- package/src/components/data-table/examples/trend.tsx +85 -0
- package/src/components/drawer/COMPONENT.md +7 -6
- package/src/components/drawer/examples/client-card.tsx +50 -0
- package/src/components/fieldset/COMPONENT.md +1 -0
- package/src/components/file-upload/COMPONENT.md +12 -8
- package/src/components/file-upload/examples/overview.tsx +14 -3
- package/src/components/gantt/COMPONENT.md +15 -5
- package/src/components/gantt/examples/row-link.tsx +96 -0
- package/src/components/kanban/COMPONENT.md +12 -4
- package/src/components/kanban/examples/item-link.tsx +92 -0
- package/src/components/list/COMPONENT.md +195 -0
- package/src/components/list/examples/as-link.tsx +37 -0
- package/src/components/list/examples/examples.module.css +18 -0
- package/src/components/list/examples/overflow.tsx +46 -0
- package/src/components/list/examples/overview.tsx +63 -0
- package/src/components/list/examples/reorder.tsx +48 -0
- package/src/components/list/examples/sizes.tsx +35 -0
- package/src/components/list/examples/states.tsx +27 -0
- package/src/components/list/examples/with-icon.tsx +60 -0
- package/src/components/message/COMPONENT.md +18 -2
- package/src/components/message/examples/bot-actions.tsx +51 -0
- package/src/components/modal/COMPONENT.md +6 -4
- package/src/components/page-content/COMPONENT.md +2 -2
- package/src/components/page-content/examples/examples.module.css +5 -12
- package/src/components/page-content/examples/list-detail.tsx +13 -18
- package/src/components/select/COMPONENT.md +38 -7
- package/src/components/select/examples/create-action.tsx +107 -0
- package/src/components/select/examples/saving.tsx +47 -0
- package/src/components/sheet/COMPONENT.md +4 -4
- package/src/components/sparkline/COMPONENT.md +16 -2
- package/src/components/sparkline/examples/compact.tsx +41 -0
- package/src/components/sparkline/examples/examples.module.css +12 -0
- package/src/components/textarea/COMPONENT.md +22 -2
- package/src/components/textarea/examples/formatting.tsx +20 -0
- package/src/components/visually-hidden/COMPONENT.md +6 -3
- package/src/components/visually-hidden/examples/overview.tsx +2 -2
- package/dist/components/composer/format.d.ts +0 -39
|
@@ -5,6 +5,18 @@
|
|
|
5
5
|
width: min(100%, var(--prime-modal-width-s));
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/* compact: a client list, the name and its trend on one line per client. */
|
|
9
|
+
.list {
|
|
10
|
+
display: grid;
|
|
11
|
+
grid-template-columns: minmax(0, 1fr) minmax(var(--prime-space-24), 1fr);
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--prime-space-3) var(--prime-space-4);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.listRow {
|
|
17
|
+
display: contents;
|
|
18
|
+
}
|
|
19
|
+
|
|
8
20
|
/* The period switch above the chart inside the card body. */
|
|
9
21
|
.body {
|
|
10
22
|
display: flex;
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
- Free-form text longer than one line: comments, descriptions, reviews, support requests, notes.
|
|
10
10
|
- A plain growing input (`rows={1} maxRows={8}`) when a full chat composer with attachments, reply and voice is not needed.
|
|
11
11
|
- Text with a length limit shown to the user (`Textarea.Counter`).
|
|
12
|
+
- Text that is later shown with its Markdown (an announcement, a comment, a task description): `formatting` adds the toolbar and hotkeys Composer has.
|
|
12
13
|
|
|
13
14
|
## When not to use
|
|
14
15
|
- A single-line value (name, e-mail, search) → use [Input](../input/COMPONENT.md).
|
|
@@ -26,6 +27,7 @@ import { Textarea } from "prime-ui-kit";
|
|
|
26
27
|
Textarea.Root label row → field box with the native <textarea> → support row (hint | error · counter)
|
|
27
28
|
├─ Textarea.CopyButton children: copies the text from the top end corner (kit-rendered)
|
|
28
29
|
└─ Textarea.Action children: the consumer's named icon action with a tooltip (button or asChild link)
|
|
30
|
+
(toolbar) with `formatting`: floating role="toolbar" over a selection — 7 ghost Buttons with Tooltip + Kbd
|
|
29
31
|
Textarea.Counter goes into Textarea.Root `counter` (right side of the support row)
|
|
30
32
|
```
|
|
31
33
|
Unlike Input, Textarea has no Wrapper / Field parts: `Textarea.Root` renders the whole field and takes native `<textarea>` props directly. Its children are only the corner actions: they sit in the top end corner as full-height segments flush with the box edges, in JSX order, after the commit status of `onCommit`.
|
|
@@ -56,6 +58,7 @@ Unlike Input, Textarea has no Wrapper / Field parts: `Textarea.Root` renders the
|
|
|
56
58
|
| `id` | `string` | — | Id of the `<textarea>` (auto-generated when omitted); hint id is `<id>-hint`, error id is `<id>-error`. |
|
|
57
59
|
| `aria-describedby` | `string` | — | Merged before the hint/error ids. |
|
|
58
60
|
| `onCommit` | `(value: string) => void \| Promise<void>` | — | Inline save: fires with a changed value on blur and Mod+Enter; Escape reverts. Return a Promise: the field shows a spinner and stays editable; a rejection restores the value — show why through `error`. |
|
|
61
|
+
| `formatting` | `boolean` | `false` | Selecting text shows a floating toolbar of seven Markdown tools and enables their hotkeys; a tool wraps the selection, a second press unwraps it. Off: plain text. |
|
|
59
62
|
| `children` | `ReactNode` | — | Actions in the field's top end corner: `Textarea.CopyButton`, `Textarea.Action`. |
|
|
60
63
|
| `labels` | `Partial<TextareaLabels>` | — | Built-in strings, see Labels. |
|
|
61
64
|
| `className` | `string` | — | Class on the field frame `<div>` (label, field box, support row), as on every field root. |
|
|
@@ -112,6 +115,7 @@ Textarea has no `variant` or `tone`: one field treatment (fill, no visible borde
|
|
|
112
115
|
| Value | Looks like | Use when | Default |
|
|
113
116
|
|---|---|---|---|
|
|
114
117
|
| `focusRing={false}` | No focus ring; focus fill and caret remain | A single composer field where focus is obvious | `true` |
|
|
118
|
+
| `formatting` | A floating toolbar over a selection (bold, italic, strikethrough, code, spoiler, link, quote) and the Mod-hotkeys; each writes Markdown around the selection | The text is shown later with its Markdown (Message renders the same subset) | `false` |
|
|
115
119
|
| `reserveSupportRow` | Empty support row of hint height | Live validation, fields side by side | `false` |
|
|
116
120
|
| `required` / `optional` | Red `*` / muted «необязательно» after the label | Mark the minority of the form | — / `false` |
|
|
117
121
|
|
|
@@ -135,6 +139,7 @@ Textarea has no `variant` or `tone`: one field treatment (fill, no visible borde
|
|
|
135
139
|
| saving | `onCommit` returned a pending Promise | `aria-busy="true"` on the textarea, a `Spinner` in the top end corner (`data-commit="pending"`); the field stays editable; a live region says `labels.saving` |
|
|
136
140
|
| saved | the Promise resolved (or `onCommit` returned nothing) | the spinner cross-fades into a success check (`data-commit="saved"`) that fades out; the live region says `labels.saved` |
|
|
137
141
|
| save refused | the Promise rejected | the committed text is put back (unless the person typed on); the owner shows why through `error` |
|
|
142
|
+
| selection | `formatting` and a non-empty selection while the focus is in the field or its toolbar (not disabled or read-only) | the floating toolbar fades in from below above the field's start edge (`overlayMotion` floating, `data-side="top"`); a tool wraps the selection in its Markdown, a second press removes it; the edit is typed into the field, so `Mod+Z` takes it back |
|
|
138
143
|
| copied | `Textarea.CopyButton` pressed | the copy glyph cross-fades into a check, the name becomes `labels.copied` (or `labels.copyError`) |
|
|
139
144
|
|
|
140
145
|
Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+Enter (Ctrl or ⌘ with Enter — a plain Enter is a line break) commit a changed text, Escape puts the committed text back and is consumed. An unchanged text never fires. Return a Promise for a server save: pending shows a spinner while the field stays editable and Tab moves on, reject restores the text, resolve shows the check.
|
|
@@ -146,6 +151,7 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
146
151
|
- Field → field in a form: `--prime-space-5`; group → actions: `--prime-space-8`.
|
|
147
152
|
- Width is always `100%` of the parent; set the width with the layout column.
|
|
148
153
|
- Long words wrap (`overflow-wrap: anywhere`), so the field never overflows horizontally.
|
|
154
|
+
- With `formatting` the toolbar floats `--prime-space-2` above the field box's start edge on the floating layer, over whatever is above the field; it takes no room in the layout.
|
|
149
155
|
|
|
150
156
|
## Accessibility
|
|
151
157
|
|
|
@@ -154,7 +160,10 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
154
160
|
|---|---|
|
|
155
161
|
| `Tab` | Focuses the field, then the buttons in its corner; Enter inserts a line break instead of submitting the form. |
|
|
156
162
|
| `Mod+Enter` | With `onCommit`: saves a changed text; focus stays in the field. |
|
|
157
|
-
| `Escape` | With `onCommit`: puts the committed text back. |
|
|
163
|
+
| `Escape` | With `formatting`: first clears a selection with the toolbar. With `onCommit`: puts the committed text back. |
|
|
164
|
+
| `Mod + B` · `Mod + I` · `Mod + Shift + X` · `Mod + E` · `Mod + Shift + H` · `Mod + K` · `Mod + Shift + 9` | With `formatting`: bold, italic, strikethrough, code, spoiler, link and quote for the selection; the physical key counts, so any layout works. |
|
|
165
|
+
| `←` · `→` | Move between the formatting buttons. |
|
|
166
|
+
| `Home` · `End` | Jump to the first / last formatting button. |
|
|
158
167
|
|
|
159
168
|
### ARIA
|
|
160
169
|
- `label` renders `<label htmlFor>` bound to the textarea; without it set `aria-label`. A placeholder never replaces the label.
|
|
@@ -163,6 +172,7 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
163
172
|
- `Textarea.Counter` shows `12/280` visually and announces `labels.counter` (`aria-live="polite"`).
|
|
164
173
|
- `Textarea.Action` and `Textarea.CopyButton` are buttons (or a link with `asChild`) named by their label, with a tooltip; copying announces `labels.copied`. A press on them never moves focus into the textarea.
|
|
165
174
|
- With `onCommit` the textarea carries `aria-busy="true"` while saving; a polite live region says `labels.saving`, then `labels.saved`.
|
|
175
|
+
- The formatting toolbar is `role="toolbar"` named `labels.formatting`, `aria-controls` the textarea, with one Tab stop and arrow keys; every button has `aria-keyshortcuts` and a tooltip with its keys (`⌘B` on Apple systems, `Ctrl+B` elsewhere). A press on a tool keeps the focus and the selection in the field.
|
|
166
176
|
|
|
167
177
|
### Labels
|
|
168
178
|
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
@@ -176,6 +186,14 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
176
186
|
| `copyError` | `"Не удалось скопировать"` | Name, tooltip and announcement when the clipboard refuses. |
|
|
177
187
|
| `saving` | `"Сохранение"` | Announced while an `onCommit` save is pending. |
|
|
178
188
|
| `saved` | `"Сохранено"` | Announced once an `onCommit` save succeeds. |
|
|
189
|
+
| `formatting` | `"Форматирование"` | Accessible name of the formatting toolbar. |
|
|
190
|
+
| `bold` | `"Жирный"` | Bold tool. |
|
|
191
|
+
| `italic` | `"Курсив"` | Italic tool. |
|
|
192
|
+
| `strikethrough` | `"Зачёркнутый"` | Strikethrough tool. |
|
|
193
|
+
| `code` | `"Моноширинный"` | Code tool. |
|
|
194
|
+
| `spoiler` | `"Скрытый текст"` | Spoiler tool (`\|\|…\|\|`). |
|
|
195
|
+
| `link` | `"Ссылка"` | Link tool. |
|
|
196
|
+
| `quote` | `"Цитата"` | Quote tool. |
|
|
179
197
|
|
|
180
198
|
## Examples
|
|
181
199
|
| Example | Shows |
|
|
@@ -188,6 +206,7 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
188
206
|
| [without-focus-ring.tsx](examples/without-focus-ring.tsx) | A single reply composer where the caret and the lighter fill show focus — `focusRing`. |
|
|
189
207
|
| [edge-actions.tsx](examples/edge-actions.tsx) | A read-only generated reply with copying and a link to the template in the field's corner — `Textarea.CopyButton`, `Textarea.Action`. |
|
|
190
208
|
| [inline-edit.tsx](examples/inline-edit.tsx) | A record card note that saves on blur and Mod+Enter, reverts on Escape and shows the server's refusal — `onCommit`, `error`. |
|
|
209
|
+
| [formatting.tsx](examples/formatting.tsx) | A long announcement where a selection gets the formatting toolbar and its hotkeys, written as Markdown around it — `formatting`. |
|
|
191
210
|
| [controlled.tsx](examples/controlled.tsx) | The parent owns the text; the counter follows it and `maxLength` stops extra input — `value`, `onValueChange`, `Textarea.Counter`, `maxLength`. |
|
|
192
211
|
| [in-form.tsx](examples/in-form.tsx) | Support request form: the description is checked on submit, its error leaves as soon as the text is long enough and does not shift the form, a sent request turns the button green — `required`, `error`, `reserveSupportRow`. |
|
|
193
212
|
|
|
@@ -200,7 +219,8 @@ Inline save (`onCommit`): the text at focus is the committed one; blur and Mod+E
|
|
|
200
219
|
- Only a placeholder, no label → add `label` or `aria-label`.
|
|
201
220
|
- A copy `Button` under a read-only result → `Textarea.CopyButton` as a child of the root.
|
|
202
221
|
- Other children than `Textarea.CopyButton` / `Textarea.Action` → the root renders the textarea itself; children are only the corner actions.
|
|
222
|
+
- `formatting` on text that is shown as plain text → the reader sees `**` and `||`; turn it on only where the text is rendered with its Markdown.
|
|
203
223
|
|
|
204
224
|
## Related
|
|
205
|
-
- **Built from:** [Label](../label/COMPONENT.md) (`label`), [Hint](../hint/COMPONENT.md) (`hint`, `error`), [Tooltip](../tooltip/COMPONENT.md) (corner actions), [Spinner](../spinner/COMPONENT.md) (`onCommit`)
|
|
225
|
+
- **Built from:** [Label](../label/COMPONENT.md) (`label`), [Hint](../hint/COMPONENT.md) (`hint`, `error`), [Tooltip](../tooltip/COMPONENT.md) (corner actions, formatting tools), [Spinner](../spinner/COMPONENT.md) (`onCommit`), [Button](../button/COMPONENT.md) and [Kbd](../kbd/COMPONENT.md) (formatting tools), Icon (`format.*`); `internal/textFormatting` + `internal/textFormattingToolbar` (the formatting shared with Composer)
|
|
206
226
|
- **See also:** [Input](../input/COMPONENT.md) — the same field contract for one line; [Composer](../composer/COMPONENT.md) — a chat message input built on Textarea; [CodeBlock](../code-block/COMPONENT.md)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** A long announcement where a selection gets the formatting toolbar and its hotkeys, written as Markdown around it — `formatting`. */
|
|
2
|
+
import { Textarea } from "prime-ui-kit";
|
|
3
|
+
|
|
4
|
+
const ANNOUNCEMENT = `С понедельника счета клиентам выставляет **отдел расчётов**, а не менеджеры проектов.
|
|
5
|
+
|
|
6
|
+
> Счёт уходит в течение _одного рабочего дня_ после подписания акта.
|
|
7
|
+
|
|
8
|
+
Шаблон договора — [в базе знаний](https://prime.app/kb/contracts). Пароль от архива актов: ||Prime-2048||. Старый процесс ~~через почту~~ отключаем 1 апреля.`;
|
|
9
|
+
|
|
10
|
+
export default function TextareaFormattingExample() {
|
|
11
|
+
return (
|
|
12
|
+
<Textarea.Root
|
|
13
|
+
label="Текст публикации"
|
|
14
|
+
hint="Выделите текст, чтобы оформить его; публикация покажет оформление"
|
|
15
|
+
defaultValue={ANNOUNCEMENT}
|
|
16
|
+
rows={6}
|
|
17
|
+
formatting
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
@@ -36,7 +36,8 @@ VisuallyHidden <span>: out of sight (1px, clipped), pinned to its containing
|
|
|
36
36
|
| Prop | Type | Default | Description |
|
|
37
37
|
|---|---|---|---|
|
|
38
38
|
| `children` | `ReactNode` | — | The text to read. |
|
|
39
|
-
|
|
|
39
|
+
| `live` | `"polite" \| "assertive"` | — | An announcement region, read as a whole on every change: `polite` — `role="status"`, `assertive` — `role="alert"` (urgent only). |
|
|
40
|
+
| `…rest` | `HTMLAttributes<HTMLSpanElement>` | — | `id` (to point `aria-describedby` at it), `className` and the other span attributes. |
|
|
40
41
|
|
|
41
42
|
## Variants
|
|
42
43
|
One look: none. It renders no pixels and takes no room.
|
|
@@ -45,7 +46,7 @@ One look: none. It renders no pixels and takes no room.
|
|
|
45
46
|
| State | Driven by | DOM |
|
|
46
47
|
|---|---|---|
|
|
47
48
|
| hidden text | children | a clipped `<span>` |
|
|
48
|
-
| live region | `role="status"`
|
|
49
|
+
| live region | `live="polite"` (`"assertive"` for an urgent one) | `role="status"` (`"alert"`), `aria-live`, `aria-atomic`: read as a whole when its text changes; mount it empty first, then set the message |
|
|
49
50
|
|
|
50
51
|
## Layout & spacing
|
|
51
52
|
- Takes no room and never scrolls its column: it is pinned to the start of the nearest positioned ancestor.
|
|
@@ -58,7 +59,7 @@ No keyboard interaction.
|
|
|
58
59
|
|
|
59
60
|
### ARIA
|
|
60
61
|
- The text stays in the accessibility tree: it joins the accessible name of the element around it.
|
|
61
|
-
- With `
|
|
62
|
+
- With `live="polite"` it is a polite live region (`role="status"`), with `live="assertive"` an alert (`role="alert"`) for what cannot wait; keep it mounted and change its text — a region mounted together with its message is often not read.
|
|
62
63
|
|
|
63
64
|
### Labels
|
|
64
65
|
<!-- Generated from api.ts by `bun run docs:build`. Edit api.ts, not this section. -->
|
|
@@ -73,6 +74,8 @@ No `labels`.
|
|
|
73
74
|
## Mistakes
|
|
74
75
|
- `display: none` or `hidden` for screen-reader text → both remove it from the accessibility tree.
|
|
75
76
|
- A live region mounted with its first message → mount it empty, then set the text.
|
|
77
|
+
- `role="status"` and `aria-live` written by hand → `live="polite"` sets them together, atomic.
|
|
78
|
+
- `live="assertive"` for a routine result («Сохранено») → it interrupts the reader; keep it for errors that block.
|
|
76
79
|
- VisuallyHidden as the only name of a button that has `aria-label` → the `aria-label` wins; use one of them.
|
|
77
80
|
- Hidden text that repeats the visible label → screen readers read it twice.
|
|
78
81
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** A count that sighted users read from the layout, said in words to screen readers, and a polite announcement after an action — `VisuallyHidden`. */
|
|
1
|
+
/** A count that sighted users read from the layout, said in words to screen readers, and a polite announcement after an action — `VisuallyHidden`, `live`. */
|
|
2
2
|
import { Badge, Button, Typography, VisuallyHidden } from "prime-ui-kit";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
@@ -14,7 +14,7 @@ export default function VisuallyHiddenOverviewExample() {
|
|
|
14
14
|
<Button.Root variant="soft" tone="neutral" onClick={() => setArchived((count) => count + 1)}>
|
|
15
15
|
В архив
|
|
16
16
|
</Button.Root>
|
|
17
|
-
<VisuallyHidden
|
|
17
|
+
<VisuallyHidden live="polite">
|
|
18
18
|
{archived > 0 ? `Счетов в архиве: ${archived}` : ""}
|
|
19
19
|
</VisuallyHidden>
|
|
20
20
|
</>
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Markdown formatting of a plain-text message (the Composer's toolbar and hotkeys): pure functions
|
|
3
|
-
* over the text and its selection, so the component only applies the result to its textarea.
|
|
4
|
-
*/
|
|
5
|
-
/** A formatting command: what the toolbar button or the hotkey applies to the selection. */
|
|
6
|
-
export type ComposerFormat = "bold" | "italic" | "strikethrough" | "code" | "link" | "quote";
|
|
7
|
-
/** Text with its selection, `start <= end` (a caret when equal). */
|
|
8
|
-
export type TextSelection = {
|
|
9
|
-
text: string;
|
|
10
|
-
start: number;
|
|
11
|
-
end: number;
|
|
12
|
-
};
|
|
13
|
-
/** The text and selection after `format` is applied to the selection. */
|
|
14
|
-
export declare function applyFormat(selection: TextSelection, format: ComposerFormat): TextSelection;
|
|
15
|
-
/**
|
|
16
|
-
* The one span that differs between two texts (common prefix and suffix removed), so the change can
|
|
17
|
-
* be typed into the textarea as one edit and stay on its undo stack.
|
|
18
|
-
*/
|
|
19
|
-
export declare function diffRange(before: string, after: string): {
|
|
20
|
-
start: number;
|
|
21
|
-
end: number;
|
|
22
|
-
insert: string;
|
|
23
|
-
};
|
|
24
|
-
/** The format a key press asks for: Mod+B · Mod+I · Mod+Shift+X · Mod+E · Mod+K · Mod+Shift+9. */
|
|
25
|
-
export declare function formatForKey(event: {
|
|
26
|
-
key: string;
|
|
27
|
-
code: string;
|
|
28
|
-
metaKey: boolean;
|
|
29
|
-
ctrlKey: boolean;
|
|
30
|
-
shiftKey: boolean;
|
|
31
|
-
altKey: boolean;
|
|
32
|
-
}): ComposerFormat | null;
|
|
33
|
-
/** Shortcut of every format, by modifier names: rendered as `⌘B` on Apple systems, `Ctrl+B` elsewhere. */
|
|
34
|
-
export declare const FORMAT_SHORTCUTS: Record<ComposerFormat, {
|
|
35
|
-
shift: boolean;
|
|
36
|
-
key: string;
|
|
37
|
-
}>;
|
|
38
|
-
/** `⌘⇧X` on Apple systems, `Ctrl+Shift+X` elsewhere. */
|
|
39
|
-
export declare function shortcutText(format: ComposerFormat, apple: boolean): string;
|