@master/internal-site 0.2.7 → 0.2.9

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 (119) hide show
  1. package/dist/astro.mjs +2 -1
  2. package/package.json +2 -2
  3. package/src/benchmarks/BenchmarkBars.astro +2 -1
  4. package/src/benchmarks/BenchmarkChart.astro +1 -1
  5. package/src/benchmarks/BenchmarkChartGroup.astro +2 -1
  6. package/src/benchmarks/BenchmarkDataTable.astro +3 -3
  7. package/src/benchmarks/BenchmarkFigure.astro +1 -1
  8. package/src/benchmarks/BenchmarkMetrics.astro +2 -1
  9. package/src/benchmarks/BenchmarkSampleSummary.astro +2 -1
  10. package/src/benchmarks/BenchmarkStackedBars.astro +2 -1
  11. package/src/demo/Demo.svelte +2 -2
  12. package/src/demo/DemoAsset.astro +1 -1
  13. package/src/demo/DemoCatalog.astro +3 -3
  14. package/src/demo/DemoComparison.svelte +2 -2
  15. package/src/demo/DemoContainer.svelte +1 -1
  16. package/src/demo/DemoCopyButton.svelte +2 -2
  17. package/src/demo/DemoFeatureSupport.svelte +2 -2
  18. package/src/demo/DemoGeneratedCSS.svelte +2 -2
  19. package/src/demo/DemoIndex.astro +1 -1
  20. package/src/demo/DemoMotion.svelte +1 -1
  21. package/src/demo/DemoViewport.svelte +5 -5
  22. package/src/demo/DemoWaterfall.astro +2 -1
  23. package/src/demo/foundations/FoundationDialog.astro +1 -1
  24. package/src/docs-shell/components/ArticleHeader.astro +2 -2
  25. package/src/docs-shell/components/Callout.astro +5 -4
  26. package/src/docs-shell/components/CodeCopyButton.astro +3 -3
  27. package/src/docs-shell/components/CodeTabBar.astro +7 -6
  28. package/src/docs-shell/components/CodeTabs.astro +4 -4
  29. package/src/docs-shell/components/CodeView.astro +2 -2
  30. package/src/docs-shell/components/DocHeader.svelte +5 -4
  31. package/src/docs-shell/components/DocMenuButton.svelte +4 -2
  32. package/src/docs-shell/components/DocumentAPIIndex.astro +4 -4
  33. package/src/docs-shell/components/DocumentChoices.astro +4 -4
  34. package/src/docs-shell/components/DocumentCodeExampleView.astro +5 -5
  35. package/src/docs-shell/components/DocumentCopyButton.svelte +2 -2
  36. package/src/docs-shell/components/DocumentDisclosure.astro +3 -3
  37. package/src/docs-shell/components/DocumentFileTree.astro +2 -1
  38. package/src/docs-shell/components/DocumentFlow.astro +2 -2
  39. package/src/docs-shell/components/DocumentIllustration.astro +4 -4
  40. package/src/docs-shell/components/DocumentKeyList.astro +3 -3
  41. package/src/docs-shell/components/DocumentOptionList.astro +2 -2
  42. package/src/docs-shell/components/DocumentParameters.astro +2 -2
  43. package/src/docs-shell/components/DocumentPrompt.astro +3 -3
  44. package/src/docs-shell/components/DocumentValueList.astro +3 -3
  45. package/src/docs-shell/components/DocumentationIndex.svelte +3 -3
  46. package/src/docs-shell/components/ExpandContent.svelte +2 -2
  47. package/src/docs-shell/components/ExplorerView.astro +3 -2
  48. package/src/docs-shell/components/GeneratedCSS.astro +3 -3
  49. package/src/docs-shell/components/InlineCode.astro +4 -3
  50. package/src/docs-shell/components/LanguageButton.svelte +1 -1
  51. package/src/docs-shell/components/NotFound.astro +1 -1
  52. package/src/docs-shell/components/PMAction.astro +1 -1
  53. package/src/docs-shell/components/PageContentDisclosure.astro +3 -3
  54. package/src/docs-shell/components/SearchButton.svelte +9 -7
  55. package/src/docs-shell/components/SearchDialogPanel.svelte +15 -14
  56. package/src/docs-shell/components/Tab.astro +2 -2
  57. package/src/docs-shell/components/Tabs.astro +2 -2
  58. package/src/docs-shell/remark/markdown-components.js +1 -1
  59. package/src/docs-shell/utils/documentation-search.ts +11 -1
  60. package/src/docs-shell/utils/highlight-code-core.ts +2 -2
  61. package/src/examples/components/ArticleTransitionScene.svelte +3 -3
  62. package/src/styles/blog-article.css +3 -1
  63. package/src/styles/demo.css +0 -3
  64. package/src/styles/docs-shell/documentation-search.css +4 -11
  65. package/src/styles/docs-shell/footer.css +2 -2
  66. package/src/styles/docs-shell/menu.css +1 -1
  67. package/src/styles/docs-shell/prose.css +0 -1
  68. package/src/styles/documentation-illustration.css +3 -3
  69. package/src/styles/documentation-index.css +0 -2
  70. package/src/styles/interface.css +0 -1
  71. package/src/styles/interface.ts +2 -1
  72. package/src/styles/site-contract.md +3 -3
  73. package/src/styles/system/browser.css +0 -1
  74. package/src/styles/system/buttons.ts +2 -0
  75. package/src/styles/system/callout.css +4 -12
  76. package/src/styles/system/callout.ts +4 -0
  77. package/src/styles/system/chart.css +1 -1
  78. package/src/styles/system/code-panel.css +23 -65
  79. package/src/styles/system/code-panel.ts +2 -0
  80. package/src/styles/system/code-tabs.css +4 -32
  81. package/src/styles/system/code-tabs.ts +2 -0
  82. package/src/styles/system/code-ui.ts +2 -0
  83. package/src/styles/system/copy.css +2 -24
  84. package/src/styles/system/dialog.css +10 -11
  85. package/src/styles/system/disclosure.css +3 -13
  86. package/src/styles/system/disclosure.ts +2 -0
  87. package/src/styles/system/header-core.css +8 -17
  88. package/src/styles/system/index.css +3 -7
  89. package/src/styles/system/index.ts +3 -0
  90. package/src/styles/system/inline-code.css +2 -2
  91. package/src/styles/system/inline-code.ts +2 -0
  92. package/src/styles/system/logos.css +1 -1
  93. package/src/styles/system/metrics.css +1 -1
  94. package/src/styles/system/parameters.css +2 -3
  95. package/src/styles/system/parameters.ts +4 -0
  96. package/src/styles/system/prompt.css +3 -5
  97. package/src/styles/system/reading.css +2 -4
  98. package/src/styles/system/search-trigger.css +2 -7
  99. package/src/styles/system/segmented.css +0 -6
  100. package/src/styles/system/sidebar.css +1 -1
  101. package/src/styles/system/stage.css +6 -12
  102. package/src/styles/system/stage.ts +2 -0
  103. package/src/styles/system/steps.css +1 -2
  104. package/src/styles/system/tabs.ts +1 -0
  105. package/src/styles/system/toc.css +3 -3
  106. package/src/styles/system/tray-code.css +2 -4
  107. package/src/styles/system/tray-layout.css +5 -5
  108. package/src/styles/system/tree.css +1 -1
  109. package/src/styles/system/waterfall.css +1 -1
  110. package/src/styles/docs-shell/code.css +0 -5
  111. package/src/styles/system/buttons.css +0 -1
  112. package/src/styles/system/code.css +0 -8
  113. package/src/styles/system/controls.css +0 -10
  114. package/src/styles/system/data.css +0 -10
  115. package/src/styles/system/sheet.css +0 -1
  116. package/src/styles/system/shell.css +0 -8
  117. package/src/styles/system/surfaces.css +0 -7
  118. package/src/styles/system/table.css +0 -3
  119. package/src/styles/system/tray.css +0 -2
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import '@master/internal-site/styles/interface.css'
2
+ import '@master/internal-site/styles/interface.ts'
3
3
  import '@master/internal-site/styles/system/copy.css'
4
4
 
5
5
  import { onMount } from 'svelte'
@@ -35,7 +35,7 @@
35
35
 
36
36
  <span class="ui-copy">
37
37
  <button type="button" class="btn btn-sm" data-size="sm" disabled={!ready} aria-label={`Copy ${label}`} onclick={copy}>
38
- {#if result === 'success'}<IconCheck stroke={1.8} aria-hidden="true" />{:else}<IconCopy stroke={1.8} aria-hidden="true" />{/if}
38
+ {#if result === 'success'}<IconCheck class="icon" stroke={1.8} aria-hidden="true" />{:else}<IconCopy class="icon" stroke={1.8} aria-hidden="true" />{/if}
39
39
  Copy
40
40
  </button>
41
41
  <span class="ui-copy-status" role="status" data-result={result}>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import '@master/internal-site/styles/documents.css'
3
- import '@master/internal-site/styles/system/disclosure.css'
3
+ import '@master/internal-site/styles/system/disclosure.ts'
4
4
  interface Props {
5
5
  title: string
6
6
  open?: boolean
@@ -10,7 +10,7 @@ interface Props {
10
10
  const { title, open = false } = Astro.props
11
11
  ---
12
12
 
13
- <details class="ui-disclosure" data-variant="rule" open={open}>
14
- <summary>{title}</summary>
13
+ <details class="accordion-item ui-disclosure" data-variant="rule" open={open}>
14
+ <summary class="accordion-trigger">{title}</summary>
15
15
  <div class="ui-disclosure-body ui-prose"><slot /></div>
16
16
  </details>
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import '@master/internal-site/styles/system/sheet.ts'
2
3
  import '@master/internal-site/styles/system/tray.ts'
3
4
  import '@master/internal-site/styles/system/tray-code.css'
4
5
  import '@master/internal-site/styles/system/tree.css'
@@ -32,6 +33,6 @@ const Entries = Astro.self
32
33
  </ul>
33
34
  : <figure class="tray ui-tray" aria-label={props.title}>
34
35
  <figcaption class="ui-tray-head"><p class="ui-tray-title">{props.title}</p></figcaption>
35
- <div class="ui-tree"><Entries entries={props.entries} nested /></div>
36
+ <div class="sheet sheet-flat ui-tree"><Entries entries={props.entries} nested /></div>
36
37
  {props.caption && <p class="ui-tray-caption">{props.caption}</p>}
37
38
  </figure>}
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/stage.css'
2
+ import '@master/internal-site/styles/system/stage.ts'
3
3
  import '@master/internal-site/styles/system/steps.css'
4
4
  import '@master/internal-site/styles/system/tray.ts'
5
5
  import '@master/internal-site/styles/system/tray-code.css'
@@ -15,7 +15,7 @@ const { title, steps, caption } = Astro.props
15
15
 
16
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
- <div class="ui-stage" data-padding="sm" data-align="start">
18
+ <div class="sheet sheet-flat ui-stage" data-padding="sm" data-align="start">
19
19
  {/* Preserve WebKit list semantics when list-style is none. */}
20
20
  <ol class="ui-steps" role="list">
21
21
  {steps.map(step => <li>
@@ -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/disclosure.css'
4
+ import '@master/internal-site/styles/system/disclosure.ts'
5
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'
@@ -25,7 +25,7 @@ const { title, alt, images, caption } = Astro.props
25
25
  <figcaption class="ui-tray-head">
26
26
  <p class="ui-tray-title">{title}</p>
27
27
  </figcaption>
28
- <div class="document-illustration" role="img" aria-label={alt}>
28
+ <div class="sheet sheet-flat document-illustration" role="img" aria-label={alt}>
29
29
  {(['light', 'dark'] as const).map(scheme => <Image
30
30
  src={images[scheme]}
31
31
  data-scheme={scheme}
@@ -35,8 +35,8 @@ const { title, alt, images, caption } = Astro.props
35
35
  />)}
36
36
  </div>
37
37
  <p class="ui-tray-caption">{caption}</p>
38
- <details class="ui-disclosure" data-variant="text-description">
39
- <summary>{t('Text description')}</summary>
38
+ <details class="accordion-item ui-disclosure" data-variant="text-description">
39
+ <summary class="accordion-trigger">{t('Text description')}</summary>
40
40
  <div class="ui-disclosure-body ui-tray-caption"><slot /></div>
41
41
  </details>
42
42
  </figure>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/disclosure.css'
2
+ import '@master/internal-site/styles/system/disclosure.ts'
3
3
  import { siteOf } from '../../astro/site-context'
4
4
  const { t } = siteOf(Astro)
5
5
 
@@ -16,8 +16,8 @@ const lists = [keys.slice(0, previewCount), keys.slice(previewCount)]
16
16
  <ul aria-label={t('Utility keys')}>
17
17
  {lists[0].map(key => <li><code>{key}</code></li>)}
18
18
  </ul>
19
- {keys.length > previewCount && <details class="ui-disclosure">
20
- <summary>{t('Show {count} more keys').replace('{count}', String(keys.length - previewCount))}</summary>
19
+ {keys.length > previewCount && <details class="accordion-item ui-disclosure">
20
+ <summary class="accordion-trigger">{t('Show {count} more keys').replace('{count}', String(keys.length - previewCount))}</summary>
21
21
  <ul aria-label={t('Utility keys')}>
22
22
  {lists[1].map(key => <li><code>{key}</code></li>)}
23
23
  </ul>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/parameters.css'
2
+ import '@master/internal-site/styles/system/parameters.ts'
3
3
 
4
4
  interface Props {
5
5
  label: string
@@ -8,4 +8,4 @@ interface Props {
8
8
  const { label } = Astro.props
9
9
  ---
10
10
 
11
- <dl class="ui-params" aria-label={label}><slot /></dl>
11
+ <dl class="sheet sheet-flat ui-params" aria-label={label}><slot /></dl>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/parameters.css'
2
+ import '@master/internal-site/styles/system/parameters.ts'
3
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'
@@ -16,7 +16,7 @@ interface Props {
16
16
  const { label, parameters } = Astro.props
17
17
  ---
18
18
 
19
- <dl class="ui-params" aria-label={label}>
19
+ <dl class="sheet sheet-flat ui-params" aria-label={label}>
20
20
  {parameters.map(parameter => <div>
21
21
  <dt>
22
22
  <span><DocumentIdentifier text={parameter.name} /></span>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/code-panel.css'
2
+ import '@master/internal-site/styles/system/code-panel.ts'
3
3
  import '@master/internal-site/styles/system/prompt.css'
4
4
  import DocumentCopyButton from '@master/internal-site/components/DocumentCopyButton.svelte'
5
5
  import type { DocumentPromptProps } from '@master/internal-site/components/document-types.ts'
@@ -12,7 +12,7 @@ type Props = DocumentPromptProps
12
12
  const { title, text } = Astro.props
13
13
  ---
14
14
 
15
- <figure class="ui-prompt" aria-label={title}>
16
- <figcaption class="ui-code-bar"><span class="ui-code-file">{title}</span><DocumentCopyButton client:idle={{ timeout: 500 }} text={text} label={title} /></figcaption>
15
+ <figure class="code-panel ui-prompt" aria-label={title}>
16
+ <figcaption class="code-header ui-code-bar"><span class="code-title ui-code-file">{title}</span><DocumentCopyButton client:idle={{ timeout: 500 }} text={text} label={title} /></figcaption>
17
17
  <p class="ui-prompt-body">{text}</p>
18
18
  </figure>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/parameters.css'
2
+ import '@master/internal-site/styles/system/parameters.ts'
3
3
  import type { DocumentValueRow } from '@master/internal-site/components/document-types.ts'
4
4
 
5
5
  export type { DocumentValueRow } from '@master/internal-site/components/document-types.ts'
@@ -14,12 +14,12 @@ const { rows, headingLevel = 3 } = Astro.props
14
14
  const Heading = `h${headingLevel}` as const
15
15
  ---
16
16
 
17
- <dl class="ui-params">
17
+ <dl class="sheet sheet-flat ui-params">
18
18
  {rows.map(row => <div>
19
19
  <dt>
20
20
  <Heading id={row.id}><a href={`#${row.id}`}>{row.title}</a></Heading>
21
21
  {row.identifier && <small>{row.identifier}</small>}
22
22
  </dt>
23
- <dd>{row.values.map(({ label, value }) => <p><small>{label}</small> <code>{value}</code></p>)}</dd>
23
+ <dd>{row.values.map(({ label, value }) => <p><small>{label}</small> <code class="code">{value}</code></p>)}</dd>
24
24
  </div>)}
25
25
  </dl>
@@ -89,9 +89,9 @@
89
89
 
90
90
  <div class="documentation-index-toolbar">
91
91
  <p>{t(name === 'guide' ? 'All guides' : 'All entries')} <span class="documentation-index-count">{entries.length}</span></p>
92
- <div class="ui-segmented" data-variant="underline" role="group" aria-label={t('Index view')}>
93
- <button type="button" aria-pressed={!alphabetical} aria-controls={panelId('category')} onclick={() => alphabetical = false}>{t('By category')}</button>
94
- <button type="button" aria-pressed={alphabetical} aria-controls={panelId('alphabetical')} onclick={() => alphabetical = true}>A–Z</button>
92
+ <div class="segmented segmented-sm" role="group" aria-label={t('Index view')}>
93
+ <button class="segmented-item" type="button" aria-pressed={!alphabetical} aria-controls={panelId('category')} onclick={() => alphabetical = false}>{t('By category')}</button>
94
+ <button class="segmented-item" type="button" aria-pressed={alphabetical} aria-controls={panelId('alphabetical')} onclick={() => alphabetical = true}>A–Z</button>
95
95
  </div>
96
96
  </div>
97
97
 
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import '@master/internal-site/styles/interface.css'
2
+ import '@master/internal-site/styles/interface.ts'
3
3
  import '@master/internal-site/styles/system/expand.css'
4
4
 
5
5
  import type { Snippet } from 'svelte'
@@ -18,7 +18,7 @@
18
18
  <div class="ui-expand-control">
19
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
- <IconChevronDown aria-hidden="true" stroke={1.5} />
21
+ <IconChevronDown class="icon" aria-hidden="true" stroke={1.5} />
22
22
  </button>
23
23
  </div>
24
24
  </div>
@@ -1,4 +1,5 @@
1
1
  ---
2
+ import '@master/internal-site/styles/system/sheet.ts'
2
3
  import '@master/internal-site/styles/system/tree.css'
3
4
  import FileIcon from './FileIcon.astro'
4
5
  import FolderSvg from '../../public/icons/folder.svg'
@@ -21,7 +22,7 @@ const extOf = (name: string) => name.includes('.') ? name.split('.').pop() : ''
21
22
  ---
22
23
 
23
24
  {nested
24
- ? <ul>
25
+ ? <ul role="list">
25
26
  {items.map((option) => {
26
27
  const ext = extOf(option.name)
27
28
  return (
@@ -35,4 +36,4 @@ const extOf = (name: string) => name.includes('.') ? name.split('.').pop() : ''
35
36
  )
36
37
  })}
37
38
  </ul>
38
- : <div class="ui-tree"><Astro.self items={items} nested /></div>}
39
+ : <div class="sheet sheet-flat ui-tree"><Astro.self items={items} nested /></div>}
@@ -1,11 +1,11 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/disclosure.css'
2
+ import '@master/internal-site/styles/system/disclosure.ts'
3
3
  import { siteOf } from '../../astro/site-context'
4
4
  const { t } = siteOf(Astro)
5
5
  /** A closed native disclosure keeps the complete output in the server HTML. */
6
6
  ---
7
7
 
8
- <details class="ui-disclosure" data-generated="">
9
- <summary>{t('Generated CSS')}</summary>
8
+ <details class="accordion-item ui-disclosure" data-generated="">
9
+ <summary class="accordion-trigger">{t('Generated CSS')}</summary>
10
10
  <slot />
11
11
  </details>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/inline-code.css'
2
+ import '@master/internal-site/styles/system/inline-code.ts'
3
3
  import clsx from 'clsx'
4
4
  import { toHtml } from 'hast-util-to-html'
5
5
  import highlightCode from '../utils/highlight-code'
@@ -10,16 +10,17 @@ interface Props {
10
10
  code?: string
11
11
  lang?: string
12
12
  class?: string
13
+ plain?: boolean
13
14
  [key: string]: any
14
15
  }
15
16
 
16
17
  /** Highlighted inline code, drawn as a `ui-inline-code` chip. */
17
- const { code: source, class: className, ...props } = Astro.props
18
+ const { code: source, class: className, plain = false, ...props } = Astro.props
18
19
  const code = source ?? await slotText(Astro.slots) ?? ''
19
20
  const hast: any = await highlightCode(code, {
20
21
  inline: true,
21
22
  ...props,
22
- className: clsx('ui-inline-code', className)
23
+ className: clsx(!plain && 'code ui-inline-code', className)
23
24
  })
24
25
  // A single token (no spaces) is marked, so reading text can keep it whole rather than split it at a hyphen.
25
26
  const element = hast.children?.[0]
@@ -1,5 +1,5 @@
1
1
  <script lang="ts">
2
- import '@master/internal-site/styles/interface.css'
2
+ import '@master/internal-site/styles/interface.ts'
3
3
  import IconLanguage from '@tabler/icons-svelte-runes/icons/language'
4
4
  import LanguageSelect from './LanguageSelect.svelte'
5
5
  import clsx from 'clsx'
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/interface.css'
2
+ import '@master/internal-site/styles/interface.ts'
3
3
  import '@master/internal-site/styles/system/pagehead.css'
4
4
  import '@master/internal-site/styles/system/search-trigger.css'
5
5
  import '../../styles/docs-shell/not-found.css'
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/code-panel.css'
2
+ import '@master/internal-site/styles/system/code-panel.ts'
3
3
  import { resolveCommand } from 'package-manager-detector/commands'
4
4
  import CodeTabs from './CodeTabs.astro'
5
5
  import { slotText } from '../utils/slot-text'
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/disclosure.css'
2
+ import '@master/internal-site/styles/system/disclosure.ts'
3
3
  import '../../styles/system/toc.css'
4
4
  import type { PageContentItem } from './page-content.svelte'
5
5
  import PageContentTitle from './PageContentTitle.svelte'
@@ -15,8 +15,8 @@ interface Props {
15
15
  const { items, label, labelLang } = Astro.props
16
16
  ---
17
17
 
18
- <details class="ui-disclosure" data-variant="rule" data-contents-disclosure="">
19
- <summary lang={labelLang}>{label}</summary>
18
+ <details class="accordion-item ui-disclosure" data-variant="rule" data-contents-disclosure="">
19
+ <summary class="accordion-trigger" lang={labelLang}>{label}</summary>
20
20
  <nav class="ui-toc" aria-label={label}>
21
21
  <ol>{groupPageContent(items).map(({ item, children }) => <li>
22
22
  <a href={`#${item.id}`} lang={item.lang} data-level={item.level}><PageContentTitle title={item.title} /></a>
@@ -1,8 +1,7 @@
1
1
  <script lang="ts">
2
- import '@master/internal-site/styles/interface.css'
3
- import '@master/internal-site/styles/system/search-trigger.css'
2
+ import '@master/internal-site/styles/interface.ts'
4
3
 
5
- import type { Snippet } from 'svelte'
4
+ import { onMount, type Snippet } from 'svelte'
6
5
  import type { HTMLButtonAttributes } from 'svelte/elements'
7
6
  import IconSearch from '@tabler/icons-svelte-runes/icons/search'
8
7
  import { openSearch, prefetchSearch, searchLabels } from '../contexts/search'
@@ -12,8 +11,11 @@
12
11
  children?: Snippet
13
12
  }
14
13
 
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()
14
+ /** Opens the page's search dialog. Without children it renders the search label and shortcut; the caller owns its placement. */
15
+ let { class: className, children, onclick, onfocus, onpointerenter, type = 'button', disabled = false, ...props }: Props = $props()
16
+ // SSR must not offer an action before this island can receive it.
17
+ let mounted = $state(false)
18
+ onMount(() => { mounted = true })
17
19
  const { t, locale } = getSite()
18
20
  const { searchText, searchLabel } = searchLabels(t, locale)
19
21
 
@@ -23,13 +25,13 @@
23
25
  }
24
26
  </script>
25
27
 
26
- <button {...props} {type} class={className} aria-label={props['aria-label'] ?? searchLabel} aria-keyshortcuts="Meta+K Control+K" onclick={handleClick}
28
+ <button {...props} {type} disabled={!mounted || disabled} class={['btn', 'btn-quiet', className]} aria-label={props['aria-label'] ?? searchLabel} aria-keyshortcuts="Meta+K Control+K" onclick={handleClick}
27
29
  onpointerenter={event => { onpointerenter?.(event); prefetchSearch() }}
28
30
  onfocus={event => { onfocus?.(event); prefetchSearch() }}>
29
31
  {#if children}
30
32
  {@render children()}
31
33
  {:else}
32
- <IconSearch aria-hidden="true" stroke={1.5} />
34
+ <IconSearch class="icon" aria-hidden="true" stroke={1.5} />
33
35
  {searchText}
34
36
  <span class="kbd" aria-hidden="true">⌘K</span>
35
37
  {/if}
@@ -20,8 +20,7 @@
20
20
  </script>
21
21
 
22
22
  <script lang="ts">
23
- import '@master/internal-site/styles/interface.css'
24
- import '@master/internal-site/styles/system/dialog.css'
23
+ import '@master/internal-site/styles/interface.ts'
25
24
 
26
25
  // SearchDialog loads documentation-search.css before mounting the panel.
27
26
  import { untrack } from 'svelte'
@@ -150,13 +149,13 @@
150
149
  {/snippet}
151
150
 
152
151
  {#if opened}
153
- <dialog bind:this={dialog} {@attach portal} {@attach closeOnBackdropClick} class="dialog ui-dialog" data-variant="search" aria-label={t('Search documentation')} oncancel={close}>
154
- <div class="ui-dialog-search">
155
- <IconSearch size={18} stroke={1.5} aria-hidden="true" />
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}
152
+ <dialog bind:this={dialog} {@attach portal} {@attach closeOnBackdropClick} class="dialog command ui-dialog" data-variant="search" aria-label={t('Search documentation')} oncancel={close}>
153
+ <div class="command-search ui-dialog-search">
154
+ <IconSearch class="icon" size={18} stroke={1.5} aria-hidden="true" />
155
+ <input class="command-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
156
  oninput={event => selectQuery(event.currentTarget.value)}
158
157
  {onkeydown} />
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}
158
+ {#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 class="icon" size={16} stroke={1.5} aria-hidden="true" /></button>{/if}
160
159
  <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
160
  </div>
162
161
  <div class="ui-dialog-body" bind:this={scroll}>
@@ -164,19 +163,21 @@
164
163
  {#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
164
  {#if !query && !error && !loading}<div class="ui-dialog-note">
166
165
  <p>{t('Try searching')}</p>
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}
166
+ {#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 class="icon" size={14} stroke={1.5} aria-hidden="true" /></button>{/each}
168
167
  </div>{/if}
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
- <ol id="documentation-search-results" class="ui-results" role="listbox" aria-label={t('Search results')} aria-busy={loading}>
168
+ {#if query && !results.length && !error && !loading}<div class="ui-dialog-note" data-align="center"><IconSearch class="icon" 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}
169
+ <ol id="documentation-search-results" class="listbox command-list ui-results" role="listbox" aria-label={t('Search results')} aria-busy={loading}>
171
170
  {#if !error}{#each results as result, index (result.page.url)}<li role="presentation">
172
- <Link id={`documentation-result-${index}`} role="option" tabindex={-1} aria-selected={selected === index} href={result.href} onclick={close} onpointermove={() => { selected = index }}>
173
- <small>{t(result.page.category ?? '')} · {t(kinds[result.page.kind ?? ''] ?? (result.page.url.includes('/guide') ? 'Guide' : 'Page'))} · {t(result.reason)}</small>
171
+ <Link class="listbox-option" id={`documentation-result-${index}`} role="option" tabindex={-1} aria-selected={selected === index} href={result.href} onclick={close} onpointermove={() => { selected = index }}>
172
+ <span class="listbox-body">
173
+ <small class="listbox-description">{t(result.page.category ?? '')} · {t(kinds[result.page.kind ?? ''] ?? (result.page.url.includes('/guide') ? 'Guide' : 'Page'))} · {t(result.reason)}</small>
174
174
  <b>{result.page.title}</b>
175
- <span>{@render excerpt(result.excerpt, query)}</span>
175
+ <span class="listbox-description ui-result-excerpt">{@render excerpt(result.excerpt, query)}</span>
176
+ </span>
176
177
  </Link>
177
178
  </li>{/each}{/if}
178
179
  </ol>
179
180
  </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
+ <div class="command-footer ui-dialog-foot" aria-hidden="true"><span class="command-hint"><span class="kbd"><IconArrowUp class="icon" size={12} /></span><span class="kbd"><IconArrowDown class="icon" size={12} /></span>{t('Navigate')}</span><span class="command-hint"><span class="kbd"><IconCornerDownLeft class="icon" 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
182
  </dialog>
182
183
  {/if}
@@ -2,7 +2,7 @@
2
2
  import Link from './Link.svelte'
3
3
 
4
4
  /** One link of `Tabs`; it takes `Link`'s props. */
5
- const props = Astro.props
5
+ const { class: className, ...props } = Astro.props
6
6
  ---
7
7
 
8
- <Link {...props}><slot /></Link>
8
+ <Link {...props} class={['tabs-item', className]}><slot /></Link>
@@ -1,5 +1,5 @@
1
1
  ---
2
- import '@master/internal-site/styles/system/segmented.css'
2
+ import '@master/internal-site/styles/system/tabs.ts'
3
3
  import type { HTMLAttributes } from 'astro/types'
4
4
 
5
5
  type Props = HTMLAttributes<'nav'>
@@ -8,4 +8,4 @@ type Props = HTMLAttributes<'nav'>
8
8
  const { class: className, ...props } = Astro.props
9
9
  ---
10
10
 
11
- <nav {...props} class:list={['ui-segmented', className]} data-variant="underline"><slot /></nav>
11
+ <nav {...props} class:list={['tabs', className]}><slot /></nav>
@@ -98,7 +98,7 @@ export default function remarkMarkdownComponents() {
98
98
  if (node.type === 'inlineCode') {
99
99
  const [first, ...rest] = node.value.split(' ')
100
100
  const lang = rest.length && inlineLanguages.has(first) ? first : ''
101
- parent.children[index] = element('mdxJsxTextElement', 'InlineCode', { lang, code: lang ? rest.join(' ') : node.value })
101
+ parent.children[index] = element('mdxJsxTextElement', 'InlineCode', { lang, code: lang ? rest.join(' ') : node.value, ...(parent.type === 'heading' ? { plain: true } : {}) })
102
102
  return SKIP
103
103
  }
104
104
  if (node.type === 'paragraph') {
@@ -17,6 +17,16 @@ export interface DocumentationSearchResult {
17
17
 
18
18
  const normalize = (text: string) => text.normalize('NFKC').toLocaleLowerCase().trim()
19
19
 
20
+ /** A title phrase is relevant before incidental code, without promoting fragments inside words. */
21
+ function titleMatches(title: string, query: string) {
22
+ const text = normalize(title)
23
+ for (let at = text.indexOf(query); at !== -1; at = text.indexOf(query, at + 1)) {
24
+ if (!/[\p{L}\p{N}\p{M}_]$/u.test(text.slice(0, at))
25
+ && !/^[\p{L}\p{N}\p{M}_]/u.test(text.slice(at + query.length))) return true
26
+ }
27
+ return false
28
+ }
29
+
20
30
  /** One index per loaded locale. Exact public identifiers outrank approximate prose. */
21
31
  export function createDocumentationSearch(pages: DocumentationSearchPage[]) {
22
32
  const enabled = pages.filter(page => !page.disabled)
@@ -41,7 +51,7 @@ export function createDocumentationSearch(pages: DocumentationSearchPage[]) {
41
51
  for (const page of enabled) {
42
52
  const identifier = page.identifiers?.find(item => normalize(item.text) === needle)
43
53
  const syntax = page.nodes.find(node => node.tag === 'code' && normalize(node.text).includes(needle))
44
- const title = normalize(page.title) === needle
54
+ const title = titleMatches(page.title, needle)
45
55
  const topic = page.terms?.some(term => normalize(term) === needle)
46
56
  if (!identifier && !syntax && !title && !topic) continue
47
57
  const node = identifier ?? syntax
@@ -82,7 +82,7 @@ export function createCodeHighlighter(adapter: HighlightAdapter = {}) {
82
82
  }),
83
83
  {
84
84
  pre(element) {
85
- element!.properties!.class = clsx(element!.properties!.class, options.className)
85
+ element!.properties!.class = clsx(element!.properties!.class, 'code-block', options.className)
86
86
  delete element!.properties!.style
87
87
  },
88
88
  code(element) {
@@ -96,7 +96,7 @@ export function createCodeHighlighter(adapter: HighlightAdapter = {}) {
96
96
  if (classes.delete(className)) line.properties.dataMark = mark
97
97
  }
98
98
  // An array: the Master CSS transformer finds lines by an exact `line` entry.
99
- line.properties.class = [...classes, 'ui-code-line']
99
+ line.properties.class = [...classes, 'code-line', 'ui-code-line', ...(line.properties.dataMark ? ['code-line-' + (line.properties.dataMark === 'active' ? 'highlight' : line.properties.dataMark)] : [])]
100
100
  }
101
101
  },
102
102
  }
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import '@master/internal-site/styles/system/button-feedback.css'
3
- import '@master/internal-site/styles/system/buttons.css'
3
+ import '@master/internal-site/styles/system/buttons.ts'
4
4
  import '@master/internal-site/styles/system/sheet.ts'
5
5
 
6
6
  import Image from '@master/internal-site/components/Image.svelte'
@@ -62,7 +62,7 @@
62
62
  <h1 bind:this={heading} tabindex="-1" style={`view-transition-name:article-${detail.id}-title`} class="mb(0) mt-sm text-2xl font-regular outline-solid:focus-visible outline(2):focus-visible outline-text-link:focus-visible outline-offset-4xs:focus-visible article-capture">{detail.title}</h1>
63
63
  <p class="mb(0) mt-md text-sm fg-text-muted">{detail.description} The image, title and date keep their names in both views. Each snapshot can move to its new bounds while surrounding content fades.</p>
64
64
  <button type="button" class="mt-lg btn" onclick={() => { const id = detail.id; transition.run(() => { selectedId = undefined }, () => buttons.get(id) ?? null) }}>
65
- <IconArrowLeft aria-hidden="true" />Back to collection
65
+ <IconArrowLeft class="icon" aria-hidden="true" />Back to collection
66
66
  </button>
67
67
  </div>
68
68
  </article>
@@ -79,7 +79,7 @@
79
79
  <button {@attach cardButton(article.id)}
80
80
  type="button" class="self-start mt-auto btn" aria-label={`Read ${article.title}`}
81
81
  onclick={() => transition.run(() => { selectedId = article.id }, () => heading ?? null)}>
82
- Read article<IconArrowUpRight aria-hidden="true" />
82
+ Read article<IconArrowUpRight class="icon" aria-hidden="true" />
83
83
  </button>
84
84
  </article>
85
85
  </DemoSurface>
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Blog post pages: what is a post's own. The text itself reads with the documentation's typography
3
- * (`docs-shell/prose.css`, code wells in `docs-shell/code.css`) and its contents with the shared contents ruler
3
+ * (`docs-shell/prose.css`, code wells from the UI code component) and its contents with the shared contents ruler
4
4
  * (`ui-toc`, `docs-shell/page-content.css`); this sheet places them and draws the post's header and close.
5
5
  *
6
6
  * - The article is a framed drawing, as the homepage frames its sections (`.blog-rails`, `.blog-rails-rule` from
@@ -409,6 +409,8 @@
409
409
  .blog-article-next {
410
410
  --blog-marks-inset: 1rem;
411
411
  display: grid;
412
+ grid-template-columns: minmax(0, 1fr);
413
+ overflow-wrap: anywhere;
412
414
  width: fit-content;
413
415
  max-width: min(100%, 38rem);
414
416
  color: var(--blog-article-text);
@@ -1,9 +1,6 @@
1
1
  /* Demo family: compositions the system surfaces leave to the examples. Trays, stages, browsers and specimens live in styles/system. */
2
2
  @layer components {
3
3
  /* Generated output closes the source panel: a native disclosure joined under the code window */
4
- .ui-tray > .ui-disclosure { margin-top: var(--ui-inset); padding-inline: var(--ui-space-sm); border-radius: var(--ui-radius-xl); background: var(--ui-surface-code); }
5
- .ui-tray > .ui-code:has(+ .ui-disclosure) { border-end-start-radius: 0; border-end-end-radius: 0; }
6
- .ui-tray > .ui-code + .ui-disclosure { margin-top: 0; border-start-start-radius: 0; border-start-end-radius: 0; box-shadow: inset 0 1px 0 var(--ui-line-hair); }
7
4
  .ui-tray > .ui-disclosure > :not(summary) { margin-inline: calc(var(--ui-space-sm) * -1); }
8
5
  /* The panel's own padding is part of the summary's inset: its chevron starts where the code lines start. */
9
6
  .ui-tray > details.ui-disclosure > summary { padding-inline: calc(var(--ui-space-md) - var(--ui-space-sm)); }
@@ -9,11 +9,8 @@
9
9
  .ui-dialog[data-variant="search"][open] { display: flex; }
10
10
  .ui-dialog[data-variant="search"] .ui-dialog-search { flex: none; }
11
11
  .ui-dialog-search > svg { flex: none; color: var(--ui-text-muted); }
12
- .ui-dialog-search input { appearance: none; padding: .5rem 0; }
13
- .ui-dialog-search input::placeholder { color: var(--ui-text-muted); }
14
- .ui-dialog-search input::-webkit-search-cancel-button { display: none; }
12
+ .ui-dialog-search input { padding-block: .5rem; }
15
13
  .ui-dialog-close > span:last-child { display: none; }
16
- .ui-dialog-close > .kbd { box-shadow: none; background: none; }
17
14
  .ui-dialog[data-variant="search"] > .ui-dialog-body { flex: 1; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
18
15
  .ui-dialog-status { margin: 0; padding: var(--ui-space-sm) var(--ui-space-md) 0; color: var(--ui-text-muted); @apply --ui-label-type; }
19
16
  .ui-dialog-note { display: flex; flex-wrap: wrap; align-items: center; gap: var(--ui-space-xs); padding: var(--ui-space-sm) var(--ui-space-md) var(--ui-space-lg); }
@@ -24,21 +21,17 @@
24
21
  .ui-dialog-note[data-align="center"] > b { color: var(--ui-text-strong); font-size: var(--ui-text-small); font-weight: var(--ui-weight-strong); }
25
22
  .ui-results:empty { display: none; }
26
23
  .ui-results > li > a { scroll-margin-block: var(--ui-inset); }
27
- .ui-results > li > a > b { overflow-wrap: anywhere; }
28
- .ui-results > li > a > span { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; color: var(--ui-text-body); font-size: .8125rem; line-height: 1.55; overflow-wrap: anywhere; }
24
+ .ui-results .listbox-body > b { overflow-wrap: anywhere; }
25
+ .ui-results .ui-result-excerpt { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; font-size: .8125rem; line-height: 1.55; overflow-wrap: anywhere; }
29
26
  .ui-results mark { background: none; color: var(--ui-text-strong); text-decoration: underline; text-decoration-color: var(--ui-line-mark); text-underline-offset: .2em; }
30
- .ui-results > li > a:focus-visible { @apply --ui-focus-ring; outline-offset: -2px; }
31
27
  .ui-dialog-foot { flex: none; }
32
28
  .ui-dialog-foot > span:last-child { margin-left: auto; }
33
29
  .ui-search-shortcut { white-space: nowrap; }
34
30
  .ui-dialog-foot .kbd svg { width: 12px; height: 12px; }
31
+ @media (forced-colors: active) { .ui-results mark { color: inherit; text-decoration-color: currentColor; } }
35
32
  @media (width < 48rem) {
36
33
  .ui-dialog[data-variant="search"] { width: 100%; max-width: 100%; height: 100dvh; max-height: 100dvh; margin: 0; border-radius: 0; }
37
34
  .ui-dialog-close > .kbd, .ui-dialog-foot { display: none; }
38
35
  .ui-dialog-close > span:last-child { display: inline; }
39
36
  }
40
- @media (forced-colors: active) {
41
- .ui-dialog[data-variant="search"] { border: 1px solid CanvasText; }
42
- .ui-results > li > a[aria-selected="true"] { outline: 2px solid Highlight; outline-offset: -2px; }
43
- }
44
37
  }