@rxova/brand 0.8.2 → 0.11.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/README.md +18 -11
- package/package.json +2 -1
- package/src/astro.css +11 -32
- package/src/chrome.css +51 -0
- package/src/components/SiteShell.astro +11 -78
- package/src/footer.css +2 -2
- package/src/index.ts +1 -0
- package/src/sites.test.ts +26 -0
- package/src/sites.ts +17 -0
- package/src/starlight.css +38 -0
- package/src/starlight.ts +8 -1
package/README.md
CHANGED
|
@@ -69,20 +69,27 @@ import { PROJECTS } from '@rxova/brand'
|
|
|
69
69
|
---
|
|
70
70
|
```
|
|
71
71
|
|
|
72
|
-
`astro.css` pulls in `
|
|
73
|
-
|
|
72
|
+
`astro.css` pulls in `chrome.css` — the tokens, the footer's styles and the
|
|
73
|
+
short aliases — and adds the reset and base element styles that Starlight gives
|
|
74
|
+
docs sites for free.
|
|
75
|
+
|
|
76
|
+
Use `chrome.css` on its own where something else already owns the document, such
|
|
77
|
+
as rxova-website's shell templates: their body is composed into a built
|
|
78
|
+
Starlight page, and the reset in `astro.css` is unlayered, so it would outrank
|
|
79
|
+
everything in `@layer starlight.*` and flatten that page.
|
|
74
80
|
|
|
75
81
|
## What's in it
|
|
76
82
|
|
|
77
|
-
| Export | What it is
|
|
78
|
-
| --------------------------------- |
|
|
79
|
-
| `@rxova/brand` | `PROJECTS`, `docsUrl()`, `siteUrl()`, `sharedStarlightConfig()`
|
|
80
|
-
| `@rxova/brand/tokens.css` | The `--rx-*` custom properties. Everything derives from these.
|
|
81
|
-
| `@rxova/brand/starlight.css` | For docs sites: maps `--rx-*` onto Starlight's `--sl-*`, plus chrome
|
|
82
|
-
| `@rxova/brand/astro.css` | For plain Astro sites:
|
|
83
|
-
| `@rxova/brand/
|
|
84
|
-
| `@rxova/brand/
|
|
85
|
-
| `@rxova/brand/
|
|
83
|
+
| Export | What it is |
|
|
84
|
+
| --------------------------------- | ---------------------------------------------------------------------- |
|
|
85
|
+
| `@rxova/brand` | `PROJECTS`, `docsUrl()`, `siteUrl()`, `sharedStarlightConfig()` |
|
|
86
|
+
| `@rxova/brand/tokens.css` | The `--rx-*` custom properties. Everything derives from these. |
|
|
87
|
+
| `@rxova/brand/starlight.css` | For docs sites: maps `--rx-*` onto Starlight's `--sl-*`, plus chrome |
|
|
88
|
+
| `@rxova/brand/astro.css` | For plain Astro sites: `chrome.css`, a reset, and base element styling |
|
|
89
|
+
| `@rxova/brand/chrome.css` | What the shared header and footer need, with nothing document-level |
|
|
90
|
+
| `@rxova/brand/fonts.css` | Self-hosted Space Grotesk + IBM Plex Mono |
|
|
91
|
+
| `@rxova/brand/components/*.astro` | `SiteTitle`, `SocialIcons`, `Footer`, `SiteFooter`, `ProjectSwitcher` |
|
|
92
|
+
| `@rxova/brand/assets/*` | The mark, logos and per-project OG images |
|
|
86
93
|
|
|
87
94
|
## The palette
|
|
88
95
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rxova/brand",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Design tokens, Starlight theme and shared site chrome for rxova.org",
|
|
6
6
|
"keywords": [
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
".": "./src/index.ts",
|
|
34
34
|
"./tokens.css": "./src/tokens.css",
|
|
35
35
|
"./astro.css": "./src/astro.css",
|
|
36
|
+
"./chrome.css": "./src/chrome.css",
|
|
36
37
|
"./starlight.css": "./src/starlight.css",
|
|
37
38
|
"./fonts.css": "./src/fonts.css",
|
|
38
39
|
"./components/*": "./src/components/*",
|
package/src/astro.css
CHANGED
|
@@ -1,42 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Entry point for plain Astro surfaces
|
|
2
|
+
* Entry point for plain Astro surfaces that own their whole document — the
|
|
3
|
+
* rxova.org landing, /blog and /updates.
|
|
3
4
|
*
|
|
4
5
|
* Starlight sites use `starlight.css` instead; it maps the same tokens onto
|
|
5
|
-
* Starlight's own variables. This file
|
|
6
|
+
* Starlight's own variables. This file is `chrome.css` — the tokens, the footer
|
|
7
|
+
* and the short aliases — plus the two things a bare Astro page needs and
|
|
6
8
|
* Starlight already provides: a reset and base element styling.
|
|
7
9
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Load this only where nothing else owns the document. A surface that renders
|
|
11
|
+
* the shared chrome *into* someone else's document — rxova-website's shell
|
|
12
|
+
* templates, whose body is composed into a built Starlight page — must load
|
|
13
|
+
* `chrome.css` instead. The reset below is unlayered, so inside a Starlight
|
|
14
|
+
* document it would outrank every rule in `@layer starlight.*` and flatten the
|
|
15
|
+
* page; see chrome.css.
|
|
13
16
|
*/
|
|
14
17
|
|
|
15
|
-
@import './
|
|
16
|
-
/* The shared site footer, which /blog, /updates and the landing all render. It
|
|
17
|
-
is the one piece of chrome common to these surfaces and the Starlight ones,
|
|
18
|
-
so its rules sit in their own file and both entry points pull them in. */
|
|
19
|
-
@import './footer.css';
|
|
20
|
-
|
|
21
|
-
:root {
|
|
22
|
-
--bg: var(--rx-bg);
|
|
23
|
-
--fg: var(--rx-fg);
|
|
24
|
-
--muted: var(--rx-muted);
|
|
25
|
-
--faint: var(--rx-faint);
|
|
26
|
-
--rule: var(--rx-rule);
|
|
27
|
-
--card: var(--rx-card);
|
|
28
|
-
--tag-bg: var(--rx-tag-bg);
|
|
29
|
-
--glow-tint: var(--rx-glow-tint);
|
|
30
|
-
--font: var(--rx-font-sans);
|
|
31
|
-
--mono: var(--rx-font-mono);
|
|
32
|
-
--max: var(--rx-max);
|
|
33
|
-
|
|
34
|
-
/* The landing's `--accent` is the foreground, not the brand violet: its
|
|
35
|
-
design is deliberately monochrome and uses the gradient only as an accent
|
|
36
|
-
rule. Mapping this to --rx-primary would tint every focus ring on the
|
|
37
|
-
site. */
|
|
38
|
-
--accent: var(--rx-fg);
|
|
39
|
-
}
|
|
18
|
+
@import './chrome.css';
|
|
40
19
|
|
|
41
20
|
/* --- Reset ---------------------------------------------------------------- */
|
|
42
21
|
|
package/src/chrome.css
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Everything the shared chrome needs, and nothing that touches the document.
|
|
3
|
+
*
|
|
4
|
+
* `Header`, `SiteFooter` and `ThemeToggle` are rendered on two kinds of page:
|
|
5
|
+
* plain Astro surfaces that own their whole document (the landing, /blog,
|
|
6
|
+
* /updates — see astro.css), and rxova-website's shell templates, whose body is
|
|
7
|
+
* composed into an already-complete Starlight document at deploy time.
|
|
8
|
+
*
|
|
9
|
+
* The second case is why this file exists. It carries the tokens, the footer's
|
|
10
|
+
* styles and the short aliases the chrome's scoped CSS is written against — but
|
|
11
|
+
* no reset and no base element styling. Those belong to whoever owns the
|
|
12
|
+
* document, and a shell that brings its own into a Starlight page destroys that
|
|
13
|
+
* page: Starlight puts all of its CSS in `@layer starlight.*`, and an unlayered
|
|
14
|
+
* `* { margin: 0; padding: 0 }` arriving from the shell beats every layered rule
|
|
15
|
+
* it has, whatever the specificity. That is not a hypothetical — it flattened
|
|
16
|
+
* every /packages/* docs page on rxova.org.
|
|
17
|
+
*
|
|
18
|
+
* So: load this to render the chrome, and astro.css (which is this plus the
|
|
19
|
+
* reset) to own a document.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
@import './tokens.css';
|
|
23
|
+
/* The shared site footer, which /blog, /updates and the landing all render. It
|
|
24
|
+
is the one piece of chrome common to these surfaces and the Starlight ones,
|
|
25
|
+
so its rules sit in their own file and both entry points pull them in. */
|
|
26
|
+
@import './footer.css';
|
|
27
|
+
|
|
28
|
+
/* The short token names the landing and the shared chrome were written against
|
|
29
|
+
(`--bg`, `--fg`, `--rule`, …), aliased onto their `--rx-*` equivalents, so
|
|
30
|
+
adopting this package did not require rewriting several hundred lines of
|
|
31
|
+
scoped component styles in one go. New work should use `--rx-*` directly; the
|
|
32
|
+
aliases exist to make the migration incremental, not to be a second API. */
|
|
33
|
+
:root {
|
|
34
|
+
--bg: var(--rx-bg);
|
|
35
|
+
--fg: var(--rx-fg);
|
|
36
|
+
--muted: var(--rx-muted);
|
|
37
|
+
--faint: var(--rx-faint);
|
|
38
|
+
--rule: var(--rx-rule);
|
|
39
|
+
--card: var(--rx-card);
|
|
40
|
+
--tag-bg: var(--rx-tag-bg);
|
|
41
|
+
--glow-tint: var(--rx-glow-tint);
|
|
42
|
+
--font: var(--rx-font-sans);
|
|
43
|
+
--mono: var(--rx-font-mono);
|
|
44
|
+
--max: var(--rx-max);
|
|
45
|
+
|
|
46
|
+
/* The landing's `--accent` is the foreground, not the brand violet: its
|
|
47
|
+
design is deliberately monochrome and uses the gradient only as an accent
|
|
48
|
+
rule. Mapping this to --rx-primary would tint every focus ring on the
|
|
49
|
+
site. */
|
|
50
|
+
--accent: var(--rx-fg);
|
|
51
|
+
}
|
|
@@ -1,83 +1,35 @@
|
|
|
1
1
|
---
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* Artifact document for rxova.org's non-Starlight page components.
|
|
4
4
|
*
|
|
5
5
|
* It lived in both packages as a 244-line file that differed on four lines, which
|
|
6
6
|
* is exactly how the menu came to render in a different order on each: a fix has to
|
|
7
7
|
* be made twice, and once was enough to forget.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
9
|
+
* This deliberately owns no site header, footer, analytics or theme bootstrap.
|
|
10
|
+
* It gives an independently-built page component a standards-compliant document
|
|
11
|
+
* for its metadata and assets; rxova-website consumes its body and supplies the
|
|
12
|
+
* public shell at deploy time.
|
|
11
13
|
*/
|
|
12
14
|
import '../fonts.css'
|
|
13
15
|
import '../astro.css'
|
|
14
16
|
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
import Header, { type HeaderItem } from './Header.astro'
|
|
18
|
-
import SiteFooter from './SiteFooter.astro'
|
|
19
|
-
import ThemeScript from './ThemeScript.astro'
|
|
17
|
+
import { canonicalUrl, siteUrl } from '../sites.ts'
|
|
20
18
|
|
|
21
19
|
interface Props {
|
|
22
20
|
title: string
|
|
23
21
|
description: string
|
|
24
|
-
/** Canonical path, e.g. `/blog/why-rxova-has-a-blog`. */
|
|
22
|
+
/** Canonical path, e.g. `/blog/why-rxova-has-a-blog`. Normalised below. */
|
|
25
23
|
path: string
|
|
26
24
|
ogType?: 'website' | 'article'
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
const { title, description, path, ogType = 'website' } = Astro.props
|
|
30
|
-
const canonical = `${RXOVA_ORIGIN}${path}`
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* The menu, in one fixed order for every surface.
|
|
34
|
-
*
|
|
35
|
-
* Which item is current is *derived* from the base the surface was built for, not
|
|
36
|
-
* declared per package — declaring it is what let the two drift into different
|
|
37
|
-
* orders. `BASE_URL` is substituted by the consuming app's build, so this is
|
|
38
|
-
* `/blog` inside @rxova/blog and `/updates` inside @rxova/updates.
|
|
39
|
-
*/
|
|
40
|
-
const base = import.meta.env.BASE_URL.replace(/\/$/, '')
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* The surfaces that can be the *current* one here — the mounted ones this shell
|
|
44
|
-
* is ever built for. /about is not among them: it is a page of the landing's own
|
|
45
|
-
* Astro build rather than a mount, so it can never match `base`, and it is added
|
|
46
|
-
* as a fixed trailing item below.
|
|
47
|
-
*/
|
|
48
|
-
const SECTIONS = [
|
|
49
|
-
{ label: 'Blog', path: '/blog' },
|
|
50
|
-
{ label: 'Updates', path: '/updates' },
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* A URL inside this surface.
|
|
55
|
-
*
|
|
56
|
-
* Anything *leaving* it goes through `siteUrl`: a bare `/updates` would resolve
|
|
57
|
-
* against the mount and point at `/blog/updates`.
|
|
58
|
-
*/
|
|
59
|
-
const inside = (p = '') => `${base}/${p}`.replace(/\/{2,}/g, '/')
|
|
60
28
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
* this owns where it points.
|
|
66
|
-
*/
|
|
67
|
-
const items: HeaderItem[] = [
|
|
68
|
-
{ label: 'Projects', href: siteUrl('/') },
|
|
69
|
-
...SECTIONS.map((section) =>
|
|
70
|
-
section.path === base
|
|
71
|
-
? { label: section.label, href: inside(), current: true }
|
|
72
|
-
: { label: section.label, href: siteUrl(section.path) },
|
|
73
|
-
),
|
|
74
|
-
// Fixed trailing item, like Projects is a fixed leading one, and for the same
|
|
75
|
-
// reason: it belongs to the landing's build, so it is always deployed and can
|
|
76
|
-
// never be the current surface here. The landing grew an About entry and these
|
|
77
|
-
// two did not, which left a reader on a post with no way to reach it — the
|
|
78
|
-
// failure mode this shell exists to prevent.
|
|
79
|
-
{ label: 'About', href: siteUrl('/about') },
|
|
80
|
-
]
|
|
29
|
+
// Normalised here rather than at the four call sites: every one of them had
|
|
30
|
+
// dropped the trailing slash, so every blog and updates page was declaring itself
|
|
31
|
+
// canonical at a URL that 301s. A caller can forget again; this cannot.
|
|
32
|
+
const canonical = canonicalUrl(path)
|
|
81
33
|
---
|
|
82
34
|
|
|
83
35
|
<!doctype html>
|
|
@@ -85,8 +37,6 @@ const items: HeaderItem[] = [
|
|
|
85
37
|
<head>
|
|
86
38
|
<meta charset="utf-8" />
|
|
87
39
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
88
|
-
<link rel="icon" type="image/png" href={siteUrl('/rxova-logo-256.png')} />
|
|
89
|
-
<link rel="apple-touch-icon" href={siteUrl('/rxova-logo-256.png')} />
|
|
90
40
|
<link rel="canonical" href={canonical} />
|
|
91
41
|
<title>{title}</title>
|
|
92
42
|
<meta name="description" content={description} />
|
|
@@ -96,35 +46,18 @@ const items: HeaderItem[] = [
|
|
|
96
46
|
<meta property="og:url" content={canonical} />
|
|
97
47
|
<meta property="og:image" content={siteUrl('/og/rxova.png')} />
|
|
98
48
|
<meta name="twitter:card" content="summary_large_image" />
|
|
99
|
-
<ThemeScript />
|
|
100
49
|
</head>
|
|
101
50
|
<body>
|
|
102
|
-
<Header homeHref={siteUrl('/')} logoSrc={siteUrl('/rxova-logo-256.png')} items={items} />
|
|
103
|
-
|
|
104
51
|
<main>
|
|
105
52
|
<slot />
|
|
106
53
|
</main>
|
|
107
54
|
|
|
108
|
-
<div class="foot">
|
|
109
|
-
<SiteFooter />
|
|
110
|
-
</div>
|
|
111
|
-
|
|
112
55
|
<style>
|
|
113
|
-
/* The header is `Header` (its own component, shared with the landing); the
|
|
114
|
-
only chrome styled here is the page body and the footer's measure. */
|
|
115
56
|
main {
|
|
116
57
|
max-width: var(--max);
|
|
117
58
|
margin: 0 auto;
|
|
118
59
|
padding: clamp(2rem, 6vh, 3.5rem) 1.5rem 4rem;
|
|
119
60
|
}
|
|
120
|
-
|
|
121
|
-
/* The footer's own rules are unscoped (footer.css, shared with the docs
|
|
122
|
-
sites); this only puts it on the page's measure. */
|
|
123
|
-
.foot {
|
|
124
|
-
max-width: var(--max);
|
|
125
|
-
margin: 0 auto;
|
|
126
|
-
padding: 0 1.5rem;
|
|
127
|
-
}
|
|
128
61
|
</style>
|
|
129
62
|
|
|
130
63
|
<!-- Prose styling for rendered markdown. Global rather than scoped: the
|
package/src/footer.css
CHANGED
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
* is why /blog and /updates shipped a dot-separated link row instead — the
|
|
8
8
|
* shared footer would have rendered unstyled there.
|
|
9
9
|
*
|
|
10
|
-
* Imported by both `starlight.css` and `
|
|
10
|
+
* Imported by both `starlight.css` and `chrome.css`; nothing needs to import it
|
|
11
11
|
* directly. Written against `--rx-*` tokens only, so it does not depend on the
|
|
12
|
-
* short aliases
|
|
12
|
+
* short aliases chrome.css defines.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
@import './tokens.css';
|
package/src/index.ts
CHANGED
package/src/sites.test.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
getRepo,
|
|
19
19
|
docsUrl,
|
|
20
20
|
siteUrl,
|
|
21
|
+
canonicalUrl,
|
|
21
22
|
projectFromBase,
|
|
22
23
|
type ProjectId,
|
|
23
24
|
} from './sites.ts'
|
|
@@ -111,6 +112,31 @@ describe('urls', () => {
|
|
|
111
112
|
})
|
|
112
113
|
})
|
|
113
114
|
|
|
115
|
+
describe('canonicalUrl', () => {
|
|
116
|
+
// The bug this exists to prevent: /blog answers 301 and only /blog/ answers
|
|
117
|
+
// 200, so a canonical without the slash points a crawler at a redirect.
|
|
118
|
+
it('always ends in a slash, whatever the caller passed', () => {
|
|
119
|
+
expect(canonicalUrl('/blog')).toBe(`${RXOVA_ORIGIN}/blog/`)
|
|
120
|
+
expect(canonicalUrl('/blog/')).toBe(`${RXOVA_ORIGIN}/blog/`)
|
|
121
|
+
expect(canonicalUrl('/updates/repos/journey')).toBe(`${RXOVA_ORIGIN}/updates/repos/journey/`)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('roots a path that arrives without a leading slash', () => {
|
|
125
|
+
expect(canonicalUrl('blog')).toBe(`${RXOVA_ORIGIN}/blog/`)
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
it('defaults to the origin root', () => {
|
|
129
|
+
expect(canonicalUrl()).toBe(`${RXOVA_ORIGIN}/`)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
// siteUrl builds nav hrefs, where following a redirect costs nothing. Keeping
|
|
133
|
+
// them different is the point; collapsing them would reintroduce the bug.
|
|
134
|
+
it('differs from siteUrl, which does not normalise', () => {
|
|
135
|
+
expect(siteUrl('/blog')).toBe(`${RXOVA_ORIGIN}/blog`)
|
|
136
|
+
expect(canonicalUrl('/blog')).not.toBe(siteUrl('/blog'))
|
|
137
|
+
})
|
|
138
|
+
})
|
|
139
|
+
|
|
114
140
|
describe('projectFromBase', () => {
|
|
115
141
|
it('recognises a mount with and without its trailing slash', () => {
|
|
116
142
|
expect(projectFromBase('/packages/journey/')).toBe('journey')
|
package/src/sites.ts
CHANGED
|
@@ -121,6 +121,23 @@ export function siteUrl(path = '/'): string {
|
|
|
121
121
|
return `${RXOVA_ORIGIN}${path.startsWith('/') ? path : `/${path}`}`
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Absolute canonical URL for a *page* on the umbrella site.
|
|
126
|
+
*
|
|
127
|
+
* Trailing slash, always — which is the whole reason this is not `siteUrl`.
|
|
128
|
+
* rxova.org is published as a directory-style tree on GitHub Pages, so `/blog`
|
|
129
|
+
* answers 301 and only `/blog/` answers 200. A self-referencing canonical naming
|
|
130
|
+
* the redirecting form points a crawler at a URL that does not serve the page,
|
|
131
|
+
* which is the one thing a canonical must never do. `siteUrl` stays as it is:
|
|
132
|
+
* a nav link may follow a redirect, a canonical may not.
|
|
133
|
+
*
|
|
134
|
+
* Pages only. Assets keep their exact path and want `siteUrl`.
|
|
135
|
+
*/
|
|
136
|
+
export function canonicalUrl(path = '/'): string {
|
|
137
|
+
const rooted = path.startsWith('/') ? path : `/${path}`
|
|
138
|
+
return `${RXOVA_ORIGIN}${rooted.endsWith('/') ? rooted : `${rooted}/`}`
|
|
139
|
+
}
|
|
140
|
+
|
|
124
141
|
/**
|
|
125
142
|
* Which project a page belongs to, inferred from Astro's `BASE_URL`.
|
|
126
143
|
*
|
package/src/starlight.css
CHANGED
|
@@ -78,6 +78,44 @@ header.header {
|
|
|
78
78
|
background: var(--sl-color-bg-nav);
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
/* In a schema-2 page bundle the umbrella header is rendered by rxova-website
|
|
82
|
+
outside Starlight's `.page`. Keep Starlight's own sticky documentation bar
|
|
83
|
+
below it instead of letting the two sticky headers occupy the same top edge. */
|
|
84
|
+
html[data-rxova-shell] {
|
|
85
|
+
--rx-shell-header-height: 3.5rem;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
html[data-rxova-shell] .page > header.header {
|
|
89
|
+
inset-block-start: var(--rx-shell-header-height);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
html[data-rxova-shell] .sidebar-pane {
|
|
93
|
+
inset-block-start: calc(var(--rx-shell-header-height) + var(--sl-nav-height));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
html[data-rxova-shell] mobile-starlight-toc nav {
|
|
97
|
+
top: calc(var(--rx-shell-header-height) + var(--sl-nav-height) - 1px);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
html[data-rxova-shell] starlight-menu-button button {
|
|
101
|
+
top: calc(
|
|
102
|
+
var(--rx-shell-header-height) + (var(--sl-nav-height) - var(--sl-menu-button-size)) / 2
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@media (min-width: 72rem) {
|
|
107
|
+
html[data-rxova-shell] .right-sidebar {
|
|
108
|
+
top: var(--rx-shell-header-height);
|
|
109
|
+
height: calc(100vh - var(--rx-shell-header-height));
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
@media (max-width: 34rem) {
|
|
114
|
+
html[data-rxova-shell] {
|
|
115
|
+
--rx-shell-header-height: 3.25rem;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
81
119
|
/* Site title: the rxova mark sits beside the project wordmark. */
|
|
82
120
|
.rx-site-title {
|
|
83
121
|
display: flex;
|
package/src/starlight.ts
CHANGED
|
@@ -27,6 +27,12 @@ export interface SharedStarlightOptions {
|
|
|
27
27
|
components?: Record<string, string>
|
|
28
28
|
/** Path under the repo root that holds the docs site, for the edit link. */
|
|
29
29
|
editLinkBase?: string
|
|
30
|
+
/**
|
|
31
|
+
* Build body-only documentation for rxova-website to place in its global
|
|
32
|
+
* shell. Starlight's search, sidebar and page navigation remain page UI; only
|
|
33
|
+
* the umbrella footer is omitted.
|
|
34
|
+
*/
|
|
35
|
+
pageComponent?: boolean
|
|
30
36
|
}
|
|
31
37
|
|
|
32
38
|
export function sharedStarlightConfig({
|
|
@@ -35,6 +41,7 @@ export function sharedStarlightConfig({
|
|
|
35
41
|
customCss = [],
|
|
36
42
|
components = {},
|
|
37
43
|
editLinkBase = 'apps/docs',
|
|
44
|
+
pageComponent = false,
|
|
38
45
|
}: SharedStarlightOptions) {
|
|
39
46
|
const self = getProject(project)
|
|
40
47
|
|
|
@@ -72,7 +79,7 @@ export function sharedStarlightConfig({
|
|
|
72
79
|
SocialIcons: '@rxova/brand/components/SocialIcons.astro',
|
|
73
80
|
// Starlight's default footer (pagination, edit link, last updated) plus
|
|
74
81
|
// the shared four-column site footer beneath it.
|
|
75
|
-
Footer: '@rxova/brand/components/Footer.astro',
|
|
82
|
+
...(!pageComponent ? { Footer: '@rxova/brand/components/Footer.astro' } : {}),
|
|
76
83
|
// Starlight's own picker, plus a resync when a page is restored from the
|
|
77
84
|
// back/forward cache — without it, changing the theme on one rxova.org
|
|
78
85
|
// surface and pressing Back leaves the restored page on the old theme.
|