@master/internal-site 0.2.6 → 0.2.7

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.
Files changed (112) hide show
  1. package/README.md +1 -1
  2. package/dist/astro.mjs +9 -1
  3. package/package.json +3 -2
  4. package/src/benchmarks/BenchmarkChart.astro +8 -8
  5. package/src/benchmarks/BenchmarkDelta.astro +2 -3
  6. package/src/benchmarks/BenchmarkFigure.astro +1 -1
  7. package/src/benchmarks/BenchmarkMetricTable.astro +10 -10
  8. package/src/benchmarks/BenchmarkScrollRegion.svelte +2 -2
  9. package/src/benchmarks/BenchmarkStatus.astro +2 -3
  10. package/src/benchmarks/utils.ts +1 -9
  11. package/src/css/NamespaceUtilityTable.astro +11 -11
  12. package/src/css/ThemeNumberVariableTable.astro +14 -14
  13. package/src/demo/Demo.svelte +2 -2
  14. package/src/demo/DemoAsset.astro +3 -3
  15. package/src/demo/DemoBadge.svelte +3 -3
  16. package/src/demo/DemoContainer.svelte +2 -2
  17. package/src/demo/DemoControls.svelte +1 -1
  18. package/src/demo/DemoCopyButton.svelte +1 -1
  19. package/src/demo/DemoFeatureSupport.svelte +3 -4
  20. package/src/demo/DemoIndex.astro +1 -1
  21. package/src/demo/DemoMotion.svelte +2 -2
  22. package/src/demo/DemoSurface.svelte +2 -2
  23. package/src/demo/DemoTokenTable.astro +6 -6
  24. package/src/demo/DemoViewport.svelte +11 -11
  25. package/src/demo/foundations/FoundationDialog.astro +1 -1
  26. package/src/demo/foundations/FoundationMedia.astro +2 -2
  27. package/src/demo/foundations/FoundationShrink.astro +2 -2
  28. package/src/demo/foundations/Palette.svelte +1 -1
  29. package/src/demo/reference/document.ts +3 -2
  30. package/src/docs-shell/common/locales.js +1 -1
  31. package/src/docs-shell/components/CodeCopyButton.astro +1 -1
  32. package/src/docs-shell/components/DocHeader.svelte +3 -3
  33. package/src/docs-shell/components/DocMenuButton.svelte +4 -5
  34. package/src/docs-shell/components/DocVersionSelect.svelte +2 -2
  35. package/src/docs-shell/components/DocumentCodeExampleView.astro +2 -2
  36. package/src/docs-shell/components/DocumentCodeTable.astro +5 -5
  37. package/src/docs-shell/components/DocumentCopyButton.svelte +1 -1
  38. package/src/docs-shell/components/DocumentFileTree.astro +2 -2
  39. package/src/docs-shell/components/DocumentFlow.astro +2 -2
  40. package/src/docs-shell/components/DocumentIllustration.astro +2 -2
  41. package/src/docs-shell/components/DocumentNamespaceTable.astro +6 -6
  42. package/src/docs-shell/components/DocumentParameters.astro +2 -2
  43. package/src/docs-shell/components/ExpandContent.svelte +1 -1
  44. package/src/docs-shell/components/LanguageButton.svelte +2 -2
  45. package/src/docs-shell/components/LanguageSelect.svelte +2 -2
  46. package/src/docs-shell/components/NotFound.astro +1 -1
  47. package/src/docs-shell/components/PageNavs.astro +4 -4
  48. package/src/docs-shell/components/SearchButton.svelte +1 -1
  49. package/src/docs-shell/components/SearchDialog.svelte +4 -1
  50. package/src/docs-shell/components/SearchDialogPanel.svelte +8 -8
  51. package/src/docs-shell/components/Segments.svelte +2 -1
  52. package/src/docs-shell/components/ThemeSelect.svelte +2 -2
  53. package/src/docs-shell/components/markdown/Table.astro +3 -3
  54. package/src/docs-shell/components/markdown/TableCell.astro +4 -0
  55. package/src/docs-shell/components/markdown/TableHead.astro +4 -0
  56. package/src/docs-shell/components/markdown/TableRow.astro +4 -0
  57. package/src/docs-shell/components/markdown-components.ts +6 -0
  58. package/src/docs-shell/contexts/search.ts +11 -1
  59. package/src/docs-shell/contexts/theme-mode.svelte.ts +1 -0
  60. package/src/docs-shell/data/legacy-design-routes.json +176 -0
  61. package/src/docs-shell/remark/markdown-components.js +2 -2
  62. package/src/docs-shell/utils/snackbar.ts +1 -1
  63. package/src/examples/article-transitions/page.astro +0 -1
  64. package/src/examples/components/ArticleTransitionScene.svelte +4 -4
  65. package/src/examples/components/ViewTransitionScene.svelte +1 -1
  66. package/src/examples/view-transitions/page.astro +0 -1
  67. package/src/layouts/Document.astro +1 -0
  68. package/src/scripts/legacy-design-routes.ts +76 -0
  69. package/src/scripts/style-delivery.mjs +22 -2
  70. package/src/sections/document.astro +1 -1
  71. package/src/styles/docs-shell/documentation-search.css +6 -5
  72. package/src/styles/docs-shell/materials.css +10 -22
  73. package/src/styles/docs-shell/menu.css +8 -8
  74. package/src/styles/docs-shell/segments.css +2 -2
  75. package/src/styles/docs-shell/theme.css +2 -17
  76. package/src/styles/foundation.css +1 -0
  77. package/src/styles/site-contract.md +31 -0
  78. package/src/styles/system/badge-tones.css +4 -0
  79. package/src/styles/system/badge.ts +2 -0
  80. package/src/styles/system/browser.css +3 -6
  81. package/src/styles/system/button-feedback.css +6 -9
  82. package/src/styles/system/buttons.css +1 -51
  83. package/src/styles/system/checks.css +4 -18
  84. package/src/styles/system/controls.css +0 -1
  85. package/src/styles/system/dialog.css +3 -3
  86. package/src/styles/system/expand.css +3 -3
  87. package/src/styles/system/fields.css +7 -23
  88. package/src/styles/system/header-core.css +10 -10
  89. package/src/styles/system/kbd.css +1 -4
  90. package/src/styles/system/mixins.css +2 -2
  91. package/src/styles/system/pager.css +2 -13
  92. package/src/styles/system/range.css +1 -12
  93. package/src/styles/system/search-trigger.css +2 -2
  94. package/src/styles/system/segmented.css +1 -16
  95. package/src/styles/system/sheet.css +1 -8
  96. package/src/styles/system/sheet.ts +2 -0
  97. package/src/styles/system/sidebar.css +1 -1
  98. package/src/styles/system/specimens.css +5 -17
  99. package/src/styles/system/surfaces.css +0 -1
  100. package/src/styles/system/table-layout.css +12 -0
  101. package/src/styles/system/table.css +3 -23
  102. package/src/styles/system/table.ts +4 -0
  103. package/src/styles/system/tokens.css +48 -63
  104. package/src/styles/system/tooltip.css +2 -4
  105. package/src/styles/system/tray-layout.css +20 -0
  106. package/src/styles/system/tray.css +2 -20
  107. package/src/styles/system/tray.ts +3 -0
  108. package/src/demo/DemoScrollArea.svelte +0 -17
  109. package/src/examples/scene.css +0 -3
  110. package/src/styles/system/DESIGN.md +0 -128
  111. package/src/styles/system/menu.css +0 -14
  112. 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 = () => ['mixins.css', 'buttons.css'].map(file => readFileSync(fileURLToPath(import.meta.resolve(`@master/internal-site/styles/system/${file}`)), 'utf8')).join('\n')
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', 'design-system'],
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="ui-button" data-variant="quiet" data-shape="icon" data-size="sm" aria-label={label} title={label} data-code-copy={name ?? ''} data-code-copy-text={text}>
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="ui-kbd" aria-hidden="true">⌘K</kbd>
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="ui-button ui-header-control"
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'
@@ -115,20 +114,20 @@
115
114
  <IconMenu class="ui-menu-glyph" size={18} stroke={1.5} data-open={opened} aria-hidden="true" />
116
115
  {/snippet}
117
116
 
118
- <button bind:this={trigger} type="button" class={clsx('ui-button ui-menu-toggle', className)} data-variant="quiet" data-shape="icon"
117
+ <button bind:this={trigger} type="button" class={clsx('btn btn-quiet btn-square ui-menu-toggle', className)} data-variant="quiet" data-shape="icon"
119
118
  aria-label={t('Menu')} aria-expanded={opened} aria-haspopup="dialog" aria-controls={id} onclick={open}>
120
119
  {@render lines()}
121
120
  </button>
122
- <dialog bind:this={dialog} {@attach portal} {id} class="ui-dialog ui-mobile-menu" data-variant="sheet" data-open={opened}
121
+ <dialog bind:this={dialog} {@attach portal} {id} class="ui-mobile-menu" data-variant="sheet" data-open={opened}
123
122
  aria-labelledby={`${id}-title`} oncancel={event => { event.preventDefault(); close() }} ontransitionend={transitionEnd}
124
123
  onkeydown={keydown} onclose={() => { if (!dialog.open) { opened = false; clearTimeout(closing) } }}>
125
124
  <div class="ui-mobile-menu-bar">
126
- <button type="button" class="ui-button ui-header-control ui-menu-toggle" data-variant="quiet" data-shape="icon"
125
+ <button type="button" class="btn ui-header-control ui-menu-toggle btn-quiet btn-square" data-variant="quiet" data-shape="icon"
127
126
  onclick={() => opened ? close() : open()} aria-label={opened ? t('Close menu') : t('Menu')} aria-expanded={opened} aria-controls={id}>
128
127
  {@render lines()}
129
128
  </button>
130
129
  <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="ui-button ui-header-control ui-menu-search" data-variant="quiet" data-shape="icon" onclick={search}><IconSearch size={18} stroke={1.5} aria-hidden="true" /></SearchButton>
130
+ <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
131
  </div>
133
132
  <div class="ui-mobile-menu-body">
134
133
  <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 (`ui-select[data-variant="overlay"]`), which shows the value. */
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('ui-select', className)}
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.css'
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.css'
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="ui-button" data-size="sm" disabled={!ready} aria-label={`Copy ${label}`} onclick={copy}>
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.css'
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.css'
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.css'
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.css'
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/internal-site/styles/system/specimens.css'
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="ui-badge" data-size="sm">{parameter.requirement}</span>
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="ui-button" data-size="sm" aria-expanded={expanded} aria-controls={id} onclick={() => { expanded = !expanded }}>
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('ui-button', className)} data-variant="quiet" data-shape="icon" data-size="sm">
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 (`ui-select[data-variant="overlay"]`), which shows the value. */
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('ui-select', className)}
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="ui-button" data-variant="quiet">{guide ? $('Browse the Guide') : $('Back to home')}<span aria-hidden="true">→</span></Link>
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
  )}
@@ -31,6 +31,6 @@
31
31
  {:else}
32
32
  <IconSearch aria-hidden="true" stroke={1.5} />
33
33
  {searchText}
34
- <span class="ui-kbd" aria-hidden="true">⌘K</span>
34
+ <span class="kbd" aria-hidden="true">⌘K</span>
35
35
  {/if}
36
36
  </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="ui-button" 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="ui-button ui-dialog-close" data-variant="quiet" data-size="sm" onclick={close} aria-label={t('Close search')}><span class="ui-kbd">esc</span><span>{t('Cancel')}</span></button>
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="ui-button" data-size="sm" onclick={() => { retry += 1; input?.focus() }}>{t('Try again')}</button></div>{/if}
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="ui-button" data-size="sm" onclick={() => selectQuery(value)}><code>{value}</code><IconCornerDownLeft size={14} stroke={1.5} aria-hidden="true" /></button>{/each}
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="ui-kbd"><IconArrowUp size={12} /></span><span class="ui-kbd"><IconArrowDown size={12} /></span>{t('Navigate')}</span><span><span class="ui-kbd"><IconCornerDownLeft size={12} /></span>{t('Open')}</span><span class="ui-search-shortcut">{t('Search anytime')}<kbd class="ui-kbd">{shortcutModifier}</kbd><kbd class="ui-kbd">K</kbd></span></div>
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="ui-segmented" role="tablist" aria-label={label}>
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 (`ui-select[data-variant="overlay"]`), which shows the value. */
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('ui-select', className)} value={themeMode.preference}
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.css'
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>
@@ -0,0 +1,4 @@
1
+ ---
2
+ const { class: className, ...props } = Astro.props
3
+ ---
4
+ <td {...props} class:list={['table-cell', className]}><slot /></td>
@@ -0,0 +1,4 @@
1
+ ---
2
+ const { class: className, ...props } = Astro.props
3
+ ---
4
+ <th {...props} class:list={['table-heading', className]}><slot /></th>
@@ -0,0 +1,4 @@
1
+ ---
2
+ const { class: className, ...props } = Astro.props
3
+ ---
4
+ <tr {...props} class:list={['table-row', className]}><slot /></tr>
@@ -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
- window.dispatchEvent(new CustomEvent(openSearchEvent, { detail: { trigger } }))
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)