@nanisoft/prism-llms 0.3.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.
Files changed (175) hide show
  1. package/README.md +88 -0
  2. package/THIRD-PARTY-NOTICES.md +48 -0
  3. package/dist/data.json +3998 -375
  4. package/dist/demo-graph.d.ts +21 -12
  5. package/dist/demo-graph.js +37 -21
  6. package/dist/extractor.d.ts +24 -17
  7. package/dist/extractor.js +269 -153
  8. package/dist/index.d.ts +12 -7
  9. package/dist/index.js +9 -7
  10. package/dist/llms-full.txt +7988 -1989
  11. package/dist/llms.txt +97 -91
  12. package/dist/markdown.d.ts +69 -23
  13. package/dist/markdown.js +131 -72
  14. package/dist/md/blocks/app-shell-01.md +135 -0
  15. package/dist/md/blocks/auth-form-01.md +135 -0
  16. package/dist/md/blocks/cta-01.md +88 -0
  17. package/dist/md/blocks/data-table-01.md +196 -0
  18. package/dist/md/blocks/feature-grid-01.md +92 -0
  19. package/dist/md/blocks/hero-01.md +90 -0
  20. package/dist/md/blocks/instrument-panel-01.md +109 -0
  21. package/dist/md/blocks/logo-strip-01.md +97 -0
  22. package/dist/md/blocks/note-grid-01.md +102 -0
  23. package/dist/md/blocks/page-header-01.md +97 -0
  24. package/dist/md/blocks/pricing-01.md +91 -0
  25. package/dist/md/blocks/process-rail-01.md +106 -0
  26. package/dist/md/blocks/product-grid-01.md +113 -0
  27. package/dist/md/blocks/settings-panel-01.md +148 -0
  28. package/dist/md/blocks/site-footer.md +111 -0
  29. package/dist/md/blocks/site-header.md +119 -0
  30. package/dist/md/blocks/stack-grid-01.md +108 -0
  31. package/dist/md/blocks/stats-01.md +89 -0
  32. package/dist/md/blocks/status-ledger-01.md +121 -0
  33. package/dist/md/changelogs/prism-llms.md +206 -0
  34. package/dist/md/changelogs/prism-mcp-server.md +88 -0
  35. package/dist/md/changelogs/prism-tokens.md +126 -0
  36. package/dist/md/changelogs/prism-ui.md +429 -0
  37. package/dist/md/components/accordion.md +108 -0
  38. package/dist/md/components/alert.md +90 -7
  39. package/dist/md/components/avatar.md +89 -7
  40. package/dist/md/components/badge.md +74 -7
  41. package/dist/md/components/breadcrumb.md +84 -7
  42. package/dist/md/components/button.md +90 -7
  43. package/dist/md/components/card.md +90 -7
  44. package/dist/md/components/checkbox.md +101 -7
  45. package/dist/md/components/cta-link.md +98 -0
  46. package/dist/md/components/diagram.md +124 -0
  47. package/dist/md/components/dialog.md +128 -0
  48. package/dist/md/components/dropdown-menu.md +125 -0
  49. package/dist/md/components/fact-list.md +85 -0
  50. package/dist/md/components/field.md +116 -0
  51. package/dist/md/components/input.md +86 -7
  52. package/dist/md/components/kbd.md +77 -0
  53. package/dist/md/components/pagination.md +95 -7
  54. package/dist/md/components/popover.md +95 -7
  55. package/dist/md/components/product-mark.md +123 -0
  56. package/dist/md/components/product-switcher.md +88 -0
  57. package/dist/md/components/progress.md +88 -7
  58. package/dist/md/components/prose.md +91 -0
  59. package/dist/md/components/radio-group.md +111 -0
  60. package/dist/md/components/section.md +91 -0
  61. package/dist/md/components/select.md +143 -7
  62. package/dist/md/components/separator.md +77 -0
  63. package/dist/md/components/skeleton.md +71 -7
  64. package/dist/md/components/slider.md +90 -7
  65. package/dist/md/components/switch.md +104 -7
  66. package/dist/md/components/table.md +104 -7
  67. package/dist/md/components/tabs.md +105 -7
  68. package/dist/md/components/textarea.md +101 -0
  69. package/dist/md/components/tooltip.md +95 -7
  70. package/dist/md/components/typography.md +82 -7
  71. package/dist/md/content/about-content.md +36 -0
  72. package/dist/md/content/audience.md +43 -0
  73. package/dist/md/content/glossary.md +69 -0
  74. package/dist/md/content/product-vocabulary.md +53 -0
  75. package/dist/md/content/voice.md +52 -0
  76. package/dist/md/content/writing-mechanics.md +58 -0
  77. package/dist/md/foundation/colors.md +10 -0
  78. package/dist/md/foundation/iconography.md +14 -0
  79. package/dist/md/foundation/motion.md +10 -0
  80. package/dist/md/foundation/radii.md +9 -0
  81. package/dist/md/foundation/shadows.md +9 -0
  82. package/dist/md/foundation/spacings.md +8 -0
  83. package/dist/md/foundation/typography.md +9 -0
  84. package/dist/md/foundation/variables.md +9 -0
  85. package/dist/md/overview/architecture.md +76 -0
  86. package/dist/md/overview/brand.md +41 -0
  87. package/dist/md/overview/composition.md +77 -0
  88. package/dist/md/overview/quickstart.md +97 -0
  89. package/dist/md/overview/theming.md +89 -0
  90. package/dist/md/overview/using-llms.md +83 -0
  91. package/dist/md/pages/auth-page.md +149 -0
  92. package/dist/md/pages/blog-post-page.md +136 -0
  93. package/dist/md/pages/dashboard-page.md +241 -0
  94. package/dist/md/pages/marketing-page.md +199 -0
  95. package/dist/md/pages/not-found-page.md +105 -0
  96. package/dist/md/pages/settings-page.md +206 -0
  97. package/dist/prism-skill.md +50 -0
  98. package/dist/store.d.ts +203 -0
  99. package/dist/store.js +317 -0
  100. package/package.json +29 -26
  101. package/dist/demo-graph.d.ts.map +0 -1
  102. package/dist/demo-graph.js.map +0 -1
  103. package/dist/extractor.d.ts.map +0 -1
  104. package/dist/extractor.js.map +0 -1
  105. package/dist/index.d.ts.map +0 -1
  106. package/dist/index.js.map +0 -1
  107. package/dist/markdown.d.ts.map +0 -1
  108. package/dist/markdown.js.map +0 -1
  109. package/dist/md/blocks/component-demo.md +0 -19
  110. package/dist/md/blocks/page-header.md +0 -19
  111. package/dist/md/components/affix.md +0 -14
  112. package/dist/md/components/anchor.md +0 -14
  113. package/dist/md/components/auto-complete.md +0 -14
  114. package/dist/md/components/back-top.md +0 -14
  115. package/dist/md/components/border-beam.md +0 -14
  116. package/dist/md/components/calendar.md +0 -14
  117. package/dist/md/components/carousel.md +0 -14
  118. package/dist/md/components/cascader.md +0 -14
  119. package/dist/md/components/col.md +0 -14
  120. package/dist/md/components/collapse.md +0 -14
  121. package/dist/md/components/color-picker.md +0 -14
  122. package/dist/md/components/date-picker.md +0 -14
  123. package/dist/md/components/descriptions.md +0 -14
  124. package/dist/md/components/display-title.md +0 -20
  125. package/dist/md/components/divider.md +0 -14
  126. package/dist/md/components/drawer.md +0 -14
  127. package/dist/md/components/dropdown.md +0 -14
  128. package/dist/md/components/empty.md +0 -14
  129. package/dist/md/components/flex.md +0 -14
  130. package/dist/md/components/float-button.md +0 -14
  131. package/dist/md/components/form.md +0 -14
  132. package/dist/md/components/grid.md +0 -14
  133. package/dist/md/components/image.md +0 -14
  134. package/dist/md/components/input-number.md +0 -14
  135. package/dist/md/components/layout.md +0 -14
  136. package/dist/md/components/list.md +0 -14
  137. package/dist/md/components/listy.md +0 -14
  138. package/dist/md/components/masonry.md +0 -14
  139. package/dist/md/components/mentions.md +0 -14
  140. package/dist/md/components/menu.md +0 -14
  141. package/dist/md/components/modal.md +0 -14
  142. package/dist/md/components/popconfirm.md +0 -14
  143. package/dist/md/components/qrcode.md +0 -14
  144. package/dist/md/components/radio.md +0 -14
  145. package/dist/md/components/rate.md +0 -14
  146. package/dist/md/components/result.md +0 -14
  147. package/dist/md/components/row.md +0 -14
  148. package/dist/md/components/segmented.md +0 -14
  149. package/dist/md/components/space.md +0 -14
  150. package/dist/md/components/spin.md +0 -14
  151. package/dist/md/components/splitter.md +0 -14
  152. package/dist/md/components/statistic.md +0 -14
  153. package/dist/md/components/steps.md +0 -14
  154. package/dist/md/components/tag.md +0 -14
  155. package/dist/md/components/time-picker.md +0 -14
  156. package/dist/md/components/timeline.md +0 -14
  157. package/dist/md/components/tour.md +0 -14
  158. package/dist/md/components/transfer.md +0 -14
  159. package/dist/md/components/tree-select.md +0 -14
  160. package/dist/md/components/tree.md +0 -14
  161. package/dist/md/components/upload.md +0 -14
  162. package/dist/md/components/watermark.md +0 -14
  163. package/dist/md/docs/brand.md +0 -41
  164. package/dist/md/pages/blog-layout.md +0 -19
  165. package/dist/md/pages/docs-shell.md +0 -23
  166. package/dist/md/theme/blue-dark.md +0 -127
  167. package/dist/md/theme/blue-light.md +0 -129
  168. package/dist/md/theme/green-dark.md +0 -127
  169. package/dist/md/theme/green-light.md +0 -129
  170. package/dist/md/theme/lavender-dark.md +0 -127
  171. package/dist/md/theme/lavender-light.md +0 -129
  172. package/dist/md/theme/peach-dark.md +0 -127
  173. package/dist/md/theme/peach-light.md +0 -129
  174. package/dist/md/theme/rose-dark.md +0 -127
  175. package/dist/md/theme/rose-light.md +0 -129
@@ -1,14 +1,108 @@
1
1
  # Checkbox
2
2
 
3
- antd Checkbox, unchanged — a pass-through re-export. Import from '@nanisoft/prism-ui'.
3
+ The control for an independent yes-or-no choice, with an optional mixed state.
4
4
 
5
- ```ts
6
- import { Checkbox } from '@nanisoft/prism-ui/components';
5
+ ```tsx
6
+ import { Checkbox } from '@nanisoft/prism-ui/components/checkbox'
7
7
  ```
8
8
 
9
- `Checkbox` is antd's [Checkbox](https://ant.design/components/checkbox), re-exported unchanged.
9
+ ## Overview
10
10
 
11
- - Extends: antd **Checkbox** — for inherited props and demos, use the antd MCP (`antd_info Checkbox`).
12
- - Always import from '@nanisoft/prism-ui', never from `antd` directly.
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
- _No additional props beyond the antd base component._
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.