@terra-symposium/docs 0.1.72 → 0.1.74

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.
@@ -1,108 +1,128 @@
1
1
  import { useEffect, useMemo, useRef, useState } from 'react';
2
2
 
3
3
  type SearchDocument = {
4
- title: string;
5
- description: string;
6
- href: string;
7
- text: string;
4
+ title: string;
5
+ description: string;
6
+ href: string;
7
+ text: string;
8
8
  };
9
9
 
10
10
  type Props = { base?: string };
11
11
 
12
12
  function excerpt(text: string, query: string): string {
13
- const normalized = text.replace(/\s+/g, ' ').trim();
14
- const offset = normalized.toLowerCase().indexOf(query.toLowerCase());
15
- const start = Math.max(0, offset - 72);
16
- const end = Math.min(normalized.length, start + 190);
17
- return `${start > 0 ? '…' : ''}${normalized.slice(start, end)}${end < normalized.length ? '…' : ''}`;
13
+ const normalized = text.replace(/\s+/g, ' ').trim();
14
+ const offset = normalized.toLowerCase().indexOf(query.toLowerCase());
15
+ const start = Math.max(0, offset - 72);
16
+ const end = Math.min(normalized.length, start + 190);
17
+ return `${start > 0 ? '…' : ''}${normalized.slice(start, end)}${end < normalized.length ? '…' : ''}`;
18
18
  }
19
19
 
20
20
  export function DocsSiteSearch({ base = '/' }: Props) {
21
- const dialog = useRef<HTMLDialogElement>(null);
22
- const input = useRef<HTMLInputElement>(null);
23
- const [query, setQuery] = useState('');
24
- const [documents, setDocuments] = useState<SearchDocument[]>([]);
25
- const [loaded, setLoaded] = useState(false);
26
- const [failed, setFailed] = useState(false);
27
- const [opened, setOpened] = useState(false);
28
- const normalizedBase = base.endsWith('/') ? base : `${base}/`;
21
+ const dialog = useRef<HTMLDialogElement>(null);
22
+ const input = useRef<HTMLInputElement>(null);
23
+ const [query, setQuery] = useState('');
24
+ const [documents, setDocuments] = useState<SearchDocument[]>([]);
25
+ const [loaded, setLoaded] = useState(false);
26
+ const [failed, setFailed] = useState(false);
27
+ const [opened, setOpened] = useState(false);
28
+ const normalizedBase = base.endsWith('/') ? base : `${base}/`;
29
29
 
30
- const open = () => {
31
- if (!dialog.current?.open) dialog.current?.showModal();
32
- setOpened(true);
33
- window.setTimeout(() => input.current?.focus(), 0);
34
- };
30
+ const open = () => {
31
+ if (!dialog.current?.open) dialog.current?.showModal();
32
+ setOpened(true);
33
+ window.setTimeout(() => input.current?.focus(), 0);
34
+ };
35
35
 
36
- useEffect(() => {
37
- const onKeyDown = (event: KeyboardEvent) => {
38
- if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') {
39
- event.preventDefault();
40
- open();
41
- } else if (event.key === '/' && !/input|textarea|select/i.test((event.target as HTMLElement)?.tagName ?? '')) {
42
- event.preventDefault();
43
- open();
44
- }
45
- };
46
- document.addEventListener('keydown', onKeyDown);
47
- return () => document.removeEventListener('keydown', onKeyDown);
48
- }, []);
36
+ useEffect(() => {
37
+ const onKeyDown = (event: KeyboardEvent) => {
38
+ if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === 'k') {
39
+ event.preventDefault();
40
+ open();
41
+ } else if (
42
+ event.key === '/' &&
43
+ !/input|textarea|select/i.test((event.target as HTMLElement)?.tagName ?? '')
44
+ ) {
45
+ event.preventDefault();
46
+ open();
47
+ }
48
+ };
49
+ document.addEventListener('keydown', onKeyDown);
50
+ return () => document.removeEventListener('keydown', onKeyDown);
51
+ }, []);
49
52
 
50
- useEffect(() => {
51
- if (!opened || loaded) return;
52
- fetch(`${normalizedBase}_terra-docs/search-index.json`)
53
- .then((response) => {
54
- if (!response.ok) throw new Error(`Search index returned ${response.status}`);
55
- return response.json() as Promise<SearchDocument[]>;
56
- })
57
- .then((data) => {
58
- setDocuments(data);
59
- setLoaded(true);
60
- })
61
- .catch(() => setFailed(true));
62
- }, [loaded, normalizedBase, opened]);
53
+ useEffect(() => {
54
+ if (!opened || loaded) return;
55
+ fetch(`${normalizedBase}_terra-docs/search-index.json`)
56
+ .then((response) => {
57
+ if (!response.ok) throw new Error(`Search index returned ${response.status}`);
58
+ return response.json() as Promise<SearchDocument[]>;
59
+ })
60
+ .then((data) => {
61
+ setDocuments(data);
62
+ setLoaded(true);
63
+ })
64
+ .catch(() => setFailed(true));
65
+ }, [loaded, normalizedBase, opened]);
63
66
 
64
- const results = useMemo(() => {
65
- const terms = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
66
- if (!terms.length) return [];
67
- return documents
68
- .map((document) => {
69
- const title = document.title.toLowerCase();
70
- const text = `${document.description} ${document.text}`.toLowerCase();
71
- const matches = terms.filter((term) => title.includes(term) || text.includes(term));
72
- const score = matches.length * 10 + terms.filter((term) => title.includes(term)).length * 5;
73
- return { document, score };
74
- })
75
- .filter((result) => result.score > 0)
76
- .sort((left, right) => right.score - left.score || left.document.title.localeCompare(right.document.title))
77
- .slice(0, 10);
78
- }, [documents, query]);
67
+ const results = useMemo(() => {
68
+ const terms = query.toLowerCase().trim().split(/\s+/).filter(Boolean);
69
+ if (!terms.length) return [];
70
+ return documents
71
+ .map((document) => {
72
+ const title = document.title.toLowerCase();
73
+ const text = `${document.description} ${document.text}`.toLowerCase();
74
+ const matches = terms.filter((term) => title.includes(term) || text.includes(term));
75
+ const score = matches.length * 10 + terms.filter((term) => title.includes(term)).length * 5;
76
+ return { document, score };
77
+ })
78
+ .filter((result) => result.score > 0)
79
+ .sort(
80
+ (left, right) =>
81
+ right.score - left.score || left.document.title.localeCompare(right.document.title),
82
+ )
83
+ .slice(0, 10);
84
+ }, [documents, query]);
79
85
 
80
- return (
81
- <div className="terra-docs-search">
82
- <button className="terra-docs-search-trigger" type="button" onClick={open} aria-label="Search documentation">
83
- <span aria-hidden="true">⌕</span><span>Search docs</span><kbd>⌘ K</kbd>
84
- </button>
85
- <dialog className="terra-docs-search-dialog" ref={dialog} onClose={() => setQuery('')}>
86
- <div className="terra-docs-search-panel">
87
- <label className="terra-docs-search-input-row">
88
- <span aria-hidden="true">⌕</span>
89
- <input ref={input} value={query} onChange={(event) => setQuery(event.currentTarget.value)} placeholder="Search documentation…" />
90
- <button type="button" onClick={() => dialog.current?.close()} aria-label="Close search">Esc</button>
91
- </label>
92
- <div className="terra-docs-search-results" aria-live="polite">
93
- {failed ? <p>Search is unavailable right now.</p> : null}
94
- {!loaded && !failed ? <p>Loading search…</p> : null}
95
- {loaded && query.trim() && results.length === 0 ? <p>No matching pages.</p> : null}
96
- {results.map(({ document }) => (
97
- <a key={document.href} href={document.href} onClick={() => dialog.current?.close()}>
98
- <strong>{document.title}</strong>
99
- {document.description ? <span>{document.description}</span> : null}
100
- <small>{excerpt(document.text, query.trim().split(/\s+/)[0] ?? query)}</small>
101
- </a>
102
- ))}
103
- </div>
104
- </div>
105
- </dialog>
106
- </div>
107
- );
86
+ return (
87
+ <div className="terra-docs-search">
88
+ <button
89
+ className="terra-docs-search-trigger"
90
+ type="button"
91
+ onClick={open}
92
+ aria-label="Search documentation"
93
+ >
94
+ <span aria-hidden="true">⌕</span>
95
+ <span>Search docs</span>
96
+ <kbd>⌘ K</kbd>
97
+ </button>
98
+ <dialog className="terra-docs-search-dialog" ref={dialog} onClose={() => setQuery('')}>
99
+ <div className="terra-docs-search-panel">
100
+ <label className="terra-docs-search-input-row">
101
+ <span aria-hidden="true">⌕</span>
102
+ <input
103
+ ref={input}
104
+ value={query}
105
+ onChange={(event) => setQuery(event.currentTarget.value)}
106
+ placeholder="Search documentation…"
107
+ />
108
+ <button type="button" onClick={() => dialog.current?.close()} aria-label="Close search">
109
+ Esc
110
+ </button>
111
+ </label>
112
+ <div className="terra-docs-search-results" aria-live="polite">
113
+ {failed ? <p>Search is unavailable right now.</p> : null}
114
+ {!loaded && !failed ? <p>Loading search…</p> : null}
115
+ {loaded && query.trim() && results.length === 0 ? <p>No matching pages.</p> : null}
116
+ {results.map(({ document }) => (
117
+ <a key={document.href} href={document.href} onClick={() => dialog.current?.close()}>
118
+ <strong>{document.title}</strong>
119
+ {document.description ? <span>{document.description}</span> : null}
120
+ <small>{excerpt(document.text, query.trim().split(/\s+/)[0] ?? query)}</small>
121
+ </a>
122
+ ))}
123
+ </div>
124
+ </div>
125
+ </dialog>
126
+ </div>
127
+ );
108
128
  }
@@ -3,149 +3,156 @@
3
3
  import type { DocsNavNode } from '../../../src/components/navigation.js';
4
4
 
5
5
  type SidebarFrontmatter = {
6
- label?: string;
7
- order?: number;
8
- hidden?: boolean;
6
+ label?: string;
7
+ order?: number;
8
+ hidden?: boolean;
9
9
  };
10
10
 
11
11
  type DocsFrontmatter = {
12
- title?: string;
13
- description?: string;
14
- hue?: number | null;
15
- label?: string;
16
- order?: number;
17
- hidden?: boolean;
18
- visibility?: 'visible' | 'hidden';
19
- sidebar?: SidebarFrontmatter;
12
+ title?: string;
13
+ description?: string;
14
+ hue?: number | null;
15
+ label?: string;
16
+ order?: number;
17
+ hidden?: boolean;
18
+ visibility?: 'visible' | 'hidden';
19
+ sidebar?: SidebarFrontmatter;
20
20
  };
21
21
 
22
22
  type ContentModule = {
23
- Content?: unknown;
24
- default?: unknown;
25
- frontmatter?: DocsFrontmatter;
23
+ Content?: unknown;
24
+ default?: unknown;
25
+ frontmatter?: DocsFrontmatter;
26
26
  };
27
27
 
28
28
  export type SitePage = {
29
- file: string;
30
- slug: string;
31
- title: string;
32
- sidebarLabel?: string;
33
- description: string;
34
- hue?: number | null;
35
- hidden: boolean;
36
- order: number;
37
- content: unknown;
38
- markdown: string;
29
+ file: string;
30
+ slug: string;
31
+ title: string;
32
+ sidebarLabel?: string;
33
+ description: string;
34
+ hue?: number | null;
35
+ hidden: boolean;
36
+ order: number;
37
+ content: unknown;
38
+ markdown: string;
39
39
  };
40
40
 
41
41
  const modules = import.meta.glob<ContentModule>('/docs/**/*.{md,mdx}', { eager: true });
42
42
  const sources = import.meta.glob<string>('/docs/**/*.{md,mdx}', {
43
- query: '?raw',
44
- import: 'default',
45
- eager: true,
43
+ query: '?raw',
44
+ import: 'default',
45
+ eager: true,
46
46
  });
47
47
  const base = import.meta.env.BASE_URL;
48
48
 
49
49
  function titleFromSource(source: string, slug: string): string {
50
- const body = source.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, '');
51
- const heading = /^#\s+(.+?)\s*#*\s*$/m.exec(body)?.[1]?.trim();
52
- if (heading) return heading;
53
- const name = slug.split('/').at(-1) || 'Overview';
54
- return name.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
50
+ const body = source.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, '');
51
+ const heading = /^#\s+(.+?)\s*#*\s*$/m.exec(body)?.[1]?.trim();
52
+ if (heading) return heading;
53
+ const name = slug.split('/').at(-1) || 'Overview';
54
+ return name.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
55
55
  }
56
56
 
57
57
  function routeForFile(file: string): string {
58
- const relative = file.replace(/^\/?docs\//, '').replace(/\.(?:md|mdx)$/i, '');
59
- return relative.replace(/(?:^|\/)index$/i, '').replace(/^\/+|\/+$/g, '');
58
+ const relative = file.replace(/^\/?docs\//, '').replace(/\.(?:md|mdx)$/i, '');
59
+ return relative.replace(/(?:^|\/)index$/i, '').replace(/^\/+|\/+$/g, '');
60
60
  }
61
61
 
62
62
  const routes = new Map<string, string>();
63
63
  export const sitePages: SitePage[] = Object.entries(modules)
64
- .map(([file, module]) => {
65
- const slug = routeForFile(file);
66
- const previous = routes.get(slug);
67
- if (previous) {
68
- throw new Error(`Duplicate Docs route "${slug || '/'}": ${previous} and ${file}`);
69
- }
70
- routes.set(slug, file);
71
- const markdown = sources[file] ?? '';
72
- const frontmatter = module.frontmatter ?? {};
73
- return {
74
- file,
75
- slug,
76
- title: frontmatter.title ?? titleFromSource(markdown, slug),
77
- ...((frontmatter.sidebar?.label ?? frontmatter.label) ? { sidebarLabel: frontmatter.sidebar?.label ?? frontmatter.label } : {}),
78
- description: frontmatter.description ?? '',
79
- ...(frontmatter.hue !== undefined ? { hue: frontmatter.hue } : {}),
80
- hidden: frontmatter.sidebar?.hidden ?? frontmatter.hidden ?? frontmatter.visibility === 'hidden',
81
- order: frontmatter.sidebar?.order ?? frontmatter.order ?? Number.MAX_SAFE_INTEGER,
82
- content: module.Content ?? module.default,
83
- markdown: markdown.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, ''),
84
- };
85
- })
86
- .sort((left, right) => left.order - right.order || left.file.localeCompare(right.file));
64
+ .map(([file, module]) => {
65
+ const slug = routeForFile(file);
66
+ const previous = routes.get(slug);
67
+ if (previous) {
68
+ throw new Error(`Duplicate Docs route "${slug || '/'}": ${previous} and ${file}`);
69
+ }
70
+ routes.set(slug, file);
71
+ const markdown = sources[file] ?? '';
72
+ const frontmatter = module.frontmatter ?? {};
73
+ return {
74
+ file,
75
+ slug,
76
+ title: frontmatter.title ?? titleFromSource(markdown, slug),
77
+ ...((frontmatter.sidebar?.label ?? frontmatter.label)
78
+ ? { sidebarLabel: frontmatter.sidebar?.label ?? frontmatter.label }
79
+ : {}),
80
+ description: frontmatter.description ?? '',
81
+ ...(frontmatter.hue !== undefined ? { hue: frontmatter.hue } : {}),
82
+ hidden:
83
+ frontmatter.sidebar?.hidden ?? frontmatter.hidden ?? frontmatter.visibility === 'hidden',
84
+ order: frontmatter.sidebar?.order ?? frontmatter.order ?? Number.MAX_SAFE_INTEGER,
85
+ content: module.Content ?? module.default,
86
+ markdown: markdown.replace(/^---\s*\n[\s\S]*?\n---\s*\n/, ''),
87
+ };
88
+ })
89
+ .sort((left, right) => left.order - right.order || left.file.localeCompare(right.file));
87
90
 
88
91
  if (sitePages.length === 0) {
89
- throw new Error('No Markdown files found in docs/. Add docs/index.md to start a Terra Docs site.');
92
+ throw new Error(
93
+ 'No Markdown files found in docs/. Add docs/index.md to start a Terra Docs site.',
94
+ );
90
95
  }
91
96
 
92
97
  type MutableNode = Omit<DocsNavNode, 'children'> & { children: Map<string, MutableNode> };
93
98
  const rootNodes = new Map<string, MutableNode>();
94
99
 
95
100
  function label(value: string): string {
96
- return value.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
101
+ return value.replace(/[-_]+/g, ' ').replace(/\b\p{L}/gu, (letter) => letter.toUpperCase());
97
102
  }
98
103
 
99
104
  for (const page of sitePages.filter((item) => !item.hidden && item.slug !== '404')) {
100
- const segments = page.slug.split('/').filter(Boolean);
101
- let currentNodes = rootNodes;
102
- let current: MutableNode | undefined;
103
- let prefix = '';
104
- if (segments.length === 0) {
105
- const overview = currentNodes.get('overview') ?? {
106
- id: 'overview', title: 'Overview', children: new Map(),
107
- };
108
- if (!currentNodes.has('overview')) currentNodes.set('overview', overview);
109
- Object.assign(overview, pageMetadata(page, pageHref('', base)));
110
- continue;
111
- }
112
- for (const segment of segments) {
113
- prefix = prefix ? `${prefix}/${segment}` : segment;
114
- let node = currentNodes.get(segment);
115
- if (!node) {
116
- node = { id: prefix, title: label(segment), children: new Map() };
117
- currentNodes.set(segment, node);
118
- }
119
- current = node;
120
- currentNodes = node.children;
121
- }
122
- if (current) Object.assign(current, pageMetadata(page, pageHref(page.slug, base)));
105
+ const segments = page.slug.split('/').filter(Boolean);
106
+ let currentNodes = rootNodes;
107
+ let current: MutableNode | undefined;
108
+ let prefix = '';
109
+ if (segments.length === 0) {
110
+ const overview = currentNodes.get('overview') ?? {
111
+ id: 'overview',
112
+ title: 'Overview',
113
+ children: new Map(),
114
+ };
115
+ if (!currentNodes.has('overview')) currentNodes.set('overview', overview);
116
+ Object.assign(overview, pageMetadata(page, pageHref('', base)));
117
+ continue;
118
+ }
119
+ for (const segment of segments) {
120
+ prefix = prefix ? `${prefix}/${segment}` : segment;
121
+ let node = currentNodes.get(segment);
122
+ if (!node) {
123
+ node = { id: prefix, title: label(segment), children: new Map() };
124
+ currentNodes.set(segment, node);
125
+ }
126
+ current = node;
127
+ currentNodes = node.children;
128
+ }
129
+ if (current) Object.assign(current, pageMetadata(page, pageHref(page.slug, base)));
123
130
  }
124
131
 
125
132
  function pageMetadata(page: SitePage, href: string): Partial<MutableNode> {
126
- return {
127
- id: page.slug || 'index',
128
- title: page.sidebarLabel ?? page.title,
129
- href,
130
- ...(page.description ? { description: page.description } : {}),
131
- ...(page.hue !== undefined ? { hue: page.hue } : {}),
132
- };
133
+ return {
134
+ id: page.slug || 'index',
135
+ title: page.sidebarLabel ?? page.title,
136
+ href,
137
+ ...(page.description ? { description: page.description } : {}),
138
+ ...(page.hue !== undefined ? { hue: page.hue } : {}),
139
+ };
133
140
  }
134
141
 
135
142
  function materialize(nodes: Map<string, MutableNode>): DocsNavNode[] {
136
- return [...nodes.values()].map(({ children, ...node }) => ({
137
- ...node,
138
- ...(children.size ? { children: materialize(children) } : {}),
139
- }));
143
+ return [...nodes.values()].map(({ children, ...node }) => ({
144
+ ...node,
145
+ ...(children.size ? { children: materialize(children) } : {}),
146
+ }));
140
147
  }
141
148
 
142
149
  export const siteNavigation = materialize(rootNodes);
143
150
 
144
151
  export function pageHref(slug: string, base = '/'): string {
145
- const prefix = base === '/' ? '' : `/${base.replace(/^\/+|\/+$/g, '')}`;
146
- return slug ? `${prefix}/${slug}/` : `${prefix}/`;
152
+ const prefix = base === '/' ? '' : `/${base.replace(/^\/+|\/+$/g, '')}`;
153
+ return slug ? `${prefix}/${slug}/` : `${prefix}/`;
147
154
  }
148
155
 
149
156
  export function pageForSlug(slug: string): SitePage | undefined {
150
- return sitePages.find((page) => page.slug === slug);
157
+ return sitePages.find((page) => page.slug === slug);
151
158
  }
@@ -1,56 +1,127 @@
1
1
  .terra-docs-search {
2
- position: fixed;
3
- top: 0.65rem;
4
- right: 1rem;
5
- z-index: 80;
6
- font: inherit;
2
+ position: fixed;
3
+ top: 0.65rem;
4
+ right: 1rem;
5
+ z-index: 80;
6
+ font: inherit;
7
7
  }
8
8
 
9
9
  .terra-docs-search-trigger {
10
- display: flex;
11
- align-items: center;
12
- gap: 0.55rem;
13
- min-height: 2.4rem;
14
- padding: 0.35rem 0.55rem;
15
- border: 1px solid rgb(var(--primary-6));
16
- border-radius: 0.45rem;
17
- background: rgb(var(--primary-2));
18
- color: rgb(var(--primary-11));
19
- font-size: 0.85rem;
20
- cursor: pointer;
10
+ display: flex;
11
+ align-items: center;
12
+ gap: 0.55rem;
13
+ min-height: 2.4rem;
14
+ padding: 0.35rem 0.55rem;
15
+ border: 1px solid rgb(var(--primary-6));
16
+ border-radius: 0.45rem;
17
+ background: rgb(var(--primary-2));
18
+ color: rgb(var(--primary-11));
19
+ font-size: 0.85rem;
20
+ cursor: pointer;
21
21
  }
22
22
 
23
- .terra-docs-search-trigger:hover { background: rgb(var(--primary-3)); }
24
- .terra-docs-search-trigger > span:first-child { font-size: 1.25rem; line-height: 1; }
25
- .terra-docs-search-trigger kbd { padding: 0.05rem 0.25rem; border: 1px solid rgb(var(--primary-6)); border-radius: 0.25rem; font-size: 0.7rem; }
23
+ .terra-docs-search-trigger:hover {
24
+ background: rgb(var(--primary-3));
25
+ }
26
+ .terra-docs-search-trigger > span:first-child {
27
+ font-size: 1.25rem;
28
+ line-height: 1;
29
+ }
30
+ .terra-docs-search-trigger kbd {
31
+ padding: 0.05rem 0.25rem;
32
+ border: 1px solid rgb(var(--primary-6));
33
+ border-radius: 0.25rem;
34
+ font-size: 0.7rem;
35
+ }
26
36
 
27
37
  .terra-docs-search-dialog {
28
- width: min(42rem, calc(100vw - 2rem));
29
- max-width: none;
30
- max-height: min(75vh, 42rem);
31
- padding: 0;
32
- border: 1px solid rgb(var(--primary-7));
33
- border-radius: 0.75rem;
34
- background: rgb(var(--primary-2));
35
- color: rgb(var(--primary-12));
36
- box-shadow: 0 1.5rem 5rem rgb(0 0 0 / 0.35);
38
+ width: min(42rem, calc(100vw - 2rem));
39
+ max-width: none;
40
+ max-height: min(75vh, 42rem);
41
+ padding: 0;
42
+ border: 1px solid rgb(var(--primary-7));
43
+ border-radius: 0.75rem;
44
+ background: rgb(var(--primary-2));
45
+ color: rgb(var(--primary-12));
46
+ box-shadow: 0 1.5rem 5rem rgb(0 0 0 / 0.35);
37
47
  }
38
48
 
39
- .terra-docs-search-dialog::backdrop { background: rgb(0 0 0 / 0.58); backdrop-filter: blur(2px); }
40
- .terra-docs-search-panel { overflow: hidden; }
41
- .terra-docs-search-input-row { display: flex; align-items: center; gap: 0.75rem; padding: 1rem; border-bottom: 1px solid rgb(var(--primary-5)); }
42
- .terra-docs-search-input-row > span { font-size: 1.3rem; }
43
- .terra-docs-search-input-row input { min-width: 0; flex: 1; border: 0; outline: 0; background: transparent; color: inherit; font: inherit; }
44
- .terra-docs-search-input-row button { border: 1px solid rgb(var(--primary-6)); border-radius: 0.3rem; background: transparent; color: inherit; font-size: 0.7rem; cursor: pointer; }
45
- .terra-docs-search-results { max-height: calc(75vh - 4rem); overflow: auto; padding: 0.5rem; }
46
- .terra-docs-search-results > p { padding: 1rem; color: rgb(var(--primary-10)); font-size: 0.9rem; }
47
- .terra-docs-search-results > a { display: grid; gap: 0.25rem; padding: 0.75rem; border-radius: 0.45rem; color: inherit; text-decoration: none; }
48
- .terra-docs-search-results > a:hover, .terra-docs-search-results > a:focus { outline: 0; background: rgb(var(--primary-4)); }
49
- .terra-docs-search-results > a span, .terra-docs-search-results > a small { color: rgb(var(--primary-10)); }
50
- .terra-docs-search-results > a small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
49
+ .terra-docs-search-dialog::backdrop {
50
+ background: rgb(0 0 0 / 0.58);
51
+ backdrop-filter: blur(2px);
52
+ }
53
+ .terra-docs-search-panel {
54
+ overflow: hidden;
55
+ }
56
+ .terra-docs-search-input-row {
57
+ display: flex;
58
+ align-items: center;
59
+ gap: 0.75rem;
60
+ padding: 1rem;
61
+ border-bottom: 1px solid rgb(var(--primary-5));
62
+ }
63
+ .terra-docs-search-input-row > span {
64
+ font-size: 1.3rem;
65
+ }
66
+ .terra-docs-search-input-row input {
67
+ min-width: 0;
68
+ flex: 1;
69
+ border: 0;
70
+ outline: 0;
71
+ background: transparent;
72
+ color: inherit;
73
+ font: inherit;
74
+ }
75
+ .terra-docs-search-input-row button {
76
+ border: 1px solid rgb(var(--primary-6));
77
+ border-radius: 0.3rem;
78
+ background: transparent;
79
+ color: inherit;
80
+ font-size: 0.7rem;
81
+ cursor: pointer;
82
+ }
83
+ .terra-docs-search-results {
84
+ max-height: calc(75vh - 4rem);
85
+ overflow: auto;
86
+ padding: 0.5rem;
87
+ }
88
+ .terra-docs-search-results > p {
89
+ padding: 1rem;
90
+ color: rgb(var(--primary-10));
91
+ font-size: 0.9rem;
92
+ }
93
+ .terra-docs-search-results > a {
94
+ display: grid;
95
+ gap: 0.25rem;
96
+ padding: 0.75rem;
97
+ border-radius: 0.45rem;
98
+ color: inherit;
99
+ text-decoration: none;
100
+ }
101
+ .terra-docs-search-results > a:hover,
102
+ .terra-docs-search-results > a:focus {
103
+ outline: 0;
104
+ background: rgb(var(--primary-4));
105
+ }
106
+ .terra-docs-search-results > a span,
107
+ .terra-docs-search-results > a small {
108
+ color: rgb(var(--primary-10));
109
+ }
110
+ .terra-docs-search-results > a small {
111
+ overflow: hidden;
112
+ text-overflow: ellipsis;
113
+ white-space: nowrap;
114
+ }
51
115
 
52
116
  @media (max-width: 640px) {
53
- .terra-docs-search { top: 0.5rem; right: 0.5rem; }
54
- .terra-docs-search-trigger { min-height: 2.1rem; }
55
- .terra-docs-search-trigger kbd { display: none; }
117
+ .terra-docs-search {
118
+ top: 0.5rem;
119
+ right: 0.5rem;
120
+ }
121
+ .terra-docs-search-trigger {
122
+ min-height: 2.1rem;
123
+ }
124
+ .terra-docs-search-trigger kbd {
125
+ display: none;
126
+ }
56
127
  }