@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,199 @@
|
|
|
1
|
+
# MarketingPage
|
|
2
|
+
|
|
3
|
+
A complete marketing page composing a hero, a feature grid, a KPI row, a plan comparison and a closing call to action.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { MarketingPage } from '@nanisoft/prism-ui/pages/marketing-page'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
MarketingPage is a complete marketing screen. It composes five blocks in reading
|
|
12
|
+
order and passes each one its own content, so the page adds the sequence and
|
|
13
|
+
nothing else: an opening hero, a capability grid, a row of key figures, a plan
|
|
14
|
+
comparison and a closing call to action.
|
|
15
|
+
|
|
16
|
+
The page composes these blocks:
|
|
17
|
+
|
|
18
|
+
| Section | Block | Role |
|
|
19
|
+
| --- | --- | --- |
|
|
20
|
+
| Opening | Hero01 | the headline, the supporting line and one or two actions |
|
|
21
|
+
| Capabilities | FeatureGrid01 | a grid of short feature blurbs, with or without icons |
|
|
22
|
+
| Figures | Stats01 | two to four key numbers, each with an optional delta |
|
|
23
|
+
| Plans | Pricing01 | a plan comparison with one highlighted tier |
|
|
24
|
+
| Closing | Cta01 | the final call to action on a filled surface |
|
|
25
|
+
|
|
26
|
+
Every string, number, icon, price and action is a prop. The page ships no sample
|
|
27
|
+
copy and fetches nothing. It is a product-agnostic screen model, so a consumer
|
|
28
|
+
installs it, passes their own content and owns the links. It is not this site's
|
|
29
|
+
own landing route: that page is site-owned and composes the same blocks at the
|
|
30
|
+
call site.
|
|
31
|
+
|
|
32
|
+
## Guidelines
|
|
33
|
+
|
|
34
|
+
### When to use
|
|
35
|
+
|
|
36
|
+
Use MarketingPage for a public landing route whose job is to introduce a product
|
|
37
|
+
and move a reader to one next step. It works when the five sections form one
|
|
38
|
+
argument from the headline to the closing action.
|
|
39
|
+
|
|
40
|
+
### When not to use
|
|
41
|
+
|
|
42
|
+
Do not use it inside an authenticated screen. A hero and a plan comparison carry
|
|
43
|
+
marketing weight that competes with the task an application screen exists to
|
|
44
|
+
support; compose the blocks you need directly instead.
|
|
45
|
+
|
|
46
|
+
Do not use it as a documentation page. Guides and item pages have their own
|
|
47
|
+
shell, and a marketing hero would sit above content that is already scoped.
|
|
48
|
+
|
|
49
|
+
Do not use it when the sequence is not the five sections. The page is a fixed
|
|
50
|
+
composition; a different order or a missing section is a page the consumer
|
|
51
|
+
builds from the blocks.
|
|
52
|
+
|
|
53
|
+
### Best practices
|
|
54
|
+
|
|
55
|
+
- Pass every block its own props. The page does not merge or default them, so
|
|
56
|
+
omitting a section's content renders an empty section rather than a fallback.
|
|
57
|
+
- Keep the hero as the only `h1`. The page defaults `headingLevel` to `h1`; when
|
|
58
|
+
it is embedded under a heading the consumer already owns, pass one level
|
|
59
|
+
deeper and the rest of the outline follows.
|
|
60
|
+
- Put the primary action on the hero and the secondary action on the closing
|
|
61
|
+
band, not both in each. One decision per band keeps the page from reading as
|
|
62
|
+
two pitches.
|
|
63
|
+
- Keep the figures real. Stats01 renders exactly the numbers it is given, so the
|
|
64
|
+
page makes no claim the consumer did not make.
|
|
65
|
+
|
|
66
|
+
### Content guidelines
|
|
67
|
+
|
|
68
|
+
- The hero headline states an outcome, not a feature name.
|
|
69
|
+
- The feature titles are the four or five things the product does; the bodies
|
|
70
|
+
are one sentence each.
|
|
71
|
+
- The closing line is a verb phrase and the action names what the reader gets.
|
|
72
|
+
|
|
73
|
+
**The marketing page, composed with placeholder sections.**
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
import { Blocks, Palette, ShieldCheck, Zap } from 'lucide-react'
|
|
77
|
+
|
|
78
|
+
import { MarketingPage } from '@nanisoft/prism-ui/pages/marketing-page'
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* The marketing page, composed with placeholder sections.
|
|
82
|
+
*
|
|
83
|
+
* The page owns the sequence; the demo owns the strings, the numbers and the
|
|
84
|
+
* feature icons. It renders at `h3` because the documentation page already owns
|
|
85
|
+
* an `h1`, which is the same reason a block demo nests its heading.
|
|
86
|
+
*/
|
|
87
|
+
export default function MarketingPageDemo() {
|
|
88
|
+
return (
|
|
89
|
+
<MarketingPage
|
|
90
|
+
headingLevel="h3"
|
|
91
|
+
hero={{
|
|
92
|
+
eyebrow: 'Preview',
|
|
93
|
+
title: 'A headline that fits on two lines',
|
|
94
|
+
description:
|
|
95
|
+
'One or two sentences of supporting copy, so the measure and the spacing around it can be judged.',
|
|
96
|
+
actions: [
|
|
97
|
+
{ label: 'Primary action' },
|
|
98
|
+
{ label: 'Secondary', variant: 'outline' },
|
|
99
|
+
],
|
|
100
|
+
}}
|
|
101
|
+
features={{
|
|
102
|
+
eyebrow: 'Preview',
|
|
103
|
+
title: 'Section heading',
|
|
104
|
+
description: 'An optional line that explains what the set below it has in common.',
|
|
105
|
+
features: [
|
|
106
|
+
{
|
|
107
|
+
icon: Palette,
|
|
108
|
+
title: 'First item',
|
|
109
|
+
body: 'A short sentence describing the first thing in the set.',
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
icon: Blocks,
|
|
113
|
+
title: 'Second item',
|
|
114
|
+
body: 'A short sentence describing the second thing in the set.',
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
icon: Zap,
|
|
118
|
+
title: 'Third item',
|
|
119
|
+
body: 'A short sentence describing the third thing in the set.',
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
icon: ShieldCheck,
|
|
123
|
+
title: 'Fourth item',
|
|
124
|
+
body: 'A short sentence describing the fourth thing in the set.',
|
|
125
|
+
},
|
|
126
|
+
],
|
|
127
|
+
}}
|
|
128
|
+
stats={{
|
|
129
|
+
eyebrow: 'Preview',
|
|
130
|
+
title: 'Section heading',
|
|
131
|
+
stats: [
|
|
132
|
+
{ label: 'First metric', value: '1,284', delta: 12, hint: 'vs last month' },
|
|
133
|
+
{ label: 'Second metric', value: '47.2%', delta: -3, hint: 'vs last month' },
|
|
134
|
+
{ label: 'Third metric', value: '2.4d', delta: 0, hint: 'vs last quarter' },
|
|
135
|
+
{ label: 'Fourth metric', value: '138' },
|
|
136
|
+
],
|
|
137
|
+
}}
|
|
138
|
+
pricing={{
|
|
139
|
+
title: 'Section heading',
|
|
140
|
+
plans: [
|
|
141
|
+
{
|
|
142
|
+
name: 'First plan',
|
|
143
|
+
price: '$0',
|
|
144
|
+
period: ' / month',
|
|
145
|
+
body: 'One line on who it is for.',
|
|
146
|
+
features: ['First included line', 'Second included line', 'Third included line'],
|
|
147
|
+
cta: 'Choose',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
name: 'Second plan',
|
|
151
|
+
price: '$24',
|
|
152
|
+
period: ' / month',
|
|
153
|
+
body: 'One line on who it is for.',
|
|
154
|
+
features: ['Everything in the first plan', 'One extra line', 'Another extra line'],
|
|
155
|
+
cta: 'Choose',
|
|
156
|
+
featured: true,
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: 'Third plan',
|
|
160
|
+
price: '$68',
|
|
161
|
+
period: ' / month',
|
|
162
|
+
body: 'One line on who it is for.',
|
|
163
|
+
features: ['Everything in the second plan', 'One extra line', 'Another extra line'],
|
|
164
|
+
cta: 'Choose',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
}}
|
|
168
|
+
cta={{
|
|
169
|
+
title: 'A closing line, two lines at most',
|
|
170
|
+
description: 'A sentence that says what happens next, then one action.',
|
|
171
|
+
action: { label: 'Do the thing', href: '/components/button' },
|
|
172
|
+
}}
|
|
173
|
+
/>
|
|
174
|
+
)
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Props
|
|
179
|
+
|
|
180
|
+
**`hero`** `ComponentProps<typeof Hero01>` · required · default: — — The opening band: an optional eyebrow, the headline and one or two actions.
|
|
181
|
+
**`features`** `ComponentProps<typeof FeatureGrid01>` · required · default: — — The capability grid below the hero.
|
|
182
|
+
**`stats`** `ComponentProps<typeof Stats01>` · required · default: — — The key-figure row.
|
|
183
|
+
**`pricing`** `ComponentProps<typeof Pricing01>` · required · default: — — The plan comparison.
|
|
184
|
+
**`cta`** `ComponentProps<typeof Cta01>` · required · default: — — The closing call to action.
|
|
185
|
+
**`headingLevel`** `HeadingLevel` · optional · default: — — The heading level for the hero. Defaults to `h1`, because a page owns the top of the document outline. A consumer that embeds the page under a heading it already owns passes one level deeper.
|
|
186
|
+
|
|
187
|
+
## Composition
|
|
188
|
+
|
|
189
|
+
**`exports`** `MarketingPage` — the public runtime names this Page promises
|
|
190
|
+
**`source`** `packages/ui/src/pages/marketing-page/index.tsx` — the file this Page is defined in
|
|
191
|
+
**`dependencies`** `Cta01, FeatureGrid01, Hero01, Pricing01, Stats01` — the public Prism exports this item composes
|
|
192
|
+
|
|
193
|
+
## Blocks
|
|
194
|
+
|
|
195
|
+
- [Cta01](https://prism.nanisoft.com/blocks/cta-01.md)
|
|
196
|
+
- [FeatureGrid01](https://prism.nanisoft.com/blocks/feature-grid-01.md)
|
|
197
|
+
- [Hero01](https://prism.nanisoft.com/blocks/hero-01.md)
|
|
198
|
+
- [Pricing01](https://prism.nanisoft.com/blocks/pricing-01.md)
|
|
199
|
+
- [Stats01](https://prism.nanisoft.com/blocks/stats-01.md)
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# NotFoundPage
|
|
2
|
+
|
|
3
|
+
A complete not-found screen: the status code as the heading of the page, one sentence about what happened, and the ways out.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
NotFoundPage is a complete not-found screen: the code, what happened, and the ways
|
|
12
|
+
out.
|
|
13
|
+
|
|
14
|
+
All four NaniSoft sites compose one, each in its own not-found route, and three of
|
|
15
|
+
them are the same six lines with a different product name on it: a display title
|
|
16
|
+
carrying the code, one muted sentence, and two or three links. The fourth wrote
|
|
17
|
+
the same thing in its own markup. Four hand-written screens for one shape.
|
|
18
|
+
|
|
19
|
+
It is a Page rather than a Block because it is a whole screen: it owns the
|
|
20
|
+
document's `h1`, it is what a router renders when a route does not resolve, and
|
|
21
|
+
the band's job is not separable from the screen's. There is one correct page here
|
|
22
|
+
and it is short.
|
|
23
|
+
|
|
24
|
+
## Guidelines
|
|
25
|
+
|
|
26
|
+
### When to use
|
|
27
|
+
|
|
28
|
+
Use NotFoundPage as the body of whatever route your framework names for a
|
|
29
|
+
not-found response: Next's `not-found.tsx`, a Nuxt error page, a route your own
|
|
30
|
+
router falls through to.
|
|
31
|
+
|
|
32
|
+
Use it for every status that means "this address is not a page here", not only
|
|
33
|
+
404. A 410 and a 404 are the same screen with a different code, and the code is a
|
|
34
|
+
prop.
|
|
35
|
+
|
|
36
|
+
### When not to use
|
|
37
|
+
|
|
38
|
+
Do not use it for a request that failed. That is an error page with a retry, and a
|
|
39
|
+
reader who sees "this page does not exist" when the page exists and did not load
|
|
40
|
+
will not believe you next time.
|
|
41
|
+
|
|
42
|
+
Do not use it for a permission failure the reader might be granted later. That is
|
|
43
|
+
a 403, and it needs a sign-in link rather than a way back to the landing.
|
|
44
|
+
|
|
45
|
+
### Best practices
|
|
46
|
+
|
|
47
|
+
- **The code is the `h1` and the sentence is not.** A not-found page whose `h1` is
|
|
48
|
+
"Page not found" gives a search engine and a screen reader nothing distinct to
|
|
49
|
+
index, and the code is the one string on the page that is the same for every
|
|
50
|
+
broken URL. The code takes the display step and the sentence takes the muted one,
|
|
51
|
+
which is the reverse of what a reader sees first and the right way round for
|
|
52
|
+
anything that reads the outline.
|
|
53
|
+
- Put the most useful destination first, and weight it as the primary action. A
|
|
54
|
+
not-found page that offers the homepage link before the documentation sends a
|
|
55
|
+
reader further from what they wanted.
|
|
56
|
+
- Leave `newTab` off every link. A reader who followed a broken link and is sent
|
|
57
|
+
to a new tab has to find their way back.
|
|
58
|
+
- Use the `children` slot for a search box or a list of recent posts, which is
|
|
59
|
+
what turns a dead end into a page.
|
|
60
|
+
|
|
61
|
+
### Content guidelines
|
|
62
|
+
|
|
63
|
+
- Write the sentence as a fact about the address, not as an apology. "No node
|
|
64
|
+
here" beats "Sorry, we could not find that page".
|
|
65
|
+
- Say whether the page might exist later if it does. "This page does not exist
|
|
66
|
+
(yet)" is one clause longer and saves a support ticket.
|
|
67
|
+
- Keep each link label to one or two words.
|
|
68
|
+
|
|
69
|
+
**The not-found screen: the code as the h1, one sentence, and the ways out.**
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { NotFoundPage } from '@nanisoft/prism-ui/pages/not-found-page'
|
|
73
|
+
|
|
74
|
+
/** The not-found screen: the code as the h1, one sentence, and the ways out. */
|
|
75
|
+
export default function NotFoundPageDemo() {
|
|
76
|
+
return (
|
|
77
|
+
<NotFoundPage
|
|
78
|
+
code="404"
|
|
79
|
+
title="No node here."
|
|
80
|
+
description="The estate is fully mapped. This URL is not in the graph."
|
|
81
|
+
linksLabel="Ways out"
|
|
82
|
+
links={[
|
|
83
|
+
{ label: 'Read the docs', href: '#docs' },
|
|
84
|
+
{ label: 'Back to the landing', href: '#landing' },
|
|
85
|
+
]}
|
|
86
|
+
/>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Props
|
|
92
|
+
|
|
93
|
+
**`code`** `string` · required · default: — — The status code, shown as the page's own `h1`. Required, and a string rather than a number because it is displayed, not computed: a Page never decides what code it is answering.
|
|
94
|
+
**`title`** `string` · required · default: — — The headline under the code: the sentence that says what happened. It is the part a reader actually reads, and it is the caller's because every product says it differently - "No node here", "This page does not exist (yet)".
|
|
95
|
+
**`description`** `string` · optional · default: — — One or two sentences under the headline, for anything a reader should know before they follow one of the links: that the URL may be mistyped, that the page is planned, that a search would find it.
|
|
96
|
+
**`links`** `readonly NotFoundLink[]` · required · default: — — The ways out, in the order a reader should see them. Put the destination most likely to help first; a not-found page that offers a homepage link before the documentation sends a reader further from what they wanted.
|
|
97
|
+
**`linksLabel`** `string` · required · default: — — The accessible name of the row of ways out. It is required, because it is a word a reader hears and a Page that ships no copy ships no reader-facing copy either. "Ways out" is the Page's own phrasing; a site that files its destinations differently names the same landmark differently.
|
|
98
|
+
**`children`** `ReactNode` · optional · default: — — A slot for whatever else the site wants to say here: a search box, a list of recent posts, a contact address.
|
|
99
|
+
**`className`** `string` · optional · default: — — Layout only, exactly as on every Component. Changing a Prism-owned visual property from here is prohibited.
|
|
100
|
+
|
|
101
|
+
## Composition
|
|
102
|
+
|
|
103
|
+
**`exports`** `NotFoundPage` — the public runtime names this Page promises
|
|
104
|
+
**`source`** `packages/ui/src/pages/not-found-page/index.tsx` — the file this Page is defined in
|
|
105
|
+
**`dependencies`** `CtaLink, Prose, Section` — the public Prism exports this item composes
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# SettingsPage
|
|
2
|
+
|
|
3
|
+
A full settings screen composing the app shell, a page header and tabs of grouped settings forms.
|
|
4
|
+
|
|
5
|
+
```tsx
|
|
6
|
+
import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Overview
|
|
10
|
+
|
|
11
|
+
SettingsPage is a complete settings screen. It composes the shell, a page header
|
|
12
|
+
and a set of tabs, where each tab is either a saved settings form or a read-only
|
|
13
|
+
panel. The page owns the sequence and the tab wiring only.
|
|
14
|
+
|
|
15
|
+
The page composes these parts:
|
|
16
|
+
|
|
17
|
+
| Region | Piece | Role |
|
|
18
|
+
| --- | --- | --- |
|
|
19
|
+
| Frame | AppShell01 | the navigation rail, the top bar and the mobile navigation sheet |
|
|
20
|
+
| Header | PageHeader01 | the trail, the screen title and its actions |
|
|
21
|
+
| Tabs | Tabs, TabsList, TabsTrigger, TabsContent | the peer settings groups |
|
|
22
|
+
| Forms | SettingsPanel01 | the grouped and saved form for one tab |
|
|
23
|
+
|
|
24
|
+
A tab that carries `panel` renders `SettingsPanel01`: a titled card with grouped
|
|
25
|
+
sections, a save footer and one submit. A tab that carries `content` renders the
|
|
26
|
+
node as-is, which suits a read-only summary or a view that is not a form. Sections,
|
|
27
|
+
fields, options and labels are all props, and the page fetches nothing.
|
|
28
|
+
|
|
29
|
+
## Guidelines
|
|
30
|
+
|
|
31
|
+
### When to use
|
|
32
|
+
|
|
33
|
+
Use SettingsPage when a screen changes several settings that group naturally, and
|
|
34
|
+
each group can be saved on its own. It works when the tabs are stable and a reader
|
|
35
|
+
returns to one group rather than scanning the whole screen.
|
|
36
|
+
|
|
37
|
+
### When not to use
|
|
38
|
+
|
|
39
|
+
Do not use it for a single setting. One field behind a tab is a heavier frame
|
|
40
|
+
than the choice deserves; put the control on the screen that owns it.
|
|
41
|
+
|
|
42
|
+
Do not use it when the settings must be compared side by side. Tabs hide one
|
|
43
|
+
group to show another, so a choice that depends on another group's value belongs
|
|
44
|
+
on one page, not behind a tab.
|
|
45
|
+
|
|
46
|
+
### Best practices
|
|
47
|
+
|
|
48
|
+
- Keep one save per panel. A mixed model, where some fields save and others apply
|
|
49
|
+
immediately, makes the footer's promise unclear.
|
|
50
|
+
- Give every field a stable `id`, so the label is linked to the control.
|
|
51
|
+
- Use `content` for a read-only group. A panel with no `submitLabel` renders no
|
|
52
|
+
footer, which is the honest shape for a view that does not save.
|
|
53
|
+
- Set `defaultValue` to the group a reader is most likely to want, rather than
|
|
54
|
+
relying on the first tab by luck.
|
|
55
|
+
- Pass the same navigation node to both the rail and the sheet, and keep its ids
|
|
56
|
+
unique because AppShell01 renders it twice.
|
|
57
|
+
|
|
58
|
+
### Content guidelines
|
|
59
|
+
|
|
60
|
+
- A tab label is one word in sentence case: "General", "Notifications".
|
|
61
|
+
- A section title is one or two words and a field label is a short noun phrase.
|
|
62
|
+
- A description states the effect of the group, not a policy for it.
|
|
63
|
+
|
|
64
|
+
**The settings page, with a grouped form per tab.**
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
'use client'
|
|
68
|
+
|
|
69
|
+
import { SettingsPage } from '@nanisoft/prism-ui/pages/settings-page'
|
|
70
|
+
|
|
71
|
+
const LINKS = [
|
|
72
|
+
{ href: '#general', label: 'General', current: false },
|
|
73
|
+
{ href: '#settings', label: 'Settings', current: true },
|
|
74
|
+
{ href: '#members', label: 'Members', current: false },
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
/** The settings page, with a grouped form per tab. */
|
|
78
|
+
export default function SettingsPageDemo() {
|
|
79
|
+
return (
|
|
80
|
+
<SettingsPage
|
|
81
|
+
shell={{
|
|
82
|
+
navigationLabel: 'Primary',
|
|
83
|
+
brand: <span className="text-sm font-semibold">Northwind</span>,
|
|
84
|
+
breadcrumbs: [{ label: 'Settings', href: '#settings' }, { label: 'Workspace' }],
|
|
85
|
+
navigation: (
|
|
86
|
+
<ul className="flex flex-col gap-1 text-sm">
|
|
87
|
+
{LINKS.map((link) => (
|
|
88
|
+
<li key={link.href}>
|
|
89
|
+
<a
|
|
90
|
+
href={link.href}
|
|
91
|
+
className={
|
|
92
|
+
link.current
|
|
93
|
+
? 'bg-accent text-accent-foreground block rounded-md px-3 py-2 font-medium'
|
|
94
|
+
: 'text-muted-foreground hover:text-foreground block rounded-md px-3 py-2'
|
|
95
|
+
}
|
|
96
|
+
>
|
|
97
|
+
{link.label}
|
|
98
|
+
</a>
|
|
99
|
+
</li>
|
|
100
|
+
))}
|
|
101
|
+
</ul>
|
|
102
|
+
),
|
|
103
|
+
}}
|
|
104
|
+
header={{
|
|
105
|
+
title: 'Workspace settings',
|
|
106
|
+
description: 'Manage how this workspace behaves for everyone on the team.',
|
|
107
|
+
}}
|
|
108
|
+
tabs={[
|
|
109
|
+
{
|
|
110
|
+
value: 'general',
|
|
111
|
+
label: 'General',
|
|
112
|
+
panel: {
|
|
113
|
+
title: 'General',
|
|
114
|
+
description: 'Shown to everyone you collaborate with.',
|
|
115
|
+
submitLabel: 'Save changes',
|
|
116
|
+
secondaryAction: { label: 'Cancel' },
|
|
117
|
+
sections: [
|
|
118
|
+
{
|
|
119
|
+
id: 'identity',
|
|
120
|
+
title: 'Identity',
|
|
121
|
+
fields: [
|
|
122
|
+
{
|
|
123
|
+
kind: 'text',
|
|
124
|
+
id: 'settings-workspace-name',
|
|
125
|
+
label: 'Workspace name',
|
|
126
|
+
defaultValue: 'Northwind',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
kind: 'textarea',
|
|
130
|
+
id: 'settings-workspace-description',
|
|
131
|
+
label: 'Description',
|
|
132
|
+
placeholder: 'What does this workspace do?',
|
|
133
|
+
rows: 3,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
kind: 'select',
|
|
137
|
+
id: 'settings-workspace-region',
|
|
138
|
+
label: 'Data region',
|
|
139
|
+
placeholder: 'Choose a region',
|
|
140
|
+
defaultValue: 'eu-west',
|
|
141
|
+
options: [
|
|
142
|
+
{ label: 'Europe West', value: 'eu-west' },
|
|
143
|
+
{ label: 'US East', value: 'us-east' },
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
],
|
|
147
|
+
},
|
|
148
|
+
],
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
value: 'notifications',
|
|
153
|
+
label: 'Notifications',
|
|
154
|
+
panel: {
|
|
155
|
+
title: 'Notifications',
|
|
156
|
+
description: 'Choose what the workspace sends and when.',
|
|
157
|
+
submitLabel: 'Save changes',
|
|
158
|
+
sections: [
|
|
159
|
+
{
|
|
160
|
+
id: 'email',
|
|
161
|
+
title: 'Email',
|
|
162
|
+
fields: [
|
|
163
|
+
{
|
|
164
|
+
kind: 'switch',
|
|
165
|
+
id: 'settings-weekly-digest',
|
|
166
|
+
label: 'Weekly digest',
|
|
167
|
+
description: 'A summary of activity every Monday.',
|
|
168
|
+
defaultChecked: true,
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
kind: 'switch',
|
|
172
|
+
id: 'settings-mention-alerts',
|
|
173
|
+
label: 'Mention alerts',
|
|
174
|
+
description: 'Notify me when someone mentions my name.',
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
]}
|
|
182
|
+
/>
|
|
183
|
+
)
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Props
|
|
188
|
+
|
|
189
|
+
**`shell`** `Omit<ComponentProps<typeof AppShell01>, 'children'>` · required · default: — — The frame: rail, top bar and mobile navigation sheet.
|
|
190
|
+
**`header`** `ComponentProps<typeof PageHeader01>` · required · default: — — The page title band.
|
|
191
|
+
**`tabs`** `SettingsPageTab[]` · required · default: — — The tabs, in order. At least one is required.
|
|
192
|
+
**`defaultValue`** `string` · optional · default: — — The tab shown first, for uncontrolled tabs. Defaults to the first tab.
|
|
193
|
+
**`value`** `string` · optional · default: — — The controlled active tab.
|
|
194
|
+
**`onValueChange`** `(value: string) => void` · optional · default: —
|
|
195
|
+
|
|
196
|
+
## Composition
|
|
197
|
+
|
|
198
|
+
**`exports`** `SettingsPage` — the public runtime names this Page promises
|
|
199
|
+
**`source`** `packages/ui/src/pages/settings-page/index.tsx` — the file this Page is defined in
|
|
200
|
+
**`dependencies`** `AppShell01, PageHeader01, SettingsPanel01, Tabs` — the public Prism exports this item composes
|
|
201
|
+
|
|
202
|
+
## Blocks
|
|
203
|
+
|
|
204
|
+
- [AppShell01](https://prism.nanisoft.com/blocks/app-shell-01.md)
|
|
205
|
+
- [PageHeader01](https://prism.nanisoft.com/blocks/page-header-01.md)
|
|
206
|
+
- [SettingsPanel01](https://prism.nanisoft.com/blocks/settings-panel-01.md)
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Prism agent skill
|
|
2
|
+
|
|
3
|
+
Prism is NaniSoft's design system: design tokens, a React component library, a
|
|
4
|
+
documentation site, and this agent surface. This is the fast path. The index is
|
|
5
|
+
[`/llms.txt`](https://prism.nanisoft.com/llms.txt) and every page in full is
|
|
6
|
+
[`/llms-full.txt`](https://prism.nanisoft.com/llms-full.txt); both are generated from the
|
|
7
|
+
checked catalogue and the authored pages.
|
|
8
|
+
|
|
9
|
+
## Start here
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
import '@nanisoft/prism-ui/styles.css'
|
|
13
|
+
|
|
14
|
+
import { PrismProvider, PrismThemeScript } from '@nanisoft/prism-ui/provider'
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Import the one stylesheet once. The provider is optional: the declarative axes
|
|
18
|
+
are `data-pack` on `<html>` and the `dark` class for mode.
|
|
19
|
+
|
|
20
|
+
## Import contract
|
|
21
|
+
|
|
22
|
+
- Components: `@nanisoft/prism-ui/components/<slug>`
|
|
23
|
+
- Blocks: `@nanisoft/prism-ui/blocks/<slug>`
|
|
24
|
+
- Pages: `@nanisoft/prism-ui/pages/<slug>`
|
|
25
|
+
|
|
26
|
+
Compound parts stay inside their module. Base UI and every internal path are
|
|
27
|
+
never a consumer import.
|
|
28
|
+
|
|
29
|
+
## MCP
|
|
30
|
+
|
|
31
|
+
The read-only MCP endpoint is `https://prism.nanisoft.com/mcp`. It exposes nine tools:
|
|
32
|
+
`list_items`, `get_item_doc`, `get_item_props`, `get_item_source`,
|
|
33
|
+
`get_theme_doc`, `list_pages`, `get_page`, `search_docs` and
|
|
34
|
+
`get_changelog`.
|
|
35
|
+
|
|
36
|
+
## Truth rules
|
|
37
|
+
|
|
38
|
+
- Prism is the one source of truth. A consumer composes; it never writes CSS and
|
|
39
|
+
never overrides a style.
|
|
40
|
+
- There is no override path. When Prism lacks a component, token or variant,
|
|
41
|
+
request it upstream.
|
|
42
|
+
- Generated code imports from `@nanisoft/prism-ui` only.
|
|
43
|
+
|
|
44
|
+
## This corpus
|
|
45
|
+
|
|
46
|
+
Generated from the catalogue and the authored pages: 34
|
|
47
|
+
Components, 19 Blocks and 7 Pages, plus the Overview,
|
|
48
|
+
Foundation, Content and Changelogs pages. The Changelogs pages are each
|
|
49
|
+
published package's own changelog, byte for byte; `get_changelog` returns one
|
|
50
|
+
package's, optionally one version of it.
|