Skip to content

Commit 81d783e

Browse files
committed
Improve landing and pricing component documents.
1 parent 330b0bd commit 81d783e

18 files changed

Lines changed: 861 additions & 151 deletions

File tree

‎frontend/docs/componentGuide.ts‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,56 @@ export function registerComponentGuideStyles() {
347347
fontSize: '0.85rem',
348348
color: accent.text.default,
349349
})
350+
root
351+
.select('.landing-appearance-sample, .landing-directory-preview > *')
352+
.css({
353+
width: '100%',
354+
minWidth: '0',
355+
})
356+
root
357+
.select('.landing-appearance-sample > *, .landing-directory-preview > *')
358+
.css({
359+
marginBottom: '0',
360+
})
361+
root
362+
.select('.landing-appearance-gallery pre, .landing-directory-preview pre')
363+
.css({
364+
whiteSpace: 'pre-wrap',
365+
overflowWrap: 'anywhere',
366+
})
367+
root
368+
.select(
369+
'.landing-appearance-gallery .grid, .landing-directory-preview .grid',
370+
)
371+
.css({
372+
gridTemplateColumns: 'minmax(0, 1fr)',
373+
})
374+
root.select('.landing-band-mini, .landing-directory-preview').css({
375+
minWidth: '0',
376+
overflow: 'hidden',
377+
})
378+
root
379+
.select(
380+
'.landing-band-mini > section, .landing-appearance-sample > section, .landing-directory-preview > section',
381+
)
382+
.css({
383+
marginInlineStart: '0 !important',
384+
marginInlineEnd: '0 !important',
385+
paddingInlineStart: '1rem !important',
386+
paddingInlineEnd: '1rem !important',
387+
})
388+
root
389+
.select(
390+
'.landing-appearance-gallery h2, .landing-appearance-gallery h3, .landing-directory-preview h2, .landing-directory-preview h3',
391+
)
392+
.css({
393+
fontSize: '1.15rem',
394+
lineHeight: '1.35',
395+
})
396+
root.select('.landing-title-tags .section-header > .text-title').css({
397+
fontSize: '1.15rem',
398+
lineHeight: '1.35',
399+
})
350400
root
351401
.media(mediaBelow(BREAKPOINTS.md))
352402
.select('.component-guide-grid')

‎frontend/docs/docsComponents.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@ import { defineApiPropertyComponent } from './apiProperty'
88
import { defineComponentGuideComponents } from './componentGuide'
99
import { defineChartAppearanceGallery } from './dataGuide'
1010
import { defineFormAppearanceGallery } from './formAppearance'
11+
import { defineLandingAppearanceGallery } from './landingGuide'
1112
import { defineModalExampleComponents } from './modal'
1213

1314
export function defineDocumentationComponents(site: SiteConfig) {
1415
return {
1516
...defineComponentGuideComponents(),
1617
FormAppearanceGallery: defineFormAppearanceGallery(),
1718
ChartAppearanceGallery: defineChartAppearanceGallery(),
19+
LandingAppearanceGallery: defineLandingAppearanceGallery(),
1820
ApiProperty: defineApiPropertyComponent(),
1921
ConsentPreview: defineConsentPreviewComponent(site),
2022
NavMenuPreview: defineNavMenuPreviewComponent(site),

‎frontend/docs/landingGuide.ts‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import type { ComponentVariant } from '@purestack/ts-components'
2+
import { SEMANTIC_TONES } from '@purestack/ts-style'
3+
import { defineComponent, html, type RefOrValue, unref } from 'regor'
4+
5+
const variants: ComponentVariant[] = [
6+
'solid',
7+
'surface',
8+
'surfaceAlt',
9+
'spotlight',
10+
'glass',
11+
'flat',
12+
'flatAlt',
13+
'flatSolid',
14+
'outlineFill',
15+
'outline',
16+
'subtle',
17+
'subtleBtn',
18+
'link',
19+
'sheen',
20+
'underline',
21+
'rail',
22+
'bracket',
23+
'none',
24+
]
25+
26+
/** Full, simultaneously visible samples of each component's public appearance API. */
27+
export function defineLandingAppearanceGallery() {
28+
return defineComponent<{
29+
component: RefOrValue<string>
30+
axis: RefOrValue<'tone' | 'variant' | 'mode'>
31+
}>(
32+
html`<div class="component-appearance-grid landing-appearance-gallery">
33+
<div class="component-appearance-cell" r-for="sample in samples">
34+
<code>{{ sample.label }}</code>
35+
<div class="landing-appearance-sample" r-if="component === 'LandingBand'"><LandingBand :tone="sample.tone" :variant="sample.variant" :variantMode="sample.mode" height="9rem" edgeSize="1rem" alignItems="center"><strong>A new chapter</strong></LandingBand></div>
36+
<div class="landing-appearance-sample" r-if="component === 'LandingSection'"><LandingSection :tone="sample.tone" :variant="sample.variant" :variantMode="sample.mode" eyebrow="THE WORKFLOW" title="Build together" subtitle="A shared starting point." titleTag="h3" columnsLg="1"><Badge :tone="sample.tone">Ready to compose</Badge></LandingSection></div>
37+
<div class="landing-appearance-sample" r-if="component === 'FeatureCard'"><FeatureCard :tone="sample.tone" :variant="sample.variant" eyebrow="DESIGNED TOGETHER" title="One language" summary="Consistent from the first screen." icon="lucide:check" badge="Included"><template #actions><BtnLink href="/components/" :tone="sample.tone" variant="outline">Explore</BtnLink></template></FeatureCard></div>
38+
<div class="landing-appearance-sample" r-if="component === 'MetricStrip'"><MetricStrip :tone="sample.tone" :variant="sample.variant" columns="1" columnsSm="1" columnsLg="1"><MetricItem label="Components" value="48" detail="One shared design language" icon="lucide:check" :tone="sample.tone"/></MetricStrip></div>
39+
<div class="landing-appearance-sample" r-if="component === 'MetricItem'"><MetricItem label="Components" value="48" detail="One shared design language" icon="lucide:check" :tone="sample.tone"/></div>
40+
<div class="landing-appearance-sample" r-if="component === 'CodeShowcase'"><CodeShowcase :tone="sample.tone" :variant="sample.variant" title="A small building block" language="MDX" resultTitle="Result" resultMeta="Rendered"><pre><code>&lt;Badge&gt;Ready&lt;/Badge&gt;</code></pre><template #result><Badge :tone="sample.tone">Ready</Badge></template></CodeShowcase></div>
41+
<div class="landing-appearance-sample" r-if="component === 'ComparisonTable'"><ComparisonTable :tone="sample.tone" :variant="sample.variant" title="Choose your workflow" columns="1" columnsLg="1"><ComparisonColumn title="Shared system" summary="Less repetition." variant="none"><ul class="m-0 p-0"><ComparisonFeature :tone="sample.tone">Reusable patterns</ComparisonFeature></ul></ComparisonColumn></ComparisonTable></div>
42+
<div class="landing-appearance-sample" r-if="component === 'ComparisonColumn'"><ComparisonColumn :tone="sample.tone" :variant="sample.variant" title="Shared system" summary="One coherent toolkit." badge="Recommended" icon="lucide:check"><ul class="m-0 p-0"><ComparisonFeature :tone="sample.tone">Reusable patterns</ComparisonFeature></ul></ComparisonColumn></div>
43+
<div class="landing-appearance-sample" r-if="component === 'ComparisonFeature'"><ul class="m-0 p-0"><ComparisonFeature :tone="sample.tone"><span>One shared theme<br/><small>Across every screen.</small></span></ComparisonFeature></ul></div>
44+
<div class="landing-appearance-sample" r-if="component === 'CtaSection'"><CtaSection :tone="sample.tone" :variant="sample.variant" title="Make it yours" subtitle="Start with a useful pattern." primaryLabel="Explore" primaryHref="/components/" meta="Bring your own content."/></div>
45+
<div class="landing-appearance-sample" r-if="component === 'PricingTable'"><PricingTable :tone="sample.tone" :variant="sample.variant" :variantMode="sample.mode" title="Choose your starting point" footnote="Illustrative plans." columns="1" columnsLg="1" columnsXl="1"><PricingPlan title="Studio" price="$24" period="/ month" variant="none" :tone="sample.tone"><PricingFeature :tone="sample.tone">Theme-aware components</PricingFeature></PricingPlan></PricingTable></div>
46+
<div class="landing-appearance-sample" r-if="component === 'PricingPlan'"><PricingPlan :tone="sample.tone" :variant="sample.variant" :variantMode="sample.mode" title="Studio" summary="Room to build together." price="$24" period="/ month" badge="Popular" icon="lucide:check" note="Illustrative pricing." ctaLabel="Explore" ctaLink="/components/"><PricingFeature :tone="sample.tone">Theme-aware components</PricingFeature></PricingPlan></div>
47+
<div class="landing-appearance-sample" r-if="component === 'PricingFeature'"><ul class="m-0 p-0"><PricingFeature :tone="sample.tone" :variant="sample.variant">Theme-aware components</PricingFeature></ul></div>
48+
</div>
49+
</div>`,
50+
{
51+
props: ['component', 'axis'],
52+
context: (head) => {
53+
const axis = unref(head.props.axis)
54+
const values =
55+
axis === 'tone'
56+
? SEMANTIC_TONES
57+
: axis === 'variant'
58+
? variants
59+
: ['stateless', 'stateful']
60+
return {
61+
...head.props,
62+
samples: values.map((value) => ({
63+
label: value,
64+
tone: axis === 'tone' ? value : 'accent',
65+
variant:
66+
axis === 'variant'
67+
? value
68+
: axis === 'mode'
69+
? 'outlineFill'
70+
: 'surface',
71+
mode: axis === 'mode' ? value : 'stateless',
72+
})),
73+
}
74+
},
75+
},
76+
)
77+
}

‎frontend/purestack.studio/components/landing/code-showcase/code-showcase.mdx‎

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,16 @@ nav:
1313

1414
# Code<wbr/>Showcase
1515

16-
Pair a code block with its visible result and the context needed to understand both.
17-
18-
<Badge tone="accent" variant="surface">CodeShowcase</Badge>
19-
20-
[View source](https://github.com/PureStackStudio/PureStack/blob/main/packages/ts-components/src/standard/landing/landingTypes.ts) · [API reference](#api-reference)
21-
22-
16+
<ComponentHeader name="CodeShowcase" kind="Code and result" summary="Pair a code block with its visible result and the context needed to understand both." source="https://github.com/PureStackStudio/PureStack/blob/main/packages/ts-components/src/standard/landing/landingTypes.ts" section="Landing &amp; pricing" sectionHref="/components/landing/"/>
2317

2418
## Code and its result
2519

2620
Write a normal fenced code block in the default slot. ts-ssg highlights it automatically; the result slot renders the matching component.
2721

2822
<Tabs group="code-showcase-sample-1" selectedTab="code-showcase-sample-1-preview" ariaLabel="Code and its result example" tone="neutral" variant="surface" tabVariant="underline">
2923
<TabPane id="code-showcase-sample-1-preview" label="Preview">
24+
<ComponentExample label="CodeShowcase in context" caption="Compare the composition, then open its source tab to adapt it.">
25+
3026
<CodeShowcase
3127
eyebrow="A SMALL EXAMPLE"
3228
title="Semantic status"
@@ -45,6 +41,8 @@ Write a normal fenced code block in the default slot. ts-ssg highlights it autom
4541
<Badge tone="success">Ready</Badge>
4642
</template>
4743
</CodeShowcase>
44+
45+
</ComponentExample>
4846
</TabPane>
4947
<TabPane id="code-showcase-sample-1-source-0" label="code-result.mdx">
5048
````html
@@ -76,10 +74,13 @@ Omit resultTitle and resultMeta when a result panel is unnecessary.
7674

7775
<Tabs group="code-showcase-sample-2" selectedTab="code-showcase-sample-2-preview" ariaLabel="A focused code note example" tone="neutral" variant="surface" tabVariant="underline">
7876
<TabPane id="code-showcase-sample-2-preview" label="Preview">
77+
<div class="component-preview-stage">
78+
7979
<CodeShowcase title="A named value" language="TypeScript" variant="outline">
8080
<pre><code>const releaseName = 'Preview'</code></pre>
8181
</CodeShowcase>
82-
</TabPane>
82+
83+
</div> </TabPane>
8384
<TabPane id="code-showcase-sample-2-source-0" label="code-note.mdx">
8485
```html
8586
<CodeShowcase title="A named value" language="TypeScript" variant="outline">
@@ -89,6 +90,45 @@ Omit resultTitle and resultMeta when a result panel is unnecessary.
8990
</TabPane>
9091
</Tabs>
9192

93+
## All ten semantic tones
94+
95+
The same composition in every semantic tone. Child tones are explicit where the composition owns them, including navigation actions.
96+
97+
<ComponentExample label="All ten semantic tones" caption="Switch the site theme to compare the same samples in both palettes.">
98+
<div data-landing-gallery="tone"><LandingAppearanceGallery component="CodeShowcase" axis="tone"/></div>
99+
</ComponentExample>
100+
101+
## All eighteen visual variants
102+
103+
Every supported variant is shown in accent, including none. Variant controls the outer treatment; nested content may use its own treatment.
104+
105+
<ComponentExample label="All eighteen visual variants" caption="Switch the site theme to compare the same samples in both palettes.">
106+
<div data-landing-gallery="variant"><LandingAppearanceGallery component="CodeShowcase" axis="variant"/></div>
107+
</ComponentExample>
108+
109+
## Result panel conditions
110+
111+
<ComponentExample label="Code alone, a title, or result metadata" caption="Either resultTitle or resultMeta enables the result slot. language is a visible badge; syntax highlighting comes from MDX fenced code.">
112+
<div class="component-appearance-grid">
113+
<div class="component-appearance-cell"><code>Code only</code><CodeShowcase title="A named value" summary="No result panel needed." language="TypeScript"><pre><code>const status = 'ready'</code></pre></CodeShowcase></div>
114+
<div class="component-appearance-cell"><code>Result title only</code><CodeShowcase title="Status label" resultTitle="Preview"><pre><code>&lt;Badge&gt;Ready&lt;/Badge&gt;</code></pre><template #result><Badge tone="success">Ready</Badge></template></CodeShowcase></div>
115+
<div class="component-appearance-cell"><code>Result metadata only</code><CodeShowcase eyebrow="ONE COMPONENT" title="Inline status" resultMeta="Live" tone="feature"><pre><code>&lt;Badge&gt;Ready&lt;/Badge&gt;</code></pre><template #result><Badge tone="feature">Ready</Badge></template></CodeShowcase></div>
116+
</div>
117+
</ComponentExample>
118+
119+
## Feature map
120+
121+
| Public feature | Visible example |
122+
| --- | --- |
123+
| tone, variant | Complete galleries above, with all supported values visible together. |
124+
| eyebrow, title, summary | The original code-and-result example introduces the purpose of the snippet. |
125+
| language | MDX and TypeScript badges label the snippets; the title-only result sample omits the language badge. |
126+
| resultTitle, resultMeta | Compare code-only, title-only result, metadata-only result, and the original result with both fields. |
127+
| Default and result slots | The default slot holds code; the named result slot holds live rendered content. A result heading or metadata is required to show that panel. |
128+
| Native attributes and events | Pass attributes through the root; keyboard behavior belongs to the composed native controls. |
129+
130+
This component exposes tone and variant, but no variantMode. Style individual child components explicitly when their appearance should match.
131+
92132
## Behavior and accessibility
93133

94134
The language prop is a badge, not a syntax-highlighting engine. ts-ssg highlights fenced code in MDX automatically. A result slot is rendered only when resultTitle or resultMeta is present. Keep results keyboard-accessible when they contain controls.
@@ -149,8 +189,6 @@ The language prop is a badge, not a syntax-highlighting engine. ts-ssg highlight
149189
<p><strong>Default slot:</strong> code or other explanatory content. <strong>result:</strong> rendered example. Register defineCodeShowcaseComponent with Panel, Flex, SectionHeader and Badge.</p>
150190
</div>
151191

152-
153-
154192
## Related components
155193

156194
- [Tabs](/components/layout/tabs/)

0 commit comments

Comments
 (0)