diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 000000000..b2dbcaf5b --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,8 @@ +{ + "permissions": { + "allow": [ + "Skill(playwright-cli)", + "Skill(playwright-cli:*)" + ] + } +} diff --git a/docs/src/lib/attachments/hideybar.ts b/docs/src/lib/attachments/hideybar.ts new file mode 100644 index 000000000..3ac78683c --- /dev/null +++ b/docs/src/lib/attachments/hideybar.ts @@ -0,0 +1,57 @@ +import { on } from 'svelte/events'; + +/** Hides a sticky bar on scroll down, reveals on scroll up. */ +export function hideybar({ offsetTop = '0px', mx = '0px', threshold = 0 } = {}) { + return (node: HTMLElement) => { + const parent = node.parentElement; + if (!parent) return; + + const spacer = document.createElement('div'); + node.insertAdjacentElement('afterend', spacer); + + node.style.position = 'fixed'; + node.style.top = offsetTop; + node.style.transform = 'translateY(0)'; + node.style.transition = 'transform 200ms ease-in-out'; + node.style.overflow = 'hidden'; + + const syncSize = () => { + const parentRect = parent.getBoundingClientRect(); + node.style.left = `calc(${parentRect.left}px + ${mx})`; + node.style.width = `calc(${parentRect.width}px - ${mx} * 2)`; + const h = node.getBoundingClientRect().height; + if (h > 0) spacer.style.height = `${h}px`; + }; + syncSize(); + + const ro = new ResizeObserver(syncSize); + ro.observe(parent); + ro.observe(node); + + let lastScrollY = window.scrollY; + let isHidden = false; + const cleanupScroll = on( + window, + 'scroll', + () => { + const currentScrollY = window.scrollY; + const goingUp = currentScrollY < lastScrollY; + const shouldHide = !goingUp && currentScrollY > threshold; + if (shouldHide !== isHidden) { + node.style.transform = shouldHide + ? `translateY(calc(-100% - ${offsetTop}))` + : 'translateY(0)'; + isHidden = shouldHide; + } + lastScrollY = currentScrollY; + }, + { passive: true } + ); + + return () => { + cleanupScroll(); + ro.disconnect(); + spacer.remove(); + }; + }; +} diff --git a/docs/src/lib/components/OpenWithButton.svelte b/docs/src/lib/components/OpenWithButton.svelte index 1aeb9908e..bc1c00a69 100644 --- a/docs/src/lib/components/OpenWithButton.svelte +++ b/docs/src/lib/components/OpenWithButton.svelte @@ -90,10 +90,18 @@ } - + - - {/if} - -
-
- {metadata.category} -
+ const title = $derived( + pageExample?.module?.title ?? + toTitleCase(page.params.example?.replaceAll('-', ' ') ?? toTitleCase(metadata.name)) + ); - {#if page.params.example} - - {metadata.name} - {/if} -
+ const breadcrumbs = $derived([ + { label: metadata.category }, + ...(page.params.example + ? [{ label: metadata.name, href: `/docs/components/${page.params.name}` }] + : []), + { + label: title, + href: `/docs/components/${metadata.name}/${title.toLowerCase().replaceAll(' ', '-')}` + } + ]); + -
-

- {pageExample?.module?.title ?? page.params.example?.replaceAll('-', ' ') ?? metadata.name} -

- +
+
+ + {#snippet item({ item }: { item: (typeof breadcrumbs)[number] })} + {#if item.href} + {item.label} + {:else} + {item.label} + {/if} + {/snippet} + + {#if layers?.length} {#each layers as layer} {toTitleCase(layer)} {/each} {/if} - +
- - {#if pageExample?.module?.description} -
{pageExample.module.description}
- {/if} - - {#if page.params.example == null} -
{metadata.description}
- -
- - - - - -
- {/if}
+{#if showScrollToTop} +
+ + + +
+{/if} + +

{ + navigator.clipboard.writeText(`[${title}](${url})`); + }} +> + {title} +

+{#if pageExample?.module?.description} +
{pageExample.module.description}
+{/if} + +{#if page.params.example == null} +
{metadata.description}
+ + +{/if} + {#snippet pending()} diff --git a/docs/src/routes/docs/components/[name]/[example]/+page.svelte b/docs/src/routes/docs/components/[name]/[example]/+page.svelte index 0ff3daef5..0e737d1aa 100644 --- a/docs/src/routes/docs/components/[name]/[example]/+page.svelte +++ b/docs/src/routes/docs/components/[name]/[example]/+page.svelte @@ -5,7 +5,6 @@ import ComponentLink from '$lib/components/ComponentLink.svelte'; import ExampleListing from '$lib/components/ExampleListing.svelte'; - import OpenWithButton from '$lib/components/OpenWithButton.svelte'; let { data } = $props(); @@ -15,10 +14,6 @@ const exampleInfo = $derived(data.catalog?.examples.find((e) => e.name === example)); -
- -
-

Components

diff --git a/docs/vite.config.ts b/docs/vite.config.ts index 772b633b6..3f641764d 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -34,7 +34,7 @@ export default defineConfig({ }) /*, devtoolsJson()*/ ], server: { - // allowedHosts: ['.trycloudflare.com'], + allowedHosts: ['.ngrok-free.app', '.trycloudflare.com'], fs: { allow: ['.live-code'] },