Skip to content

Commit 649b06b

Browse files
feat(default-theme): preview component (#138)
1 parent 2c1bac5 commit 649b06b

20 files changed

Lines changed: 1224 additions & 18 deletions

File tree

dev/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
},
1010
"dependencies": {
1111
"@kobalte/solidbase": "workspace:*",
12+
"@kobalte/core": "0.13.11",
1213
"@solidjs/router": "^0.15.3",
1314
"@solidjs/start": "https://pkg.pr.new/solidjs/solid-start/@solidjs/start@2080",
1415
"nitro": "3.0.260311-beta",

dev/src/app.css

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,152 @@
11
body {
22
margin: 0;
33
}
4+
5+
.sb-preview-demo-accordion-wrap {
6+
width: 100%;
7+
display: flex;
8+
justify-content: center;
9+
}
10+
11+
.sb-preview-demo-accordion {
12+
width: min(100%, 27rem);
13+
border-radius: 0.75rem;
14+
border: 1px solid rgb(20 20 20 / 0.12);
15+
background: rgb(255 255 255 / 0.92);
16+
overflow: hidden;
17+
}
18+
19+
.sb-preview-demo-item + .sb-preview-demo-item {
20+
border-top: 1px solid rgb(15 23 42 / 0.08);
21+
}
22+
23+
.sb-preview-demo-header {
24+
display: block;
25+
}
26+
27+
.sb-preview-demo-trigger {
28+
width: 100%;
29+
min-height: 3.25rem;
30+
padding: 0.95rem 1rem;
31+
display: flex;
32+
align-items: center;
33+
justify-content: space-between;
34+
gap: 1rem;
35+
border: none;
36+
background: transparent;
37+
color: rgb(15 23 42 / 0.92);
38+
font: inherit;
39+
font-weight: 600;
40+
text-align: left;
41+
cursor: pointer;
42+
}
43+
44+
.sb-preview-demo-trigger:focus-visible {
45+
outline: 2px solid rgb(59 130 246 / 0.9);
46+
outline-offset: -2px;
47+
}
48+
49+
.chevron-icon {
50+
font-size: 0.95rem;
51+
line-height: 1;
52+
transition: transform 180ms ease;
53+
}
54+
55+
.sb-preview-demo-trigger[data-expanded] .chevron-icon {
56+
transform: rotate(180deg);
57+
}
58+
59+
.sb-preview-demo-content {
60+
padding: 0 1rem 1rem;
61+
color: rgb(51 65 85 / 0.9);
62+
}
63+
64+
.sb-preview-demo-content p {
65+
margin: 0;
66+
line-height: 1.65;
67+
}
68+
69+
.sb-preview-demo-cards {
70+
width: min(100%, 42rem);
71+
display: grid;
72+
grid-template-columns: repeat(3, minmax(0, 1fr));
73+
gap: 0.9rem;
74+
}
75+
76+
.sb-preview-demo-card {
77+
padding: 1rem;
78+
border-radius: 0.75rem;
79+
background: rgb(255 255 255 / 0.78);
80+
border: 1px solid rgb(15 23 42 / 0.08);
81+
color: rgb(15 23 42 / 0.94);
82+
backdrop-filter: blur(10px);
83+
}
84+
85+
.sb-preview-demo-card-kicker {
86+
display: inline-block;
87+
margin-bottom: 0.65rem;
88+
font-size: 0.72rem;
89+
font-weight: 700;
90+
letter-spacing: 0;
91+
text-transform: uppercase;
92+
color: rgb(37 99 235 / 0.92);
93+
}
94+
95+
.sb-preview-demo-card h3 {
96+
margin: 0 0 0.45rem;
97+
font-size: 1rem;
98+
line-height: 1.3;
99+
}
100+
101+
.sb-preview-demo-card p {
102+
margin: 0;
103+
color: rgb(51 65 85 / 0.9);
104+
line-height: 1.55;
105+
}
106+
107+
html[data-theme*="dark"] .sb-preview-demo-accordion {
108+
border-color: rgb(255 255 255 / 0.14);
109+
background: rgb(17 17 17 / 0.92);
110+
}
111+
112+
html[data-theme*="dark"] .sb-preview-demo-item + .sb-preview-demo-item {
113+
border-top-color: rgb(255 255 255 / 0.1);
114+
}
115+
116+
html[data-theme*="dark"] .sb-preview-demo-trigger {
117+
color: rgb(245 245 245 / 0.96);
118+
}
119+
120+
html[data-theme*="dark"] .sb-preview-demo-content {
121+
color: rgb(212 212 216 / 0.9);
122+
}
123+
124+
html[data-theme*="dark"] .sb-preview-demo-card {
125+
background: rgb(255 255 255 / 0.08);
126+
border-color: rgb(255 255 255 / 0.1);
127+
color: rgb(250 250 250 / 0.95);
128+
}
129+
130+
html[data-theme*="dark"] .sb-preview-demo-card-kicker {
131+
color: rgb(147 197 253 / 0.92);
132+
}
133+
134+
html[data-theme*="dark"] .sb-preview-demo-card p {
135+
color: rgb(228 228 231 / 0.85);
136+
}
137+
138+
@media (max-width: 48rem) {
139+
.sb-preview-demo-cards {
140+
grid-template-columns: 1fr;
141+
}
142+
}
143+
144+
@media (max-width: 40rem) {
145+
.sb-preview-demo-trigger {
146+
padding: 0.9rem 0.85rem;
147+
}
148+
149+
.sb-preview-demo-content {
150+
padding: 0 0.85rem 0.9rem;
151+
}
152+
}

dev/src/preview-demo.tsx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import { Accordion } from "@kobalte/core/accordion";
2+
import { For } from "solid-js";
3+
4+
function ChevronDownIcon(props: { class?: string }) {
5+
return (
6+
<svg
7+
xmlns="http://www.w3.org/2000/svg"
8+
width="24"
9+
height="24"
10+
viewBox="0 0 24 24"
11+
class={props.class}
12+
aria-hidden="true"
13+
>
14+
<path
15+
fill="currentColor"
16+
d="m12 13.171 4.95-4.95 1.414 1.415L12 16 5.636 9.636 7.05 8.222z"
17+
/>
18+
</svg>
19+
);
20+
}
21+
22+
const accordionItems = [
23+
{
24+
value: "item-1",
25+
title: "Is it accessible?",
26+
body: "Yes. It follows the WAI-ARIA accordion pattern and supports keyboard navigation.",
27+
},
28+
{
29+
value: "item-2",
30+
title: "Is it unstyled?",
31+
body: "Yes. The example styling is local to the dev app so theme authors can review the shell in isolation.",
32+
},
33+
{
34+
value: "item-3",
35+
title: "Does it hold up on mobile?",
36+
body: "The trigger rows keep their tap targets and the stage allows horizontal overflow when a demo needs it.",
37+
},
38+
];
39+
40+
export function PreviewAccordionExample() {
41+
return (
42+
<div class="sb-preview-demo-accordion-wrap">
43+
<Accordion
44+
class="sb-preview-demo-accordion"
45+
defaultValue={["item-1"]}
46+
collapsible
47+
>
48+
<For each={accordionItems}>
49+
{(item) => (
50+
<Accordion.Item class="sb-preview-demo-item" value={item.value}>
51+
<Accordion.Header class="sb-preview-demo-header">
52+
<Accordion.Trigger class="sb-preview-demo-trigger">
53+
<span>{item.title}</span>
54+
<ChevronDownIcon class="chevron-icon" />
55+
</Accordion.Trigger>
56+
</Accordion.Header>
57+
<Accordion.Content class="sb-preview-demo-content">
58+
<p>{item.body}</p>
59+
</Accordion.Content>
60+
</Accordion.Item>
61+
)}
62+
</For>
63+
</Accordion>
64+
</div>
65+
);
66+
}
67+
68+
const cardItems = [
69+
{
70+
title: "Preview-only",
71+
body: "Shows the dark stage without the lighter supporting panel.",
72+
},
73+
{
74+
title: "Responsive",
75+
body: "Cards wrap and keep enough breathing room on narrow viewports.",
76+
},
77+
{
78+
title: "Theme-aware",
79+
body: "The stage shell adapts to light and dark theme variables.",
80+
},
81+
];
82+
83+
export function PreviewCardsExample() {
84+
return (
85+
<div class="sb-preview-demo-cards">
86+
<For each={cardItems}>
87+
{(item) => (
88+
<article class="sb-preview-demo-card">
89+
<span class="sb-preview-demo-card-kicker">Preview</span>
90+
<h3>{item.title}</h3>
91+
<p>{item.body}</p>
92+
</article>
93+
)}
94+
</For>
95+
</div>
96+
);
97+
}

dev/src/routes/index.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ www.example.com
8484

8585
[Router French About](/router/fr/about)
8686

87+
[Preview examples](/preview)
88+
8789
[External v0](https://solidbase.dev)
8890

8991
#20 also #4 but no \\#20

0 commit comments

Comments
 (0)