@nanisoft/prism-llms 0.4.0 → 0.5.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 +88 -0
- package/THIRD-PARTY-NOTICES.md +48 -0
- package/dist/data.json +3996 -387
- 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 +269 -153
- package/dist/index.d.ts +12 -7
- package/dist/index.js +9 -7
- package/dist/llms-full.txt +7968 -2013
- package/dist/llms.txt +97 -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 +102 -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 +113 -0
- package/dist/md/blocks/settings-panel-01.md +148 -0
- package/dist/md/blocks/site-footer.md +103 -11
- package/dist/md/blocks/site-header.md +111 -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 +206 -0
- package/dist/md/changelogs/prism-mcp-server.md +88 -0
- package/dist/md/changelogs/prism-tokens.md +126 -0
- package/dist/md/changelogs/prism-ui.md +429 -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 +123 -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/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/pages/docs-shell.md +0 -23
- 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
|
@@ -1,14 +1,108 @@
|
|
|
1
1
|
# Checkbox
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The control for an independent yes-or-no choice, with an optional mixed state.
|
|
4
4
|
|
|
5
|
-
```
|
|
6
|
-
import { Checkbox } from '@nanisoft/prism-ui/components'
|
|
5
|
+
```tsx
|
|
6
|
+
import { Checkbox } from '@nanisoft/prism-ui/components/checkbox'
|
|
7
7
|
```
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## Overview
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
A Checkbox is an independent choice that is either ticked, unticked, or mixed.
|
|
12
|
+
It renders as a styled control with a hidden native checkbox beside it, so it
|
|
13
|
+
submits with a form and validates like the element it stands in for. Space
|
|
14
|
+
toggles the focused control, and a mixed state is announced as "mixed" rather
|
|
15
|
+
than as checked or unchecked.
|
|
13
16
|
|
|
14
|
-
|
|
17
|
+
Use the `indeterminate` prop for a parent choice that summarizes children, such
|
|
18
|
+
as a select-all control. The mixed state is a summary, not a third answer: a
|
|
19
|
+
click should move it to ticked or unticked.
|
|
20
|
+
|
|
21
|
+
## Guidelines
|
|
22
|
+
|
|
23
|
+
### When to use
|
|
24
|
+
|
|
25
|
+
Use a Checkbox when each choice stands on its own and several may be ticked, or
|
|
26
|
+
when one choice confirms something, such as accepting terms or selecting a row
|
|
27
|
+
in a table.
|
|
28
|
+
|
|
29
|
+
### When not to use
|
|
30
|
+
|
|
31
|
+
Do not use a Checkbox for a setting that takes effect the moment it changes.
|
|
32
|
+
That is a Switch, which reads as immediate rather than as pending a save.
|
|
33
|
+
|
|
34
|
+
Do not use one when exactly one of several options must be chosen. A RadioGroup
|
|
35
|
+
announces the single answer; a set of checkboxes implies that all, some or none
|
|
36
|
+
may be ticked.
|
|
37
|
+
|
|
38
|
+
Do not use a Checkbox as a button that performs an action. It holds a state, it
|
|
39
|
+
does not do a thing.
|
|
40
|
+
|
|
41
|
+
### Best practices
|
|
42
|
+
|
|
43
|
+
- Give every Checkbox a label through `FieldLabel` and `htmlFor`, or an
|
|
44
|
+
`aria-label` when the design has no room for visible text. A bare box is
|
|
45
|
+
unlabelled to a screen reader.
|
|
46
|
+
- Make the label the click target where you can, so the reader does not have to
|
|
47
|
+
hit the small control.
|
|
48
|
+
- Use `indeterminate` only to summarize child checkboxes, and update it from the
|
|
49
|
+
children rather than setting it by hand in unrelated places.
|
|
50
|
+
- Keep the state in the consumer. Pass `checked` with `onCheckedChange` for a
|
|
51
|
+
controlled box, or `defaultChecked` when the form owns it.
|
|
52
|
+
- Show a required checkbox's consequence in the label, not as a separate error
|
|
53
|
+
after submission.
|
|
54
|
+
|
|
55
|
+
### Content guidelines
|
|
56
|
+
|
|
57
|
+
- Write the label as a positive statement of what is true when ticked:
|
|
58
|
+
"Email me release notes", not "Do not email me release notes".
|
|
59
|
+
- Use sentence case and no trailing period on a short label.
|
|
60
|
+
- Put an explanation in an adjacent helper line, not inside the label.
|
|
61
|
+
|
|
62
|
+
**Checkbox at rest, ticked, mixed and disabled.**
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
'use client'
|
|
66
|
+
|
|
67
|
+
import { Checkbox } from '@nanisoft/prism-ui/components/checkbox'
|
|
68
|
+
import { FieldLabel } from '@nanisoft/prism-ui/components/field'
|
|
69
|
+
|
|
70
|
+
/** Checkbox at rest, ticked, mixed and disabled. */
|
|
71
|
+
export default function CheckboxDemo() {
|
|
72
|
+
return (
|
|
73
|
+
<div className="flex max-w-measure-narrow flex-col gap-4">
|
|
74
|
+
<div className="flex items-center gap-3">
|
|
75
|
+
<Checkbox id="checkbox-news" defaultChecked />
|
|
76
|
+
<FieldLabel htmlFor="checkbox-news">Email me release notes</FieldLabel>
|
|
77
|
+
</div>
|
|
78
|
+
<div className="flex items-center gap-3">
|
|
79
|
+
<Checkbox id="checkbox-all" indeterminate />
|
|
80
|
+
<FieldLabel htmlFor="checkbox-all">Select all invoices</FieldLabel>
|
|
81
|
+
</div>
|
|
82
|
+
<div className="flex items-center gap-3">
|
|
83
|
+
<Checkbox id="checkbox-quiet" />
|
|
84
|
+
<FieldLabel htmlFor="checkbox-quiet">Send a weekly digest</FieldLabel>
|
|
85
|
+
</div>
|
|
86
|
+
<div className="flex items-center gap-3">
|
|
87
|
+
<Checkbox id="checkbox-sso" disabled />
|
|
88
|
+
<FieldLabel htmlFor="checkbox-sso" className="text-muted-foreground">
|
|
89
|
+
Single sign-on (paid plan)
|
|
90
|
+
</FieldLabel>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Props
|
|
98
|
+
|
|
99
|
+
**`checked`** `boolean` · optional · default: — — The controlled ticked state.
|
|
100
|
+
**`defaultChecked`** `boolean` · optional · default: — — The initially ticked state, for an uncontrolled checkbox.
|
|
101
|
+
**`indeterminate`** `boolean` · optional · default: — — Whether the checkbox shows a mixed state: neither ticked nor unticked.
|
|
102
|
+
**`disabled`** `boolean` · optional · default: — — Whether the control ignores user interaction.
|
|
103
|
+
**`readOnly`** `boolean` · optional · default: — — Whether the value must be ticked before the form submits.
|
|
104
|
+
**`required`** `boolean` · optional · default: — — Whether the value must be ticked before the form submits.
|
|
105
|
+
**`name`** `string` · optional · default: — — The form field name submitted with the form.
|
|
106
|
+
**`value`** `string` · optional · default: — — The value submitted when the checkbox is ticked.
|
|
107
|
+
**`form`** `string` · optional · default: — — Identifies the form that owns the hidden input.
|
|
108
|
+
**`onCheckedChange`** `(checked: boolean) => void` · optional · default: — — Called when the ticked state changes.
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# CtaLink
|
|
2
|
+
|
|
3
|
+
The call to action that goes somewhere: a native link carrying the weight of a button.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { CtaLink } from '@nanisoft/prism-ui/components/cta-link'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
The CtaLink is the call to action that goes somewhere. It renders a native
|
|
12
|
+
`<a>` and carries the visual weight of a Button, so a marketing page can have a
|
|
13
|
+
primary action that is genuinely a link: right-clickable, openable in a new tab,
|
|
14
|
+
and announced as a link rather than as a button.
|
|
15
|
+
|
|
16
|
+
`href` is required. There is no form of this component without a destination,
|
|
17
|
+
because an action with no handler navigates nothing, and a control that
|
|
18
|
+
announces itself as a button and does not move the reader anywhere is worse than
|
|
19
|
+
a control that is plainly a button.
|
|
20
|
+
|
|
21
|
+
The rendered control is a second component rather than a `Button` that changes
|
|
22
|
+
element by prop. The design system had already answered this twice, in
|
|
23
|
+
`Breadcrumb` and in `Pagination`, where the link is a second export beside the
|
|
24
|
+
item rather than an `as` on the item. Following the existing answer costs no
|
|
25
|
+
client JavaScript: the CtaLink is a server component.
|
|
26
|
+
|
|
27
|
+
## Guidelines
|
|
28
|
+
|
|
29
|
+
### When to use
|
|
30
|
+
|
|
31
|
+
Use a CtaLink wherever the reader's intent is to go somewhere: the primary
|
|
32
|
+
action on a landing section, the closing action on a page, a cross-reference
|
|
33
|
+
between two pages.
|
|
34
|
+
|
|
35
|
+
Set `newTab` when opening a new browsing context is what the reader wants, such
|
|
36
|
+
as an external playground or a reference. The link relationship then defaults to
|
|
37
|
+
`noopener noreferrer`, so the opened page cannot reach back through `window.opener`.
|
|
38
|
+
|
|
39
|
+
### When not to use
|
|
40
|
+
|
|
41
|
+
Do not use a CtaLink for an action that changes the page's state rather than its
|
|
42
|
+
address: submitting a form, saving a change, deleting a record. That is a Button,
|
|
43
|
+
and the Button's own guidance says so.
|
|
44
|
+
|
|
45
|
+
Do not reach for `newTab` because a URL looks external. Prism does not parse the
|
|
46
|
+
destination and makes no guess about what counts as external, because a
|
|
47
|
+
cross-origin URL is not by itself a reason to take the reader out of the page
|
|
48
|
+
they are reading. Decide per link.
|
|
49
|
+
|
|
50
|
+
### Best practices
|
|
51
|
+
|
|
52
|
+
- One CtaLink per section carries `default` weight. Two primaries make neither
|
|
53
|
+
of them primary.
|
|
54
|
+
- Keep the label in the imperative and state the outcome, the same as a Button.
|
|
55
|
+
- Prefer a same-tab link unless the destination is genuinely somewhere else.
|
|
56
|
+
- If the destination is the current route, use a different control: a link to
|
|
57
|
+
where the reader already is is a dead link.
|
|
58
|
+
|
|
59
|
+
### Content guidelines
|
|
60
|
+
|
|
61
|
+
- Start with a verb: "Read the guides", "Compare variants", "Open the playground".
|
|
62
|
+
- Sentence case, no period, three words where possible.
|
|
63
|
+
- Never "Click here". The label should state the outcome, not the mechanism.
|
|
64
|
+
|
|
65
|
+
**The call to action at each variant, same tab and new tab.**
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { CtaLink } from '@nanisoft/prism-ui/components/cta-link'
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The call to action at each variant, same tab and new tab.
|
|
72
|
+
*
|
|
73
|
+
* Self-contained: the only import is from the package, and it has a default
|
|
74
|
+
* export. The file is the source for the live preview, the copy control and the
|
|
75
|
+
* corpus.
|
|
76
|
+
*/
|
|
77
|
+
export default function CtaLinkDemo() {
|
|
78
|
+
return (
|
|
79
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
80
|
+
<CtaLink href="/components/button">Read the guide</CtaLink>
|
|
81
|
+
<CtaLink href="/components/button" variant="secondary">
|
|
82
|
+
Compare variants
|
|
83
|
+
</CtaLink>
|
|
84
|
+
<CtaLink href="/components/button" variant="outline">
|
|
85
|
+
See the API
|
|
86
|
+
</CtaLink>
|
|
87
|
+
<CtaLink href="https://example.com" newTab>
|
|
88
|
+
Open the playground
|
|
89
|
+
</CtaLink>
|
|
90
|
+
</div>
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Props
|
|
96
|
+
|
|
97
|
+
**`href`** `string` · required · default: — — The destination. Required, because an anchor without one is not a link: a screen reader announces no destination, the middle-click and open-in-new-tab affordances go quiet, and the control is a button that cannot act.
|
|
98
|
+
**`newTab`** `boolean` · optional · default: — — Opens the destination in a new browsing context. This is the only way to ask for one: `target` is not accepted, so the safe relationship below cannot be opted out of by accident. Prism does not decide what counts as external. A destination on another origin is not automatically a new tab, and a destination on this origin is not automatically the same tab, so the caller declares it.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# Diagram
|
|
2
|
+
|
|
3
|
+
Named things and the labelled relations between them, drawn as inline vector markup whose every stroke and fill is a token.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Diagram } from '@nanisoft/prism-ui/components/diagram'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A Diagram draws named things and the labelled relations between them, as inline
|
|
12
|
+
vector markup. It takes its geometry as data and returns an `<svg>`, so a
|
|
13
|
+
consumer needs no hook, no mode, no provider and no client code to render one.
|
|
14
|
+
|
|
15
|
+
Every stroke and fill it draws is a semantic utility on the emitted token
|
|
16
|
+
contract, and never a resolved value. That is the whole reason it exists: a
|
|
17
|
+
drawing that reads a colour out of computed style at runtime takes its value from
|
|
18
|
+
one element, while a pack is an attribute on an ancestor, so a scoped boundary
|
|
19
|
+
hands it the pack's light values on a dark page. Inline markup inherits the pack
|
|
20
|
+
the way every other element does, and a subtree carrying a second pack restyles
|
|
21
|
+
in place.
|
|
22
|
+
|
|
23
|
+
`x` and `y` are in your coordinate space and are normalised into the canvas, so
|
|
24
|
+
fractions, pixels or any other monotonic scale draw the same shape and keep their
|
|
25
|
+
aspect ratio. A fixed canvas is deliberate: a viewBox derived from your numbers
|
|
26
|
+
would make the label size a function of how large a number you happened to use,
|
|
27
|
+
so the same drawing would come out with unreadable labels from `0..1` fractions
|
|
28
|
+
and enormous ones from `0..4000` pixels.
|
|
29
|
+
|
|
30
|
+
## Guidelines
|
|
31
|
+
|
|
32
|
+
### When to use
|
|
33
|
+
|
|
34
|
+
Use a Diagram when the thing you are showing is a set of named things and the
|
|
35
|
+
relations between them: a pipeline, a data flow, a set of moving parts. It is the
|
|
36
|
+
right replacement for a canvas that drew the same thing, because it inherits the
|
|
37
|
+
pack, ships no client code, and is legible to a screen reader.
|
|
38
|
+
|
|
39
|
+
Mark at most one node with `emphasis`. It is the node the drawing is about, and
|
|
40
|
+
it takes the brand ink. Two emphasised nodes is a caller's mistake, not a second
|
|
41
|
+
level.
|
|
42
|
+
|
|
43
|
+
Use `indirect` on a relation that happens rather than causes, for example a
|
|
44
|
+
review that follows a merge. It draws the line dashed, chosen over fading the
|
|
45
|
+
line because a dashed line keeps its contrast and a faded one does not.
|
|
46
|
+
|
|
47
|
+
### When not to use
|
|
48
|
+
|
|
49
|
+
Do not use a Diagram for a series of values, a time axis or anything quantitative.
|
|
50
|
+
A drawing of a shape with no name on it is not a diagram, and a fabricated series
|
|
51
|
+
presented under a live label is a lie the surface is not able to make.
|
|
52
|
+
|
|
53
|
+
Do not use a Diagram where the relationships are a linear sequence. A numbered
|
|
54
|
+
list is a linear sequence, and it is more honest and more accessible than a
|
|
55
|
+
drawing of one.
|
|
56
|
+
|
|
57
|
+
Do not pass `decorative` to a drawing that carries meaning. `label` is required
|
|
58
|
+
unless the drawing is decorative, and the union is what makes the compiler hold
|
|
59
|
+
that: a single optional prop could only be required everywhere or optional
|
|
60
|
+
everywhere, and both halves of that are wrong.
|
|
61
|
+
|
|
62
|
+
### Best practices
|
|
63
|
+
|
|
64
|
+
- Give the Diagram a `label` that says what the drawing is, not what it is called.
|
|
65
|
+
The name is read aloud; "How a finding is produced" beats "architecture".
|
|
66
|
+
- Keep the node count readable. A drawing that needs a legend to be understood is
|
|
67
|
+
a table.
|
|
68
|
+
- Two nodes at the same position collapse onto one another, so spread a column
|
|
69
|
+
rather than repeating a number.
|
|
70
|
+
- Put the emphasised node near the middle. The eye goes there first and the
|
|
71
|
+
relations read outward from it.
|
|
72
|
+
- Do not nest a pack boundary inside a drawing. A boundary moves the pack's
|
|
73
|
+
corner radius, and a drawing's marks are circles and paths with no radius
|
|
74
|
+
concept, so a boundary on one changes its colour and nothing else. That is the
|
|
75
|
+
property that makes a drawing safe under a boundary.
|
|
76
|
+
|
|
77
|
+
### Content guidelines
|
|
78
|
+
|
|
79
|
+
- Node names are labels: one or two words, sentence case, no period.
|
|
80
|
+
- Relation labels are the verb or preposition that says what the line is: "feeds",
|
|
81
|
+
"confirms", "blocks on".
|
|
82
|
+
- A relation label is placed beside its line rather than on it. A label drawn over
|
|
83
|
+
a line has to be knocked out with a halo, and the halo has to be filled with
|
|
84
|
+
the colour of the surface the drawing happens to sit on, which the component is
|
|
85
|
+
not told.
|
|
86
|
+
|
|
87
|
+
**A three-node loop with one emphasised node and one indirect relation.**
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { Diagram } from '@nanisoft/prism-ui/components/diagram'
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* A three-node loop with one emphasised node and one indirect relation.
|
|
94
|
+
*
|
|
95
|
+
* Self-contained: the only import is from the package, and it has a default
|
|
96
|
+
* export. No hook, no mode, no provider, which is the point of the component.
|
|
97
|
+
* The coordinates are fractions, and they draw the same shape they would as
|
|
98
|
+
* pixels.
|
|
99
|
+
*/
|
|
100
|
+
export default function DiagramDemo() {
|
|
101
|
+
return (
|
|
102
|
+
<Diagram
|
|
103
|
+
label="How a finding is produced, checked and published"
|
|
104
|
+
nodes={[
|
|
105
|
+
{ id: 'capture', name: 'Capture', x: 0.12, y: 0.3 },
|
|
106
|
+
{ id: 'read', name: 'Read', x: 0.5, y: 0.62, emphasis: true },
|
|
107
|
+
{ id: 'review', name: 'Review', x: 0.88, y: 0.3 },
|
|
108
|
+
{ id: 'publish', name: 'Publish', x: 0.5, y: 0.12 },
|
|
109
|
+
]}
|
|
110
|
+
relations={[
|
|
111
|
+
{ from: 'capture', to: 'read', label: 'feeds' },
|
|
112
|
+
{ from: 'read', to: 'review', label: 'raises' },
|
|
113
|
+
{ from: 'review', to: 'publish', label: 'confirms', indirect: true },
|
|
114
|
+
{ from: 'publish', to: 'capture', label: 'returns' },
|
|
115
|
+
]}
|
|
116
|
+
/>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Props
|
|
122
|
+
|
|
123
|
+
**`decorative`** `true` · required · default: — — Hides the drawing from assistive technology and drops the name. Use it when the surrounding sentence already says what the diagram shows, and nothing inside the hidden tree is named either: there is no `<title>` here, so there is no name stranded inside an `aria-hidden` subtree.
|
|
124
|
+
**`label`** `never` · optional · default: —
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
The modal surface for a decision or a short task, with a side-anchored sheet variant.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, DialogClose } from '@nanisoft/prism-ui/components/dialog'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A Dialog is a modal surface for a decision or a short task. It ships as
|
|
12
|
+
`Dialog`, `DialogTrigger`, `DialogContent`, `DialogHeader`, `DialogFooter`,
|
|
13
|
+
`DialogTitle`, `DialogDescription` and `DialogClose`. It also covers the old
|
|
14
|
+
drawer pattern through the `side` prop on `DialogContent`: `center` is the modal
|
|
15
|
+
card, and `top`, `bottom`, `left` and `right` anchor the panel to an edge as a
|
|
16
|
+
sheet.
|
|
17
|
+
|
|
18
|
+
While it is open the dialog traps focus, locks page scroll, closes on Escape and
|
|
19
|
+
on an outside press, and returns focus to its trigger when it closes. Always
|
|
20
|
+
render a `DialogTitle`: it names the dialog and is announced on open.
|
|
21
|
+
|
|
22
|
+
## Guidelines
|
|
23
|
+
|
|
24
|
+
### When to use
|
|
25
|
+
|
|
26
|
+
Use a Dialog when the reader must stop and make a decision before continuing, or
|
|
27
|
+
when a short task needs focus without losing the page behind it: a confirmation,
|
|
28
|
+
a rename, or a compact form.
|
|
29
|
+
|
|
30
|
+
### When not to use
|
|
31
|
+
|
|
32
|
+
Do not use a Dialog for content that is not a task. Reading material or settings
|
|
33
|
+
belong on a page or in a Popover.
|
|
34
|
+
|
|
35
|
+
Do not stack dialogs, and do not use a centered Dialog for a long list or a
|
|
36
|
+
full-screen form. The side variant covers a sheet.
|
|
37
|
+
|
|
38
|
+
### Best practices
|
|
39
|
+
|
|
40
|
+
- Always include a `DialogTitle`. It is the dialog's accessible name, and
|
|
41
|
+
without it a screen reader announces an unnamed dialog.
|
|
42
|
+
- Put the primary action last in `DialogFooter`, and keep one primary action per
|
|
43
|
+
dialog.
|
|
44
|
+
- For a destructive action, state the consequence in the `DialogDescription`,
|
|
45
|
+
not only in the button label.
|
|
46
|
+
- The component returns focus to the trigger on close, so the reader resumes
|
|
47
|
+
where they left off. Do not move focus yourself.
|
|
48
|
+
- Prefer the side variant on narrow screens when the reader is deciding about
|
|
49
|
+
content the centered card would cover.
|
|
50
|
+
|
|
51
|
+
### Content guidelines
|
|
52
|
+
|
|
53
|
+
- Make the title a short statement of the task: "Rename workspace", not "Are you
|
|
54
|
+
sure?".
|
|
55
|
+
- Put the consequence in the description, in one sentence, before the actions.
|
|
56
|
+
- Name the action in the confirming button: "Delete project", not "Confirm".
|
|
57
|
+
|
|
58
|
+
**A centered modal and a side-anchored sheet, the old drawer re-expressed.**
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
'use client'
|
|
62
|
+
|
|
63
|
+
import { Button } from '@nanisoft/prism-ui/components/button'
|
|
64
|
+
import {
|
|
65
|
+
Dialog,
|
|
66
|
+
DialogClose,
|
|
67
|
+
DialogContent,
|
|
68
|
+
DialogDescription,
|
|
69
|
+
DialogFooter,
|
|
70
|
+
DialogHeader,
|
|
71
|
+
DialogTitle,
|
|
72
|
+
DialogTrigger,
|
|
73
|
+
} from '@nanisoft/prism-ui/components/dialog'
|
|
74
|
+
|
|
75
|
+
/** A centered modal and a side-anchored sheet, the old drawer re-expressed. */
|
|
76
|
+
export default function DialogDemo() {
|
|
77
|
+
return (
|
|
78
|
+
<div className="flex flex-wrap items-center gap-3">
|
|
79
|
+
<Dialog>
|
|
80
|
+
<DialogTrigger>Rename workspace</DialogTrigger>
|
|
81
|
+
<DialogContent>
|
|
82
|
+
<DialogHeader>
|
|
83
|
+
<DialogTitle>Rename workspace</DialogTitle>
|
|
84
|
+
<DialogDescription>
|
|
85
|
+
The new name appears in every menu, link and email.
|
|
86
|
+
</DialogDescription>
|
|
87
|
+
</DialogHeader>
|
|
88
|
+
<DialogFooter>
|
|
89
|
+
<DialogClose className="bg-background hover:bg-accent hover:text-accent-foreground h-9 rounded-md border px-4 text-sm font-medium">
|
|
90
|
+
Cancel
|
|
91
|
+
</DialogClose>
|
|
92
|
+
<Button>Rename</Button>
|
|
93
|
+
</DialogFooter>
|
|
94
|
+
</DialogContent>
|
|
95
|
+
</Dialog>
|
|
96
|
+
|
|
97
|
+
<Dialog>
|
|
98
|
+
<DialogTrigger>Open filters</DialogTrigger>
|
|
99
|
+
<DialogContent side="right">
|
|
100
|
+
<DialogHeader>
|
|
101
|
+
<DialogTitle>Filters</DialogTitle>
|
|
102
|
+
<DialogDescription>Narrow the table to the rows you need.</DialogDescription>
|
|
103
|
+
</DialogHeader>
|
|
104
|
+
<p className="text-muted-foreground text-sm">
|
|
105
|
+
Filters open from the edge on a narrow screen, where a centered
|
|
106
|
+
dialog would hide the table.
|
|
107
|
+
</p>
|
|
108
|
+
<DialogFooter>
|
|
109
|
+
<DialogClose className="bg-background hover:bg-accent hover:text-accent-foreground h-9 rounded-md border px-4 text-sm font-medium">
|
|
110
|
+
Done
|
|
111
|
+
</DialogClose>
|
|
112
|
+
</DialogFooter>
|
|
113
|
+
</DialogContent>
|
|
114
|
+
</Dialog>
|
|
115
|
+
</div>
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Props
|
|
121
|
+
|
|
122
|
+
**`open`** `boolean` · optional · default: — — The controlled open state.
|
|
123
|
+
**`defaultOpen`** `boolean` · optional · default: — — The initially open state, for an uncontrolled dialog.
|
|
124
|
+
**`onOpenChange`** `(open: boolean) => void` · optional · default: — — Called when the open state changes.
|
|
125
|
+
**`modal`** `boolean | 'trap-focus'` · optional · default: `true` — Whether the dialog is modal.
|
|
126
|
+
**`children`** `React.ReactNode` · optional · default: — — The trigger and content.
|
|
127
|
+
**`side`** `'center' | 'top' | 'bottom' | 'left' | 'right'` · optional · default: `center` — Where the dialog is anchored. `center` is a modal card; `top`, `bottom`, `left` and `right` anchor the panel to an edge as a sheet, which is the old drawer re-expressed.
|
|
128
|
+
**`showCloseButton`** `boolean` · optional · default: `true` — Whether the built-in close control is rendered.
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# DropdownMenu
|
|
2
|
+
|
|
3
|
+
The menu of actions and choices opened from one trigger.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent } from '@nanisoft/prism-ui/components/dropdown-menu'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A DropdownMenu is a list of actions and choices opened from one trigger. It
|
|
12
|
+
ships as `DropdownMenu`, `DropdownMenuTrigger`, `DropdownMenuContent`,
|
|
13
|
+
`DropdownMenuItem`, `DropdownMenuCheckboxItem`, `DropdownMenuRadioItem`,
|
|
14
|
+
`DropdownMenuLabel`, `DropdownMenuSeparator`, `DropdownMenuGroup`,
|
|
15
|
+
`DropdownMenuSub`, `DropdownMenuSubTrigger` and `DropdownMenuSubContent`.
|
|
16
|
+
|
|
17
|
+
The menu supports arrow-key navigation, typeahead by item label, Home and End,
|
|
18
|
+
and Escape to close. A submenu opens from its trigger with the right arrow, and
|
|
19
|
+
focus returns to the trigger when the menu closes.
|
|
20
|
+
|
|
21
|
+
## Guidelines
|
|
22
|
+
|
|
23
|
+
### When to use
|
|
24
|
+
|
|
25
|
+
Use a DropdownMenu for a short list of commands attached to one control: a row's
|
|
26
|
+
actions, an account menu, or a toolbar overflow. It keeps secondary actions out
|
|
27
|
+
of the way without losing them.
|
|
28
|
+
|
|
29
|
+
### When not to use
|
|
30
|
+
|
|
31
|
+
Do not hide a primary action in a menu. If it is the main thing a view is for,
|
|
32
|
+
keep it visible as a Button.
|
|
33
|
+
|
|
34
|
+
Do not use a DropdownMenu for navigation between pages, and do not nest menus
|
|
35
|
+
more than one level deep. Both cases want a page or a sidebar.
|
|
36
|
+
|
|
37
|
+
### Best practices
|
|
38
|
+
|
|
39
|
+
- Put a `DropdownMenuLabel` inside a `DropdownMenuGroup`. The label is tied to
|
|
40
|
+
its group, so it must have one.
|
|
41
|
+
- Use `DropdownMenuCheckboxItem` for toggles that do not close the menu, so the
|
|
42
|
+
reader can change several in a row.
|
|
43
|
+
- Put a destructive action last, after a `DropdownMenuSeparator`, with
|
|
44
|
+
`variant="destructive"`.
|
|
45
|
+
- Keep items to a verb or a short noun phrase, and name the object when the
|
|
46
|
+
action is ambiguous: "Duplicate project" beats "Duplicate".
|
|
47
|
+
- One level of `DropdownMenuSub` is the ceiling. Beyond that, promote the
|
|
48
|
+
commands to a page.
|
|
49
|
+
|
|
50
|
+
### Content guidelines
|
|
51
|
+
|
|
52
|
+
- Write items as imperative commands: "Duplicate", "Archive", "Sign out".
|
|
53
|
+
- Use sentence case and no trailing periods.
|
|
54
|
+
- Group related commands and label the group in sentence case, such as
|
|
55
|
+
"Account" or "Danger zone".
|
|
56
|
+
|
|
57
|
+
**A menu with items, a checkbox item and a nested submenu.**
|
|
58
|
+
|
|
59
|
+
```tsx
|
|
60
|
+
'use client'
|
|
61
|
+
|
|
62
|
+
import {
|
|
63
|
+
DropdownMenu,
|
|
64
|
+
DropdownMenuCheckboxItem,
|
|
65
|
+
DropdownMenuContent,
|
|
66
|
+
DropdownMenuGroup,
|
|
67
|
+
DropdownMenuItem,
|
|
68
|
+
DropdownMenuLabel,
|
|
69
|
+
DropdownMenuSeparator,
|
|
70
|
+
DropdownMenuSub,
|
|
71
|
+
DropdownMenuSubContent,
|
|
72
|
+
DropdownMenuSubTrigger,
|
|
73
|
+
DropdownMenuTrigger,
|
|
74
|
+
} from '@nanisoft/prism-ui/components/dropdown-menu'
|
|
75
|
+
|
|
76
|
+
/** A menu with items, a checkbox item and a nested submenu. */
|
|
77
|
+
export default function DropdownMenuDemo() {
|
|
78
|
+
return (
|
|
79
|
+
<DropdownMenu>
|
|
80
|
+
<DropdownMenuTrigger>Open menu</DropdownMenuTrigger>
|
|
81
|
+
<DropdownMenuContent className="w-56">
|
|
82
|
+
<DropdownMenuGroup>
|
|
83
|
+
<DropdownMenuLabel>Account</DropdownMenuLabel>
|
|
84
|
+
<DropdownMenuItem>Profile</DropdownMenuItem>
|
|
85
|
+
<DropdownMenuItem>Settings</DropdownMenuItem>
|
|
86
|
+
</DropdownMenuGroup>
|
|
87
|
+
<DropdownMenuSeparator />
|
|
88
|
+
<DropdownMenuCheckboxItem defaultChecked>
|
|
89
|
+
Show archived rows
|
|
90
|
+
</DropdownMenuCheckboxItem>
|
|
91
|
+
<DropdownMenuSub>
|
|
92
|
+
<DropdownMenuSubTrigger>Invite</DropdownMenuSubTrigger>
|
|
93
|
+
<DropdownMenuSubContent>
|
|
94
|
+
<DropdownMenuItem>Send by email</DropdownMenuItem>
|
|
95
|
+
<DropdownMenuItem>Copy invite link</DropdownMenuItem>
|
|
96
|
+
</DropdownMenuSubContent>
|
|
97
|
+
</DropdownMenuSub>
|
|
98
|
+
<DropdownMenuSeparator />
|
|
99
|
+
<DropdownMenuItem variant="destructive">Sign out</DropdownMenuItem>
|
|
100
|
+
</DropdownMenuContent>
|
|
101
|
+
</DropdownMenu>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Props
|
|
107
|
+
|
|
108
|
+
**`open`** `boolean` · optional · default: — — The controlled open state.
|
|
109
|
+
**`defaultOpen`** `boolean` · optional · default: — — The initially open state, for an uncontrolled menu.
|
|
110
|
+
**`onOpenChange`** `(open: boolean) => void` · optional · default: — — Called when the open state changes.
|
|
111
|
+
**`disabled`** `boolean` · optional · default: — — Whether the menu ignores user interaction.
|
|
112
|
+
**`children`** `React.ReactNode` · optional · default: — — The trigger and the menu content.
|
|
113
|
+
**`side`** `'top' | 'right' | 'bottom' | 'left'` · optional · default: `bottom` — Which side of the trigger the menu is placed on.
|
|
114
|
+
**`align`** `'start' | 'center' | 'end'` · optional · default: `start` — How the menu aligns against the trigger.
|
|
115
|
+
**`sideOffset`** `number` · optional · default: `4` — The distance in pixels between the trigger and the menu.
|
|
116
|
+
**`alignOffset`** `number` · optional · default: `0` — The offset in pixels along the alignment axis.
|
|
117
|
+
**`inset`** `boolean` · optional · default: `false` — Whether the item aligns with the labels above it.
|
|
118
|
+
**`variant`** `'default' | 'destructive'` · optional · default: `default` — Whether the item reads as a destructive action.
|
|
119
|
+
**`closeOnClick`** `boolean` · optional · default: `true` — Whether the menu closes when the item is chosen.
|
|
120
|
+
**`checked`** `boolean` · optional · default: — — The controlled ticked state.
|
|
121
|
+
**`defaultChecked`** `boolean` · optional · default: — — The initially ticked state, for an uncontrolled item.
|
|
122
|
+
**`onCheckedChange`** `(checked: boolean) => void` · optional · default: — — Called when the ticked state changes.
|
|
123
|
+
**`value`** `string` · optional · default: — — The controlled value of the selected radio item.
|
|
124
|
+
**`defaultValue`** `string` · optional · default: — — The initially selected value, for an uncontrolled group.
|
|
125
|
+
**`onValueChange`** `(value: string) => void` · optional · default: — — Called when the selected value changes.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# FactList
|
|
2
|
+
|
|
3
|
+
A short list of named facts as a definition list, where a value may be a link and the term column stays aligned down its length.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { FactList } from '@nanisoft/prism-ui/components/fact-list'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
A FactList is a short list of named facts: a term beside its value, in a column a
|
|
12
|
+
reader can scan. It renders a real `<dl>`, so a screen reader announces the term
|
|
13
|
+
before the value instead of reading a list of labels and then a list of answers.
|
|
14
|
+
|
|
15
|
+
Every NaniSoft site states facts beside prose: what a plan costs, what a feed
|
|
16
|
+
carries, which version a document describes, when a collector went live. Each one
|
|
17
|
+
re-derived a `<dl>`, and each one got the alignment and the term-before-value
|
|
18
|
+
wiring subtly wrong.
|
|
19
|
+
|
|
20
|
+
## Guidelines
|
|
21
|
+
|
|
22
|
+
### When to use
|
|
23
|
+
|
|
24
|
+
Use a FactList for two to six facts that belong to one thing and are worth reading
|
|
25
|
+
together: a release, a feed source, a plan, a deployment.
|
|
26
|
+
|
|
27
|
+
Use it beside prose rather than inside it. A fact in the middle of a paragraph is
|
|
28
|
+
a sentence, and a sentence is not a fact list.
|
|
29
|
+
|
|
30
|
+
### When not to use
|
|
31
|
+
|
|
32
|
+
Do not use a FactList for a table of records. That is `Table`, and a fact list of
|
|
33
|
+
twenty rows is a table with its column headers removed.
|
|
34
|
+
|
|
35
|
+
Do not use it for a set of links. That is a footer's column or a plain list, and a
|
|
36
|
+
column of destinations is not a column of terms.
|
|
37
|
+
|
|
38
|
+
Do not use it to compare products. A comparison has a row per product and a column
|
|
39
|
+
per fact, and this is the other way round.
|
|
40
|
+
|
|
41
|
+
### Best practices
|
|
42
|
+
|
|
43
|
+
- Keep the label column short. The column is a fixed fraction so a list of facts
|
|
44
|
+
lines up down its whole length, and a label that wraps costs every other row its
|
|
45
|
+
alignment.
|
|
46
|
+
- Give a fact an `href` only when the fact is kept somewhere else. A link to a fact
|
|
47
|
+
already on the page is a click that changes nothing.
|
|
48
|
+
- Omit `label` when the list is already inside something that names it.
|
|
49
|
+
- An empty list renders nothing, so a caller with nothing to state does not get a
|
|
50
|
+
bordered box with a title above it.
|
|
51
|
+
|
|
52
|
+
### Content guidelines
|
|
53
|
+
|
|
54
|
+
- Write a label as a name, not a question: "Last capture", not "When did it last
|
|
55
|
+
capture".
|
|
56
|
+
- Keep a value to a word or a short phrase. A value that needs a sentence belongs
|
|
57
|
+
in a `NoteGrid01` row.
|
|
58
|
+
- Write values as they would be read aloud, because that is how they are scanned.
|
|
59
|
+
|
|
60
|
+
**Named facts, with one value that is a link and one that is a count.**
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { FactList } from '@nanisoft/prism-ui/components/fact-list'
|
|
64
|
+
|
|
65
|
+
/** Named facts, with one value that is a link and one that is a count. */
|
|
66
|
+
export default function FactListDemo() {
|
|
67
|
+
return (
|
|
68
|
+
<FactList
|
|
69
|
+
label="Release"
|
|
70
|
+
facts={[
|
|
71
|
+
{ label: 'Version', value: '0.5.1' },
|
|
72
|
+
{ label: 'Package', value: '@nanisoft/prism-ui' },
|
|
73
|
+
{ label: 'Axes', value: 'Two: pack and mode' },
|
|
74
|
+
{ label: 'Changelog', value: 'Read it', href: '/changelogs/prism-ui' },
|
|
75
|
+
]}
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Props
|
|
82
|
+
|
|
83
|
+
**`facts`** `readonly Fact[]` · required · default: — — The facts, in the order a reader should meet them. Order is the caller's because it is a claim about importance, and a list that sorted itself would be making that claim on the caller's behalf.
|
|
84
|
+
**`label`** `ReactNode` · optional · default: — — A heading above the list, for a set of facts that needs to say what it is. Rendered as a `dt`-level caption rather than as a heading, so it does not compete with the document's own outline.
|
|
85
|
+
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|