Skip to content

Commit 69f4924

Browse files
committed
Improve feature-card component.
1 parent f37e886 commit 69f4924

5 files changed

Lines changed: 200 additions & 95 deletions

File tree

‎frontend/docs/landingGuide.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,12 @@ export function defineLandingAppearanceGallery() {
6969
icon="lucide:check"
7070
badge="Included"
7171
><template #actions
72-
><BtnLink href="/components/" :tone="sample.tone" variant="outline"
72+
><BtnLink
73+
href="/components/"
74+
:tone="sample.tone"
75+
variant="surface"
76+
icon="lucide:arrow-up-right"
77+
iconPosition="end"
7378
>Explore</BtnLink></template></FeatureCard>
7479
</div>
7580
<div class="landing-appearance-sample" r-if="component === 'MetricStrip'">
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<Grid columns="1" columnsMd="2" alignItems="stretch" class="gap-5">
2+
<FeatureCard
3+
eyebrow="CONTENT, CONNECTED"
4+
title="A good story starts here."
5+
summary="Bring your words and components together. Write pages that are a pleasure to read and easy to make your own."
6+
icon="lucide:file-code"
7+
badge="Native MDX"
8+
tone="accent"
9+
>
10+
<template #actions>
11+
<BtnLink
12+
href="/guides/"
13+
tone="accent"
14+
icon="lucide:arrow-right"
15+
iconPosition="end"
16+
>
17+
Explore the guides
18+
</BtnLink>
19+
</template>
20+
</FeatureCard>
21+
<FeatureCard
22+
eyebrow="MAKE ROOM FOR THE DETAILS"
23+
title="Small pieces. A complete experience."
24+
summary="Build on a shared set of components, then add the details that make your site feel like yours."
25+
icon="lucide:layers"
26+
badge="Made to compose"
27+
tone="neutral"
28+
>
29+
<Flex align="start" class="gap-2 fs-body lh-6">
30+
<Icon name="lucide:check" aria-hidden="true"/>
31+
<span
32+
>One design language, from the first heading to the final link.</span>
33+
</Flex>
34+
<template #actions>
35+
<BtnLink
36+
href="/components/"
37+
tone="neutral"
38+
variant="outline"
39+
icon="lucide:arrow-right"
40+
iconPosition="end"
41+
>
42+
Browse components
43+
</BtnLink>
44+
</template>
45+
</FeatureCard>
46+
</Grid>
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<Grid
2+
columns="1"
3+
columnsMd="2"
4+
columnsLg="3"
5+
alignItems="stretch"
6+
class="gap-5"
7+
>
8+
<FeatureCard
9+
eyebrow="01 / WRITE"
10+
title="Start with your story"
11+
summary="Give your ideas a home with readable content and a clear page structure."
12+
icon="lucide:file-code"
13+
tone="accent"
14+
variant="surface"
15+
>
16+
<template #actions>
17+
<BtnLink
18+
href="/guides/"
19+
tone="accent"
20+
variant="link"
21+
icon="lucide:arrow-up-right"
22+
iconPosition="end"
23+
>
24+
Start writing
25+
</BtnLink>
26+
</template>
27+
</FeatureCard>
28+
<FeatureCard
29+
eyebrow="02 / COMPOSE"
30+
title="Find a shared rhythm"
31+
summary="Use familiar components to connect every part of the experience."
32+
icon="lucide:blocks"
33+
tone="secondary"
34+
variant="surface"
35+
>
36+
<template #actions>
37+
<BtnLink
38+
href="/components/layout/"
39+
tone="secondary"
40+
variant="link"
41+
icon="lucide:arrow-up-right"
42+
iconPosition="end"
43+
>
44+
Explore layouts
45+
</BtnLink>
46+
</template>
47+
</FeatureCard>
48+
<FeatureCard
49+
eyebrow="03 / INTERACT"
50+
title="Make the details count"
51+
summary="Add focused interactions that help visitors take their next step."
52+
icon="lucide:mouse-pointer-2"
53+
tone="info"
54+
variant="surface"
55+
>
56+
<template #actions>
57+
<BtnLink
58+
href="/components/runtime/regor-app/"
59+
tone="info"
60+
variant="link"
61+
icon="lucide:arrow-up-right"
62+
iconPosition="end"
63+
>
64+
Add interaction
65+
</BtnLink>
66+
</template>
67+
</FeatureCard>
68+
</Grid>

‎frontend/purestack.studio/components/landing/feature-card/feature-card.mdx‎

Lines changed: 37 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,18 @@ nav:
1717
name="FeatureCard"
1818
kind="Feature story"
1919
summary="Present one capability with a recognizable icon, short explanation and an optional next step."
20-
source="https://github.com/PureStackStudio/PureStack/blob/main/packages/ts-components/src/standard/landing/landingTypes.ts"
20+
source="https://github.com/PureStackStudio/PureStack/blob/main/packages/ts-components/src/standard/landing/featureCard.ts"
2121
section="Landing &amp; pricing"
2222
sectionHref="/components/landing/"/>
2323

2424
## A feature with a next step
2525

26-
The actions slot gives readers a clear continuation.
26+
FeatureCard gives one capability a clear introduction: an icon and optional
27+
badge, a short heading, and a readable explanation. Content follows a consistent
28+
start alignment, with room between each part of the story.
29+
30+
Use the `actions` slot for a next step. Cards stretch to fill their grid row,
31+
keeping actions aligned even when one card has more content than another.
2732

2833
<Tabs
2934
group="feature-card-sample-1"
@@ -35,54 +40,23 @@ The actions slot gives readers a clear continuation.
3540
>
3641
<TabPane id="feature-card-sample-1-preview" label="Preview">
3742
<ComponentExample
38-
label="FeatureCard in context"
39-
caption="Compare the composition, then open its source tab to adapt it."
43+
data-toc-ignore
44+
label="Two features, one clear rhythm"
45+
caption="An icon introduces each feature, a badge adds context, and the actions share a baseline."
4046
>
41-
<FeatureCard
42-
eyebrow="AUTHORING"
43-
title="Readable by design"
44-
summary="Keep content and components close together in MDX."
45-
badge="Native"
46-
icon="lucide:check"
47-
tone="accent"
48-
>
49-
<p>Use the same primitives in documentation and product UI.</p>
50-
<template #actions>
51-
<BtnLink
52-
href="/components/runtime/regor-app/"
53-
tone="accent"
54-
variant="outline"
55-
>
56-
Add browser state
57-
</BtnLink>
58-
</template>
59-
</FeatureCard>
47+
<import-content src="./_feature-action.mdx"/>
6048
</ComponentExample>
6149
</TabPane>
6250
<TabPane id="feature-card-sample-1-source-0" label="feature-action.mdx">
63-
```html
64-
<FeatureCard
65-
eyebrow="AUTHORING"
66-
title="Readable by design"
67-
summary="Keep content and components close together in MDX."
68-
badge="Native"
69-
icon="lucide:check"
70-
tone="accent"
71-
>
72-
<p>Use the same primitives in documentation and product UI.</p>
73-
<template #actions>
74-
<BtnLink href="/components/runtime/regor-app/" tone="accent" variant="outline">
75-
Add browser state
76-
</BtnLink>
77-
</template>
78-
</FeatureCard>
79-
```
51+
<import-codeblock src="./_feature-action.mdx" lang="html"/>
8052
</TabPane>
8153
</Tabs>
8254

8355
## A coherent feature set
8456

85-
Cards share a theme but can express distinct intent.
57+
Use a consistent heading level and content structure across a set. The cards
58+
below share spacing and typography while their tones distinguish each step.
59+
The layout stacks on smaller screens.
8660

8761
<Tabs
8862
group="feature-card-sample-2"
@@ -93,38 +67,16 @@ Cards share a theme but can express distinct intent.
9367
tabVariant="underline"
9468
>
9569
<TabPane id="feature-card-sample-2-preview" label="Preview">
96-
<div class="component-preview-stage">
97-
<Grid columns="1" columnsSm="2">
98-
<FeatureCard
99-
title="Content first"
100-
summary="Ship readable pages with native HTML."
101-
tone="info"
102-
variant="outline"/>
103-
<FeatureCard
104-
title="State when needed"
105-
summary="Mount focused browser apps for interaction."
106-
tone="success"
107-
variant="surface"/>
108-
</Grid>
109-
</div>
70+
<ComponentExample
71+
data-toc-ignore
72+
label="A connected feature set"
73+
caption="The same card structure works across different tones, copy lengths, and destinations."
74+
>
75+
<import-content src="./_feature-set.mdx"/>
76+
</ComponentExample>
11077
</TabPane>
11178
<TabPane id="feature-card-sample-2-source-0" label="feature-set.mdx">
112-
```html
113-
<Grid columns="1" columnsSm="2">
114-
<FeatureCard
115-
title="Content first"
116-
summary="Ship readable pages with native HTML."
117-
tone="info"
118-
variant="outline"
119-
/>
120-
<FeatureCard
121-
title="State when needed"
122-
summary="Mount focused browser apps for interaction."
123-
tone="success"
124-
variant="surface"
125-
/>
126-
</Grid>
127-
```
79+
<import-codeblock src="./_feature-set.mdx" lang="html"/>
12880
</TabPane>
12981
</Tabs>
13082

@@ -133,6 +85,7 @@ Cards share a theme but can express distinct intent.
13385
The same composition in every semantic tone. Child tones are explicit where the composition owns them, including navigation actions.
13486

13587
<ComponentExample
88+
data-toc-ignore
13689
label="All ten semantic tones"
13790
caption="Switch the site theme to compare the same samples in both palettes."
13891
>
@@ -143,9 +96,12 @@ The same composition in every semantic tone. Child tones are explicit where the
14396

14497
## All eighteen visual variants
14598

146-
Every supported variant is shown in accent, including none. Variant controls the outer treatment; nested content may use its own treatment.
99+
Every supported variant is shown in accent, including none. The variant controls
100+
the card's outer treatment. The icon keeps its own surface treatment so it stays
101+
recognizable across the set.
147102

148103
<ComponentExample
104+
data-toc-ignore
149105
label="All eighteen visual variants"
150106
caption="Switch the site theme to compare the same samples in both palettes."
151107
>
@@ -157,6 +113,7 @@ Every supported variant is shown in accent, including none. Variant controls the
157113
## Optional content and both slots
158114

159115
<ComponentExample
116+
data-toc-ignore
160117
label="A card can be brief or complete"
161118
caption="The default slot extends the story; actions holds navigation. Each optional text and decoration can be omitted independently."
162119
>
@@ -202,14 +159,20 @@ Every supported variant is shown in accent, including none. Variant controls the
202159
| eyebrow, title, summary | Compare the text-only card and the complete workflow card. |
203160
| icon, badge | Icon-only, badge-only, and combined decoration are visible together. |
204161
| Default slot | The complete workflow card adds rich supporting text below the summary. |
205-
| actions slot | Compare one destination in the original example with two destinations in Both slots. |
162+
| actions slot | Actions sit at the bottom of equal-height cards. Compare one destination with two destinations in Both slots. |
206163
| Native attributes and events | Pass attributes through the root; keyboard behavior belongs to the composed native controls. |
207164

208165
This component exposes tone and variant, but no variantMode. Style individual child components explicitly when their appearance should match.
209166

210167
## Behavior and accessibility
211168

212-
The generated title is h3. Place feature cards under an h2 section heading, and keep summaries comparable in length. An icon and a badge support the title; they should not carry the only explanation.
169+
The generated title is h3. Place feature cards under an h2 section heading. The
170+
icon is decorative; the heading and summary describe the feature. The card is
171+
a content container, and links or buttons in `actions` provide interaction.
172+
173+
FeatureCard uses built-in layout, spacing, and typography utilities and adds no
174+
component-specific stylesheet. Use its `feature-card` class for any additional
175+
styling your site needs.
213176

214177
## API reference
215178

‎packages/ts-components/src/standard/landing/featureCard.ts‎

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,49 @@ import { defineComponent, html } from 'regor'
22
import type { FeatureCard } from './landingTypes'
33

44
export function defineFeatureCardComponent() {
5-
const featureCardTemplate = html`<Panel :tone="tone" :variant="variant || 'surface'">
6-
<Flex direction="column" align="start" justify="center">
7-
<Flex align="center" justify="center" class="w-full" r-if="icon || badge">
8-
<IconFrame
9-
r-if="icon"
10-
:name="icon"
11-
:tone="tone"
12-
:variant="variant"
13-
size="lg"/>
14-
<Badge r-if="badge" :tone="tone">{{ badge }}</Badge>
15-
</Flex>
16-
<Flex direction="column" align="center" class="text-justify">
17-
<p class="text-eyebrow" r-if="eyebrow">{{ eyebrow }}</p>
18-
<h3 class="fs-h4 fw-700 my-0" r-if="title">{{ title }}</h3>
19-
<p class="text-tagline mb-0" r-if="summary">{{ summary }}</p>
20-
<slot></slot>
21-
</Flex>
22-
<Flex wrap="true" class="mt-auto">
23-
<slot name="actions"></slot>
24-
</Flex>
5+
const featureCardTemplate = html`<Panel
6+
class="feature-card h-full min-w-0 p-5"
7+
bodyClass="feature-card__body flex flex-column h-full gap-5"
8+
:tone="tone"
9+
:variant="variant || 'surface'"
10+
>
11+
<Flex
12+
r-if="icon || badge"
13+
class="feature-card__header gap-3"
14+
align="start"
15+
justify="between"
16+
wrap="true"
17+
>
18+
<IconFrame
19+
r-if="icon"
20+
class="feature-card__icon p-2"
21+
:name="icon"
22+
:tone="tone || 'accent'"
23+
variant="surface"
24+
aria-hidden="true"/>
25+
<Badge r-if="badge" :tone="tone || 'accent'"
26+
>{{ badge }}</Badge>
27+
</Flex>
28+
<Flex direction="column" align="start" class="feature-card__content gap-3">
29+
<p
30+
r-if="eyebrow"
31+
class="feature-card__eyebrow fs-xxs fw-700 uppercase opacity-75 m-0"
32+
>
33+
{{ eyebrow }}
34+
</p>
35+
<h3
36+
r-if="title"
37+
class="feature-card__title fs-h4 fw-600 lh-2 m-0 wrap-anywhere"
38+
>
39+
{{ title }}
40+
</h3>
41+
<p r-if="summary" class="feature-card__summary fs-body lh-6 opacity-75 m-0">
42+
{{ summary }}
43+
</p>
44+
<slot></slot>
45+
</Flex>
46+
<Flex wrap="true" align="center" class="feature-card__actions mt-auto gap-3">
47+
<slot name="actions"></slot>
2548
</Flex>
2649
</Panel>`
2750

0 commit comments

Comments
 (0)