@nanisoft/prism-llms 0.4.0 → 0.5.1
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 +88 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/dist/data.json +4037 -386
- package/dist/demo-graph.d.ts +21 -12
- package/dist/demo-graph.js +37 -21
- package/dist/extractor.d.ts +24 -17
- package/dist/extractor.js +299 -156
- package/dist/index.d.ts +12 -7
- package/dist/index.js +9 -7
- package/dist/llms-full.txt +8248 -2013
- package/dist/llms.txt +98 -93
- package/dist/markdown.d.ts +69 -23
- package/dist/markdown.js +131 -72
- package/dist/md/blocks/app-shell-01.md +135 -0
- package/dist/md/blocks/auth-form-01.md +135 -0
- package/dist/md/blocks/cta-01.md +88 -0
- package/dist/md/blocks/data-table-01.md +196 -0
- package/dist/md/blocks/feature-grid-01.md +92 -0
- package/dist/md/blocks/hero-01.md +90 -0
- package/dist/md/blocks/instrument-panel-01.md +109 -0
- package/dist/md/blocks/logo-strip-01.md +97 -0
- package/dist/md/blocks/note-grid-01.md +98 -0
- package/dist/md/blocks/page-header-01.md +97 -0
- package/dist/md/blocks/pricing-01.md +91 -0
- package/dist/md/blocks/process-rail-01.md +106 -0
- package/dist/md/blocks/product-grid-01.md +107 -0
- package/dist/md/blocks/settings-panel-01.md +146 -0
- package/dist/md/blocks/site-footer.md +103 -11
- package/dist/md/blocks/site-header.md +107 -11
- package/dist/md/blocks/stack-grid-01.md +108 -0
- package/dist/md/blocks/stats-01.md +89 -0
- package/dist/md/blocks/status-ledger-01.md +121 -0
- package/dist/md/changelogs/prism-llms.md +244 -0
- package/dist/md/changelogs/prism-mcp-server.md +95 -0
- package/dist/md/changelogs/prism-tokens.md +126 -0
- package/dist/md/changelogs/prism-ui.md +467 -0
- package/dist/md/components/accordion.md +108 -0
- package/dist/md/components/alert.md +90 -7
- package/dist/md/components/avatar.md +89 -7
- package/dist/md/components/badge.md +74 -7
- package/dist/md/components/breadcrumb.md +84 -7
- package/dist/md/components/button.md +90 -7
- package/dist/md/components/card.md +90 -7
- package/dist/md/components/checkbox.md +101 -7
- package/dist/md/components/cta-link.md +98 -0
- package/dist/md/components/diagram.md +124 -0
- package/dist/md/components/dialog.md +128 -0
- package/dist/md/components/dropdown-menu.md +125 -0
- package/dist/md/components/fact-list.md +85 -0
- package/dist/md/components/field.md +116 -0
- package/dist/md/components/input.md +86 -7
- package/dist/md/components/kbd.md +77 -0
- package/dist/md/components/pagination.md +95 -7
- package/dist/md/components/popover.md +95 -7
- package/dist/md/components/product-mark.md +114 -0
- package/dist/md/components/product-switcher.md +88 -0
- package/dist/md/components/progress.md +88 -7
- package/dist/md/components/prose.md +91 -0
- package/dist/md/components/radio-group.md +111 -0
- package/dist/md/components/section.md +91 -0
- package/dist/md/components/select.md +143 -7
- package/dist/md/components/separator.md +77 -0
- package/dist/md/components/skeleton.md +71 -7
- package/dist/md/components/slider.md +90 -7
- package/dist/md/components/switch.md +104 -7
- package/dist/md/components/table.md +104 -7
- package/dist/md/components/tabs.md +105 -7
- package/dist/md/components/textarea.md +101 -0
- package/dist/md/components/tooltip.md +95 -7
- package/dist/md/components/typography.md +82 -7
- package/dist/md/content/about-content.md +36 -0
- package/dist/md/content/audience.md +43 -0
- package/dist/md/content/glossary.md +69 -0
- package/dist/md/content/product-vocabulary.md +53 -0
- package/dist/md/content/voice.md +52 -0
- package/dist/md/content/writing-mechanics.md +58 -0
- package/dist/md/foundation/colors.md +10 -0
- package/dist/md/foundation/iconography.md +14 -0
- package/dist/md/foundation/motion.md +10 -0
- package/dist/md/foundation/radii.md +9 -0
- package/dist/md/foundation/shadows.md +9 -0
- package/dist/md/foundation/spacings.md +8 -0
- package/dist/md/foundation/typography.md +9 -0
- package/dist/md/foundation/variables.md +9 -0
- package/dist/md/overview/architecture.md +76 -0
- package/dist/md/overview/brand.md +41 -0
- package/dist/md/overview/composition.md +77 -0
- package/dist/md/overview/quickstart.md +97 -0
- package/dist/md/overview/theming.md +89 -0
- package/dist/md/overview/using-llms.md +83 -0
- package/dist/md/pages/auth-page.md +149 -0
- package/dist/md/pages/blog-post-page.md +136 -0
- package/dist/md/pages/dashboard-page.md +241 -0
- package/dist/md/pages/docs-shell.md +210 -15
- package/dist/md/pages/marketing-page.md +199 -0
- package/dist/md/pages/not-found-page.md +105 -0
- package/dist/md/pages/settings-page.md +206 -0
- package/dist/prism-skill.md +50 -0
- package/dist/store.d.ts +203 -0
- package/dist/store.js +317 -0
- package/package.json +29 -26
- package/dist/demo-graph.d.ts.map +0 -1
- package/dist/demo-graph.js.map +0 -1
- package/dist/extractor.d.ts.map +0 -1
- package/dist/extractor.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/markdown.d.ts.map +0 -1
- package/dist/markdown.js.map +0 -1
- package/dist/md/blocks/component-demo.md +0 -19
- package/dist/md/blocks/page-header.md +0 -19
- package/dist/md/components/affix.md +0 -14
- package/dist/md/components/anchor.md +0 -14
- package/dist/md/components/auto-complete.md +0 -14
- package/dist/md/components/back-top.md +0 -14
- package/dist/md/components/border-beam.md +0 -14
- package/dist/md/components/calendar.md +0 -14
- package/dist/md/components/carousel.md +0 -14
- package/dist/md/components/cascader.md +0 -14
- package/dist/md/components/col.md +0 -14
- package/dist/md/components/collapse.md +0 -14
- package/dist/md/components/color-picker.md +0 -14
- package/dist/md/components/date-picker.md +0 -14
- package/dist/md/components/descriptions.md +0 -14
- package/dist/md/components/display-title.md +0 -20
- package/dist/md/components/divider.md +0 -14
- package/dist/md/components/drawer.md +0 -14
- package/dist/md/components/dropdown.md +0 -14
- package/dist/md/components/empty.md +0 -14
- package/dist/md/components/flex.md +0 -14
- package/dist/md/components/float-button.md +0 -14
- package/dist/md/components/form.md +0 -14
- package/dist/md/components/grid.md +0 -14
- package/dist/md/components/image.md +0 -14
- package/dist/md/components/input-number.md +0 -14
- package/dist/md/components/layout.md +0 -14
- package/dist/md/components/list.md +0 -14
- package/dist/md/components/listy.md +0 -14
- package/dist/md/components/masonry.md +0 -14
- package/dist/md/components/mentions.md +0 -14
- package/dist/md/components/menu.md +0 -14
- package/dist/md/components/modal.md +0 -14
- package/dist/md/components/popconfirm.md +0 -14
- package/dist/md/components/qrcode.md +0 -14
- package/dist/md/components/radio.md +0 -14
- package/dist/md/components/rate.md +0 -14
- package/dist/md/components/result.md +0 -14
- package/dist/md/components/row.md +0 -14
- package/dist/md/components/segmented.md +0 -14
- package/dist/md/components/space.md +0 -14
- package/dist/md/components/spin.md +0 -14
- package/dist/md/components/splitter.md +0 -14
- package/dist/md/components/statistic.md +0 -14
- package/dist/md/components/steps.md +0 -14
- package/dist/md/components/tag.md +0 -14
- package/dist/md/components/time-picker.md +0 -14
- package/dist/md/components/timeline.md +0 -14
- package/dist/md/components/tour.md +0 -14
- package/dist/md/components/transfer.md +0 -14
- package/dist/md/components/tree-select.md +0 -14
- package/dist/md/components/tree.md +0 -14
- package/dist/md/components/upload.md +0 -14
- package/dist/md/components/watermark.md +0 -14
- package/dist/md/docs/brand.md +0 -41
- package/dist/md/pages/blog-layout.md +0 -19
- package/dist/md/theme/blue-dark.md +0 -127
- package/dist/md/theme/blue-light.md +0 -129
- package/dist/md/theme/green-dark.md +0 -127
- package/dist/md/theme/green-light.md +0 -129
- package/dist/md/theme/lavender-dark.md +0 -127
- package/dist/md/theme/lavender-light.md +0 -129
- package/dist/md/theme/peach-dark.md +0 -127
- package/dist/md/theme/peach-light.md +0 -129
- package/dist/md/theme/rose-dark.md +0 -127
- package/dist/md/theme/rose-light.md +0 -129
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Section
|
|
2
|
+
|
|
3
|
+
The container and heading primitives every Block composes for rhythm.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Section, SectionHeading } from '@nanisoft/prism-ui/components/section'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
`Section` is the container primitive every Block composes. It owns the page
|
|
12
|
+
container width and the vertical rhythm (`py-16 sm:py-24`), so one page keeps one
|
|
13
|
+
rhythm instead of each block re-deriving its own padding.
|
|
14
|
+
|
|
15
|
+
`SectionHeading` is the heading that sits inside it: an optional eyebrow, a
|
|
16
|
+
title, and an optional description. Its `as` prop selects the heading level, and
|
|
17
|
+
it defaults to `h2` because a Block is composed rather than a page.
|
|
18
|
+
|
|
19
|
+
## Guidelines
|
|
20
|
+
|
|
21
|
+
### When to use
|
|
22
|
+
|
|
23
|
+
Use `Section` for any full-width band of a page, and `SectionHeading` for the
|
|
24
|
+
heading that introduces it. A Block uses both, and a page composition uses them
|
|
25
|
+
between blocks to keep the rhythm continuous.
|
|
26
|
+
|
|
27
|
+
Use `SectionHeading` with `as="h1"` when the section is the page's primary
|
|
28
|
+
heading, and with a deeper level when the document already names the content.
|
|
29
|
+
|
|
30
|
+
### When not to use
|
|
31
|
+
|
|
32
|
+
Do not use `Section` for a card or an inline group. It is a page-level band, and
|
|
33
|
+
its padding is the page's vertical rhythm; nesting it produces uneven spacing.
|
|
34
|
+
|
|
35
|
+
Do not re-declare the container width or the section padding at a call site. If
|
|
36
|
+
a band needs a different width, that is a token or a component change, not a
|
|
37
|
+
`max-w-*` on the section.
|
|
38
|
+
|
|
39
|
+
### Best practices
|
|
40
|
+
|
|
41
|
+
- One `h1` per page. Every other heading nests under it, and `SectionHeading`'s
|
|
42
|
+
default `h2` is the level below the page title.
|
|
43
|
+
- Pass `headingLevel` or `as` at the call site when a Block sits under a heading
|
|
44
|
+
the document already owns, so the outline stays single-rooted.
|
|
45
|
+
- Keep `eyebrow` opt-in. It has no default, because a hardcoded eyebrow makes
|
|
46
|
+
every consumer inherit a claim about their product.
|
|
47
|
+
- Use `align="left"` for data sections and the centered default for hero and
|
|
48
|
+
closing sections, and keep the choice consistent within a page.
|
|
49
|
+
|
|
50
|
+
### Content guidelines
|
|
51
|
+
|
|
52
|
+
- A heading is a noun phrase in sentence case.
|
|
53
|
+
- A description is one or two sentences and states the section's job.
|
|
54
|
+
- An eyebrow is a short label, three words at most, and it never repeats the
|
|
55
|
+
heading.
|
|
56
|
+
|
|
57
|
+
**A section band with a heading, at a heading level the demo owns.**
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
import { Section, SectionHeading } from '@nanisoft/prism-ui/components/section'
|
|
61
|
+
|
|
62
|
+
/** A section band with a heading, at a heading level the demo owns. */
|
|
63
|
+
export default function SectionDemo() {
|
|
64
|
+
return (
|
|
65
|
+
<Section className="bg-muted/30 rounded-xl">
|
|
66
|
+
<SectionHeading
|
|
67
|
+
as="h3"
|
|
68
|
+
eyebrow="Release 2.4"
|
|
69
|
+
title="What changed"
|
|
70
|
+
description="Three fixes and one new block. No token changes."
|
|
71
|
+
align="left"
|
|
72
|
+
className="mb-6"
|
|
73
|
+
/>
|
|
74
|
+
<p className="text-muted-foreground text-sm">
|
|
75
|
+
The section owns the container width and the vertical rhythm, so this
|
|
76
|
+
band keeps the page's spacing without re-declaring it.
|
|
77
|
+
</p>
|
|
78
|
+
</Section>
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Props
|
|
84
|
+
|
|
85
|
+
**`index`** `string` · optional · default: — — A short ordinal for the section: "01", "02", "7". It is rendered in the mono face above the title, because a section's position in a sequence is machine notation rather than a word, and the mono stack is what this repository annotates machine-readable values with. It is a separate prop from `eyebrow` and not a default value of it, because the two say different things: an eyebrow is a word a reader reads, and an index is a number that is only meaningful beside the section it counts. All four NaniSoft sites render one of these above every section heading, and three of them render it beside a label rather than above a title, which is the same fact in a different arrangement.
|
|
86
|
+
**`eyebrow`** `ReactNode` · optional · default: —
|
|
87
|
+
**`title`** `ReactNode` · required · default: —
|
|
88
|
+
**`description`** `ReactNode` · optional · default: —
|
|
89
|
+
**`align`** `'center' | 'left'` · optional · default: —
|
|
90
|
+
**`as`** `HeadingLevel` · optional · default: — — Heading level. Defaults to `h2` because blocks compose under a page heading. A page that renders a block as its primary heading passes `as="h1"`; a document with no `h1` gives screen-reader and search engines no top-level entry point.
|
|
91
|
+
**`className`** `string` · optional · default: —
|
|
@@ -1,14 +1,150 @@
|
|
|
1
1
|
# Select
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The control that chooses one option from a list that opens on demand.
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
import { Select } from '@nanisoft/prism-ui/components'
|
|
5
|
+
```tsx
|
|
6
|
+
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem, SelectGroup, SelectLabel, SelectSeparator } from '@nanisoft/prism-ui/components/select'
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A Select chooses one option from a list that opens on demand. It ships as
|
|
12
|
+
`Select`, `SelectTrigger`, `SelectValue`, `SelectContent`, `SelectItem`,
|
|
13
|
+
`SelectGroup`, `SelectLabel` and `SelectSeparator`. `Select` holds the value,
|
|
14
|
+
`SelectTrigger` shows the current choice, and `SelectContent` carries the
|
|
15
|
+
options. Pass the options to the root as `items` too, so the trigger can render
|
|
16
|
+
a label before any option has mounted.
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
The trigger is a button with a combobox role, so it is reachable by Tab. In the
|
|
19
|
+
open popup the arrow keys move through the options, typing letters jumps to a
|
|
20
|
+
match, Enter chooses, and Escape closes without changing the value.
|
|
21
|
+
|
|
22
|
+
## Guidelines
|
|
23
|
+
|
|
24
|
+
### When to use
|
|
25
|
+
|
|
26
|
+
Use a Select when the option set is long enough that a radio group would
|
|
27
|
+
overwhelm the form, or when only the chosen value needs to stay visible. It fits
|
|
28
|
+
settings and filters where the reader picks one value from a known list.
|
|
29
|
+
|
|
30
|
+
### When not to use
|
|
31
|
+
|
|
32
|
+
Do not use a Select for two or three mutually exclusive options. A RadioGroup
|
|
33
|
+
shows every choice at once and needs no opening click.
|
|
34
|
+
|
|
35
|
+
Do not use it when the reader may choose more than one value, or for navigation.
|
|
36
|
+
Checkboxes state independence; a link handles a route change.
|
|
37
|
+
|
|
38
|
+
### Best practices
|
|
39
|
+
|
|
40
|
+
- Pair the Select with a `FieldLabel` whose `htmlFor` matches the trigger's
|
|
41
|
+
`id`. The value shows in the trigger, so the label names the field.
|
|
42
|
+
- Pass `items` so the trigger can resolve a label before an option has mounted.
|
|
43
|
+
Without it, Base UI falls back to the raw value.
|
|
44
|
+
- Give `SelectValue` a placeholder that says what to do, such as "Choose a
|
|
45
|
+
region", rather than naming a default the reader did not choose.
|
|
46
|
+
- Add `SelectGroup` and `SelectLabel` once a list passes roughly eight options,
|
|
47
|
+
so the reader can scan by group.
|
|
48
|
+
- A disabled option is still readable. Explain why it cannot be chosen in
|
|
49
|
+
adjacent text rather than leaving a dead row unexplained.
|
|
50
|
+
|
|
51
|
+
### Content guidelines
|
|
52
|
+
|
|
53
|
+
- Write option labels as sentence-case nouns: "Europe West", not "EUROPE WEST".
|
|
54
|
+
- Order options by the reader's expectation: size, plan, region, or product.
|
|
55
|
+
- Reserve the first option for a real choice. Do not add an empty "Select one"
|
|
56
|
+
row when the placeholder already asks the question.
|
|
57
|
+
|
|
58
|
+
**A labelled Select with a grouped option list and a controlled value.**
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
'use client'
|
|
62
|
+
|
|
63
|
+
import { useState } from 'react'
|
|
64
|
+
|
|
65
|
+
import { Field, FieldLabel } from '@nanisoft/prism-ui/components/field'
|
|
66
|
+
import {
|
|
67
|
+
Select,
|
|
68
|
+
SelectContent,
|
|
69
|
+
SelectGroup,
|
|
70
|
+
SelectItem,
|
|
71
|
+
SelectLabel,
|
|
72
|
+
SelectTrigger,
|
|
73
|
+
SelectValue,
|
|
74
|
+
} from '@nanisoft/prism-ui/components/select'
|
|
75
|
+
|
|
76
|
+
/** A labelled Select with a grouped option list and a controlled value. */
|
|
77
|
+
export default function SelectDemo() {
|
|
78
|
+
const [role, setRole] = useState('editor')
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<div className="flex max-w-measure-narrow flex-col gap-6">
|
|
82
|
+
<Field>
|
|
83
|
+
<FieldLabel htmlFor="select-role">Role</FieldLabel>
|
|
84
|
+
<Select
|
|
85
|
+
value={role}
|
|
86
|
+
onValueChange={(value) => setRole(value ?? '')}
|
|
87
|
+
items={{ viewer: 'Viewer', editor: 'Editor', admin: 'Admin' }}
|
|
88
|
+
>
|
|
89
|
+
<SelectTrigger id="select-role" className="w-full">
|
|
90
|
+
<SelectValue placeholder="Choose a role" />
|
|
91
|
+
</SelectTrigger>
|
|
92
|
+
<SelectContent>
|
|
93
|
+
<SelectGroup>
|
|
94
|
+
<SelectLabel>Team roles</SelectLabel>
|
|
95
|
+
<SelectItem value="viewer">Viewer</SelectItem>
|
|
96
|
+
<SelectItem value="editor">Editor</SelectItem>
|
|
97
|
+
<SelectItem value="admin">Admin</SelectItem>
|
|
98
|
+
</SelectGroup>
|
|
99
|
+
</SelectContent>
|
|
100
|
+
</Select>
|
|
101
|
+
</Field>
|
|
102
|
+
<Field>
|
|
103
|
+
<FieldLabel htmlFor="select-region">Region</FieldLabel>
|
|
104
|
+
<Select
|
|
105
|
+
defaultValue="eu-west"
|
|
106
|
+
items={{
|
|
107
|
+
'eu-west': 'Europe West',
|
|
108
|
+
'us-east': 'US East',
|
|
109
|
+
'ap-south': 'Asia South',
|
|
110
|
+
}}
|
|
111
|
+
>
|
|
112
|
+
<SelectTrigger id="select-region" className="w-full">
|
|
113
|
+
<SelectValue placeholder="Choose a region" />
|
|
114
|
+
</SelectTrigger>
|
|
115
|
+
<SelectContent>
|
|
116
|
+
<SelectItem value="eu-west">Europe West</SelectItem>
|
|
117
|
+
<SelectItem value="us-east">US East</SelectItem>
|
|
118
|
+
<SelectItem value="ap-south" disabled>
|
|
119
|
+
Asia South (paused)
|
|
120
|
+
</SelectItem>
|
|
121
|
+
</SelectContent>
|
|
122
|
+
</Select>
|
|
123
|
+
</Field>
|
|
124
|
+
</div>
|
|
125
|
+
)
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Props
|
|
130
|
+
|
|
131
|
+
**`value`** `string` · optional · default: — — The selected value, when the select is controlled.
|
|
132
|
+
**`defaultValue`** `string` · optional · default: — — The value selected initially, for an uncontrolled select.
|
|
133
|
+
**`onValueChange`** `(value: string | null) => void` · optional · default: — — Called when the selected value changes.
|
|
134
|
+
**`open`** `boolean` · optional · default: — — The controlled open state of the popup.
|
|
135
|
+
**`defaultOpen`** `boolean` · optional · default: — — The initially open state of the popup.
|
|
136
|
+
**`onOpenChange`** `(open: boolean) => void` · optional · default: — — Called when the popup opens or closes.
|
|
137
|
+
**`name`** `string` · optional · default: — — The form field name submitted with the form.
|
|
138
|
+
**`form`** `string` · optional · default: — — Identifies the form that owns the hidden input.
|
|
139
|
+
**`required`** `boolean` · optional · default: — — Whether a value must be chosen before the form submits.
|
|
140
|
+
**`disabled`** `boolean` · optional · default: — — Whether the select ignores user interaction.
|
|
141
|
+
**`readOnly`** `boolean` · optional · default: — — Whether the user may open the popup but not change the value.
|
|
142
|
+
**`items`** `Record<string, React.ReactNode> | ReadonlyArray<{ label: React.ReactNode; value: string; }>` · optional · default: — — The options, keyed by value, so the trigger can render a label before any item has mounted. Without it, `SelectValue` shows the raw value.
|
|
143
|
+
**`itemToStringLabel`** `(value: string) => string` · optional · default: — — Converts an item value to the label shown in the trigger.
|
|
144
|
+
**`children`** `React.ReactNode` · optional · default: — — The trigger and the popup content.
|
|
145
|
+
**`size`** `'sm' | 'default'` · optional · default: `default` — The trigger's height.
|
|
146
|
+
**`placeholder`** `React.ReactNode` · optional · default: — — Shown when no value is selected.
|
|
147
|
+
**`side`** `'top' | 'right' | 'bottom' | 'left'` · optional · default: `bottom` — Which side of the trigger the list is placed on.
|
|
148
|
+
**`align`** `'start' | 'center' | 'end'` · optional · default: `center` — How the list aligns against the trigger.
|
|
149
|
+
**`sideOffset`** `number` · optional · default: `4` — The distance in pixels between the trigger and the list.
|
|
150
|
+
**`label`** `string` · optional · default: — — A text label used for keyboard typeahead when the option text differs.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Separator
|
|
2
|
+
|
|
3
|
+
A hairline rule that divides content, horizontally or vertically.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Separator } from '@nanisoft/prism-ui/components/separator'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A Separator is a hairline rule that divides content. It renders a single
|
|
12
|
+
`<div>` at either `horizontal` or `vertical` orientation, drawn with the border
|
|
13
|
+
token.
|
|
14
|
+
|
|
15
|
+
The rule is decorative by default, so it is hidden from assistive technology and
|
|
16
|
+
does not enter the reading order. Pass `decorative={false}` when the rule marks a
|
|
17
|
+
real separation in a set of controls, such as between groups in a toolbar, and
|
|
18
|
+
it becomes an ARIA separator with a matching orientation.
|
|
19
|
+
|
|
20
|
+
## Guidelines
|
|
21
|
+
|
|
22
|
+
### When to use
|
|
23
|
+
|
|
24
|
+
Use a Separator to divide two groups of content in a stack, or two items inside
|
|
25
|
+
a horizontal row such as a toolbar or a breadcrumb-style meta line.
|
|
26
|
+
|
|
27
|
+
### When not to use
|
|
28
|
+
|
|
29
|
+
Do not use a Separator where whitespace would do. A rule between two paragraphs
|
|
30
|
+
adds ink without adding structure; space already separates them.
|
|
31
|
+
|
|
32
|
+
Do not use one as a card border or a panel edge. A surface boundary is a border
|
|
33
|
+
on the surface itself, not a rule placed beside it.
|
|
34
|
+
|
|
35
|
+
Do not use a Separator as decoration. A rule that does not divide anything is
|
|
36
|
+
noise the reader has to interpret.
|
|
37
|
+
|
|
38
|
+
### Best practices
|
|
39
|
+
|
|
40
|
+
- Keep the default `horizontal` orientation for stacked content and switch to
|
|
41
|
+
`vertical` only inside a row.
|
|
42
|
+
- Give a vertical Separator a height through its parent. It fills the parent's
|
|
43
|
+
height, so a parent with no height collapses the rule to nothing.
|
|
44
|
+
- Leave the rule decorative unless it marks a boundary a screen reader needs,
|
|
45
|
+
and pass `decorative={false}` only in that case.
|
|
46
|
+
- Use one orientation per region. Mixing rules in a single stack reads as two
|
|
47
|
+
different structures.
|
|
48
|
+
- Prefer the token's hairline and colour. A thicker or tinted rule is a second
|
|
49
|
+
visual language for the same job.
|
|
50
|
+
|
|
51
|
+
**A horizontal rule between rows, and vertical rules inside one row.**
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import { Separator } from '@nanisoft/prism-ui/components/separator'
|
|
55
|
+
|
|
56
|
+
/** A horizontal rule between rows, and vertical rules inside one row. */
|
|
57
|
+
export default function SeparatorDemo() {
|
|
58
|
+
return (
|
|
59
|
+
<div className="flex max-w-measure flex-col gap-4">
|
|
60
|
+
<p className="text-muted-foreground text-sm">Account</p>
|
|
61
|
+
<Separator />
|
|
62
|
+
<p className="text-muted-foreground text-sm">Notifications</p>
|
|
63
|
+
<div className="flex h-5 items-center gap-4">
|
|
64
|
+
<span className="text-sm">Draft</span>
|
|
65
|
+
<Separator orientation="vertical" />
|
|
66
|
+
<span className="text-sm">Review</span>
|
|
67
|
+
<Separator orientation="vertical" />
|
|
68
|
+
<span className="text-sm">Published</span>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Props
|
|
76
|
+
|
|
77
|
+
> Extends: the native `<div>` element. No additional Prism-specific props.
|
|
@@ -1,14 +1,78 @@
|
|
|
1
1
|
# Skeleton
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A placeholder surface that mirrors the shape of content while it loads.
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
import { Skeleton } from '@nanisoft/prism-ui/components'
|
|
5
|
+
```tsx
|
|
6
|
+
import { Skeleton } from '@nanisoft/prism-ui/components/skeleton'
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A Skeleton is a placeholder surface that mirrors the shape of content while it
|
|
12
|
+
loads. It renders a single muted `<div>` whose size comes from `className`, so
|
|
13
|
+
one component stands in for a title, a line of text, an avatar or an action.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
It ships without a shimmer on purpose. Prism authors no keyframes, so the
|
|
16
|
+
placeholder is static and the shape, not a pulse, is what tells the reader that
|
|
17
|
+
content is coming. The element is hidden from assistive technology, so a screen
|
|
18
|
+
reader hears the finished content when it arrives rather than an empty box.
|
|
19
|
+
|
|
20
|
+
## Guidelines
|
|
21
|
+
|
|
22
|
+
### When to use
|
|
23
|
+
|
|
24
|
+
Use a Skeleton when content is loading into a layout the reader already knows,
|
|
25
|
+
such as a list, a card grid or a detail panel that reloads in place. The
|
|
26
|
+
placeholder keeps the page from jumping when the content lands.
|
|
27
|
+
|
|
28
|
+
### When not to use
|
|
29
|
+
|
|
30
|
+
Do not use a Skeleton for work the reader has just started. A button that is
|
|
31
|
+
submitting shows its own loading state; a placeholder elsewhere on the page
|
|
32
|
+
implies a different region is loading.
|
|
33
|
+
|
|
34
|
+
Do not use a Skeleton as a loading indicator for the whole application. A
|
|
35
|
+
first paint with no known layout is better served by a spinner or a simple
|
|
36
|
+
progress bar.
|
|
37
|
+
|
|
38
|
+
Do not use one when the load is near instant. A placeholder that appears and
|
|
39
|
+
disappears within a frame reads as a glitch.
|
|
40
|
+
|
|
41
|
+
### Best practices
|
|
42
|
+
|
|
43
|
+
- Match the final shape and size. A skeleton smaller than the content it
|
|
44
|
+
replaces causes a layout shift, which is the problem it exists to prevent.
|
|
45
|
+
- Group the placeholders of one region into a single block, and mirror the real
|
|
46
|
+
structure: a title line, two body lines, an action.
|
|
47
|
+
- Keep the surrounding layout identical to the loaded state, so only the content
|
|
48
|
+
changes.
|
|
49
|
+
- Render the same number of placeholder rows as the content the layout will
|
|
50
|
+
hold. A grid that collapses from six boxes to two is a lie in both states.
|
|
51
|
+
- Do not add a spinner inside a skeleton. One loading signal per region is
|
|
52
|
+
enough.
|
|
53
|
+
- Keep the placeholder decorative. The live region around it, or the arriving
|
|
54
|
+
content, should carry the announcement.
|
|
55
|
+
|
|
56
|
+
**A card-shaped placeholder: title, two body lines and an action.**
|
|
57
|
+
|
|
58
|
+
```tsx
|
|
59
|
+
import { Skeleton } from '@nanisoft/prism-ui/components/skeleton'
|
|
60
|
+
|
|
61
|
+
/** A card-shaped placeholder: title, two body lines and an action. */
|
|
62
|
+
export default function SkeletonDemo() {
|
|
63
|
+
return (
|
|
64
|
+
<div className="flex max-w-measure-narrow flex-col gap-4">
|
|
65
|
+
<Skeleton className="h-5 w-40" />
|
|
66
|
+
<div className="flex flex-col gap-2">
|
|
67
|
+
<Skeleton className="h-4 w-full" />
|
|
68
|
+
<Skeleton className="h-4 w-4/5" />
|
|
69
|
+
</div>
|
|
70
|
+
<Skeleton className="h-9 w-28" />
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Props
|
|
77
|
+
|
|
78
|
+
> Extends: the native `<div>` element. No additional Prism-specific props.
|
|
@@ -1,14 +1,97 @@
|
|
|
1
1
|
# Slider
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The control that chooses a number along a range.
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
import { Slider } from '@nanisoft/prism-ui/components'
|
|
5
|
+
```tsx
|
|
6
|
+
import { Slider } from '@nanisoft/prism-ui/components/slider'
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A Slider chooses a number along a range. It renders a styled track with a real
|
|
12
|
+
range input beside it, so it is reachable by Tab and moved by the arrow keys,
|
|
13
|
+
with Home and End jumping to the ends. The current value is exposed to assistive
|
|
14
|
+
technology through the input's range semantics.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
Use the `min`, `max` and `step` props to describe the range, and give the
|
|
17
|
+
control an `aria-label` or a visible label, because a slider with no name tells
|
|
18
|
+
a screen reader nothing about what it changes.
|
|
19
|
+
|
|
20
|
+
## Guidelines
|
|
21
|
+
|
|
22
|
+
### When to use
|
|
23
|
+
|
|
24
|
+
Use a Slider when the value is approximate and the reader benefits from seeing
|
|
25
|
+
where it sits in a range: volume, opacity, a threshold, a size with a sensible
|
|
26
|
+
middle.
|
|
27
|
+
|
|
28
|
+
### When not to use
|
|
29
|
+
|
|
30
|
+
Do not use a Slider when the exact number matters. An Input of type number lets
|
|
31
|
+
the reader type or step to the value and is easier to make precise.
|
|
32
|
+
|
|
33
|
+
Do not use one for a range with only two or three meaningful positions. A
|
|
34
|
+
RadioGroup or a Select names each choice; a slider makes the reader hunt.
|
|
35
|
+
|
|
36
|
+
Do not use a Slider for a value you cannot plot, such as a colour name. Pick the
|
|
37
|
+
control that matches the kind of value.
|
|
38
|
+
|
|
39
|
+
### Best practices
|
|
40
|
+
|
|
41
|
+
- Pair the control with a visible label and an `aria-label`. The label names the
|
|
42
|
+
quantity; the value is read from the control.
|
|
43
|
+
- Snap the range to meaningful steps. `step` should divide the span from `min`
|
|
44
|
+
to `max` evenly, so every reachable value is one the reader would want.
|
|
45
|
+
- Show the current value near the slider when precision matters, and update it
|
|
46
|
+
as the value changes.
|
|
47
|
+
- Set sensible `min` and `max` for the task. An unbounded slider invites values
|
|
48
|
+
the rest of the product cannot use.
|
|
49
|
+
- Use the disabled state with a nearby reason, as with any other control.
|
|
50
|
+
|
|
51
|
+
### Content guidelines
|
|
52
|
+
|
|
53
|
+
- Name the quantity, not the control: "Opacity", "Export size".
|
|
54
|
+
- Keep units out of the label when they can live in the value readout, and
|
|
55
|
+
include them in the readout when they are needed.
|
|
56
|
+
- Avoid phrasing the label as a question. State the value being set.
|
|
57
|
+
|
|
58
|
+
**Sliders for an adjustable value, a stepped value and a disabled one.**
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
'use client'
|
|
62
|
+
|
|
63
|
+
import { Slider } from '@nanisoft/prism-ui/components/slider'
|
|
64
|
+
|
|
65
|
+
/** Sliders for an adjustable value, a stepped value and a disabled one. */
|
|
66
|
+
export default function SliderDemo() {
|
|
67
|
+
return (
|
|
68
|
+
<div className="flex max-w-measure-narrow flex-col gap-8">
|
|
69
|
+
<div className="flex flex-col gap-3">
|
|
70
|
+
<p className="text-sm font-medium">Opacity</p>
|
|
71
|
+
<Slider defaultValue={75} aria-label="Opacity" />
|
|
72
|
+
</div>
|
|
73
|
+
<div className="flex flex-col gap-3">
|
|
74
|
+
<p className="text-sm font-medium">Export size</p>
|
|
75
|
+
<Slider defaultValue={40} aria-label="Export size" min={0} max={100} step={10} />
|
|
76
|
+
</div>
|
|
77
|
+
<div className="flex flex-col gap-3">
|
|
78
|
+
<p className="text-muted-foreground text-sm font-medium">Frame rate</p>
|
|
79
|
+
<Slider defaultValue={60} aria-label="Frame rate" disabled />
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Props
|
|
87
|
+
|
|
88
|
+
**`value`** `number` · optional · default: — — The current value, when the slider is controlled.
|
|
89
|
+
**`defaultValue`** `number` · optional · default: — — The value the slider starts at, for an uncontrolled slider.
|
|
90
|
+
**`min`** `number` · optional · default: `0` — The minimum allowed value.
|
|
91
|
+
**`max`** `number` · optional · default: `100` — The maximum allowed value.
|
|
92
|
+
**`step`** `number` · optional · default: `1` — The granularity the slider steps by.
|
|
93
|
+
**`disabled`** `boolean` · optional · default: — — Whether the slider ignores user interaction.
|
|
94
|
+
**`orientation`** `'horizontal' | 'vertical'` · optional · default: `horizontal` — The axis the slider moves along.
|
|
95
|
+
**`name`** `string` · optional · default: — — The form field name submitted with the form.
|
|
96
|
+
**`form`** `string` · optional · default: — — Identifies the form that owns the hidden input.
|
|
97
|
+
**`onValueChange`** `(value: number) => void` · optional · default: — — Called as the value changes.
|
|
@@ -1,14 +1,111 @@
|
|
|
1
1
|
# Switch
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The control that turns a setting on or off immediately.
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
import { Switch } from '@nanisoft/prism-ui/components'
|
|
5
|
+
```tsx
|
|
6
|
+
import { Switch } from '@nanisoft/prism-ui/components/switch'
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A Switch turns a single setting on or off, and the change takes effect at once.
|
|
12
|
+
It renders a styled track with a hidden native checkbox beside it, so it submits
|
|
13
|
+
with a form while reading as a physical toggle. Space toggles the focused
|
|
14
|
+
control, and its on and off states are announced to assistive technology.
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
The difference from a Checkbox is timing, not shape. A Switch is a setting that
|
|
17
|
+
is already in force; a Checkbox is a choice collected before a save.
|
|
18
|
+
|
|
19
|
+
## Guidelines
|
|
20
|
+
|
|
21
|
+
### When to use
|
|
22
|
+
|
|
23
|
+
Use a Switch when flipping the control applies the change immediately and the
|
|
24
|
+
reader expects no further step: enabling notifications, publishing a preview, or
|
|
25
|
+
turning a feature on.
|
|
26
|
+
|
|
27
|
+
### When not to use
|
|
28
|
+
|
|
29
|
+
Do not use a Switch inside a form that still needs a Save action. If the change
|
|
30
|
+
is pending a submit, a Checkbox is the honest control.
|
|
31
|
+
|
|
32
|
+
Do not use one to choose between two named options, such as Light and Dark. That
|
|
33
|
+
is a choice between values, and a RadioGroup or a Select names both.
|
|
34
|
+
|
|
35
|
+
Do not use a Switch for an action that cannot be undone with the same control. A
|
|
36
|
+
one-way action is a Button.
|
|
37
|
+
|
|
38
|
+
### Best practices
|
|
39
|
+
|
|
40
|
+
- Label the setting, not the state. The label describes what the switch
|
|
41
|
+
controls; the on and off positions are conveyed by the control itself.
|
|
42
|
+
- Pair each Switch with a `FieldLabel` and `htmlFor`, and put the consequence in
|
|
43
|
+
an adjacent helper line rather than in the label.
|
|
44
|
+
- For a change that affects a shared resource, confirm or offer an undo. An
|
|
45
|
+
immediate setting with wide effect is easy to flip by accident.
|
|
46
|
+
- Keep the on state visually distinct beyond position alone, so the state is
|
|
47
|
+
legible to a reader who cannot rely on the thumb's movement.
|
|
48
|
+
- Use `disabled` with a reason in reach, and prefer an explanatory line over a
|
|
49
|
+
silent greyed row.
|
|
50
|
+
|
|
51
|
+
### Content guidelines
|
|
52
|
+
|
|
53
|
+
- Write the label as the thing being controlled, in sentence case: "Release
|
|
54
|
+
notifications", "Preview builds".
|
|
55
|
+
- Keep helper text to one sentence that states the effect, including who is
|
|
56
|
+
affected when it is shared.
|
|
57
|
+
- Avoid "Enable" or "Turn on" in the label; the control already says that.
|
|
58
|
+
|
|
59
|
+
**Switches that take effect immediately, one of them already on.**
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
'use client'
|
|
63
|
+
|
|
64
|
+
import { FieldLabel } from '@nanisoft/prism-ui/components/field'
|
|
65
|
+
import { Switch } from '@nanisoft/prism-ui/components/switch'
|
|
66
|
+
|
|
67
|
+
/** Switches that take effect immediately, one of them already on. */
|
|
68
|
+
export default function SwitchDemo() {
|
|
69
|
+
return (
|
|
70
|
+
<div className="flex max-w-measure-narrow flex-col gap-5">
|
|
71
|
+
<div className="flex items-center justify-between gap-4">
|
|
72
|
+
<div className="flex flex-col gap-1">
|
|
73
|
+
<FieldLabel htmlFor="switch-notifications">Release notifications</FieldLabel>
|
|
74
|
+
<span className="text-muted-foreground text-sm">
|
|
75
|
+
A message when a new version is published.
|
|
76
|
+
</span>
|
|
77
|
+
</div>
|
|
78
|
+
<Switch id="switch-notifications" defaultChecked />
|
|
79
|
+
</div>
|
|
80
|
+
<div className="flex items-center justify-between gap-4">
|
|
81
|
+
<div className="flex flex-col gap-1">
|
|
82
|
+
<FieldLabel htmlFor="switch-preview">Preview builds</FieldLabel>
|
|
83
|
+
<span className="text-muted-foreground text-sm">
|
|
84
|
+
Build every pull request on the free plan.
|
|
85
|
+
</span>
|
|
86
|
+
</div>
|
|
87
|
+
<Switch id="switch-preview" />
|
|
88
|
+
</div>
|
|
89
|
+
<div className="flex items-center justify-between gap-4">
|
|
90
|
+
<FieldLabel htmlFor="switch-sso" className="text-muted-foreground">
|
|
91
|
+
Single sign-on
|
|
92
|
+
</FieldLabel>
|
|
93
|
+
<Switch id="switch-sso" disabled />
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Props
|
|
101
|
+
|
|
102
|
+
**`checked`** `boolean` · optional · default: — — The controlled active state.
|
|
103
|
+
**`defaultChecked`** `boolean` · optional · default: — — The initially active state, for an uncontrolled switch.
|
|
104
|
+
**`disabled`** `boolean` · optional · default: — — Whether the control ignores user interaction.
|
|
105
|
+
**`readOnly`** `boolean` · optional · default: — — Whether the user may not change the state.
|
|
106
|
+
**`required`** `boolean` · optional · default: — — Whether the state must be active before the form submits.
|
|
107
|
+
**`name`** `string` · optional · default: — — The form field name submitted with the form.
|
|
108
|
+
**`value`** `string` · optional · default: — — The value submitted when the switch is on.
|
|
109
|
+
**`uncheckedValue`** `string` · optional · default: — — The value submitted when the switch is off.
|
|
110
|
+
**`form`** `string` · optional · default: — — Identifies the form that owns the hidden input.
|
|
111
|
+
**`onCheckedChange`** `(checked: boolean) => void` · optional · default: — — Called when the active state changes.
|