@tenphi/renderer 0.20.3 → 0.20.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -10,7 +10,7 @@ collections remain independent.
10
10
 
11
11
  `@tenphi/renderer/styling` exports `tasty`, `useGlobalStyles`, `mergeStyles`,
12
12
  the `Styles` type, and the `defineComponent` and `resolveComponentStyles`
13
- helpers for merging `theme.styles` into custom components. The facade exposes
13
+ helpers for merging `theme.customStyles` into custom components. The facade exposes
14
14
  the same API through `@tenphi/cookbook/styling`.
15
15
 
16
16
  `@tenphi/renderer/eslint-plugin` exports the default Tasty ESLint plugin,
@@ -19,5 +19,5 @@ the same API through `@tenphi/cookbook/styling`.
19
19
  Use `extends: "@tenphi/renderer"` in `tasty.config.ts` to inherit this preset
20
20
  and list only your additional tokens, states, or presets.
21
21
  It matches `@tenphi/cookbook/eslint-plugin`; see
22
- [Linting custom styles](https://cookbook.tenphi.me/theme-and-components/#linting-custom-styles)
22
+ [Linting custom styles](https://cookbook.tenphi.me/custom-components/#linting-custom-styles)
23
23
  for ESLint and oxlint setup.
@@ -1,3 +1,4 @@
1
+ import { initializePopoverMotion } from "./popover-motion.js";
1
2
  //#region src/client/navigation.ts
2
3
  var CookbookSidebarPane = class extends HTMLElement {
3
4
  #listeners;
@@ -93,6 +94,7 @@ var CookbookHeaderLinks = class extends HTMLElement {
93
94
  const close = () => {
94
95
  if (panel?.matches(":popover-open")) panel.hidePopover();
95
96
  };
97
+ if (panel) initializePopoverMotion(panel, signal);
96
98
  desktop.addEventListener("change", () => {
97
99
  if (desktop.matches) close();
98
100
  }, { signal });
@@ -1 +1 @@
1
- {"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["export {};\n\nclass CookbookSidebarPane extends HTMLElement {\n #listeners?: AbortController;\n #inert = new Map<HTMLElement, boolean>();\n #trigger: HTMLButtonElement | undefined;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n this.#trigger =\n document.querySelector<HTMLButtonElement>(\n '.td-menu-button[popovertarget=\"cookbook__sidebar\"]',\n ) ?? undefined;\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const syncViewport = () => {\n if (desktop.matches) {\n if (this.matches(\":popover-open\")) this.hidePopover();\n this.#release();\n this.popover = null;\n this.removeAttribute(\"role\");\n this.removeAttribute(\"aria-modal\");\n } else {\n this.popover = \"auto\";\n this.setAttribute(\"role\", \"dialog\");\n this.setAttribute(\"aria-modal\", \"true\");\n }\n };\n syncViewport();\n desktop.addEventListener(\"change\", syncViewport, { signal });\n this.addEventListener(\n \"toggle\",\n () => {\n const open = !desktop.matches && this.matches(\":popover-open\");\n this.#trigger?.setAttribute(\"aria-expanded\", String(open));\n if (open) {\n // Establish the closed position after the popover enters the top\n // layer so its attribute change transitions from an actual layout.\n // Tasty's global SSR renderer does not preserve @starting-style.\n this.getBoundingClientRect();\n this.setAttribute(\"data-open\", \"\");\n for (const element of document.querySelectorAll<HTMLElement>(\n \".header, .main-frame, .cookbook-skip-link\",\n )) {\n this.#inert.set(element, element.inert);\n element.inert = true;\n }\n this.querySelector<HTMLElement>(\"[autofocus]\")?.focus({\n preventScroll: true,\n });\n } else {\n const restoreFocus =\n this.contains(document.activeElement) ||\n document.activeElement === document.body;\n this.#release();\n if (restoreFocus && !desktop.matches) this.#trigger?.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"keydown\",\n (event) => {\n if (desktop.matches || !this.matches(\":popover-open\")) return;\n const sections = this.querySelector<HTMLDetailsElement>(\n \".td-mobile-tabs details[open]\",\n );\n if (event.key === \"Escape\" && sections) {\n event.preventDefault();\n sections.open = false;\n sections.querySelector(\"summary\")?.focus();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n this.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), select:not([disabled]), input:not([disabled]), summary, [tabindex=\"0\"]',\n ),\n ).filter(\n (element) =>\n element.tabIndex >= 0 && element.getClientRects().length > 0,\n );\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) {\n event.preventDefault();\n this.focus();\n return;\n }\n if (\n event.shiftKey &&\n (document.activeElement === first || document.activeElement === this)\n ) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"click\",\n (event) => {\n if (\n !event.defaultPrevented &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\") &&\n this.matches(\":popover-open\")\n )\n this.hidePopover();\n },\n { signal },\n );\n }\n\n #release() {\n this.removeAttribute(\"data-open\");\n for (const [element, inert] of this.#inert) element.inert = inert;\n this.#inert.clear();\n this.#trigger?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n this.#release();\n }\n}\n\nclass CookbookHeaderLinks extends HTMLElement {\n #listeners?: AbortController;\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n const panel = this.querySelector<HTMLElement>(\"[popover]\");\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const close = () => {\n if (panel?.matches(\":popover-open\")) panel.hidePopover();\n };\n desktop.addEventListener(\n \"change\",\n () => {\n if (desktop.matches) close();\n },\n { signal },\n );\n panel?.addEventListener(\n \"click\",\n (event) => {\n if (event.target instanceof Element && event.target.closest(\"a[href]\"))\n close();\n },\n { signal },\n );\n }\n disconnectedCallback() {\n this.#listeners?.abort();\n }\n}\n\nif (!customElements.get(\"cookbook-sidebar-pane\"))\n customElements.define(\"cookbook-sidebar-pane\", CookbookSidebarPane);\nif (!customElements.get(\"cookbook-header-links\"))\n customElements.define(\"cookbook-header-links\", CookbookHeaderLinks);\n"],"mappings":"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"}
1
+ {"version":3,"file":"navigation.js","names":[],"sources":["../../src/client/navigation.ts"],"sourcesContent":["import { initializePopoverMotion } from \"./popover-motion.js\";\n\nclass CookbookSidebarPane extends HTMLElement {\n #listeners?: AbortController;\n #inert = new Map<HTMLElement, boolean>();\n #trigger: HTMLButtonElement | undefined;\n\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n this.#trigger =\n document.querySelector<HTMLButtonElement>(\n '.td-menu-button[popovertarget=\"cookbook__sidebar\"]',\n ) ?? undefined;\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const syncViewport = () => {\n if (desktop.matches) {\n if (this.matches(\":popover-open\")) this.hidePopover();\n this.#release();\n this.popover = null;\n this.removeAttribute(\"role\");\n this.removeAttribute(\"aria-modal\");\n } else {\n this.popover = \"auto\";\n this.setAttribute(\"role\", \"dialog\");\n this.setAttribute(\"aria-modal\", \"true\");\n }\n };\n syncViewport();\n desktop.addEventListener(\"change\", syncViewport, { signal });\n this.addEventListener(\n \"toggle\",\n () => {\n const open = !desktop.matches && this.matches(\":popover-open\");\n this.#trigger?.setAttribute(\"aria-expanded\", String(open));\n if (open) {\n // Establish the closed position after the popover enters the top\n // layer so its attribute change transitions from an actual layout.\n // Tasty's global SSR renderer does not preserve @starting-style.\n this.getBoundingClientRect();\n this.setAttribute(\"data-open\", \"\");\n for (const element of document.querySelectorAll<HTMLElement>(\n \".header, .main-frame, .cookbook-skip-link\",\n )) {\n this.#inert.set(element, element.inert);\n element.inert = true;\n }\n this.querySelector<HTMLElement>(\"[autofocus]\")?.focus({\n preventScroll: true,\n });\n } else {\n const restoreFocus =\n this.contains(document.activeElement) ||\n document.activeElement === document.body;\n this.#release();\n if (restoreFocus && !desktop.matches) this.#trigger?.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"keydown\",\n (event) => {\n if (desktop.matches || !this.matches(\":popover-open\")) return;\n const sections = this.querySelector<HTMLDetailsElement>(\n \".td-mobile-tabs details[open]\",\n );\n if (event.key === \"Escape\" && sections) {\n event.preventDefault();\n sections.open = false;\n sections.querySelector(\"summary\")?.focus();\n return;\n }\n if (event.key !== \"Tab\") return;\n const focusable = Array.from(\n this.querySelectorAll<HTMLElement>(\n 'a[href], button:not([disabled]), select:not([disabled]), input:not([disabled]), summary, [tabindex=\"0\"]',\n ),\n ).filter(\n (element) =>\n element.tabIndex >= 0 && element.getClientRects().length > 0,\n );\n const first = focusable[0];\n const last = focusable.at(-1);\n if (!first || !last) {\n event.preventDefault();\n this.focus();\n return;\n }\n if (\n event.shiftKey &&\n (document.activeElement === first || document.activeElement === this)\n ) {\n event.preventDefault();\n last.focus();\n } else if (!event.shiftKey && document.activeElement === last) {\n event.preventDefault();\n first.focus();\n }\n },\n { signal },\n );\n this.addEventListener(\n \"click\",\n (event) => {\n if (\n !event.defaultPrevented &&\n event.target instanceof Element &&\n event.target.closest(\"a[href]\") &&\n this.matches(\":popover-open\")\n )\n this.hidePopover();\n },\n { signal },\n );\n }\n\n #release() {\n this.removeAttribute(\"data-open\");\n for (const [element, inert] of this.#inert) element.inert = inert;\n this.#inert.clear();\n this.#trigger?.setAttribute(\"aria-expanded\", \"false\");\n }\n\n disconnectedCallback() {\n this.#listeners?.abort();\n this.#release();\n }\n}\n\nclass CookbookHeaderLinks extends HTMLElement {\n #listeners?: AbortController;\n connectedCallback() {\n this.#listeners?.abort();\n this.#listeners = new AbortController();\n const { signal } = this.#listeners;\n const panel = this.querySelector<HTMLElement>(\"[popover]\");\n const desktop = matchMedia(\"(min-width: 50rem)\");\n const close = () => {\n if (panel?.matches(\":popover-open\")) panel.hidePopover();\n };\n if (panel) initializePopoverMotion(panel, signal);\n desktop.addEventListener(\n \"change\",\n () => {\n if (desktop.matches) close();\n },\n { signal },\n );\n panel?.addEventListener(\n \"click\",\n (event) => {\n if (event.target instanceof Element && event.target.closest(\"a[href]\"))\n close();\n },\n { signal },\n );\n }\n disconnectedCallback() {\n this.#listeners?.abort();\n }\n}\n\nif (!customElements.get(\"cookbook-sidebar-pane\"))\n customElements.define(\"cookbook-sidebar-pane\", CookbookSidebarPane);\nif (!customElements.get(\"cookbook-header-links\"))\n customElements.define(\"cookbook-header-links\", CookbookHeaderLinks);\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ //#region src/client/popover-motion.d.ts
2
+ /** Animate popovers after they have entered the top layer. */
3
+ declare function initializePopoverMotion(panel: HTMLElement, signal?: AbortSignal): void;
4
+ //#endregion
5
+ export { initializePopoverMotion };
6
+ //# sourceMappingURL=popover-motion.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-motion.d.ts","names":[],"sources":["../../src/client/popover-motion.ts"],"mappings":";;iBACgB,wBACd,OAAO,aACP,SAAS"}
@@ -0,0 +1,14 @@
1
+ //#region src/client/popover-motion.ts
2
+ /** Animate popovers after they have entered the top layer. */
3
+ function initializePopoverMotion(panel, signal) {
4
+ panel.addEventListener("toggle", () => {
5
+ if (panel.matches(":popover-open")) {
6
+ panel.getBoundingClientRect();
7
+ panel.setAttribute("data-open", "");
8
+ } else panel.removeAttribute("data-open");
9
+ }, signal ? { signal } : void 0);
10
+ }
11
+ //#endregion
12
+ export { initializePopoverMotion };
13
+
14
+ //# sourceMappingURL=popover-motion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popover-motion.js","names":[],"sources":["../../src/client/popover-motion.ts"],"sourcesContent":["/** Animate popovers after they have entered the top layer. */\nexport function initializePopoverMotion(\n panel: HTMLElement,\n signal?: AbortSignal,\n): void {\n panel.addEventListener(\n \"toggle\",\n () => {\n if (panel.matches(\":popover-open\")) {\n panel.getBoundingClientRect();\n panel.setAttribute(\"data-open\", \"\");\n } else {\n panel.removeAttribute(\"data-open\");\n }\n },\n signal ? { signal } : undefined,\n );\n}\n"],"mappings":";;AACA,SAAgB,wBACd,OACA,QACM;CACN,MAAM,iBACJ,gBACM;EACJ,IAAI,MAAM,QAAQ,eAAe,GAAG;GAClC,MAAM,sBAAsB;GAC5B,MAAM,aAAa,aAAa,EAAE;EACpC,OACE,MAAM,gBAAgB,WAAW;CAErC,GACA,SAAS,EAAE,OAAO,IAAI,KAAA,CACxB;AACF"}
@@ -52,7 +52,10 @@ function initializeSearch(element, options, development, base) {
52
52
  const show = async () => {
53
53
  if (dialog.open) return;
54
54
  returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : open;
55
+ dialog.removeAttribute("data-open");
55
56
  dialog.showModal();
57
+ dialog.getBoundingClientRect();
58
+ dialog.setAttribute("data-open", "");
56
59
  document.body.setAttribute("data-search-modal-open", "");
57
60
  if (!development && status) status.hidden = true;
58
61
  try {
@@ -70,6 +73,7 @@ function initializeSearch(element, options, development, base) {
70
73
  if (event.target.closest("a[href]") || !frame.contains(event.target)) dialog.close();
71
74
  });
72
75
  dialog.addEventListener("close", () => {
76
+ dialog.removeAttribute("data-open");
73
77
  document.body.removeAttribute("data-search-modal-open");
74
78
  returnFocus?.focus();
75
79
  });
@@ -1 +1 @@
1
- {"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\".dialog-frame\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let returnFocus: HTMLElement | null = null;\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n const format = (url: string) =>\n element.hasAttribute(\"data-strip-trailing-slash\")\n ? url.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : url;\n new PagefindUI({\n ...options,\n element: \"#cookbook__search\",\n baseUrl: base,\n bundlePath: `${base.replace(/\\/$/, \"\")}/pagefind/`,\n showImages: false,\n showSubResults: true,\n translations,\n processResult(result: SearchResult) {\n result = options.processResult?.(result) ?? result;\n result.url = format(result.url);\n result.sub_results?.forEach((child) => {\n child.url = format(child.url);\n });\n return result;\n },\n });\n })().catch((error: unknown) => {\n initialized = undefined;\n if (status) {\n status.hidden = false;\n // Reuse the localized Pagefind error, with a plain fallback.\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n status.textContent =\n translations.error ?? \"Search could not load. Close and try again.\";\n }\n throw error;\n }));\n };\n const show = async () => {\n if (dialog.open) return;\n returnFocus =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : open;\n dialog.showModal();\n document.body.setAttribute(\"data-search-modal-open\", \"\");\n if (!development && status) status.hidden = true;\n try {\n await initialize();\n // Pagefind mounts synchronously. Only focus if the user has not closed it.\n if (dialog.open) element.querySelector(\"input\")?.focus();\n } catch {\n /* Keep the close control usable when the search bundle fails. */\n }\n };\n open.addEventListener(\"click\", () => {\n void show();\n });\n open.disabled = false;\n close.addEventListener(\"click\", () => dialog.close());\n dialog.addEventListener(\"click\", (event) => {\n if (!(event.target instanceof Element)) return;\n if (event.target.closest(\"a[href]\") || !frame.contains(event.target))\n dialog.close();\n });\n dialog.addEventListener(\"close\", () => {\n document.body.removeAttribute(\"data-search-modal-open\");\n returnFocus?.focus();\n });\n window.addEventListener(\"keydown\", (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n if (dialog.open) dialog.close();\n else void show();\n }\n });\n}\n"],"mappings":";;AAMA,SAAgB,iBACd,SACA,SACA,aACA,MACM;CACN,IAAI,QAAQ,QAAQ,aAAa;CACjC,QAAQ,QAAQ,cAAc;CAC9B,MAAM,OAAO,QAAQ,cAAiC,mBAAmB;CACzE,MAAM,QAAQ,QAAQ,cAAiC,oBAAoB;CAC3E,MAAM,SAAS,QAAQ,cAAc,QAAQ;CAC7C,MAAM,QAAQ,QAAQ,cAAc,eAAe;CACnD,MAAM,SAAS,QAAQ,cAA2B,sBAAsB;CACxE,MAAM,WAAW,KAAK,cAAc,KAAK;CACzC,IAAI,0BAA0B,KAAK,UAAU,QAAQ,GAAG;EACtD,SAAS,cAAc,KAAK,CAAC,CAAE,cAAc;EAC7C,KAAK,aAAa,qBAAqB,QAAQ;CACjD;CACA,OAAO,SAAS,QAAQ;CACxB,IAAI;CACJ,IAAI,cAAkC;CACtC,MAAM,mBAAmB;EACvB,IAAI,aAAa,OAAO,QAAQ,QAAQ;EACxC,OAAQ,iBAAiB,YAAY;GAEnC,MAAM,EAAE,eAAe,MAAM,OAAO;GACpC,MAAM,eAAe,KAAK,MAAM,QAAQ,QAAQ,gBAAgB,IAAI;GACpE,MAAM,UAAU,QACd,QAAQ,aAAa,2BAA2B,IAC5C,IAAI,QAAQ,gBAAgB,MAAM,IAClC;GACN,IAAI,WAAW;IACb,GAAG;IACH,SAAS;IACT,SAAS;IACT,YAAY,GAAG,KAAK,QAAQ,OAAO,EAAE,EAAE;IACvC,YAAY;IACZ,gBAAgB;IAChB;IACA,cAAc,QAAsB;KAClC,SAAS,QAAQ,gBAAgB,MAAM,KAAK;KAC5C,OAAO,MAAM,OAAO,OAAO,GAAG;KAC9B,OAAO,aAAa,SAAS,UAAU;MACrC,MAAM,MAAM,OAAO,MAAM,GAAG;KAC9B,CAAC;KACD,OAAO;IACT;GACF,CAAC;EACH,EAAA,CAAG,CAAC,CAAC,OAAO,UAAmB;GAC7B,cAAc,KAAA;GACd,IAAI,QAAQ;IACV,OAAO,SAAS;IAEhB,MAAM,eAAe,KAAK,MAAM,QAAQ,QAAQ,gBAAgB,IAAI;IACpE,OAAO,cACL,aAAa,SAAS;GAC1B;GACA,MAAM;EACR,CAAC;CACH;CACA,MAAM,OAAO,YAAY;EACvB,IAAI,OAAO,MAAM;EACjB,cACE,SAAS,yBAAyB,cAC9B,SAAS,gBACT;EACN,OAAO,UAAU;EACjB,SAAS,KAAK,aAAa,0BAA0B,EAAE;EACvD,IAAI,CAAC,eAAe,QAAQ,OAAO,SAAS;EAC5C,IAAI;GACF,MAAM,WAAW;GAEjB,IAAI,OAAO,MAAM,QAAQ,cAAc,OAAO,CAAC,EAAE,MAAM;EACzD,QAAQ,CAER;CACF;CACA,KAAK,iBAAiB,eAAe;EACnC,KAAU;CACZ,CAAC;CACD,KAAK,WAAW;CAChB,MAAM,iBAAiB,eAAe,OAAO,MAAM,CAAC;CACpD,OAAO,iBAAiB,UAAU,UAAU;EAC1C,IAAI,EAAE,MAAM,kBAAkB,UAAU;EACxC,IAAI,MAAM,OAAO,QAAQ,SAAS,KAAK,CAAC,MAAM,SAAS,MAAM,MAAM,GACjE,OAAO,MAAM;CACjB,CAAC;CACD,OAAO,iBAAiB,eAAe;EACrC,SAAS,KAAK,gBAAgB,wBAAwB;EACtD,aAAa,MAAM;CACrB,CAAC;CACD,OAAO,iBAAiB,YAAY,UAAU;EAC5C,KAAK,MAAM,WAAW,MAAM,YAAY,MAAM,IAAI,YAAY,MAAM,KAAK;GACvE,MAAM,eAAe;GACrB,IAAI,OAAO,MAAM,OAAO,MAAM;QACzB,KAAU;EACjB;CACF,CAAC;AACH"}
1
+ {"version":3,"file":"search.js","names":[],"sources":["../../src/client/search.ts"],"sourcesContent":["type SearchResult = { url: string; sub_results?: SearchResult[] };\ntype PagefindOptions = Record<string, unknown> & {\n processResult?: (result: SearchResult) => SearchResult | void;\n};\n\n/** Own the dialog lifecycle; Pagefind owns indexing, filtering and result rendering. */\nexport function initializeSearch(\n element: HTMLElement,\n options: PagefindOptions,\n development: boolean,\n base: string,\n): void {\n if (element.dataset.initialized) return;\n element.dataset.initialized = \"true\";\n const open = element.querySelector<HTMLButtonElement>(\"[data-open-modal]\")!;\n const close = element.querySelector<HTMLButtonElement>(\"[data-close-modal]\")!;\n const dialog = element.querySelector(\"dialog\")!;\n const frame = element.querySelector(\".dialog-frame\")!;\n const status = element.querySelector<HTMLElement>(\"[data-search-status]\");\n const shortcut = open.querySelector(\"kbd\")!;\n if (/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)) {\n shortcut.querySelector(\"kbd\")!.textContent = \"⌘\";\n open.setAttribute(\"aria-keyshortcuts\", \"Meta+K\");\n }\n delete shortcut.dataset.pending;\n let initialized: Promise<void> | undefined;\n let returnFocus: HTMLElement | null = null;\n const initialize = () => {\n if (development) return Promise.resolve();\n return (initialized ??= (async () => {\n // @ts-expect-error Pagefind publishes no declarations for its default UI.\n const { PagefindUI } = await import(\"@pagefind/default-ui\");\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n const format = (url: string) =>\n element.hasAttribute(\"data-strip-trailing-slash\")\n ? url.replace(/(.)\\/(#.*)?$/, \"$1$2\")\n : url;\n new PagefindUI({\n ...options,\n element: \"#cookbook__search\",\n baseUrl: base,\n bundlePath: `${base.replace(/\\/$/, \"\")}/pagefind/`,\n showImages: false,\n showSubResults: true,\n translations,\n processResult(result: SearchResult) {\n result = options.processResult?.(result) ?? result;\n result.url = format(result.url);\n result.sub_results?.forEach((child) => {\n child.url = format(child.url);\n });\n return result;\n },\n });\n })().catch((error: unknown) => {\n initialized = undefined;\n if (status) {\n status.hidden = false;\n // Reuse the localized Pagefind error, with a plain fallback.\n const translations = JSON.parse(element.dataset.translations ?? \"{}\");\n status.textContent =\n translations.error ?? \"Search could not load. Close and try again.\";\n }\n throw error;\n }));\n };\n const show = async () => {\n if (dialog.open) return;\n returnFocus =\n document.activeElement instanceof HTMLElement\n ? document.activeElement\n : open;\n dialog.removeAttribute(\"data-open\");\n dialog.showModal();\n // Establish the initial state after entering the top layer. The global\n // style renderer does not preserve @starting-style in server output.\n dialog.getBoundingClientRect();\n dialog.setAttribute(\"data-open\", \"\");\n document.body.setAttribute(\"data-search-modal-open\", \"\");\n if (!development && status) status.hidden = true;\n try {\n await initialize();\n // Pagefind mounts synchronously. Only focus if the user has not closed it.\n if (dialog.open) element.querySelector(\"input\")?.focus();\n } catch {\n /* Keep the close control usable when the search bundle fails. */\n }\n };\n open.addEventListener(\"click\", () => {\n void show();\n });\n open.disabled = false;\n close.addEventListener(\"click\", () => dialog.close());\n dialog.addEventListener(\"click\", (event) => {\n if (!(event.target instanceof Element)) return;\n if (event.target.closest(\"a[href]\") || !frame.contains(event.target))\n dialog.close();\n });\n dialog.addEventListener(\"close\", () => {\n dialog.removeAttribute(\"data-open\");\n document.body.removeAttribute(\"data-search-modal-open\");\n returnFocus?.focus();\n });\n window.addEventListener(\"keydown\", (event) => {\n if ((event.metaKey || event.ctrlKey) && event.key.toLowerCase() === \"k\") {\n event.preventDefault();\n if (dialog.open) dialog.close();\n else void show();\n }\n });\n}\n"],"mappings":";;AAMA,SAAgB,iBACd,SACA,SACA,aACA,MACM;CACN,IAAI,QAAQ,QAAQ,aAAa;CACjC,QAAQ,QAAQ,cAAc;CAC9B,MAAM,OAAO,QAAQ,cAAiC,mBAAmB;CACzE,MAAM,QAAQ,QAAQ,cAAiC,oBAAoB;CAC3E,MAAM,SAAS,QAAQ,cAAc,QAAQ;CAC7C,MAAM,QAAQ,QAAQ,cAAc,eAAe;CACnD,MAAM,SAAS,QAAQ,cAA2B,sBAAsB;CACxE,MAAM,WAAW,KAAK,cAAc,KAAK;CACzC,IAAI,0BAA0B,KAAK,UAAU,QAAQ,GAAG;EACtD,SAAS,cAAc,KAAK,CAAC,CAAE,cAAc;EAC7C,KAAK,aAAa,qBAAqB,QAAQ;CACjD;CACA,OAAO,SAAS,QAAQ;CACxB,IAAI;CACJ,IAAI,cAAkC;CACtC,MAAM,mBAAmB;EACvB,IAAI,aAAa,OAAO,QAAQ,QAAQ;EACxC,OAAQ,iBAAiB,YAAY;GAEnC,MAAM,EAAE,eAAe,MAAM,OAAO;GACpC,MAAM,eAAe,KAAK,MAAM,QAAQ,QAAQ,gBAAgB,IAAI;GACpE,MAAM,UAAU,QACd,QAAQ,aAAa,2BAA2B,IAC5C,IAAI,QAAQ,gBAAgB,MAAM,IAClC;GACN,IAAI,WAAW;IACb,GAAG;IACH,SAAS;IACT,SAAS;IACT,YAAY,GAAG,KAAK,QAAQ,OAAO,EAAE,EAAE;IACvC,YAAY;IACZ,gBAAgB;IAChB;IACA,cAAc,QAAsB;KAClC,SAAS,QAAQ,gBAAgB,MAAM,KAAK;KAC5C,OAAO,MAAM,OAAO,OAAO,GAAG;KAC9B,OAAO,aAAa,SAAS,UAAU;MACrC,MAAM,MAAM,OAAO,MAAM,GAAG;KAC9B,CAAC;KACD,OAAO;IACT;GACF,CAAC;EACH,EAAA,CAAG,CAAC,CAAC,OAAO,UAAmB;GAC7B,cAAc,KAAA;GACd,IAAI,QAAQ;IACV,OAAO,SAAS;IAEhB,MAAM,eAAe,KAAK,MAAM,QAAQ,QAAQ,gBAAgB,IAAI;IACpE,OAAO,cACL,aAAa,SAAS;GAC1B;GACA,MAAM;EACR,CAAC;CACH;CACA,MAAM,OAAO,YAAY;EACvB,IAAI,OAAO,MAAM;EACjB,cACE,SAAS,yBAAyB,cAC9B,SAAS,gBACT;EACN,OAAO,gBAAgB,WAAW;EAClC,OAAO,UAAU;EAGjB,OAAO,sBAAsB;EAC7B,OAAO,aAAa,aAAa,EAAE;EACnC,SAAS,KAAK,aAAa,0BAA0B,EAAE;EACvD,IAAI,CAAC,eAAe,QAAQ,OAAO,SAAS;EAC5C,IAAI;GACF,MAAM,WAAW;GAEjB,IAAI,OAAO,MAAM,QAAQ,cAAc,OAAO,CAAC,EAAE,MAAM;EACzD,QAAQ,CAER;CACF;CACA,KAAK,iBAAiB,eAAe;EACnC,KAAU;CACZ,CAAC;CACD,KAAK,WAAW;CAChB,MAAM,iBAAiB,eAAe,OAAO,MAAM,CAAC;CACpD,OAAO,iBAAiB,UAAU,UAAU;EAC1C,IAAI,EAAE,MAAM,kBAAkB,UAAU;EACxC,IAAI,MAAM,OAAO,QAAQ,SAAS,KAAK,CAAC,MAAM,SAAS,MAAM,MAAM,GACjE,OAAO,MAAM;CACjB,CAAC;CACD,OAAO,iBAAiB,eAAe;EACrC,OAAO,gBAAgB,WAAW;EAClC,SAAS,KAAK,gBAAgB,wBAAwB;EACtD,aAAa,MAAM;CACrB,CAAC;CACD,OAAO,iBAAiB,YAAY,UAAU;EAC5C,KAAK,MAAM,WAAW,MAAM,YAAY,MAAM,IAAI,YAAY,MAAM,KAAK;GACvE,MAAM,eAAe;GACrB,IAAI,OAAO,MAAM,OAAO,MAAM;QACzB,KAAU;EACjB;CACF,CAAC;AACH"}
@@ -9,6 +9,7 @@ import closeIcon from "../icons/close.svg?raw";
9
9
  import copyIcon from "../icons/copy.svg?raw";
10
10
  import searchIcon from "../icons/search.svg?raw";
11
11
  import { resolveComponentStyles } from "./component-styles.js";
12
+ import { selectPopoverStyles } from "./select-popover-styles.js";
12
13
  import { svgIconUrl } from "./svg-icon.js";
13
14
  import { configureCookbookStates } from "./tasty-states.js";
14
15
  import { getDefaultFontUsage, getFontFaces } from "../theme/fonts.js";
@@ -40,7 +41,7 @@ export default function GlobalStyles() {
40
41
  colorScheme: "dark",
41
42
  "$docs-nav-height": {
42
43
  "": "4.5rem",
43
- ":has(.td-top-tabs)": "7rem",
44
+ ":has(.td-top-tabs)": "7.25rem",
44
45
  "@mobile": "3.5rem",
45
46
  "@mobile & [data-has-sidebar]": "6.5rem",
46
47
  },
@@ -313,6 +314,7 @@ export default function GlobalStyles() {
313
314
  "site-search",
314
315
  resolveComponentStyles("Search", {
315
316
  display: "contents",
317
+ "$dialog-transition": "120ms",
316
318
  Status: {
317
319
  $: "[data-search-status]",
318
320
  margin: "auto",
@@ -323,7 +325,7 @@ export default function GlobalStyles() {
323
325
  Dialog: {
324
326
  $: "dialog",
325
327
  radius: { "": "$card-radius", "@mobile": "0" },
326
- inlineSize: { "": "90% max 40rem", "@mobile": "100% max 100%" },
328
+ inlineSize: { "": "0 90% 40rem", "@mobile": "100%" },
327
329
  blockSize: { "": "max-content", "@mobile": "100%" },
328
330
  maxBlockSize: { "": "(100% - 8rem)", "@mobile": "100%" },
329
331
  minBlockSize: { "": "15rem", "@mobile": "100%" },
@@ -333,6 +335,13 @@ export default function GlobalStyles() {
333
335
  border: true,
334
336
  fill: "#surface",
335
337
  shadow: "0 1rem 3rem #shadow",
338
+ opacity: "0",
339
+ scale: { "": "0.98", "@mobile": "1" },
340
+ transition: {
341
+ "": "none",
342
+ "!@reduced-motion":
343
+ "opacity $dialog-transition ease-out, scale $dialog-transition ease-out, display $dialog-transition allow-discrete, overlay $dialog-transition allow-discrete",
344
+ },
336
345
  },
337
346
  CloseIcon: {
338
347
  $: "button[data-close-modal]::before",
@@ -347,46 +356,58 @@ export default function GlobalStyles() {
347
356
  mask: `url("${svgIconUrl(closeIcon)}") center / contain no-repeat`,
348
357
  },
349
358
  OpenDialog: { $: "dialog[open]", display: "flex" },
359
+ EnteredDialog: {
360
+ $: "dialog[open][data-open]",
361
+ opacity: "1",
362
+ scale: "1",
363
+ },
350
364
  Backdrop: {
351
365
  $: "dialog::backdrop",
352
366
  fill: "#overlay",
353
367
  backdropFilter: "blur(0.25rem)",
368
+ opacity: "0",
369
+ transition: {
370
+ "": "none",
371
+ "!@reduced-motion":
372
+ "opacity $dialog-transition ease-out, display $dialog-transition allow-discrete, overlay $dialog-transition allow-discrete",
373
+ },
374
+ },
375
+ EnteredBackdrop: {
376
+ $: "dialog[open][data-open]::backdrop",
377
+ opacity: "1",
354
378
  },
355
379
  Frame: {
356
380
  $: ".dialog-frame",
357
- position: "relative",
358
381
  display: "flex",
359
382
  flow: "column",
360
383
  flexGrow: "1",
384
+ minBlockSize: "0",
361
385
  gap: "($gap * 2)",
362
- padding: { "": "($gap * 3)", "@mobile": "($gap * 2)" },
363
- overflow: "auto",
386
+ padding: { "": "($gap * 3)", "@mobile": "($gap * 2) ($gap * 2) 0" },
387
+ overflow: "hidden",
364
388
  },
365
389
  Container: {
366
390
  $: ".search-container",
391
+ display: "flex",
392
+ flow: "column",
393
+ flexGrow: "1",
367
394
  inlineSize: "100%",
368
- paddingBlockStart: { "": "0", "@mobile": "4rem" },
395
+ minBlockSize: "0",
369
396
  },
370
397
  Close: {
371
398
  $: "button[data-close-modal]",
372
- position: "absolute",
373
- zIndex: "1",
374
- insetBlockStart: "($gap * 2)",
375
- insetInlineEnd: "($gap * 2)",
376
- display: { "": "none", "@mobile": "flex" },
377
- alignItems: "center",
378
- justifyContent: "center",
379
- gap: "0.375rem",
380
- blockSize: "3rem",
381
- minBlockSize: "3rem",
382
- paddingInlineStart: "0.625rem",
383
- paddingInlineEnd: "0.625rem",
399
+ display: { "": "none", "@mobile": "grid" },
400
+ placeItems: "center",
401
+ alignSelf: "flex-end",
402
+ flexShrink: "0",
403
+ inlineSize: "$docs-menu-button-size",
404
+ blockSize: "$docs-menu-button-size",
405
+ minBlockSize: "$docs-menu-button-size",
406
+ padding: "0",
384
407
  color: "#text-soft",
385
- border: true,
386
- borderColor: "#border",
387
- radius: "$radius",
388
- fill: "#surface-3",
389
- preset: "small / strong",
408
+ border: "0",
409
+ radius: "$header-control-radius",
410
+ fill: "#clear",
390
411
  boxShadow: "none",
391
412
  cursor: "pointer",
392
413
  transition: "color $transition, background-color $transition",
@@ -394,12 +415,12 @@ export default function GlobalStyles() {
394
415
  HoverClose: {
395
416
  $: "button[data-close-modal]:hover",
396
417
  color: "#text",
397
- fill: "#surface-3-hover",
418
+ fill: "#surface-2-hover",
398
419
  },
399
420
  ActiveClose: {
400
421
  $: "button[data-close-modal]:active",
401
422
  color: "#text",
402
- fill: "#surface-3-pressed",
423
+ fill: "#surface-2-pressed",
403
424
  },
404
425
  }),
405
426
  );
@@ -600,7 +621,7 @@ export default function GlobalStyles() {
600
621
  minBlockSize: "100%",
601
622
  inlinePadding: "$docs-sidebar-pad-x",
602
623
  gap: "($gap * 2)",
603
- paddingBlockStart: "($gap * 2)",
624
+ paddingBlockStart: { "": "($gap * 3)", "@mobile": "($gap * 2)" },
604
625
  paddingBlockEnd: "($gap * 6)",
605
626
  },
606
627
  Tree: { $: "cookbook-sidebar", display: "block" },
@@ -723,7 +744,7 @@ export default function GlobalStyles() {
723
744
  },
724
745
  TopLevelLink: {
725
746
  $: 'a.large:not([aria-current="page"])',
726
- color: "#text",
747
+ color: "#sidebar-text",
727
748
  preset: "navigation",
728
749
  },
729
750
  }),
@@ -734,7 +755,7 @@ export default function GlobalStyles() {
734
755
  resolveComponentStyles("TableOfContents", {
735
756
  display: "block",
736
757
  hide: { "": false, "@narrow-layout": true },
737
- paddingBlockStart: "($gap * 3)",
758
+ paddingBlockStart: "($gap * 4)",
738
759
  paddingInlineStart: "$docs-sidebar-pad-x",
739
760
  paddingInlineEnd: "$docs-sidebar-pad-x",
740
761
  Heading: {
@@ -915,8 +936,9 @@ export default function GlobalStyles() {
915
936
  marginBlockStart: "0",
916
937
  marginBlockEnd: "0",
917
938
  },
939
+ // Linked Cards are block content even though their root is an anchor.
918
940
  BlockSpacing: {
919
- $: ":not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *)",
941
+ $: ":not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *), :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br) + a.td-card, a.td-card + :not(a):not(strong):not(em):not(del):not(span):not(input):not(code):not(br):not(li):not(dt):not(dd):not(.not-content *), a.td-card + a.td-card",
920
942
  marginBlockStart: "($gap * 3)",
921
943
  },
922
944
  HeadingSpacing: {
@@ -1153,21 +1175,21 @@ export default function GlobalStyles() {
1153
1175
  lineHeight: "0",
1154
1176
  },
1155
1177
  DiffLine: {
1156
- $: "pre.td-diff .line",
1178
+ $: "pre.td-diff > code > .line",
1157
1179
  display: "block",
1158
1180
  inlinePadding: "1rem",
1159
1181
  preset: "code",
1160
1182
  },
1161
1183
  EmptyDiffLine: {
1162
- $: "pre.td-diff .line:empty::before",
1184
+ $: "pre.td-diff > code > .line:empty::before",
1163
1185
  content: '"\\200b"',
1164
1186
  },
1165
1187
  InsertedLine: {
1166
- $: "pre.td-diff .td-diff-line--inserted",
1188
+ $: "pre.td-diff > code > .td-diff-line--inserted",
1167
1189
  fill: "#green-surface",
1168
1190
  },
1169
1191
  DeletedLine: {
1170
- $: "pre.td-diff .td-diff-line--deleted",
1192
+ $: "pre.td-diff > code > .td-diff-line--deleted",
1171
1193
  fill: "#red-surface",
1172
1194
  },
1173
1195
  }),
@@ -1367,6 +1389,10 @@ export default function GlobalStyles() {
1367
1389
  gap: "$gap",
1368
1390
  inlineSize: { "": "100%", "@mobile": "$docs-menu-button-size" },
1369
1391
  maxInlineSize: "22rem",
1392
+ marginInlineStart: {
1393
+ "": "0",
1394
+ "@media(w >= 80rem)": "min(5rem, max(0px, calc(100% - 22rem)))",
1395
+ },
1370
1396
  blockSize: { "": "$control-height", "@mobile": "$docs-menu-button-size" },
1371
1397
  minBlockSize: "0",
1372
1398
  padding: { "": "0 $gap 0 ($gap * 1.5)", "@mobile": "0" },
@@ -1407,53 +1433,95 @@ export default function GlobalStyles() {
1407
1433
  }),
1408
1434
  );
1409
1435
 
1436
+ const languageSelectStyles = selectPopoverStyles();
1410
1437
  useGlobalStyles(
1411
1438
  "cookbook-language-select",
1412
1439
  resolveComponentStyles("LanguageSelect", {
1413
- display: "block",
1414
- Label: {
1415
- $: "label",
1416
- position: "relative",
1417
- display: "flex",
1418
- alignItems: "center",
1419
- color: "#text-soft",
1420
- },
1421
- HoverLabel: { $: "label:hover", color: "#text" },
1422
- LabelIcon: {
1423
- $: ".label-icon",
1424
- position: "absolute",
1425
- zIndex: "1",
1426
- insetInlineStart: "$gap",
1427
- pointerEvents: "none",
1440
+ display: "flex",
1441
+ flexShrink: "0",
1442
+ "$popover-transition": languageSelectStyles["$popover-transition"],
1443
+ Compact: {
1444
+ $: "&[data-compact]",
1428
1445
  },
1429
- Select: {
1430
- $: "select",
1431
- appearance: "none",
1446
+ Trigger: {
1447
+ ...languageSelectStyles.Trigger,
1432
1448
  inlineSize: "8rem",
1433
- minBlockSize: "$control-height",
1434
- paddingInlineStart: "($gap * 3.5)",
1435
- paddingInlineEnd: "($gap * 3.5)",
1436
- color: "#text-soft",
1437
- border: "0",
1438
- radius: "$header-control-radius",
1449
+ blockSize: "$control-height",
1450
+ padding: "0 $gap",
1439
1451
  fill: "#clear",
1440
- preset: "small",
1441
- cursor: "pointer",
1442
- textOverflow: "ellipsis",
1452
+ border: "0",
1453
+ transition: "color $transition, fill $transition",
1443
1454
  },
1444
- Caret: {
1445
- $: ".caret",
1446
- position: "absolute",
1447
- insetInlineEnd: "$gap",
1448
- pointerEvents: "none",
1455
+ HoverTrigger: languageSelectStyles.HoverTrigger,
1456
+ ActiveTrigger: {
1457
+ $: "> button:active",
1458
+ color: "#text",
1459
+ fill: "#surface-2-pressed",
1460
+ },
1461
+ LabelIcon: {
1462
+ $: "> button > .label-icon",
1463
+ display: "block",
1464
+ flexShrink: "0",
1465
+ inlineSize: { "": "1.25rem", "@mobile": "1.125rem" },
1466
+ blockSize: { "": "1.25rem", "@mobile": "1.125rem" },
1467
+ },
1468
+ TriggerLabel: languageSelectStyles.TriggerLabel,
1469
+ Caret: languageSelectStyles.Caret,
1470
+ CompactTrigger: {
1471
+ $: "&[data-compact] > button",
1472
+ inlineSize: "$docs-menu-button-size",
1473
+ blockSize: "$docs-menu-button-size",
1474
+ padding: "0",
1449
1475
  },
1450
- Option: { $: "option", color: "#text", fill: "#surface-2" },
1476
+ CompactLabel: {
1477
+ $: "&[data-compact] > button > .trigger-label",
1478
+ hide: true,
1479
+ },
1480
+ CompactCaret: { $: "&[data-compact] > button > .caret", hide: true },
1481
+ Label: { $: "> button" },
1482
+ HoverLabel: { $: "> button:hover" },
1483
+ Select: { $: "> button" },
1484
+ CompactSelect: { $: "&[data-compact] > button" },
1485
+ CompactLabelIcon: { $: "&[data-compact] > button > .label-icon" },
1486
+ SidebarTrigger: {
1487
+ $: "&[data-sidebar] > button",
1488
+ anchorName: "--language-trigger",
1489
+ },
1490
+ Panel: {
1491
+ ...languageSelectStyles.Panel,
1492
+ blockInset: { "": "4rem start", "@mobile": "3.5rem start" },
1493
+ inlineInset:
1494
+ "max($docs-nav-pad-x, ((100vw - $layout-width) / 2 + $docs-sidebar-pad-x)) end",
1495
+ },
1496
+ SidebarPanel: {
1497
+ $: "&[data-sidebar] > [popover]",
1498
+ positionAnchor: "--language-trigger",
1499
+ blockInset: "auto start, anchor(top) end",
1500
+ blockMargin: "$gap end",
1501
+ inlineInset: "$gap start, auto end",
1502
+ inlineSize: "min(20rem, calc(100vw - 4rem))",
1503
+ blockSize: "max (100dvh - 8rem)",
1504
+ transformOrigin: "bottom",
1505
+ },
1506
+ OpenPanel: languageSelectStyles.OpenPanel,
1507
+ PanelTitle: languageSelectStyles.PanelTitle,
1508
+ Options: languageSelectStyles.Options,
1509
+ Option: languageSelectStyles.Option,
1510
+ HoverOption: languageSelectStyles.HoverOption,
1511
+ CurrentOption: languageSelectStyles.CurrentOption,
1512
+ Fallback: { $: ".fallback-label", color: "#text-muted" },
1513
+ Checkmark: languageSelectStyles.Checkmark,
1514
+ SelectedCheckmark: languageSelectStyles.SelectedCheckmark,
1451
1515
  }),
1452
1516
  );
1453
1517
 
1454
1518
  useGlobalStyles(
1455
1519
  "#cookbook__search",
1456
1520
  resolveComponentStyles("SearchResults", {
1521
+ display: "flex",
1522
+ flow: "column",
1523
+ flexGrow: "1",
1524
+ minBlockSize: "0",
1457
1525
  "$pagefind-ui-primary": "#accent-text",
1458
1526
  "$pagefind-ui-text": "#text-soft",
1459
1527
  "$pagefind-ui-background": "#surface",
@@ -1461,9 +1529,31 @@ export default function GlobalStyles() {
1461
1529
  "$pagefind-ui-border-width": "$border-width",
1462
1530
  "$pagefind-ui-tag": "#surface-3",
1463
1531
  preset: "body",
1464
- Form: { $: ".pagefind-ui__form", position: "relative" },
1532
+ UI: {
1533
+ $: ".pagefind-ui",
1534
+ display: "flex",
1535
+ flow: "column",
1536
+ flexGrow: "1",
1537
+ minBlockSize: "0",
1538
+ },
1539
+ Form: {
1540
+ $: ".pagefind-ui__form",
1541
+ position: "relative",
1542
+ display: "flex",
1543
+ flow: "column",
1544
+ flexGrow: "1",
1545
+ minBlockSize: "0",
1546
+ },
1547
+ Drawer: {
1548
+ $: ".pagefind-ui__drawer",
1549
+ display: "flex",
1550
+ flow: "column",
1551
+ flexGrow: "1",
1552
+ minBlockSize: "0",
1553
+ },
1465
1554
  Input: {
1466
1555
  $: ".pagefind-ui__search-input",
1556
+ flexShrink: "0",
1467
1557
  inlineSize: "100%",
1468
1558
  minBlockSize: "3rem",
1469
1559
  paddingInlineStart: "2.75rem",
@@ -1494,7 +1584,15 @@ export default function GlobalStyles() {
1494
1584
  },
1495
1585
  Results: {
1496
1586
  $: ".pagefind-ui__results-area",
1497
- marginBlockStart: "($gap * 3)",
1587
+ flexGrow: "1",
1588
+ minBlockSize: "0",
1589
+ overflowY: "auto",
1590
+ marginBlockStart: { "": "($gap * 3)", "@mobile": "($gap * 2)" },
1591
+ borderBlockStart: "$border-width solid #border",
1592
+ inlineSize: { "@mobile": "(100% + ($gap * 4))" },
1593
+ inlineMargin: { "@mobile": "(-1 * $gap * 2)" },
1594
+ inlinePadding: { "@mobile": "($gap * 2)" },
1595
+ paddingBlockEnd: { "@mobile": "($gap * 2)" },
1498
1596
  },
1499
1597
  Result: {
1500
1598
  $: ".pagefind-ui__result",
@@ -1544,6 +1642,9 @@ export default function GlobalStyles() {
1544
1642
  },
1545
1643
  More: {
1546
1644
  $: ".pagefind-ui__button",
1645
+ display: { "@mobile": "block" },
1646
+ inlineSize: { "@mobile": "max-content" },
1647
+ marginInlineStart: { "@mobile": "auto" },
1547
1648
  padding: "1x 2x",
1548
1649
  border: true,
1549
1650
  radius: "$radius",
@@ -1,11 +1,22 @@
1
1
  ---
2
2
  import { messages } from "../localization.js";
3
+ import { localeHref, routeLocale } from "../localization.js";
4
+ import { navigationPath } from "../navigation.js";
3
5
  import { content } from "virtual:cookbook/config";
4
6
  import { HeaderLinksRoot } from "./LayoutComponents.js";
5
7
 
6
8
  const links = content.site.headerLinks ?? [];
7
9
  const base = import.meta.env.BASE_URL.replace(/\/$/, "");
8
- const href = (link: string) => (link.startsWith("/") ? `${base}${link}` : link);
10
+ const currentPath = navigationPath(Astro.url.pathname, base || "/");
11
+ const href = (link: string) =>
12
+ localeHref(link, currentPath, content.routes, content, base || "/");
13
+ const locale = routeLocale(currentPath, content);
14
+ const language =
15
+ content.locales?.[locale]?.lang ?? (locale === "root" ? "en" : locale);
16
+ const label = (value: string) =>
17
+ content.translations?.[language]?.[`navigation.${value}`] ??
18
+ content.translations?.[language.split("-")[0]!]?.[`navigation.${value}`] ??
19
+ value;
9
20
  const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
10
21
  ---
11
22
 
@@ -20,7 +31,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
20
31
  target={link.newTab ? "_blank" : undefined}
21
32
  rel={link.newTab ? "noopener noreferrer" : undefined}
22
33
  >
23
- {link.label}
34
+ {label(link.label)}
24
35
  </a>
25
36
  ))}
26
37
  </nav>
@@ -74,7 +85,7 @@ const ui = messages(Astro.locals.cookbookRoute?.lang ?? "en", content);
74
85
  target={link.newTab ? "_blank" : undefined}
75
86
  rel={link.newTab ? "noopener noreferrer" : undefined}
76
87
  >
77
- {link.label}
88
+ {label(link.label)}
78
89
  </a>
79
90
  ))}
80
91
  </nav>
@@ -23,7 +23,7 @@ const originals: Record<string, string> = {
23
23
  laptop: desktop,
24
24
  "approve-check": check,
25
25
  translate:
26
- '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><path d="M3 12h18M12 3a15 15 0 0 1 0 18M12 3a15 15 0 0 0 0 18"/></svg>',
26
+ '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><circle cx="12" cy="12" r="9"/><ellipse cx="12" cy="12" rx="4" ry="9"/><path d="M3 12h18"/></svg>',
27
27
  github:
28
28
  '<svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 2a10 10 0 0 0-3.16 19.49c.5.09.68-.22.68-.48v-1.7c-2.77.6-3.36-1.18-3.36-1.18-.45-1.14-1.1-1.44-1.1-1.44-.9-.62.07-.6.07-.6 1 .07 1.53 1.03 1.53 1.03.89 1.52 2.33 1.08 2.9.83.09-.65.35-1.08.63-1.33-2.21-.25-4.53-1.1-4.53-4.94 0-1.09.39-1.98 1.03-2.68-.1-.25-.45-1.27.1-2.65 0 0 .84-.27 2.75 1.02A9.6 9.6 0 0 1 12 6.66c.85 0 1.7.11 2.5.34 1.9-1.29 2.74-1.02 2.74-1.02.55 1.38.2 2.4.1 2.65.64.7 1.03 1.59 1.03 2.68 0 3.85-2.33 4.68-4.55 4.93.36.31.68.92.68 1.86v2.91c0 .27.18.58.69.48A10 10 0 0 0 12 2Z"/></svg>',
29
29
  gitlab: