@casoon/pages-theme 0.0.0-stage → 0.12.8
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/LICENSE +21 -0
- package/README.md +279 -2
- package/assets/casoon-logo-dark.svg +70 -0
- package/assets/casoon-logo.svg +71 -0
- package/assets/favicon.svg +1 -0
- package/components/AnchorGrid.astro +135 -0
- package/components/ApiEntry.astro +136 -0
- package/components/Badge.astro +31 -0
- package/components/Badges.astro +10 -0
- package/components/BuildOutput.astro +84 -0
- package/components/Button.astro +55 -0
- package/components/CallToAction.astro +64 -0
- package/components/Callout.astro +66 -0
- package/components/CodeBlock.astro +84 -0
- package/components/Demo.astro +80 -0
- package/components/ExamplePanel.astro +153 -0
- package/components/Facts.astro +112 -0
- package/components/Faq.astro +123 -0
- package/components/Features.astro +139 -0
- package/components/FileSet.astro +258 -0
- package/components/Footer.astro +160 -0
- package/components/Header.astro +278 -0
- package/components/Hero.astro +318 -0
- package/components/Install.astro +154 -0
- package/components/Integrations.astro +125 -0
- package/components/Keymap.astro +102 -0
- package/components/Quickstart.astro +95 -0
- package/components/ReleaseHighlights.astro +115 -0
- package/components/Spotlight.astro +177 -0
- package/components/Swatch.astro +45 -0
- package/components/Tabs.astro +90 -0
- package/components/Terminal.astro +79 -0
- package/components/index.ts +25 -0
- package/content.ts +23 -0
- package/fonts/OFL.txt +95 -0
- package/fonts/inter-latin-400-normal.woff2 +0 -0
- package/fonts/inter-latin-500-normal.woff2 +0 -0
- package/fonts/inter-latin-600-normal.woff2 +0 -0
- package/fonts/jetbrains-mono-latin-400-normal.woff2 +0 -0
- package/fonts/jetbrains-mono-latin-500-normal.woff2 +0 -0
- package/fonts/onest-latin-wght-normal.woff2 +0 -0
- package/index.ts +204 -0
- package/layouts/Base.astro +131 -0
- package/layouts/Docs.astro +286 -0
- package/lib/ansi.ts +168 -0
- package/lib/changelog.ts +85 -0
- package/lib/docs.ts +54 -0
- package/lib/i18n.ts +136 -0
- package/lib/og.ts +91 -0
- package/lib/showcase.ts +48 -0
- package/lib/url.ts +16 -0
- package/lib/version.ts +50 -0
- package/package.json +71 -4
- package/routes/404.astro +49 -0
- package/routes/changelog.astro +129 -0
- package/routes/docs/[...slug].astro +39 -0
- package/routes/showcase/[slug].astro +108 -0
- package/routes/showcase/index.astro +195 -0
- package/styles/base.css +307 -0
- package/styles/fonts.css +52 -0
- package/styles/tokens.css +136 -0
- package/virtual.d.ts +12 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Overview entry for a public type or function. Item-level docs stay on docs.rs / TypeDoc. */
|
|
3
|
+
import { Code } from 'astro:components';
|
|
4
|
+
import config from 'virtual:casoon-pages/config';
|
|
5
|
+
import { t } from '../lib/i18n';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
kind: string;
|
|
9
|
+
name: string;
|
|
10
|
+
signature: string;
|
|
11
|
+
lang?: string;
|
|
12
|
+
since?: string;
|
|
13
|
+
params?: { name: string; type: string; desc: string }[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { kind, name, signature, lang = 'rust', since, params = [] } = Astro.props;
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<section class="api">
|
|
20
|
+
<header>
|
|
21
|
+
<span class="kind">{kind}</span>
|
|
22
|
+
<code class="name">{name}</code>
|
|
23
|
+
{since && <span class="since">{since}</span>}
|
|
24
|
+
</header>
|
|
25
|
+
<div class="body">
|
|
26
|
+
<div class="sig"><Code code={signature} lang={lang as never} theme="css-variables" /></div>
|
|
27
|
+
<slot />
|
|
28
|
+
{
|
|
29
|
+
params.length > 0 && (
|
|
30
|
+
<>
|
|
31
|
+
<p class="label">{t(config.lang).parameters}</p>
|
|
32
|
+
<dl>
|
|
33
|
+
{params.map((p) => (
|
|
34
|
+
<div>
|
|
35
|
+
<dt>
|
|
36
|
+
<code>{p.name}</code>
|
|
37
|
+
</dt>
|
|
38
|
+
<dd class="type">
|
|
39
|
+
<code>{p.type}</code>
|
|
40
|
+
</dd>
|
|
41
|
+
<dd>{p.desc}</dd>
|
|
42
|
+
</div>
|
|
43
|
+
))}
|
|
44
|
+
</dl>
|
|
45
|
+
</>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
</div>
|
|
49
|
+
</section>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.api {
|
|
53
|
+
margin-bottom: 26px;
|
|
54
|
+
overflow: hidden;
|
|
55
|
+
border: 1px solid var(--border);
|
|
56
|
+
border-radius: 16px;
|
|
57
|
+
background: var(--surface);
|
|
58
|
+
box-shadow: var(--shadow);
|
|
59
|
+
}
|
|
60
|
+
header {
|
|
61
|
+
display: flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: 10px;
|
|
64
|
+
padding: 14px 20px;
|
|
65
|
+
border-bottom: 1px solid var(--border);
|
|
66
|
+
background: var(--bg-deep);
|
|
67
|
+
}
|
|
68
|
+
.kind {
|
|
69
|
+
padding: 2px 7px;
|
|
70
|
+
border: 1px solid var(--border);
|
|
71
|
+
border-radius: 5px;
|
|
72
|
+
color: var(--muted);
|
|
73
|
+
font-family: var(--font-mono);
|
|
74
|
+
font-size: 12px;
|
|
75
|
+
letter-spacing: 0.06em;
|
|
76
|
+
text-transform: uppercase;
|
|
77
|
+
}
|
|
78
|
+
.name {
|
|
79
|
+
color: var(--heading);
|
|
80
|
+
font-size: 14.5px;
|
|
81
|
+
font-weight: 500;
|
|
82
|
+
}
|
|
83
|
+
.since {
|
|
84
|
+
margin-left: auto;
|
|
85
|
+
color: var(--muted);
|
|
86
|
+
font-family: var(--font-mono);
|
|
87
|
+
font-size: 12px;
|
|
88
|
+
}
|
|
89
|
+
.body {
|
|
90
|
+
padding: 20px;
|
|
91
|
+
font-size: 14.5px;
|
|
92
|
+
}
|
|
93
|
+
.sig {
|
|
94
|
+
margin-bottom: 18px;
|
|
95
|
+
overflow: hidden;
|
|
96
|
+
border-radius: 10px;
|
|
97
|
+
}
|
|
98
|
+
.sig :global(pre.astro-code) {
|
|
99
|
+
padding: 14px 16px;
|
|
100
|
+
line-height: 1.7;
|
|
101
|
+
}
|
|
102
|
+
.body :global(p) {
|
|
103
|
+
margin: 0 0 18px;
|
|
104
|
+
}
|
|
105
|
+
.label {
|
|
106
|
+
margin-bottom: 8px !important;
|
|
107
|
+
color: var(--muted);
|
|
108
|
+
font-family: var(--font-mono);
|
|
109
|
+
font-size: 12px;
|
|
110
|
+
letter-spacing: 0.08em;
|
|
111
|
+
text-transform: uppercase;
|
|
112
|
+
}
|
|
113
|
+
dl {
|
|
114
|
+
margin: 0;
|
|
115
|
+
}
|
|
116
|
+
dl div {
|
|
117
|
+
display: grid;
|
|
118
|
+
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
|
|
119
|
+
gap: 4px 16px;
|
|
120
|
+
align-items: baseline;
|
|
121
|
+
padding: 10px 0;
|
|
122
|
+
border-top: 1px solid var(--border);
|
|
123
|
+
font-size: 14px;
|
|
124
|
+
}
|
|
125
|
+
dd {
|
|
126
|
+
margin: 0;
|
|
127
|
+
}
|
|
128
|
+
dt code {
|
|
129
|
+
color: var(--heading);
|
|
130
|
+
font-size: 13px;
|
|
131
|
+
}
|
|
132
|
+
.type code {
|
|
133
|
+
color: var(--accent);
|
|
134
|
+
font-size: 12.5px;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Static badge: version, licence, registry, status. No external badge services. */
|
|
3
|
+
interface Props {
|
|
4
|
+
tone?: 'muted' | 'accent' | 'brand';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const { tone = 'muted' } = Astro.props;
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<span class:list={['badge', tone]}><slot /></span>
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
.badge {
|
|
14
|
+
display: inline-block;
|
|
15
|
+
padding: 3px 9px;
|
|
16
|
+
border: 1px solid var(--border);
|
|
17
|
+
border-radius: 6px;
|
|
18
|
+
font-family: var(--font-mono);
|
|
19
|
+
font-size: 12px;
|
|
20
|
+
line-height: 1.5;
|
|
21
|
+
}
|
|
22
|
+
.muted {
|
|
23
|
+
color: var(--muted);
|
|
24
|
+
}
|
|
25
|
+
.accent {
|
|
26
|
+
color: var(--accent);
|
|
27
|
+
}
|
|
28
|
+
.brand {
|
|
29
|
+
color: var(--brand);
|
|
30
|
+
}
|
|
31
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Home section showing one real output generated during the build. */
|
|
3
|
+
import config from 'virtual:casoon-pages/config';
|
|
4
|
+
import { t } from '../lib/i18n';
|
|
5
|
+
import { url } from '../lib/url';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
caption: string;
|
|
9
|
+
file: string;
|
|
10
|
+
heading?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const s = t(config.lang);
|
|
14
|
+
const { caption, file, heading = s.buildOutputHeading } = Astro.props;
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
<section class="build">
|
|
18
|
+
<div class="head">
|
|
19
|
+
<h2 class="cp-label">{heading}</h2>
|
|
20
|
+
{config.hasShowcase && <a href={url('showcase/')}>{s.allExamples} →</a>}
|
|
21
|
+
</div>
|
|
22
|
+
<figure>
|
|
23
|
+
<div class="output"><slot /></div>
|
|
24
|
+
<figcaption>
|
|
25
|
+
<p>{caption}</p>
|
|
26
|
+
<span class="file">{file}</span>
|
|
27
|
+
</figcaption>
|
|
28
|
+
</figure>
|
|
29
|
+
</section>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
.build {
|
|
33
|
+
max-width: var(--max);
|
|
34
|
+
margin: 0 auto;
|
|
35
|
+
padding: 0 24px 80px;
|
|
36
|
+
}
|
|
37
|
+
.head {
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: baseline;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
gap: 16px;
|
|
42
|
+
margin-bottom: 20px;
|
|
43
|
+
}
|
|
44
|
+
.head h2 {
|
|
45
|
+
margin: 0;
|
|
46
|
+
}
|
|
47
|
+
.head a {
|
|
48
|
+
font-size: 14px;
|
|
49
|
+
}
|
|
50
|
+
figure {
|
|
51
|
+
margin: 0;
|
|
52
|
+
overflow: hidden;
|
|
53
|
+
border: 1px solid var(--border);
|
|
54
|
+
border-radius: 16px;
|
|
55
|
+
background: var(--surface);
|
|
56
|
+
box-shadow: var(--shadow);
|
|
57
|
+
}
|
|
58
|
+
.output {
|
|
59
|
+
border-bottom: 1px solid var(--border);
|
|
60
|
+
}
|
|
61
|
+
.output :global(.terminal) {
|
|
62
|
+
border: 0;
|
|
63
|
+
border-radius: 0;
|
|
64
|
+
box-shadow: none;
|
|
65
|
+
}
|
|
66
|
+
figcaption {
|
|
67
|
+
display: flex;
|
|
68
|
+
flex-wrap: wrap;
|
|
69
|
+
align-items: center;
|
|
70
|
+
justify-content: space-between;
|
|
71
|
+
gap: 16px;
|
|
72
|
+
padding: 18px 22px;
|
|
73
|
+
}
|
|
74
|
+
p {
|
|
75
|
+
margin: 0;
|
|
76
|
+
font-size: 14.5px;
|
|
77
|
+
}
|
|
78
|
+
.file {
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
color: var(--muted);
|
|
81
|
+
font-family: var(--font-mono);
|
|
82
|
+
font-size: 12px;
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Link styled as button. One primary per view. */
|
|
3
|
+
interface Props {
|
|
4
|
+
href: string;
|
|
5
|
+
variant?: 'primary' | 'secondary' | 'quiet';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const { href, variant = 'primary' } = Astro.props;
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<a class:list={['btn', variant]} href={href}><span class="label"><slot /></span></a>
|
|
12
|
+
|
|
13
|
+
<style>
|
|
14
|
+
/* Pill with a rolling label on hover. */
|
|
15
|
+
.btn {
|
|
16
|
+
--roll: 2.6em;
|
|
17
|
+
position: relative;
|
|
18
|
+
display: inline-flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
justify-content: center;
|
|
21
|
+
min-height: 47px;
|
|
22
|
+
padding: 10px 25px;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
border-radius: 30px;
|
|
25
|
+
font-size: 15px;
|
|
26
|
+
font-weight: 500;
|
|
27
|
+
line-height: 1.4;
|
|
28
|
+
white-space: nowrap;
|
|
29
|
+
}
|
|
30
|
+
.label {
|
|
31
|
+
display: block;
|
|
32
|
+
text-shadow: 0 var(--roll) 0 currentColor;
|
|
33
|
+
transition: transform 0.4s var(--ease-roll);
|
|
34
|
+
}
|
|
35
|
+
.btn:hover .label,
|
|
36
|
+
.btn:focus-visible .label {
|
|
37
|
+
transform: translateY(calc(-1 * var(--roll)));
|
|
38
|
+
}
|
|
39
|
+
.primary {
|
|
40
|
+
background: linear-gradient(180deg, var(--accent-top) 0%, var(--accent-fill) 25%, var(--accent-fill) 100%);
|
|
41
|
+
color: #fff;
|
|
42
|
+
}
|
|
43
|
+
.secondary {
|
|
44
|
+
background: linear-gradient(180deg, #383532 0%, #11100e 25%, #11100e 100%);
|
|
45
|
+
color: #fff;
|
|
46
|
+
}
|
|
47
|
+
.primary:hover,
|
|
48
|
+
.secondary:hover {
|
|
49
|
+
color: #fff;
|
|
50
|
+
}
|
|
51
|
+
.quiet {
|
|
52
|
+
padding-inline: 0;
|
|
53
|
+
color: var(--accent);
|
|
54
|
+
}
|
|
55
|
+
</style>
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Closing band on the accent ground: one large centred line and one button. Put it last on the
|
|
4
|
+
* start page, right above the footer.
|
|
5
|
+
*/
|
|
6
|
+
interface Props {
|
|
7
|
+
title: string;
|
|
8
|
+
href: string;
|
|
9
|
+
label: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const { title, href, label } = Astro.props;
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
<section class="cta">
|
|
16
|
+
<h2>{title}</h2>
|
|
17
|
+
<a class="btn" href={href}><span class="label">{label}</span></a>
|
|
18
|
+
</section>
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.cta {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 40px;
|
|
26
|
+
padding: 120px 24px;
|
|
27
|
+
background: var(--accent-fill);
|
|
28
|
+
text-align: center;
|
|
29
|
+
}
|
|
30
|
+
h2 {
|
|
31
|
+
max-width: 14ch;
|
|
32
|
+
margin: 0;
|
|
33
|
+
color: #fff;
|
|
34
|
+
font-size: clamp(40px, 6vw, 70px);
|
|
35
|
+
font-weight: 600;
|
|
36
|
+
letter-spacing: -0.02em;
|
|
37
|
+
line-height: 1;
|
|
38
|
+
}
|
|
39
|
+
.btn {
|
|
40
|
+
--roll: 3.2em;
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
min-height: 60px;
|
|
44
|
+
padding: 0 25px;
|
|
45
|
+
overflow: hidden;
|
|
46
|
+
border-radius: 30px;
|
|
47
|
+
background: linear-gradient(180deg, #383532 0%, #11100e 25%, #11100e 100%);
|
|
48
|
+
color: #fff;
|
|
49
|
+
font-size: 17px;
|
|
50
|
+
font-weight: 500;
|
|
51
|
+
}
|
|
52
|
+
.btn:hover {
|
|
53
|
+
color: #fff;
|
|
54
|
+
}
|
|
55
|
+
.label {
|
|
56
|
+
display: block;
|
|
57
|
+
text-shadow: 0 var(--roll) 0 currentColor;
|
|
58
|
+
transition: transform 0.4s var(--ease-roll);
|
|
59
|
+
}
|
|
60
|
+
.btn:hover .label,
|
|
61
|
+
.btn:focus-visible .label {
|
|
62
|
+
transform: translateY(calc(-1 * var(--roll)));
|
|
63
|
+
}
|
|
64
|
+
</style>
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
import config from 'virtual:casoon-pages/config';
|
|
3
|
+
import { t } from '../lib/i18n';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
type?: 'note' | 'tip' | 'caution' | 'deprecated';
|
|
7
|
+
title?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const TITLES = t(config.lang).callout;
|
|
11
|
+
const { type = 'note', title = TITLES[type] } = Astro.props;
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<div class:list={['callout', type]} role="note">
|
|
15
|
+
<p class="title">{title}</p>
|
|
16
|
+
<div class="body"><slot /></div>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
.callout {
|
|
21
|
+
margin: 32px 0;
|
|
22
|
+
padding: 16px 18px;
|
|
23
|
+
border: 1px solid var(--border);
|
|
24
|
+
border-left-width: 3px;
|
|
25
|
+
border-radius: 4px 12px 12px 4px;
|
|
26
|
+
font-size: 14.5px;
|
|
27
|
+
}
|
|
28
|
+
.note {
|
|
29
|
+
border-left-color: var(--accent);
|
|
30
|
+
background: var(--accent-soft);
|
|
31
|
+
}
|
|
32
|
+
.tip {
|
|
33
|
+
border-left-color: var(--accent);
|
|
34
|
+
}
|
|
35
|
+
.caution {
|
|
36
|
+
border-left-color: var(--brand);
|
|
37
|
+
background: var(--brand-soft);
|
|
38
|
+
}
|
|
39
|
+
.deprecated {
|
|
40
|
+
border-left-color: var(--border-strong);
|
|
41
|
+
background: var(--bg-deep);
|
|
42
|
+
}
|
|
43
|
+
.title {
|
|
44
|
+
margin: 0 0 3px;
|
|
45
|
+
color: var(--heading);
|
|
46
|
+
font-weight: 600;
|
|
47
|
+
}
|
|
48
|
+
/* The tinted backgrounds lower the contrast of the accent colour below 4.5:1, for any
|
|
49
|
+
project accent. Links use the heading colour and keep the accent as underline. */
|
|
50
|
+
.body :global(a),
|
|
51
|
+
.body :global(a:hover) {
|
|
52
|
+
color: var(--heading);
|
|
53
|
+
text-decoration: underline;
|
|
54
|
+
text-decoration-color: var(--accent);
|
|
55
|
+
text-underline-offset: 2px;
|
|
56
|
+
}
|
|
57
|
+
.body :global(a:hover) {
|
|
58
|
+
text-decoration-thickness: 2px;
|
|
59
|
+
}
|
|
60
|
+
.body :global(> :last-child) {
|
|
61
|
+
margin-bottom: 0;
|
|
62
|
+
}
|
|
63
|
+
.body :global(p) {
|
|
64
|
+
margin: 0 0 8px;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Highlighted at build time (Shiki, theme-aware via CSS variables). */
|
|
3
|
+
import { Code } from 'astro:components';
|
|
4
|
+
import config from 'virtual:casoon-pages/config';
|
|
5
|
+
import { t } from '../lib/i18n';
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
code: string;
|
|
9
|
+
lang?: string;
|
|
10
|
+
/** File name shown left in the bar. */
|
|
11
|
+
title?: string;
|
|
12
|
+
/** Language label shown right in the bar. */
|
|
13
|
+
label?: string;
|
|
14
|
+
copy?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const { code, lang = 'text', title, label, copy = true } = Astro.props;
|
|
18
|
+
const s = t(config.lang);
|
|
19
|
+
|
|
20
|
+
let hash = 5381;
|
|
21
|
+
for (const ch of code) hash = ((hash * 33) ^ ch.charCodeAt(0)) >>> 0;
|
|
22
|
+
const id = `code-${hash.toString(36)}`;
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<figure class="codeblock">
|
|
26
|
+
{
|
|
27
|
+
(title || label || copy) && (
|
|
28
|
+
<figcaption>
|
|
29
|
+
<span>{title}</span>
|
|
30
|
+
<span class="right">
|
|
31
|
+
{label}
|
|
32
|
+
{copy && (
|
|
33
|
+
<button class="copy" type="button" data-copy={id} data-copied={s.copied} hidden>
|
|
34
|
+
{s.copy}
|
|
35
|
+
</button>
|
|
36
|
+
)}
|
|
37
|
+
</span>
|
|
38
|
+
</figcaption>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
<div id={id}><Code code={code} lang={lang as never} theme="css-variables" /></div>
|
|
42
|
+
</figure>
|
|
43
|
+
|
|
44
|
+
<style>
|
|
45
|
+
.codeblock {
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
border: 1px solid var(--border);
|
|
48
|
+
border-radius: 14px;
|
|
49
|
+
background: var(--code-bg);
|
|
50
|
+
}
|
|
51
|
+
figcaption {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
gap: 12px;
|
|
56
|
+
min-height: 42px;
|
|
57
|
+
padding: 8px 16px;
|
|
58
|
+
border-bottom: 1px solid var(--border);
|
|
59
|
+
color: var(--muted);
|
|
60
|
+
font-family: var(--font-mono);
|
|
61
|
+
font-size: 12px;
|
|
62
|
+
}
|
|
63
|
+
.right {
|
|
64
|
+
display: flex;
|
|
65
|
+
align-items: center;
|
|
66
|
+
gap: 12px;
|
|
67
|
+
}
|
|
68
|
+
.copy {
|
|
69
|
+
padding: 2px 9px;
|
|
70
|
+
border: 1px solid var(--border);
|
|
71
|
+
border-radius: 7px;
|
|
72
|
+
background: none;
|
|
73
|
+
color: var(--muted);
|
|
74
|
+
font-size: 12px;
|
|
75
|
+
cursor: pointer;
|
|
76
|
+
}
|
|
77
|
+
.copy:hover {
|
|
78
|
+
border-color: var(--border-strong);
|
|
79
|
+
color: var(--heading);
|
|
80
|
+
}
|
|
81
|
+
.copy[hidden] {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
</style>
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* A stage for the project running live in the visitor's browser.
|
|
4
|
+
*
|
|
5
|
+
* The showcase shows what the package produced at build time; this shows the
|
|
6
|
+
* package itself, working. The stage is marked `data-demo` and that mark is
|
|
7
|
+
* load-bearing: a demo may deliberately contain what the project reports on —
|
|
8
|
+
* a broken form, a failing check, an unlabelled control — so the site check
|
|
9
|
+
* measures the page around the stage, not the exhibit inside it. Everything the
|
|
10
|
+
* demo needs, including its `<script is:inline>`, belongs in the default slot.
|
|
11
|
+
*
|
|
12
|
+
* Nothing here loads from another origin. A demo that needs a CDN is a demo
|
|
13
|
+
* that cannot ship on these pages.
|
|
14
|
+
*/
|
|
15
|
+
interface Props {
|
|
16
|
+
title: string;
|
|
17
|
+
/** One sentence above the stage: what the visitor is looking at. */
|
|
18
|
+
lead?: string;
|
|
19
|
+
/** Accessible name of the stage region. Default: the title. */
|
|
20
|
+
label?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const { title, lead, label } = Astro.props;
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
<section class="demo">
|
|
27
|
+
<header>
|
|
28
|
+
<h2>{title}</h2>
|
|
29
|
+
{lead && <p class="lead">{lead}</p>}
|
|
30
|
+
<slot name="controls" />
|
|
31
|
+
</header>
|
|
32
|
+
|
|
33
|
+
<!-- data-demo: the exhibit. The site check excludes it from axe and expects
|
|
34
|
+
the demo's own scripts inside it. -->
|
|
35
|
+
<div class="stage" data-demo role="region" aria-label={label ?? title}>
|
|
36
|
+
<slot />
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<slot name="note" />
|
|
40
|
+
</section>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
.demo {
|
|
44
|
+
overflow: hidden;
|
|
45
|
+
border: 1px solid var(--border);
|
|
46
|
+
border-radius: 16px;
|
|
47
|
+
background: var(--surface);
|
|
48
|
+
box-shadow: var(--shadow);
|
|
49
|
+
}
|
|
50
|
+
header {
|
|
51
|
+
padding: 18px 20px;
|
|
52
|
+
border-bottom: 1px solid var(--border);
|
|
53
|
+
}
|
|
54
|
+
h2 {
|
|
55
|
+
margin: 0;
|
|
56
|
+
color: var(--heading);
|
|
57
|
+
font-size: 16px;
|
|
58
|
+
font-weight: 600;
|
|
59
|
+
}
|
|
60
|
+
.lead {
|
|
61
|
+
margin: 6px 0 0;
|
|
62
|
+
color: var(--muted);
|
|
63
|
+
font-size: 14.5px;
|
|
64
|
+
}
|
|
65
|
+
header :global(> :last-child:not(.lead):not(h2)) {
|
|
66
|
+
margin-top: 14px;
|
|
67
|
+
}
|
|
68
|
+
.stage {
|
|
69
|
+
position: relative;
|
|
70
|
+
padding: 20px;
|
|
71
|
+
background: var(--bg-deep);
|
|
72
|
+
}
|
|
73
|
+
.demo :global(> [slot='note']) {
|
|
74
|
+
margin: 0;
|
|
75
|
+
padding: 12px 20px;
|
|
76
|
+
border-top: 1px solid var(--border);
|
|
77
|
+
color: var(--muted);
|
|
78
|
+
font-size: 13.5px;
|
|
79
|
+
}
|
|
80
|
+
</style>
|