@rxova/astro-ui 0.0.0 → 0.2.0
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 +88 -2
- package/package.json +65 -6
- package/src/components/BackLink.astro +24 -0
- package/src/components/CodeRecipes.astro +67 -0
- package/src/components/CtaBand.astro +121 -0
- package/src/components/DataTable.astro +114 -0
- package/src/components/DocAccordion.astro +15 -0
- package/src/components/DocAccordionItem.astro +83 -0
- package/src/components/Header.astro +148 -0
- package/src/components/Icon.astro +29 -0
- package/src/components/ModeTabs.astro +124 -0
- package/src/components/PageHeader.astro +63 -0
- package/src/components/ProjectSwitcher.astro +95 -0
- package/src/components/ProofStats.astro +207 -0
- package/src/components/QuickStart.astro +156 -0
- package/src/components/ScreenshotGrid.astro +164 -0
- package/src/components/Section.astro +103 -0
- package/src/components/ShowMore.astro +82 -0
- package/src/components/SiteFooter.astro +149 -0
- package/src/components/SiteShell.astro +155 -0
- package/src/components/SizeTable.astro +118 -0
- package/src/components/ThemeScript.astro +31 -0
- package/src/components/ThemeToggle.astro +163 -0
- package/src/components/ValueGrid.astro +116 -0
- package/src/components/VisuallyHidden.astro +23 -0
- package/src/components/icons/Collapse.astro +11 -0
- package/src/components/icons/Expand.astro +11 -0
- package/src/components/icons/Next.astro +11 -0
- package/src/components/icons/Pause.astro +11 -0
- package/src/components/icons/Play.astro +11 -0
- package/src/components/icons/Prev.astro +11 -0
- package/src/components/icons/Replay.astro +11 -0
- package/src/env.d.ts +15 -0
- package/src/lib/entries.ts +72 -0
- package/src/lib/icons.ts +15 -0
- package/src/scripts/show-more.ts +46 -0
- package/src/starlight/Footer.astro +16 -0
- package/src/starlight/SiteTitle.astro +34 -0
- package/src/starlight/SocialIcons.astro +18 -0
- package/src/starlight/ThemeSelect.astro +42 -0
- package/src/starlight/index.ts +103 -0
- package/src/styles/chrome.css +8 -0
- package/src/styles/document.css +72 -0
- package/src/styles/footer.css +124 -0
- package/src/styles/landing.css +55 -0
- package/src/styles/mermaid.css +75 -0
- package/src/styles/starlight.css +162 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jonatan Kruszewski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,2 +1,88 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
<h1 align="center">@rxova/astro-ui</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
Astro components, the Starlight preset and the shared chrome for every
|
|
5
|
+
<a href="https://rxova.org">rxova.org</a> surface, built on
|
|
6
|
+
<a href="../brand"><code>@rxova/brand</code></a>.
|
|
7
|
+
</p>
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Use
|
|
12
|
+
|
|
13
|
+
### In a Starlight docs site
|
|
14
|
+
|
|
15
|
+
```js
|
|
16
|
+
// astro.config.mjs
|
|
17
|
+
import { defineConfig } from 'astro/config'
|
|
18
|
+
import starlight from '@astrojs/starlight'
|
|
19
|
+
import { sharedStarlightConfig } from '@rxova/astro-ui/starlight'
|
|
20
|
+
|
|
21
|
+
export default defineConfig({
|
|
22
|
+
site: process.env.DOCS_URL ?? 'https://rxova.org',
|
|
23
|
+
base: process.env.DOCS_BASE_URL ?? '/',
|
|
24
|
+
integrations: [
|
|
25
|
+
starlight(
|
|
26
|
+
sharedStarlightConfig({
|
|
27
|
+
project: 'use-everywhere',
|
|
28
|
+
sidebar: [{ label: 'Learn', items: [{ autogenerate: { directory: 'learn' } }] }],
|
|
29
|
+
}),
|
|
30
|
+
),
|
|
31
|
+
],
|
|
32
|
+
})
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
That gets you the tokens, the typefaces, the rxova mark linking back to the
|
|
36
|
+
umbrella site, the cross-project switcher, the shared footer and Pagefind search.
|
|
37
|
+
|
|
38
|
+
### In a plain Astro site
|
|
39
|
+
|
|
40
|
+
```astro
|
|
41
|
+
---
|
|
42
|
+
import '@rxova/brand/fonts.css'
|
|
43
|
+
import '@rxova/astro-ui/styles/document.css'
|
|
44
|
+
import SiteFooter from '@rxova/astro-ui/components/SiteFooter.astro'
|
|
45
|
+
---
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`document.css` is `chrome.css` plus a reset and base element styles. Load
|
|
49
|
+
`chrome.css` alone where something else owns the document: its reset is
|
|
50
|
+
unlayered and would flatten a Starlight page.
|
|
51
|
+
|
|
52
|
+
## What's in it
|
|
53
|
+
|
|
54
|
+
| Export | What it is |
|
|
55
|
+
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `@rxova/astro-ui/starlight` | `sharedStarlightConfig()`, the preset every docs site spreads |
|
|
57
|
+
| `@rxova/astro-ui/starlight/*.astro` | The Starlight overrides: `SiteTitle`, `SocialIcons`, `Footer`, `ThemeSelect` |
|
|
58
|
+
| `@rxova/astro-ui/components/*.astro` | Chrome (`SiteShell`, `Header`, `SiteFooter`, …), primitives (`PageHeader`, `BackLink`, `ShowMore`, `VisuallyHidden`, `Icon`) and the components in the gallery |
|
|
59
|
+
| `@rxova/astro-ui/components/icons/*.astro` | Glyphs in the `Icon` frame: `Prev`, `Next`, `Play`, `Pause`, `Replay`, `Expand`, `Collapse` |
|
|
60
|
+
| `@rxova/astro-ui/scripts/show-more` | `enhanceShowMore()`: batches a `[data-reveal-list]` behind a `ShowMore` |
|
|
61
|
+
| `@rxova/astro-ui/lib/entries` | Ordering, bylines, dates and excerpts shared by /blog and /updates |
|
|
62
|
+
| `@rxova/astro-ui/styles/document.css` | For sites that own their document: `chrome.css`, a reset, base element styling |
|
|
63
|
+
| `@rxova/astro-ui/styles/chrome.css` | What the header and footer need, with nothing document-level |
|
|
64
|
+
| `@rxova/astro-ui/styles/starlight.css` | Maps `--rx-*` onto Starlight's `--sl-*`, plus the footer |
|
|
65
|
+
| `@rxova/astro-ui/styles/landing.css` | The Starlight overrides a splash landing page needs; load it through `customCss` |
|
|
66
|
+
| `@rxova/astro-ui/styles/mermaid.css` | Restyles `rehype-mermaid`'s build-time SVG with the tokens, so diagrams follow the theme |
|
|
67
|
+
|
|
68
|
+
There is no barrel: each component has its own path, so a page only loads the
|
|
69
|
+
CSS of the components it imports.
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
Run everything from the repo root. `apps/preview` renders the Starlight preset
|
|
74
|
+
and the plain-Astro chrome; `pnpm run verify` runs `astro check`, the tests and
|
|
75
|
+
the export checks for this package.
|
|
76
|
+
|
|
77
|
+
`apps/preview` also carries the gallery: one page per component under
|
|
78
|
+
`/gallery/`, each state in a `Story` frame. `pnpm --filter @rxova/preview
|
|
79
|
+
screenshots` rebuilds it and writes `screenshots/<component>.png` here, light and
|
|
80
|
+
dark, for the pull request that adds or changes a component.
|
|
81
|
+
|
|
82
|
+
`apps/storybook` is the Storybook: a story file per component with its states,
|
|
83
|
+
a Docs page built from the component's frontmatter, and a light/dark toolbar.
|
|
84
|
+
`pnpm --filter @rxova/storybook dev` serves it with live controls.
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT © Jonatan Kruszewski
|
package/package.json
CHANGED
|
@@ -1,12 +1,71 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxova/astro-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Astro components, Starlight preset and shared chrome for rxova.org",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"rxova",
|
|
8
|
+
"astro",
|
|
9
|
+
"starlight",
|
|
10
|
+
"components"
|
|
11
|
+
],
|
|
5
12
|
"license": "MIT",
|
|
6
|
-
"author": "Jonatan Kruszewski",
|
|
13
|
+
"author": "Jonatan Kruszewski <jonakrusze@gmail.com>",
|
|
14
|
+
"homepage": "https://rxova.org",
|
|
7
15
|
"repository": {
|
|
8
16
|
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/rxova/
|
|
17
|
+
"url": "git+https://github.com/rxova/rxova-website.git",
|
|
18
|
+
"directory": "packages/astro-ui"
|
|
10
19
|
},
|
|
11
|
-
"
|
|
12
|
-
|
|
20
|
+
"bugs": "https://github.com/rxova/rxova-website/issues",
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=24.0.0"
|
|
23
|
+
},
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"*.css"
|
|
26
|
+
],
|
|
27
|
+
"files": [
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
30
|
+
"exports": {
|
|
31
|
+
"./components/*": "./src/components/*",
|
|
32
|
+
"./lib/entries": "./src/lib/entries.ts",
|
|
33
|
+
"./scripts/show-more": "./src/scripts/show-more.ts",
|
|
34
|
+
"./starlight": "./src/starlight/index.ts",
|
|
35
|
+
"./starlight/*": "./src/starlight/*",
|
|
36
|
+
"./styles/*": "./src/styles/*",
|
|
37
|
+
"./package.json": "./package.json"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"@astrojs/starlight": ">=0.36.0",
|
|
41
|
+
"astro": ">=5.6.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependenciesMeta": {
|
|
44
|
+
"@astrojs/starlight": {
|
|
45
|
+
"optional": true
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@rxova/brand": "^1.1.0",
|
|
50
|
+
"lucide-static": "^1.45.0"
|
|
51
|
+
},
|
|
52
|
+
"devDependencies": {
|
|
53
|
+
"@astrojs/check": "^0.9.10",
|
|
54
|
+
"@astrojs/starlight": "^0.42.1",
|
|
55
|
+
"@rxova/repo-tooling": "0.0.0",
|
|
56
|
+
"@types/node": "^26.6.1",
|
|
57
|
+
"@vitest/coverage-v8": "^5.0.1",
|
|
58
|
+
"astro": "^7.3.2",
|
|
59
|
+
"happy-dom": "^20.14.5",
|
|
60
|
+
"publint": "^0.3.24",
|
|
61
|
+
"tsx": "^4.23.13",
|
|
62
|
+
"typescript": "6.0.3",
|
|
63
|
+
"vitest": "^5.0.1"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"check:astro": "astro check",
|
|
67
|
+
"check:exports": "publint --strict",
|
|
68
|
+
"pack:smoke": "node --import tsx ../brand/scripts/pack-smoke.ts",
|
|
69
|
+
"test": "vitest run --coverage"
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
---
|
|
2
|
+
import type { HTMLAttributes } from 'astro/types'
|
|
3
|
+
|
|
4
|
+
/** An "← up one level" link; the caller's class sets its spacing. */
|
|
5
|
+
type Props = HTMLAttributes<'a'> & { href: string }
|
|
6
|
+
|
|
7
|
+
const { href, class: className, ...rest } = Astro.props
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<a class:list={['back-link', className]} href={href} {...rest}>
|
|
11
|
+
← <slot />
|
|
12
|
+
</a>
|
|
13
|
+
|
|
14
|
+
<style>
|
|
15
|
+
.back-link {
|
|
16
|
+
display: inline-block;
|
|
17
|
+
color: var(--rx-muted);
|
|
18
|
+
text-decoration: none;
|
|
19
|
+
font-size: 0.95rem;
|
|
20
|
+
}
|
|
21
|
+
.back-link:hover {
|
|
22
|
+
color: var(--rx-fg);
|
|
23
|
+
}
|
|
24
|
+
</style>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** Titled source listings, one per recipe: a heading linking to the library, then the source in a code frame. */
|
|
3
|
+
export interface Recipe {
|
|
4
|
+
id: string
|
|
5
|
+
label: string
|
|
6
|
+
href: string
|
|
7
|
+
source: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
recipes: readonly Recipe[]
|
|
12
|
+
/** Heading ids are `<idPrefix>-<recipe.id>`, so a page can link to one recipe. */
|
|
13
|
+
idPrefix?: string
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const { recipes, idPrefix = 'recipe' } = Astro.props
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
<div class="rx-recipes">
|
|
20
|
+
{recipes.map(({ id, label, href, source }) => (
|
|
21
|
+
<section class="rx-recipe">
|
|
22
|
+
<h3 class="rx-recipe__title" id={`${idPrefix}-${id}`}>
|
|
23
|
+
<a href={href}>{label}</a>
|
|
24
|
+
</h3>
|
|
25
|
+
<pre class="rx-recipe__source"><code>{source}</code></pre>
|
|
26
|
+
</section>
|
|
27
|
+
))}
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<style>
|
|
31
|
+
.rx-recipes {
|
|
32
|
+
display: grid;
|
|
33
|
+
gap: 2rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.rx-recipe__title {
|
|
37
|
+
margin: 0 0 0.75rem;
|
|
38
|
+
font-size: 1.05rem;
|
|
39
|
+
font-weight: 620;
|
|
40
|
+
letter-spacing: -0.015em;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.rx-recipe__title a {
|
|
44
|
+
color: var(--rx-fg);
|
|
45
|
+
text-decoration: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.rx-recipe__title a:hover {
|
|
49
|
+
color: var(--rx-primary);
|
|
50
|
+
text-decoration: underline;
|
|
51
|
+
text-underline-offset: 3px;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.rx-recipe__source {
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 1.1rem 1.25rem;
|
|
57
|
+
background: var(--rx-card);
|
|
58
|
+
border: 1px solid var(--rx-rule);
|
|
59
|
+
border-radius: var(--rx-radius);
|
|
60
|
+
overflow-x: auto;
|
|
61
|
+
color: var(--rx-fg);
|
|
62
|
+
font-family: var(--rx-font-mono);
|
|
63
|
+
font-size: 0.86rem;
|
|
64
|
+
line-height: 1.65;
|
|
65
|
+
tab-size: 2;
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* A centred call to action: title, lede and a row of pill buttons. Internal hrefs must arrive
|
|
4
|
+
* base-aware; external ones get `rel="noopener"` and a visible marker.
|
|
5
|
+
*/
|
|
6
|
+
export interface CtaAction {
|
|
7
|
+
text: string
|
|
8
|
+
href: string
|
|
9
|
+
variant?: 'primary' | 'minimal'
|
|
10
|
+
external?: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
title: string
|
|
15
|
+
lede: string
|
|
16
|
+
actions: readonly CtaAction[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const { title, lede, actions } = Astro.props
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
<aside class="rx-cta not-content">
|
|
23
|
+
<h2 class="rx-cta__title">{title}</h2>
|
|
24
|
+
<p class="rx-cta__lede">{lede}</p>
|
|
25
|
+
<div class="rx-cta__actions">
|
|
26
|
+
{actions.map((action) => (
|
|
27
|
+
<a
|
|
28
|
+
class:list={['rx-btn', `rx-btn--${action.variant ?? 'minimal'}`]}
|
|
29
|
+
href={action.href}
|
|
30
|
+
rel={action.external ? 'noopener' : undefined}
|
|
31
|
+
>
|
|
32
|
+
{action.text}
|
|
33
|
+
{action.external && (
|
|
34
|
+
<svg
|
|
35
|
+
viewBox="0 0 24 24"
|
|
36
|
+
width="14"
|
|
37
|
+
height="14"
|
|
38
|
+
fill="none"
|
|
39
|
+
stroke="currentColor"
|
|
40
|
+
stroke-width="2"
|
|
41
|
+
stroke-linecap="round"
|
|
42
|
+
stroke-linejoin="round"
|
|
43
|
+
aria-hidden="true"
|
|
44
|
+
>
|
|
45
|
+
<path d="M14 4h6v6M20 4l-9 9M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5" />
|
|
46
|
+
</svg>
|
|
47
|
+
)}
|
|
48
|
+
</a>
|
|
49
|
+
))}
|
|
50
|
+
</div>
|
|
51
|
+
</aside>
|
|
52
|
+
|
|
53
|
+
<style>
|
|
54
|
+
.rx-cta {
|
|
55
|
+
margin-block: 6rem 1rem;
|
|
56
|
+
padding: clamp(2rem, 1rem + 4vw, 3.5rem);
|
|
57
|
+
text-align: center;
|
|
58
|
+
background: var(--rx-card);
|
|
59
|
+
border: 1px solid var(--rx-rule);
|
|
60
|
+
border-radius: var(--rx-radius);
|
|
61
|
+
box-shadow: var(--rx-shadow-soft);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.rx-cta__title {
|
|
65
|
+
margin: 0;
|
|
66
|
+
color: var(--rx-fg);
|
|
67
|
+
font-size: clamp(1.5rem, 1.15rem + 1.5vw, 2.1rem);
|
|
68
|
+
font-weight: 640;
|
|
69
|
+
line-height: 1.15;
|
|
70
|
+
letter-spacing: -0.02em;
|
|
71
|
+
text-wrap: balance;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.rx-cta__lede {
|
|
75
|
+
max-width: 46ch;
|
|
76
|
+
margin: 0.9rem auto 0;
|
|
77
|
+
color: var(--rx-muted);
|
|
78
|
+
font-size: 1rem;
|
|
79
|
+
line-height: 1.6;
|
|
80
|
+
text-wrap: pretty;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.rx-cta__actions {
|
|
84
|
+
display: flex;
|
|
85
|
+
flex-wrap: wrap;
|
|
86
|
+
gap: 0.75rem;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
margin-top: 2rem;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.rx-btn {
|
|
92
|
+
display: inline-flex;
|
|
93
|
+
align-items: center;
|
|
94
|
+
gap: 0.5rem;
|
|
95
|
+
padding: 0.7rem 1.4rem;
|
|
96
|
+
border: 1px solid transparent;
|
|
97
|
+
border-radius: var(--rx-radius-pill);
|
|
98
|
+
font-size: 0.95rem;
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
text-decoration: none;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* --rx-on-primary, not #fff: white on the lightened dark-mode violet is about 2.9:1 as a fill. */
|
|
104
|
+
.rx-btn--primary {
|
|
105
|
+
color: var(--rx-on-primary);
|
|
106
|
+
background: var(--rx-primary);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.rx-btn--primary:hover {
|
|
110
|
+
background: var(--rx-primary-dark);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.rx-btn--minimal {
|
|
114
|
+
color: var(--rx-fg);
|
|
115
|
+
border-color: var(--rx-rule-strong);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.rx-btn--minimal:hover {
|
|
119
|
+
border-color: var(--rx-primary);
|
|
120
|
+
}
|
|
121
|
+
</style>
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* Facts a page reads from somewhere else, as a framed table: column headings, a row heading per
|
|
4
|
+
* row, cells that may render as code. Scrollable and focusable when narrow, so a keyboard can reach it.
|
|
5
|
+
*/
|
|
6
|
+
export type Cell = string | { code: string }
|
|
7
|
+
|
|
8
|
+
export interface DataRow {
|
|
9
|
+
label: string
|
|
10
|
+
cells: readonly Cell[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
/** The accessible name of the scrollable region: "Framework compatibility". */
|
|
15
|
+
label: string
|
|
16
|
+
columns: readonly string[]
|
|
17
|
+
rows: readonly DataRow[]
|
|
18
|
+
/** Where the facts come from, under the table. */
|
|
19
|
+
caption?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const { label, columns, rows, caption } = Astro.props
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
<div class="rx-table" tabindex="0" role="region" aria-label={label}>
|
|
26
|
+
<table class="rx-table__table">
|
|
27
|
+
{caption && <caption class="rx-table__caption">{caption}</caption>}
|
|
28
|
+
<thead>
|
|
29
|
+
<tr>
|
|
30
|
+
{columns.map((column) => (
|
|
31
|
+
<th scope="col">{column}</th>
|
|
32
|
+
))}
|
|
33
|
+
</tr>
|
|
34
|
+
</thead>
|
|
35
|
+
<tbody>
|
|
36
|
+
{rows.map((row) => (
|
|
37
|
+
<tr>
|
|
38
|
+
<th scope="row" class="rx-table__label">
|
|
39
|
+
{row.label}
|
|
40
|
+
</th>
|
|
41
|
+
{row.cells.map((cell) => (
|
|
42
|
+
<td>{typeof cell === 'string' ? cell : <code>{cell.code}</code>}</td>
|
|
43
|
+
))}
|
|
44
|
+
</tr>
|
|
45
|
+
))}
|
|
46
|
+
</tbody>
|
|
47
|
+
</table>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<style>
|
|
51
|
+
.rx-table {
|
|
52
|
+
overflow-x: auto;
|
|
53
|
+
border: 1px solid var(--rx-rule);
|
|
54
|
+
border-radius: var(--rx-radius);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.rx-table__table {
|
|
58
|
+
width: 100%;
|
|
59
|
+
margin: 0;
|
|
60
|
+
border-collapse: collapse;
|
|
61
|
+
font-size: 0.9rem;
|
|
62
|
+
line-height: 1.5;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.rx-table__caption {
|
|
66
|
+
padding: 1rem 1.25rem;
|
|
67
|
+
color: var(--rx-muted);
|
|
68
|
+
font-size: 0.82rem;
|
|
69
|
+
line-height: 1.5;
|
|
70
|
+
text-align: start;
|
|
71
|
+
caption-side: bottom;
|
|
72
|
+
border-top: 1px solid var(--rx-rule);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.rx-table__table th,
|
|
76
|
+
.rx-table__table td {
|
|
77
|
+
padding: 0.85rem 1.25rem;
|
|
78
|
+
text-align: start;
|
|
79
|
+
vertical-align: top;
|
|
80
|
+
color: var(--rx-fg);
|
|
81
|
+
border-bottom: 1px solid var(--rx-rule);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.rx-table__table thead th {
|
|
85
|
+
background: var(--rx-card);
|
|
86
|
+
color: var(--rx-muted);
|
|
87
|
+
font-size: 0.75rem;
|
|
88
|
+
font-weight: 700;
|
|
89
|
+
letter-spacing: 0.06em;
|
|
90
|
+
text-transform: uppercase;
|
|
91
|
+
white-space: nowrap;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.rx-table__table tbody tr:last-child th,
|
|
95
|
+
.rx-table__table tbody tr:last-child td {
|
|
96
|
+
border-bottom: 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.rx-table__label {
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
white-space: nowrap;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.rx-table__table td {
|
|
105
|
+
color: var(--rx-muted);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.rx-table__table code {
|
|
109
|
+
color: var(--rx-fg);
|
|
110
|
+
font-family: var(--rx-font-mono);
|
|
111
|
+
font-size: 0.84rem;
|
|
112
|
+
white-space: nowrap;
|
|
113
|
+
}
|
|
114
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** A stack of `DocAccordionItem`s: `<details>` does the collapsing, so there is no client script. */
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<div class="doc-accordion">
|
|
6
|
+
<slot />
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
.doc-accordion {
|
|
11
|
+
display: grid;
|
|
12
|
+
gap: 1rem;
|
|
13
|
+
margin: 1.5rem 0 2rem;
|
|
14
|
+
}
|
|
15
|
+
</style>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
/** One collapsible block of a `DocAccordion`: a title, an optional one-line summary, and the slot. */
|
|
3
|
+
interface Props {
|
|
4
|
+
title: string
|
|
5
|
+
summary?: string
|
|
6
|
+
defaultOpen?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const { title, summary, defaultOpen = false } = Astro.props
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<details class="doc-accordion-item" open={defaultOpen}>
|
|
13
|
+
<summary>
|
|
14
|
+
<span class="summary-text">
|
|
15
|
+
<span class="title">{title}</span>
|
|
16
|
+
{summary && <span class="summary-copy">{summary}</span>}
|
|
17
|
+
</span>
|
|
18
|
+
</summary>
|
|
19
|
+
<div class="content">
|
|
20
|
+
<slot />
|
|
21
|
+
</div>
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<style>
|
|
25
|
+
.doc-accordion-item {
|
|
26
|
+
border: 1px solid var(--rx-rule);
|
|
27
|
+
border-radius: 1rem;
|
|
28
|
+
background: var(--rx-bg);
|
|
29
|
+
overflow: hidden;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
summary {
|
|
33
|
+
list-style: none;
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
padding: 1rem 1.1rem 1rem 1.25rem;
|
|
36
|
+
display: flex;
|
|
37
|
+
align-items: center;
|
|
38
|
+
justify-content: space-between;
|
|
39
|
+
gap: 1rem;
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
color: var(--rx-fg);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
summary::-webkit-details-marker {
|
|
45
|
+
display: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
summary::after {
|
|
49
|
+
content: '+';
|
|
50
|
+
flex: 0 0 auto;
|
|
51
|
+
font-size: 1.3rem;
|
|
52
|
+
line-height: 1;
|
|
53
|
+
color: var(--rx-primary);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.doc-accordion-item[open] summary::after {
|
|
57
|
+
content: '−';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.summary-text {
|
|
61
|
+
display: grid;
|
|
62
|
+
gap: 0.18rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.title {
|
|
66
|
+
font-size: 1.02rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.summary-copy {
|
|
70
|
+
font-size: 0.92rem;
|
|
71
|
+
font-weight: 500;
|
|
72
|
+
color: var(--rx-muted);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.content {
|
|
76
|
+
border-top: 1px solid var(--rx-rule);
|
|
77
|
+
padding: 1rem 1.25rem 1.25rem;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.content > :last-child {
|
|
81
|
+
margin-bottom: 0;
|
|
82
|
+
}
|
|
83
|
+
</style>
|