@master/internal-site 0.2.6 → 0.2.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/README.md +1 -1
- package/dist/astro.mjs +9 -1
- package/package.json +3 -2
- package/src/benchmarks/BenchmarkChart.astro +8 -8
- package/src/benchmarks/BenchmarkDelta.astro +2 -3
- package/src/benchmarks/BenchmarkFigure.astro +1 -1
- package/src/benchmarks/BenchmarkMetricTable.astro +10 -10
- package/src/benchmarks/BenchmarkScrollRegion.svelte +2 -2
- package/src/benchmarks/BenchmarkStatus.astro +2 -3
- package/src/benchmarks/utils.ts +1 -9
- package/src/css/NamespaceUtilityTable.astro +11 -11
- package/src/css/ThemeNumberVariableTable.astro +14 -14
- package/src/demo/Demo.svelte +2 -2
- package/src/demo/DemoAsset.astro +3 -3
- package/src/demo/DemoBadge.svelte +3 -3
- package/src/demo/DemoContainer.svelte +2 -2
- package/src/demo/DemoControls.svelte +1 -1
- package/src/demo/DemoCopyButton.svelte +1 -1
- package/src/demo/DemoFeatureSupport.svelte +3 -4
- package/src/demo/DemoIndex.astro +1 -1
- package/src/demo/DemoMotion.svelte +2 -2
- package/src/demo/DemoSurface.svelte +2 -2
- package/src/demo/DemoTokenTable.astro +6 -6
- package/src/demo/DemoViewport.svelte +11 -11
- package/src/demo/foundations/FoundationDialog.astro +1 -1
- package/src/demo/foundations/FoundationMedia.astro +2 -2
- package/src/demo/foundations/FoundationShrink.astro +2 -2
- package/src/demo/foundations/Palette.svelte +1 -1
- package/src/demo/reference/document.ts +3 -2
- package/src/docs-shell/common/locales.js +1 -1
- package/src/docs-shell/components/CodeCopyButton.astro +1 -1
- package/src/docs-shell/components/DocHeader.svelte +3 -3
- package/src/docs-shell/components/DocMenuButton.svelte +6 -5
- package/src/docs-shell/components/DocVersionSelect.svelte +2 -2
- package/src/docs-shell/components/DocumentCodeExampleView.astro +2 -2
- package/src/docs-shell/components/DocumentCodeTable.astro +5 -5
- package/src/docs-shell/components/DocumentCopyButton.svelte +1 -1
- package/src/docs-shell/components/DocumentFileTree.astro +2 -2
- package/src/docs-shell/components/DocumentFlow.astro +2 -2
- package/src/docs-shell/components/DocumentIllustration.astro +2 -2
- package/src/docs-shell/components/DocumentNamespaceTable.astro +6 -6
- package/src/docs-shell/components/DocumentParameters.astro +2 -2
- package/src/docs-shell/components/ExpandContent.svelte +1 -1
- package/src/docs-shell/components/LanguageButton.svelte +2 -2
- package/src/docs-shell/components/LanguageSelect.svelte +2 -2
- package/src/docs-shell/components/NotFound.astro +1 -1
- package/src/docs-shell/components/PageNavs.astro +4 -4
- package/src/docs-shell/components/SearchButton.svelte +7 -4
- package/src/docs-shell/components/SearchDialog.svelte +4 -1
- package/src/docs-shell/components/SearchDialogPanel.svelte +8 -8
- package/src/docs-shell/components/Segments.svelte +2 -1
- package/src/docs-shell/components/ThemeSelect.svelte +2 -2
- package/src/docs-shell/components/markdown/Table.astro +3 -3
- package/src/docs-shell/components/markdown/TableCell.astro +4 -0
- package/src/docs-shell/components/markdown/TableHead.astro +4 -0
- package/src/docs-shell/components/markdown/TableRow.astro +4 -0
- package/src/docs-shell/components/markdown-components.ts +6 -0
- package/src/docs-shell/contexts/search.ts +11 -1
- package/src/docs-shell/contexts/theme-mode.svelte.ts +1 -0
- package/src/docs-shell/data/legacy-design-routes.json +176 -0
- package/src/docs-shell/remark/markdown-components.js +2 -2
- package/src/docs-shell/utils/snackbar.ts +1 -1
- package/src/examples/article-transitions/page.astro +0 -1
- package/src/examples/components/ArticleTransitionScene.svelte +4 -4
- package/src/examples/components/ViewTransitionScene.svelte +1 -1
- package/src/examples/view-transitions/page.astro +0 -1
- package/src/layouts/Document.astro +1 -0
- package/src/scripts/legacy-design-routes.ts +76 -0
- package/src/scripts/style-delivery.mjs +22 -2
- package/src/sections/document.astro +1 -1
- package/src/styles/docs-shell/documentation-search.css +6 -5
- package/src/styles/docs-shell/materials.css +10 -22
- package/src/styles/docs-shell/menu.css +8 -8
- package/src/styles/docs-shell/segments.css +2 -2
- package/src/styles/docs-shell/theme.css +2 -17
- package/src/styles/foundation.css +1 -0
- package/src/styles/site-contract.md +31 -0
- package/src/styles/system/badge-tones.css +4 -0
- package/src/styles/system/badge.ts +2 -0
- package/src/styles/system/browser.css +3 -6
- package/src/styles/system/button-feedback.css +6 -9
- package/src/styles/system/buttons.css +1 -51
- package/src/styles/system/checks.css +4 -18
- package/src/styles/system/controls.css +0 -1
- package/src/styles/system/dialog.css +3 -3
- package/src/styles/system/expand.css +3 -3
- package/src/styles/system/fields.css +7 -23
- package/src/styles/system/header-core.css +10 -10
- package/src/styles/system/kbd.css +1 -4
- package/src/styles/system/mixins.css +2 -2
- package/src/styles/system/pager.css +2 -13
- package/src/styles/system/range.css +1 -12
- package/src/styles/system/search-trigger.css +2 -2
- package/src/styles/system/segmented.css +1 -16
- package/src/styles/system/sheet.css +1 -8
- package/src/styles/system/sheet.ts +2 -0
- package/src/styles/system/sidebar.css +1 -1
- package/src/styles/system/specimens.css +5 -17
- package/src/styles/system/surfaces.css +0 -1
- package/src/styles/system/table-layout.css +12 -0
- package/src/styles/system/table.css +3 -23
- package/src/styles/system/table.ts +4 -0
- package/src/styles/system/tokens.css +48 -63
- package/src/styles/system/tooltip.css +2 -4
- package/src/styles/system/tray-layout.css +20 -0
- package/src/styles/system/tray.css +2 -20
- package/src/styles/system/tray.ts +3 -0
- package/src/demo/DemoScrollArea.svelte +0 -17
- package/src/examples/scene.css +0 -3
- package/src/styles/system/DESIGN.md +0 -128
- package/src/styles/system/menu.css +0 -14
- package/src/styles/system/scroll.css +0 -6
|
@@ -9,13 +9,14 @@ import type { DemoScene, ReferenceDemoSection } from '@master/internal-site/demo
|
|
|
9
9
|
const frameFile = fileURLToPath(import.meta.resolve('@master/internal-site/demo/reference/frame.css'))
|
|
10
10
|
const materialFile = fileURLToPath(import.meta.resolve('@master/internal-site/styles/docs-shell/materials.css'))
|
|
11
11
|
const systemTokenFile = fileURLToPath(import.meta.resolve('@master/internal-site/styles/system/tokens.css'))
|
|
12
|
-
const readSystemButtons = () =>
|
|
12
|
+
const readSystemButtons = () => readFileSync(fileURLToPath(import.meta.resolve('@master/ui/components/button.css')), 'utf8')
|
|
13
|
+
const uiTheme = readFileSync(fileURLToPath(import.meta.resolve('@master/ui/theme.css')), 'utf8')
|
|
13
14
|
const systemButtons = readSystemButtons()
|
|
14
15
|
let materials = readFileSync(materialFile, 'utf8')
|
|
15
16
|
const readSystemTokens = () => readFileSync(systemTokenFile, 'utf8').replace(/\/\*[\s\S]*?\*\//g, '')
|
|
16
17
|
let systemTokens = readSystemTokens()
|
|
17
18
|
const frameCSS = readFileSync(frameFile, 'utf8')
|
|
18
|
-
const sharedManifest = () => compileManifestSync(`@mixin --light { &:where(.light, .light *) { @contents; } }\n@mixin --dark { &:where(.dark, .dark *) { @contents; } }\n${materials}`, { baseManifest: preset }).manifest
|
|
19
|
+
const sharedManifest = () => compileManifestSync(`@mixin --light { &:where(.light, .light *) { @contents; } }\n@mixin --dark { &:where(.dark, .dark *) { @contents; } }\n${uiTheme}\n${materials}`, { baseManifest: preset }).manifest
|
|
19
20
|
let shared = sharedManifest()
|
|
20
21
|
|
|
21
22
|
export function demoDocument(section: ReferenceDemoSection, scene: DemoScene, initialTheme?: 'light' | 'dark') {
|
|
@@ -5,7 +5,7 @@ export const hreflangOfLocale = { en: 'en', tw: 'zh-TW', ja: 'ja', ko: 'ko', cn:
|
|
|
5
5
|
export const nameOfLocale = { en: 'English', tw: '繁體中文(台灣)', ja: '日本語', ko: '한국어', cn: '简体中文' }
|
|
6
6
|
/** Only first-party page links inherit the reader's language across sites. */
|
|
7
7
|
export const localizableOrigins = {
|
|
8
|
-
'https://master.co': ['blog', 'brand'
|
|
8
|
+
'https://master.co': ['blog', 'brand'],
|
|
9
9
|
'https://css.master.co': ['guide', 'reference', 'benchmarks', 'roadmap'],
|
|
10
10
|
'https://rc.css.master.co': ['guide', 'reference', 'benchmarks', 'roadmap']
|
|
11
11
|
}
|
|
@@ -22,7 +22,7 @@ const label = name ? t('Copy {name}').replace('{name}', t(name)) : t('Copy code'
|
|
|
22
22
|
|
|
23
23
|
<span class:list={['ui-copy', className]}>
|
|
24
24
|
<span class="ui-copy-status" role="status"></span>
|
|
25
|
-
<button type="button" class="
|
|
25
|
+
<button type="button" class="btn btn-sm btn-quiet btn-square" data-variant="quiet" data-shape="icon" data-size="sm" aria-label={label} title={label} data-code-copy={name ?? ''} data-code-copy-text={text}>
|
|
26
26
|
<IconCopy size={16} stroke={1.5} aria-hidden="true" />
|
|
27
27
|
<IconCheck size={16} stroke={1.6} aria-hidden="true" class="ui-result-icon" />
|
|
28
28
|
</button>
|
|
@@ -64,13 +64,13 @@
|
|
|
64
64
|
<!-- Desktop keeps the search pill and shortcut; compact headers use a 44px icon target. -->
|
|
65
65
|
<SearchButton class="ui-header-control ui-header-search" data-compact={home && !app.header?.searchOnHome ? '' : undefined}>
|
|
66
66
|
<IconSearch size={18} stroke={1.5} aria-hidden="true" />
|
|
67
|
-
<kbd class="
|
|
67
|
+
<kbd class="kbd" aria-hidden="true">⌘K</kbd>
|
|
68
68
|
</SearchButton>
|
|
69
69
|
{#each headerCommunityNavs as { Icon, disabled, fullName, ...eachLink } (eachLink.name)}
|
|
70
70
|
<Link
|
|
71
71
|
{...eachLink}
|
|
72
72
|
aria-label={fullName || eachLink.name}
|
|
73
|
-
class="
|
|
73
|
+
class="btn ui-header-control btn-quiet btn-square"
|
|
74
74
|
data-variant="quiet"
|
|
75
75
|
data-shape="icon"
|
|
76
76
|
data-disabled={disabled || undefined}
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
>
|
|
79
79
|
{#if Icon}<Icon size={18} stroke={1.5} aria-hidden="true" />{/if}
|
|
80
80
|
{#if eachLink.href?.startsWith('http')}<IconArrowUpRight class="ui-header-external" size={10} stroke={1.5} aria-hidden="true" />{/if}
|
|
81
|
-
<span class="ui-tooltip" data-side="bottom" aria-hidden="true">{fullName || eachLink.name}</span>
|
|
81
|
+
<span class="tooltip ui-tooltip" data-side="bottom" aria-hidden="true">{fullName || eachLink.name}</span>
|
|
82
82
|
</Link>
|
|
83
83
|
{/each}
|
|
84
84
|
{#if showLanguage}
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
<script lang="ts">
|
|
12
12
|
import '@master/internal-site/styles/interface.css'
|
|
13
|
-
import '@master/internal-site/styles/system/dialog.css'
|
|
14
13
|
import '@master/internal-site/styles/system/header-core.css'
|
|
15
14
|
|
|
16
15
|
import '../../styles/docs-shell/menu.css'
|
|
@@ -33,6 +32,7 @@
|
|
|
33
32
|
/** Primary destinations, with community and preferences kept in a quiet footer. */
|
|
34
33
|
let { class: className }: Props = $props()
|
|
35
34
|
let opened = $state(false)
|
|
35
|
+
let mounted = $state(false)
|
|
36
36
|
const id = $props.id()
|
|
37
37
|
let dialog: HTMLDialogElement
|
|
38
38
|
let trigger: HTMLButtonElement
|
|
@@ -97,6 +97,7 @@
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
onMount(() => {
|
|
100
|
+
mounted = true
|
|
100
101
|
const wide = matchMedia('(width >= 64rem)')
|
|
101
102
|
const motion = matchMedia('(prefers-reduced-motion: reduce)')
|
|
102
103
|
const resize = () => { if (wide.matches && dialog.open) finishClose() }
|
|
@@ -115,20 +116,20 @@
|
|
|
115
116
|
<IconMenu class="ui-menu-glyph" size={18} stroke={1.5} data-open={opened} aria-hidden="true" />
|
|
116
117
|
{/snippet}
|
|
117
118
|
|
|
118
|
-
<button bind:this={trigger} type="button" class={clsx('
|
|
119
|
+
<button bind:this={trigger} type="button" disabled={!mounted} class={clsx('btn btn-quiet btn-square ui-menu-toggle', className)} data-variant="quiet" data-shape="icon"
|
|
119
120
|
aria-label={t('Menu')} aria-expanded={opened} aria-haspopup="dialog" aria-controls={id} onclick={open}>
|
|
120
121
|
{@render lines()}
|
|
121
122
|
</button>
|
|
122
|
-
<dialog bind:this={dialog} {@attach portal} {id} class="ui-
|
|
123
|
+
<dialog bind:this={dialog} {@attach portal} {id} class="ui-mobile-menu" data-variant="sheet" data-open={opened}
|
|
123
124
|
aria-labelledby={`${id}-title`} oncancel={event => { event.preventDefault(); close() }} ontransitionend={transitionEnd}
|
|
124
125
|
onkeydown={keydown} onclose={() => { if (!dialog.open) { opened = false; clearTimeout(closing) } }}>
|
|
125
126
|
<div class="ui-mobile-menu-bar">
|
|
126
|
-
<button type="button" class="
|
|
127
|
+
<button type="button" class="btn ui-header-control ui-menu-toggle btn-quiet btn-square" data-variant="quiet" data-shape="icon"
|
|
127
128
|
onclick={() => opened ? close() : open()} aria-label={opened ? t('Close menu') : t('Menu')} aria-expanded={opened} aria-controls={id}>
|
|
128
129
|
{@render lines()}
|
|
129
130
|
</button>
|
|
130
131
|
<Link href="/" class="ui-header-brand" onclick={() => finishClose(false)} aria-label={`${app.name} ${t('home')}`}><app.Logotype style="height: 20px; width: auto" aria-hidden="true" /></Link>
|
|
131
|
-
<SearchButton class="
|
|
132
|
+
<SearchButton class="btn ui-header-control ui-menu-search btn-quiet btn-square" data-variant="quiet" data-shape="icon" onclick={search}><IconSearch size={18} stroke={1.5} aria-hidden="true" /></SearchButton>
|
|
132
133
|
</div>
|
|
133
134
|
<div class="ui-mobile-menu-body">
|
|
134
135
|
<h2 class="sr-only" id={`${id}-title`}>{t('Navigation')}</h2>
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
type Props = Omit<HTMLSelectAttributes, 'value' | 'onchange'>
|
|
9
9
|
|
|
10
|
-
/** A native select; by default invisible over its positioned label (`
|
|
10
|
+
/** A native select; by default invisible over its positioned label (`select[data-variant="overlay"]`), which shows the value. */
|
|
11
11
|
let { class: className, ...props }: Props = $props()
|
|
12
12
|
const currentURL = import.meta.env.PUBLIC_URL
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
</script>
|
|
18
18
|
|
|
19
19
|
<select name="version" value={currentURL}
|
|
20
|
-
data-variant="overlay" {...props} class={clsx('
|
|
20
|
+
data-variant="overlay" {...props} class={clsx('select site-select-overlay', className)}
|
|
21
21
|
onchange={navigate}>
|
|
22
22
|
<option value={currentURL}>v{import.meta.env.PUBLIC_VERSION}</option>
|
|
23
23
|
{#each app.versions as { name, href } (href)}<option value={href}>{name}</option>{/each}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import '@master/internal-site/styles/system/callout.css'
|
|
3
|
-
import '@master/internal-site/styles/system/tray.
|
|
3
|
+
import '@master/internal-site/styles/system/tray.ts'
|
|
4
4
|
import '@master/internal-site/styles/system/tray-code.css'
|
|
5
5
|
import IconAlertTriangle from '@tabler/icons-svelte-runes/icons/alert-triangle'
|
|
6
6
|
import IconCircleX from '@tabler/icons-svelte-runes/icons/circle-x'
|
|
@@ -21,7 +21,7 @@ const DiagnosticIcon = diagnostic?.severity === 'Error' ? IconCircleX : IconAler
|
|
|
21
21
|
const hasResult = resultCode != null || Astro.slots.has('resultCode')
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
<figure class="ui-tray" aria-label={title}>
|
|
24
|
+
<figure class="tray ui-tray" aria-label={title}>
|
|
25
25
|
<figcaption class="ui-tray-head"><p class="ui-tray-title">{title}</p></figcaption>
|
|
26
26
|
{sourceCode != null ? <RenderNode node={sourceCode} /> : <slot name="sourceCode" />}
|
|
27
27
|
{diagnostic && <div class="ui-callout" data-tone={diagnostic.severity === 'Error' ? 'danger' : 'warning'}>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { siteOf } from '../../astro/site-context'
|
|
3
3
|
const { t } = siteOf(Astro)
|
|
4
|
-
import '@master/internal-site/styles/system/table.
|
|
4
|
+
import '@master/internal-site/styles/system/table.ts'
|
|
5
5
|
|
|
6
6
|
interface Props {
|
|
7
7
|
label?: string
|
|
@@ -13,9 +13,9 @@ const { label = 'Syntax', rows } = Astro.props
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
{/* The table's narrow overflow region must be focusable for native keyboard scrolling. */}
|
|
16
|
-
<div class="ui-table" data-variant="lookup" role="region" aria-label={`${label} and CSS`} tabindex="0"><table>
|
|
17
|
-
<thead><tr><th scope="col">{t(label)}</th><th scope="col">CSS</th></tr></thead>
|
|
18
|
-
<tbody>{rows.map(({ syntax, css }) => <tr>
|
|
19
|
-
<th scope="row"><code>{syntax}</code></th><td><code>{css}</code></td>
|
|
16
|
+
<div class="ui-table sheet sheet-flat" data-variant="lookup" role="region" aria-label={`${label} and CSS`} tabindex="0"><table class="table">
|
|
17
|
+
<thead><tr class="table-row"><th class="table-heading" scope="col">{t(label)}</th><th class="table-heading" scope="col">CSS</th></tr></thead>
|
|
18
|
+
<tbody>{rows.map(({ syntax, css }) => <tr class="table-row">
|
|
19
|
+
<th class="table-heading" scope="row"><code>{syntax}</code></th><td class="table-cell"><code>{css}</code></td>
|
|
20
20
|
</tr>)}</tbody>
|
|
21
21
|
</table></div>
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
</script>
|
|
35
35
|
|
|
36
36
|
<span class="ui-copy">
|
|
37
|
-
<button type="button" class="
|
|
37
|
+
<button type="button" class="btn btn-sm" data-size="sm" disabled={!ready} aria-label={`Copy ${label}`} onclick={copy}>
|
|
38
38
|
{#if result === 'success'}<IconCheck stroke={1.8} aria-hidden="true" />{:else}<IconCopy stroke={1.8} aria-hidden="true" />{/if}
|
|
39
39
|
Copy
|
|
40
40
|
</button>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import '@master/internal-site/styles/system/tray.
|
|
2
|
+
import '@master/internal-site/styles/system/tray.ts'
|
|
3
3
|
import '@master/internal-site/styles/system/tray-code.css'
|
|
4
4
|
import '@master/internal-site/styles/system/tree.css'
|
|
5
5
|
import IconFile from '@tabler/icons-svelte-runes/icons/file'
|
|
@@ -30,7 +30,7 @@ const Entries = Astro.self
|
|
|
30
30
|
{!!entry.children?.length && <Entries entries={entry.children} nested />}
|
|
31
31
|
</li>)}
|
|
32
32
|
</ul>
|
|
33
|
-
: <figure class="ui-tray" aria-label={props.title}>
|
|
33
|
+
: <figure class="tray ui-tray" aria-label={props.title}>
|
|
34
34
|
<figcaption class="ui-tray-head"><p class="ui-tray-title">{props.title}</p></figcaption>
|
|
35
35
|
<div class="ui-tree"><Entries entries={props.entries} nested /></div>
|
|
36
36
|
{props.caption && <p class="ui-tray-caption">{props.caption}</p>}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
import '@master/internal-site/styles/system/stage.css'
|
|
3
3
|
import '@master/internal-site/styles/system/steps.css'
|
|
4
|
-
import '@master/internal-site/styles/system/tray.
|
|
4
|
+
import '@master/internal-site/styles/system/tray.ts'
|
|
5
5
|
import '@master/internal-site/styles/system/tray-code.css'
|
|
6
6
|
import type { DocumentFlowProps } from '@master/internal-site/components/document-types.ts'
|
|
7
7
|
|
|
@@ -13,7 +13,7 @@ type Props = DocumentFlowProps
|
|
|
13
13
|
const { title, steps, caption } = Astro.props
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
<figure class="ui-tray" aria-label={title}>
|
|
16
|
+
<figure class="tray ui-tray" aria-label={title}>
|
|
17
17
|
<figcaption class="ui-tray-head"><p class="ui-tray-title">{title}</p></figcaption>
|
|
18
18
|
<div class="ui-stage" data-padding="sm" data-align="start">
|
|
19
19
|
{/* Preserve WebKit list semantics when list-style is none. */}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { siteOf } from '../../astro/site-context'
|
|
3
3
|
const { t } = siteOf(Astro)
|
|
4
4
|
import '@master/internal-site/styles/system/disclosure.css'
|
|
5
|
-
import '@master/internal-site/styles/system/tray.
|
|
5
|
+
import '@master/internal-site/styles/system/tray.ts'
|
|
6
6
|
import '@master/internal-site/styles/system/tray-code.css'
|
|
7
7
|
import '@master/internal-site/styles/documentation-illustration.css'
|
|
8
8
|
import Image from '@master/internal-site/components/Image.svelte'
|
|
@@ -21,7 +21,7 @@ interface Props {
|
|
|
21
21
|
const { title, alt, images, caption } = Astro.props
|
|
22
22
|
---
|
|
23
23
|
|
|
24
|
-
<figure class="ui-tray" aria-label={title}>
|
|
24
|
+
<figure class="tray ui-tray" aria-label={title}>
|
|
25
25
|
<figcaption class="ui-tray-head">
|
|
26
26
|
<p class="ui-tray-title">{title}</p>
|
|
27
27
|
</figcaption>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
import '@master/internal-site/styles/system/table.
|
|
2
|
+
import '@master/internal-site/styles/system/table.ts'
|
|
3
3
|
import DocumentKeyList from '@master/internal-site/components/DocumentKeyList.astro'
|
|
4
4
|
import { siteOf } from '../../astro/site-context'
|
|
5
5
|
const { t } = siteOf(Astro)
|
|
@@ -13,10 +13,10 @@ const { rows } = Astro.props
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
{/* The table's narrow overflow region must be focusable for native keyboard scrolling. */}
|
|
16
|
-
<div class="ui-table" data-variant="lookup" role="region" aria-label={t('Namespace consumers')} tabindex="0"><table>
|
|
17
|
-
<thead><tr><th scope="col">{t('Namespace')}</th><th scope="col">{t('Consumers')}</th></tr></thead>
|
|
18
|
-
<tbody>{rows.map(({ namespace, consumers }) => <tr>
|
|
19
|
-
<th scope="row"><code>{namespace}-*</code></th>
|
|
20
|
-
<td><DocumentKeyList keys={consumers} previewCount={6} /></td>
|
|
16
|
+
<div class="ui-table sheet sheet-flat" data-variant="lookup" role="region" aria-label={t('Namespace consumers')} tabindex="0"><table class="table">
|
|
17
|
+
<thead><tr class="table-row"><th class="table-heading" scope="col">{t('Namespace')}</th><th class="table-heading" scope="col">{t('Consumers')}</th></tr></thead>
|
|
18
|
+
<tbody>{rows.map(({ namespace, consumers }) => <tr class="table-row">
|
|
19
|
+
<th class="table-heading" scope="row"><code>{namespace}-*</code></th>
|
|
20
|
+
<td class="table-cell"><DocumentKeyList keys={consumers} previewCount={6} /></td>
|
|
21
21
|
</tr>)}</tbody>
|
|
22
22
|
</table></div>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
import '@master/internal-site/styles/system/parameters.css'
|
|
3
|
-
import '@master/
|
|
3
|
+
import '@master/ui/components/badge.css'
|
|
4
4
|
import RenderNode from '@master/internal-site/components/RenderNode.astro'
|
|
5
5
|
import DocumentIdentifier from '@master/internal-site/components/DocumentIdentifier.astro'
|
|
6
6
|
import type { DocumentParameter } from '@master/internal-site/components/document-types.ts'
|
|
@@ -22,7 +22,7 @@ const { label, parameters } = Astro.props
|
|
|
22
22
|
<span><DocumentIdentifier text={parameter.name} /></span>
|
|
23
23
|
<small>{parameter.type}</small>
|
|
24
24
|
{parameter.requirement && (/^required$/i.test(parameter.requirement)
|
|
25
|
-
? <span class="
|
|
25
|
+
? <span class="badge badge-sm">{parameter.requirement}</span>
|
|
26
26
|
: <small>{parameter.requirement}</small>)}
|
|
27
27
|
</dt>
|
|
28
28
|
<dd><p><RenderNode node={parameter.description} /></p></dd>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<div class="ui-expand" data-expanded={expanded}>
|
|
17
17
|
<div {id}>{@render children?.()}</div>
|
|
18
18
|
<div class="ui-expand-control">
|
|
19
|
-
<button type="button" class="
|
|
19
|
+
<button type="button" class="btn btn-sm" data-size="sm" aria-expanded={expanded} aria-controls={id} onclick={() => { expanded = !expanded }}>
|
|
20
20
|
{t(expanded ? 'Collapse' : 'Expand')}
|
|
21
21
|
<IconChevronDown aria-hidden="true" stroke={1.5} />
|
|
22
22
|
</button>
|
|
@@ -11,9 +11,9 @@
|
|
|
11
11
|
</script>
|
|
12
12
|
|
|
13
13
|
{#if i18n.locales.length > 1}
|
|
14
|
-
<label class={clsx('
|
|
14
|
+
<label class={clsx('btn btn-quiet btn-sm btn-square', className)} data-variant="quiet" data-shape="icon" data-size="sm">
|
|
15
15
|
<IconLanguage size={18} stroke={1.5} aria-hidden="true" />
|
|
16
16
|
<LanguageSelect aria-label={t('Language switch')} />
|
|
17
|
-
<span class="ui-tooltip" data-side="bottom" aria-hidden="true">{t('Language')}</span>
|
|
17
|
+
<span class="tooltip ui-tooltip" data-side="bottom" aria-hidden="true">{t('Language')}</span>
|
|
18
18
|
</label>
|
|
19
19
|
{/if}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
children?: Snippet
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
/** A native select; by default invisible over its positioned label (`
|
|
14
|
+
/** A native select; by default invisible over its positioned label (`select[data-variant="overlay"]`), which shows the value. */
|
|
15
15
|
let { class: className, children, ...props }: Props = $props()
|
|
16
16
|
const { pathname, locale, i18n } = getSite()
|
|
17
17
|
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
}
|
|
35
35
|
</script>
|
|
36
36
|
|
|
37
|
-
<select data-variant="overlay" {...props} class={clsx('
|
|
37
|
+
<select data-variant="overlay" {...props} class={clsx('select site-select-overlay', className)}
|
|
38
38
|
{onchange}
|
|
39
39
|
value={locale}>
|
|
40
40
|
{#each Object.entries(i18n.nameOfLocale) as [eachLocale, localeName] (eachLocale)}
|
|
@@ -19,5 +19,5 @@ const guide = Boolean(config.sections.guide)
|
|
|
19
19
|
<p>{guide ? $('Try searching the documentation or return to the Guide.') : $('Try searching the site or return to the homepage.')}</p>
|
|
20
20
|
</div>
|
|
21
21
|
<SearchButton client:load class="ui-search-trigger" />
|
|
22
|
-
<Link href={guide ? "/guide" : "/"} class="
|
|
22
|
+
<Link href={guide ? "/guide" : "/"} class="btn btn-quiet" data-variant="quiet">{guide ? $('Browse the Guide') : $('Back to home')}<span aria-hidden="true">→</span></Link>
|
|
23
23
|
</main>
|
|
@@ -31,10 +31,10 @@ const navs = [
|
|
|
31
31
|
---
|
|
32
32
|
|
|
33
33
|
{navs.length > 0 && (
|
|
34
|
-
<nav class="ui-pager" aria-label={$('Previous and next documents')}>
|
|
35
|
-
{navs.map(({ direction, href, label, title }) => <Link {href} rel={direction} aria-label={`${label}: ${title}`}>
|
|
36
|
-
<small>{label}</small>
|
|
37
|
-
<b>{title}</b>
|
|
34
|
+
<nav class="pager ui-pager" aria-label={$('Previous and next documents')}>
|
|
35
|
+
{navs.map(({ direction, href, label, title }) => <Link class="pager-link" {href} rel={direction} aria-label={`${label}: ${title}`}>
|
|
36
|
+
<small class="pager-label">{label}</small>
|
|
37
|
+
<b class="pager-title">{title}</b>
|
|
38
38
|
</Link>)}
|
|
39
39
|
</nav>
|
|
40
40
|
)}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import '@master/internal-site/styles/interface.css'
|
|
3
3
|
import '@master/internal-site/styles/system/search-trigger.css'
|
|
4
4
|
|
|
5
|
-
import type
|
|
5
|
+
import { onMount, type Snippet } from 'svelte'
|
|
6
6
|
import type { HTMLButtonAttributes } from 'svelte/elements'
|
|
7
7
|
import IconSearch from '@tabler/icons-svelte-runes/icons/search'
|
|
8
8
|
import { openSearch, prefetchSearch, searchLabels } from '../contexts/search'
|
|
@@ -13,7 +13,10 @@
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/** Opens the page's search dialog. Without children it renders the search field trigger (`ui-search-trigger`) with its shortcut. */
|
|
16
|
-
let { class: className, children, onclick, onfocus, onpointerenter, type = 'button', ...props }: Props = $props()
|
|
16
|
+
let { class: className, children, onclick, onfocus, onpointerenter, type = 'button', disabled = false, ...props }: Props = $props()
|
|
17
|
+
// SSR must not offer an action before this island can receive it.
|
|
18
|
+
let mounted = $state(false)
|
|
19
|
+
onMount(() => { mounted = true })
|
|
17
20
|
const { t, locale } = getSite()
|
|
18
21
|
const { searchText, searchLabel } = searchLabels(t, locale)
|
|
19
22
|
|
|
@@ -23,7 +26,7 @@
|
|
|
23
26
|
}
|
|
24
27
|
</script>
|
|
25
28
|
|
|
26
|
-
<button {...props} {type} class={className} aria-label={props['aria-label'] ?? searchLabel} aria-keyshortcuts="Meta+K Control+K" onclick={handleClick}
|
|
29
|
+
<button {...props} {type} disabled={!mounted || disabled} class={className} aria-label={props['aria-label'] ?? searchLabel} aria-keyshortcuts="Meta+K Control+K" onclick={handleClick}
|
|
27
30
|
onpointerenter={event => { onpointerenter?.(event); prefetchSearch() }}
|
|
28
31
|
onfocus={event => { onfocus?.(event); prefetchSearch() }}>
|
|
29
32
|
{#if children}
|
|
@@ -31,6 +34,6 @@
|
|
|
31
34
|
{:else}
|
|
32
35
|
<IconSearch aria-hidden="true" stroke={1.5} />
|
|
33
36
|
{searchText}
|
|
34
|
-
<span class="
|
|
37
|
+
<span class="kbd" aria-hidden="true">⌘K</span>
|
|
35
38
|
{/if}
|
|
36
39
|
</button>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Component } from 'svelte'
|
|
3
|
-
import { openSearchEvent, prefetchSearchEvent } from '../contexts/search'
|
|
3
|
+
import { openSearchEvent, prefetchSearchEvent, consumeSearchRequest } from '../contexts/search'
|
|
4
4
|
// A client-only chunk delivers no CSS of its own: link the panel's compiled styles explicitly.
|
|
5
5
|
import searchStyles from '../../styles/docs-shell/documentation-search.css?url&no-inline'
|
|
6
6
|
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
async function request(event: Event) {
|
|
36
|
+
consumeSearchRequest()
|
|
36
37
|
const trigger = (event as CustomEvent<{ trigger?: HTMLElement }>).detail?.trigger
|
|
37
38
|
initialTrigger = trigger instanceof HTMLElement ? trigger : document.activeElement as HTMLElement | null
|
|
38
39
|
Panel = await load()
|
|
@@ -50,6 +51,8 @@
|
|
|
50
51
|
const prefetch = () => void load()
|
|
51
52
|
window.addEventListener(openSearchEvent, request)
|
|
52
53
|
window.addEventListener(prefetchSearchEvent, prefetch)
|
|
54
|
+
const pending = consumeSearchRequest()
|
|
55
|
+
if (pending) void request(new CustomEvent(openSearchEvent, { detail: pending }))
|
|
53
56
|
return () => {
|
|
54
57
|
window.removeEventListener(openSearchEvent, request)
|
|
55
58
|
window.removeEventListener(prefetchSearchEvent, prefetch)
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
import Link from './Link.svelte'
|
|
29
29
|
import { getSite } from '../site'
|
|
30
30
|
import { createDocumentationSearch } from '../utils/documentation-search'
|
|
31
|
-
import { openSearchEvent } from '../contexts/search'
|
|
31
|
+
import { openSearchEvent, consumeSearchRequest } from '../contexts/search'
|
|
32
32
|
import IconArrowDown from '@tabler/icons-svelte-runes/icons/arrow-down'
|
|
33
33
|
import IconArrowUp from '@tabler/icons-svelte-runes/icons/arrow-up'
|
|
34
34
|
import IconCornerDownLeft from '@tabler/icons-svelte-runes/icons/corner-down-left'
|
|
@@ -112,7 +112,7 @@
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
$effect(() => {
|
|
115
|
-
const request = (event: Event) => open((event as CustomEvent<{ trigger?: HTMLElement }>).detail?.trigger)
|
|
115
|
+
const request = (event: Event) => { consumeSearchRequest(); open((event as CustomEvent<{ trigger?: HTMLElement }>).detail?.trigger) }
|
|
116
116
|
window.addEventListener(openSearchEvent, request)
|
|
117
117
|
return () => window.removeEventListener(openSearchEvent, request)
|
|
118
118
|
})
|
|
@@ -150,21 +150,21 @@
|
|
|
150
150
|
{/snippet}
|
|
151
151
|
|
|
152
152
|
{#if opened}
|
|
153
|
-
<dialog bind:this={dialog} {@attach portal} {@attach closeOnBackdropClick} class="ui-dialog" data-variant="search" aria-label={t('Search documentation')} oncancel={close}>
|
|
153
|
+
<dialog bind:this={dialog} {@attach portal} {@attach closeOnBackdropClick} class="dialog ui-dialog" data-variant="search" aria-label={t('Search documentation')} oncancel={close}>
|
|
154
154
|
<div class="ui-dialog-search">
|
|
155
155
|
<IconSearch size={18} stroke={1.5} aria-hidden="true" />
|
|
156
156
|
<input bind:this={input} type="search" role="combobox" aria-autocomplete="list" aria-expanded={Boolean(query)} value={query} autocomplete="off" spellcheck={false} placeholder={t('Search documentation…')} aria-label={t('Search documentation')} aria-controls="documentation-search-results" aria-activedescendant={results[selected] ? `documentation-result-${selected}` : undefined}
|
|
157
157
|
oninput={event => selectQuery(event.currentTarget.value)}
|
|
158
158
|
{onkeydown} />
|
|
159
|
-
{#if query}<button type="button" class="
|
|
160
|
-
<button type="button" class="
|
|
159
|
+
{#if query}<button type="button" class="btn btn-sm btn-quiet btn-square" data-variant="quiet" data-shape="icon" data-size="sm" onclick={() => selectQuery('')} aria-label={t('Clear search')}><IconX size={16} stroke={1.5} aria-hidden="true" /></button>{/if}
|
|
160
|
+
<button type="button" class="btn ui-dialog-close btn-sm btn-quiet" data-variant="quiet" data-size="sm" onclick={close} aria-label={t('Close search')}><span class="kbd">esc</span><span>{t('Cancel')}</span></button>
|
|
161
161
|
</div>
|
|
162
162
|
<div class="ui-dialog-body" bind:this={scroll}>
|
|
163
163
|
<p class="ui-dialog-status" role="status">{loading ? (t('Loading documentation…')) : error ? (t('Search could not load.')) : query ? t(results.length === 40 ? 'Top {count} results' : '{count} results').replace('{count}', String(results.length)) : (t('Find a name, alias or CSS property'))}</p>
|
|
164
|
-
{#if error}<div class="ui-dialog-note"><p>{t('Check your connection and try again.')}</p><button type="button" class="
|
|
164
|
+
{#if error}<div class="ui-dialog-note"><p>{t('Check your connection and try again.')}</p><button type="button" class="btn btn-sm" data-size="sm" onclick={() => { retry += 1; input?.focus() }}>{t('Try again')}</button></div>{/if}
|
|
165
165
|
{#if !query && !error && !loading}<div class="ui-dialog-note">
|
|
166
166
|
<p>{t('Try searching')}</p>
|
|
167
|
-
{#each ['padding', 'padding-inline-start:', 'fg-red:hover@sm'] as value (value)}<button type="button" class="
|
|
167
|
+
{#each ['padding', 'padding-inline-start:', 'fg-red:hover@sm'] as value (value)}<button type="button" class="btn btn-sm" data-size="sm" onclick={() => selectQuery(value)}><code>{value}</code><IconCornerDownLeft size={14} stroke={1.5} aria-hidden="true" /></button>{/each}
|
|
168
168
|
</div>{/if}
|
|
169
169
|
{#if query && !results.length && !error && !loading}<div class="ui-dialog-note" data-align="center"><IconSearch size={24} stroke={1.25} aria-hidden="true" /><b>{t('No matching documents')}</b><p>{t('Try a property name, a token name or a different keyword.')}</p></div>{/if}
|
|
170
170
|
<ol id="documentation-search-results" class="ui-results" role="listbox" aria-label={t('Search results')} aria-busy={loading}>
|
|
@@ -177,6 +177,6 @@
|
|
|
177
177
|
</li>{/each}{/if}
|
|
178
178
|
</ol>
|
|
179
179
|
</div>
|
|
180
|
-
<div class="ui-dialog-foot" aria-hidden="true"><span><span class="
|
|
180
|
+
<div class="ui-dialog-foot" aria-hidden="true"><span><span class="kbd"><IconArrowUp size={12} /></span><span class="kbd"><IconArrowDown size={12} /></span>{t('Navigate')}</span><span><span class="kbd"><IconCornerDownLeft size={12} /></span>{t('Open')}</span><span class="ui-search-shortcut">{t('Search anytime')}<kbd class="kbd">{shortcutModifier}</kbd><kbd class="kbd">K</kbd></span></div>
|
|
181
181
|
</dialog>
|
|
182
182
|
{/if}
|
|
@@ -35,8 +35,9 @@
|
|
|
35
35
|
|
|
36
36
|
{#if names.length}
|
|
37
37
|
<div class="segment-views">
|
|
38
|
-
<div class="
|
|
38
|
+
<div class="segmented" role="tablist" aria-label={label}>
|
|
39
39
|
{#each names as name, index (name)}<button
|
|
40
|
+
class="segmented-item"
|
|
40
41
|
bind:this={buttons[index]}
|
|
41
42
|
type="button"
|
|
42
43
|
id={`${prefix}-tab-${index}`}
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
type Props = Omit<HTMLSelectAttributes, 'value' | 'onchange'>
|
|
10
10
|
|
|
11
|
-
/** A native select; by default invisible over its positioned label (`
|
|
11
|
+
/** A native select; by default invisible over its positioned label (`select[data-variant="overlay"]`), which shows the value. */
|
|
12
12
|
let { class: className, ...props }: Props = $props()
|
|
13
13
|
const themeMode = useThemeMode()
|
|
14
14
|
const { t } = getSite()
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
|
-
<select data-variant="overlay" {...props} class={clsx('
|
|
17
|
+
<select data-variant="overlay" {...props} class={clsx('select site-select-overlay', className)} value={themeMode.preference}
|
|
18
18
|
onchange={(event) => { themeMode.preference = event.currentTarget.value }}>
|
|
19
19
|
<option value="light">{t('Light')}</option>
|
|
20
20
|
<option value="dark">{t('Dark')}</option>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
import '@master/internal-site/styles/system/table.
|
|
2
|
+
import '@master/internal-site/styles/system/table.ts'
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
<div class="ui-table">
|
|
6
|
-
<table {...Astro.props}><slot /></table>
|
|
5
|
+
<div class="ui-table sheet sheet-flat">
|
|
6
|
+
<table class="table" {...Astro.props}><slot /></table>
|
|
7
7
|
</div>
|
|
@@ -11,6 +11,9 @@ import Anchor from './markdown/Anchor.astro'
|
|
|
11
11
|
import Heading2 from './markdown/Heading2.astro'
|
|
12
12
|
import Heading3 from './markdown/Heading3.astro'
|
|
13
13
|
import Table from './markdown/Table.astro'
|
|
14
|
+
import TableHead from './markdown/TableHead.astro'
|
|
15
|
+
import TableCell from './markdown/TableCell.astro'
|
|
16
|
+
import TableRow from './markdown/TableRow.astro'
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* How Markdown renders in MDX. Every MDX module exports these as `components` (see
|
|
@@ -24,6 +27,9 @@ export const markdownComponents = {
|
|
|
24
27
|
img: Image,
|
|
25
28
|
Image,
|
|
26
29
|
table: Table,
|
|
30
|
+
th: TableHead,
|
|
31
|
+
td: TableCell,
|
|
32
|
+
tr: TableRow,
|
|
27
33
|
Code,
|
|
28
34
|
InlineCode,
|
|
29
35
|
PMAction,
|
|
@@ -4,9 +4,19 @@ export const openSearchEvent = 'site-search:open'
|
|
|
4
4
|
/** Signals likely intent, so the dialog can load its panel and styles before the first opening. */
|
|
5
5
|
export const prefetchSearchEvent = 'site-search:prefetch'
|
|
6
6
|
|
|
7
|
+
// A hydrated trigger can precede the dialog island. Keep only its latest unconsumed request.
|
|
8
|
+
// This is written only by a browser interaction, never during SSR.
|
|
9
|
+
let pendingOpen: { trigger?: HTMLElement } | undefined
|
|
10
|
+
export function consumeSearchRequest() {
|
|
11
|
+
const request = pendingOpen
|
|
12
|
+
pendingOpen = undefined
|
|
13
|
+
return request
|
|
14
|
+
}
|
|
15
|
+
|
|
7
16
|
/** Search triggers live in independent islands; they open the page's single dialog by event. */
|
|
8
17
|
export function openSearch(trigger?: HTMLElement) {
|
|
9
|
-
|
|
18
|
+
pendingOpen = { trigger }
|
|
19
|
+
window.dispatchEvent(new CustomEvent(openSearchEvent, { detail: pendingOpen }))
|
|
10
20
|
}
|
|
11
21
|
|
|
12
22
|
/** Search triggers call this on pointer or focus intent; the dialog loads once. */
|
|
@@ -43,6 +43,7 @@ export function useThemeMode() {
|
|
|
43
43
|
const update = () => {
|
|
44
44
|
snapshot.preference = instance.preference
|
|
45
45
|
snapshot.value = instance.value
|
|
46
|
+
if (instance.value) document.documentElement.dataset.theme = instance.value
|
|
46
47
|
}
|
|
47
48
|
update()
|
|
48
49
|
document.documentElement.addEventListener('themeModeChange', update)
|