anentrypoint-design 0.0.477 → 0.0.478
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 +101 -0
- package/dist/247420.css +139 -0
- package/dist/247420.js +124 -56
- package/dist/index.html +109 -32
- package/package.json +1 -1
- package/src/components/content/hero.js +9 -2
- package/src/components/freddie/pages-missing.js +1 -1
- package/src/components/shell/app-shell.js +15 -4
- package/src/copy-code.js +103 -0
- package/src/css/app-shell/catalog-theme.css +6 -0
- package/src/css/app-shell/files.css +6 -0
- package/src/css/app-shell/hero-content.css +13 -0
- package/src/css/app-shell/kits-appended.css +13 -0
- package/src/css/app-shell/panel-row.css +15 -0
- package/src/css/app-shell/row-print.css +34 -0
- package/src/css/app-shell/states-interactions.css +42 -0
- package/src/css/app-shell/topbar.css +1 -0
- package/src/kits/os/theme.css +21 -0
- package/src/kits/os/wm.js +38 -1
- package/src/page-html/client-script.js +96 -28
- package/src/page-html.js +3 -2
- package/src/theme.js +6 -2
- package/src/web-components/ds-chat.js +9 -0
- package/types/components.d.ts +2 -0
package/dist/index.html
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
<meta name="description" content="the visual paradigm. layered surfaces, monospace labels, loud content inside quiet chrome. consumed by every 247420 surface.">
|
|
9
9
|
<meta name="keywords" content="design-system, tokens, 247420, anentrypoint">
|
|
10
|
-
<meta name="author" content="247420
|
|
10
|
+
<meta name="author" content="247420 · a design system by AnEntrypoint">
|
|
11
11
|
<meta name="robots" content="index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1">
|
|
12
12
|
<meta name="generator" content="anentrypoint-design">
|
|
13
13
|
<link rel="canonical" href="https://anentrypoint.github.io/design">
|
|
@@ -116,14 +116,21 @@ a.row:hover .ds-row-arrow { opacity: 1 }
|
|
|
116
116
|
.ds-page-footer-links a { color: var(--fg-3) }
|
|
117
117
|
.ds-page-footer-links a:hover { color: var(--fg) }
|
|
118
118
|
</style>
|
|
119
|
-
<script id="__site__" type="application/json">{"title":"design","slug":"index","siteName":"design","navItems":[["247420","https://247420.xyz"],["AnEntrypoint ->","https://github.com/AnEntrypoint"]],"theme":"auto","hero":{"heading":"design","subheading":"the 247420 design system","body":"14 kit surfaces, zero raw color literals, one importmap script tag to install. every panel, row, and form control in this system reads its color, radius, and spacing from a single token file — swap the tokens and every surface built on them changes with it.","badges":[{"label":"design-system"},{"label":"tokens"},{"label":"web"}],"ctas":[{"label":"GitHub","href":"https://github.com/AnEntrypoint/design","primary":true},{"label":"247420","href":"https://247420.xyz"}]},"sections":[],"examples":[{"label":"index shell","desc":"full navigation shell with tabs, filters, and row interactions.","href":"./index.html"},{"label":"homepage kit","desc":"hero + works layout and updated readable type scale.","href":"./ui_kits/homepage/"},{"label":"project page kit","desc":"overview, install, receipt, and changelog template.","href":"./ui_kits/project_page/"},{"label":"docs kit","desc":"technical documentation layout with sidebar and prose.","href":"./ui_kits/docs/"},{"label":"blog kit","desc":"long-form writing layout tuned for readability.","href":"./ui_kits/blog/"},{"label":"chat kit","desc":"message thread + composer with pill bubbles and room sidebar.","href":"./ui_kits/chat/"},{"label":"aicat kit","desc":"ai assistant with cat persona — ascii portrait + mood face.","href":"./ui_kits/aicat/"},{"label":"slide deck","desc":"16:9 deck stage with improved presenter controls text.","href":"./slides/"},{"label":"dashboard kit","desc":"kpis, tables, receipts, changelog — operations surface.","href":"./ui_kits/dashboard/"},{"label":"terminal kit","desc":"cli prompt, command lines, log viewer.","href":"./ui_kits/terminal/"},{"label":"settings kit","desc":"sectioned forms, toggles, segmented buttons, save bar.","href":"./ui_kits/settings/"},{"label":"signin kit","desc":"auth panel, providers, magic link.","href":"./ui_kits/signin/"},{"label":"search kit","desc":"query bar, faceted filters, ranked results.","href":"./ui_kits/search/"},{"label":"404 kit","desc":"empty-state hero with suggested routes.","href":"./ui_kits/error_404/"},{"label":"gallery kit","desc":"visual grid + lightbox over tonal cards.","href":"./ui_kits/gallery/"},{"label":"preview samples","desc":"design previews and component samples.","href":"./preview/buttons.html"}],"bodyHtml":"","sidebar":{"sections":[{"group":"open","items":[{"glyph":"+","label":"open","href":"./ui_kits/homepage/"}]},{"group":"bins","items":[{"label":"everything","href":"#all","active":true,"count":43},{"label":"pinned","href":"#kits","count":14},{"label":"shipped","href":"#previews","count":25},{"label":"drafts","href":"#decks","count":1}]},{"group":"labels","items":[{"label":"ui kits","href":"#kits","count":14},{"label":"decks","href":"#decks","count":1},{"label":"previews","href":"#previews","count":25},{"label":"docs","href":"#docs","count":3}]},{"group":"more","items":[{"label":"readme","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"label":"skill","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"label":"tokens","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"label":"source","href":"https://github.com/AnEntrypoint/design"}]}]},"marquee":{"items":["open source","design tokens","buildless components","zero raw color literals"],"sep":"/"},"panels":[{"id":"kits","title":"ui kits","count":"14 surfaces","items":[{"code":"","title":"homepage","sub":"marquee + works grid","meta":"open ->","href":"./ui_kits/homepage/"},{"code":"","title":"project page","sub":"hero receipt install changelog","meta":"open ->","href":"./ui_kits/project_page/"},{"code":"","title":"docs","sub":"long-form prose chrome","meta":"open ->","href":"./ui_kits/docs/"},{"code":"","title":"blog","sub":"dated index + reading view","meta":"open ->","href":"./ui_kits/blog/"},{"code":"","title":"chat","sub":"message thread + composer","meta":"open ->","href":"./ui_kits/chat/"},{"code":"","title":"aicat","sub":"ai assistant with cat persona","meta":"open ->","href":"./ui_kits/aicat/"},{"code":"","title":"file browser","sub":"rails by file type drop preview","meta":"open ->","href":"./ui_kits/file_browser/"},{"code":"","title":"dashboard","sub":"kpis tables receipts changelog","meta":"open ->","href":"./ui_kits/dashboard/"},{"code":"","title":"terminal","sub":"cli prompt command lines log view","meta":"open ->","href":"./ui_kits/terminal/"},{"code":"","title":"settings","sub":"sectioned forms toggles save bar","meta":"open ->","href":"./ui_kits/settings/"},{"code":"","title":"signin","sub":"auth providers magic link","meta":"open ->","href":"./ui_kits/signin/"},{"code":"","title":"search","sub":"topbar query faceted filters rows","meta":"open ->","href":"./ui_kits/search/"},{"code":"","title":"404","sub":"empty-state hero suggested routes","meta":"open ->","href":"./ui_kits/error_404/"},{"code":"","title":"gallery","sub":"visual grid tonal cards lightbox","meta":"open ->","href":"./ui_kits/gallery/"}]},{"id":"file_browser","title":"file browser","count":"primitives","items":[{"code":"fb","title":"file_browser kit","sub":"drop, list, preview, dialogs","meta":"open kit","href":"./ui_kits/file_browser/"},{"code":"fb","title":"FileRow","sub":"rail icon name meta","meta":"preview","href":"./preview/file-row.html"},{"code":"fb","title":"FileGrid","sub":"stack of rows in a panel","meta":"preview","href":"./preview/file-grid.html"},{"code":"fb","title":"DropZone","sub":"tonal upload target","meta":"preview","href":"./preview/dropzone.html"},{"code":"fb","title":"FileViewer","sub":"modal preview keyed head","meta":"preview","href":"./preview/file-viewer.html"},{"code":"fb","title":"FileToolbar","sub":"actions breadcrumb upload","meta":"preview","href":"./preview/file-toolbar.html"},{"code":"fb","title":"fsbrowse","sub":"Express + busboy backend","meta":"source","href":"https://github.com/AnEntrypoint/fsbrowse"}]},{"id":"desktop_os","title":"desktop os shell","count":"in-page wm","items":[{"code":"os","title":"createDesktopShell","sub":"menubar apps launcher taskbar window manager","meta":"shell.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/shell.js"},{"code":"os","title":"icons set","sub":"svg glyphs for menubar + taskbar","meta":"icons.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/icons.js"},{"code":"os","title":"theme.css","sub":"os chrome tokens menubar launcher wm","meta":"theme.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/theme.css"},{"code":"os","title":"import path","sub":"anentrypoint-design/desktop","meta":"exports","href":"https://github.com/AnEntrypoint/design/blob/main/package.json"}]},{"id":"web_components","title":"web components","count":"1 element","items":[{"code":"wc","title":"\u003cds-chat>","sub":"auto-registers when the sdk loads in a browser","meta":"ds-chat.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/web-components/ds-chat.js"},{"code":"wc","title":"registerChatElement","sub":"manual register helper","meta":"source","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js"}]},{"id":"api_exports","title":"public api","count":"sdk surface","items":[{"code":"api","title":"h / applyDiff","sub":"webjsx createElement + diff","meta":"index.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js"},{"code":"api","title":"installStyles / scope","sub":"ds-247420 css scope + bootstrap","meta":"styles.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js"},{"code":"api","title":"loadCss","sub":"fetch the bundled css string","meta":"styles.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js"},{"code":"api","title":"mount / mountKit","sub":"ds shell + ui_kit bootstrap","meta":"bootstrap.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/bootstrap.js"},{"code":"api","title":"registerDeckStage / getDeckStage","sub":"16:9 deck stage api","meta":"deck-stage.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/deck-stage.js"},{"code":"api","title":"renderMarkdown","sub":"marked v15 + dompurify lazy stack","meta":"markdown.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/markdown.js"},{"code":"api","title":"ensurePrism / highlightAllUnder","sub":"prism core + per-language","meta":"highlight.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/highlight.js"},{"code":"api","title":"renderPageHtml","sub":"static page html template","meta":"page-html.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/page-html.js"},{"code":"api","title":"components / motion / debug","sub":"namespaces from the default export","meta":"components.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/components.js"}]},{"id":"decks","title":"decks","count":1,"items":[{"code":"","title":"deck template","sub":"16:9 stage with auto-fit","meta":"open ->","href":"./slides/"}]},{"id":"docs","title":"docs","count":3,"items":[{"code":"md","title":"readme","sub":"overview, manifesto, conventions","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"code":"md","title":"skill","sub":"authoring rules for the agent","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"code":"css","title":"tokens","sub":"colors, type, panel surface tokens","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"}]},{"id":"features","title":"why design","count":4,"items":[{"code":"","title":"layered surfaces","sub":"panel-on-panel rhythm; loud content sits inside quiet chrome.","meta":"panel-row.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/css/app-shell/panel-row.css"},{"code":"","title":"monospace labels","sub":"mono only for codes/labels/CLI; sans for everything legible.","meta":"colors_and_type.css","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"code":"","title":"indicator rails","sub":"color-coded inset rails for category separation, never borders.","meta":"panel-row.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/css/app-shell/panel-row.css#L126"},{"code":"","title":"tokens-only","sub":"every surface, type ramp, accent driven by --panel-* / --fs-* tokens.","meta":"colors_and_type.css","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"}]},{"id":"previews","title":"previews","count":25,"items":[{"code":"","title":"buttons","sub":"preview · buttons.html","meta":"open ->","href":"./preview/buttons.html"},{"code":"","title":"colors core","sub":"preview · colors-core.html","meta":"open ->","href":"./preview/colors-core.html"},{"code":"","title":"colors lore","sub":"preview · colors-lore.html","meta":"open ->","href":"./preview/colors-lore.html"},{"code":"","title":"colors semantic","sub":"preview · colors-semantic.html","meta":"open ->","href":"./preview/colors-semantic.html"},{"code":"","title":"dateline","sub":"preview · dateline.html","meta":"open ->","href":"./preview/dateline.html"},{"code":"","title":"dropzone","sub":"preview · dropzone.html","meta":"open ->","href":"./preview/dropzone.html"},{"code":"","title":"file grid","sub":"preview · file-grid.html","meta":"open ->","href":"./preview/file-grid.html"},{"code":"","title":"file row","sub":"preview · file-row.html","meta":"open ->","href":"./preview/file-row.html"},{"code":"","title":"file toolbar","sub":"preview · file-toolbar.html","meta":"open ->","href":"./preview/file-toolbar.html"},{"code":"","title":"file viewer","sub":"preview · file-viewer.html","meta":"open ->","href":"./preview/file-viewer.html"},{"code":"","title":"header","sub":"preview · header.html","meta":"open ->","href":"./preview/header.html"},{"code":"","title":"icons unicode","sub":"preview · icons-unicode.html","meta":"open ->","href":"./preview/icons-unicode.html"},{"code":"","title":"index row","sub":"preview · index-row.html","meta":"open ->","href":"./preview/index-row.html"},{"code":"","title":"inputs","sub":"preview · inputs.html","meta":"open ->","href":"./preview/inputs.html"},{"code":"","title":"manifesto","sub":"preview · manifesto.html","meta":"open ->","href":"./preview/manifesto.html"},{"code":"","title":"rules","sub":"preview · rules.html","meta":"open ->","href":"./preview/rules.html"},{"code":"","title":"spacing","sub":"preview · spacing.html","meta":"open ->","href":"./preview/spacing.html"},{"code":"","title":"stamps","sub":"preview · stamps.html","meta":"open ->","href":"./preview/stamps.html"},{"code":"","title":"stamps lore","sub":"preview · stamps-lore.html","meta":"open ->","href":"./preview/stamps-lore.html"},{"code":"","title":"theme ink","sub":"preview · theme-ink.html","meta":"open ->","href":"./preview/theme-ink.html"},{"code":"","title":"type display","sub":"preview · type-display.html","meta":"open ->","href":"./preview/type-display.html"},{"code":"","title":"type mono","sub":"preview · type-mono.html","meta":"open ->","href":"./preview/type-mono.html"},{"code":"","title":"type prose","sub":"preview · type-prose.html","meta":"open ->","href":"./preview/type-prose.html"},{"code":"","title":"type scale","sub":"preview · type-scale.html","meta":"open ->","href":"./preview/type-scale.html"},{"code":"","title":"wordmarks","sub":"preview · wordmarks.html","meta":"open ->","href":"./preview/wordmarks.html"}]}],"quickstart":{"heading":"quick start","lines":[{"kind":"cmt","text":"# install via importmap (no bundler)"},{"kind":"cmd","text":"\u003cscript type='importmap'>{\"imports\":{\"anentrypoint-design\":\"https://unpkg.com/anentrypoint-design@latest/dist/247420.js\"}}\u003c/script>"},{"kind":"cmt","text":"# or clone the source"},{"kind":"cmd","text":"git clone https://github.com/AnEntrypoint/design.git"}]},"statusLeft":["main","utf-8","lf"],"statusRight":["anentrypoint-design@latest","14 kits"]}</script>
|
|
119
|
+
<script id="__site__" type="application/json">{"title":"design","slug":"index","siteName":"design","navItems":[["247420","https://247420.xyz"],["AnEntrypoint ->","https://github.com/AnEntrypoint"]],"theme":"auto","hero":{"heading":"design","subheading":"the 247420 design system","body":"14 kit surfaces, 25 previews, one deck, and a full desktop-OS shell — plus a web component and an SDK, all tokens-only, zero raw color literals, one importmap script tag to install. every panel, row, and form control in this system reads its color, radius, and spacing from a single token file — swap the tokens and every surface built on them changes with it.","badges":[{"label":"design-system"},{"label":"tokens"},{"label":"web"}],"ctas":[{"label":"GitHub","href":"https://github.com/AnEntrypoint/design","primary":true},{"label":"247420","href":"https://247420.xyz"}]},"sections":[],"examples":[],"bodyHtml":"","sidebar":{"sections":[{"group":"open","items":[{"glyph":"+","label":"open","href":"./ui_kits/homepage/"}]},{"group":"bins","items":[{"label":"everything","href":"#all","active":true,"count":45},{"label":"pinned","href":"#kits","count":14},{"label":"shipped","href":"#previews","count":25},{"label":"drafts","href":"#decks","count":1}]},{"group":"labels","items":[{"label":"ui kits","href":"#kits","count":14},{"label":"decks","href":"#decks","count":1},{"label":"previews","href":"#previews","count":25},{"label":"docs","href":"#docs","count":5}]},{"group":"more","items":[{"label":"readme","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"label":"skill","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"label":"tokens","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"label":"source","href":"https://github.com/AnEntrypoint/design"},{"label":"MIT license","href":"https://github.com/AnEntrypoint/design/blob/main/LICENSE"}]}]},"marquee":{"items":["open source","design tokens","buildless components","zero raw color literals"],"sep":"/"},"panels":[{"id":"kits","title":"ui kits","count":"14 surfaces","items":[{"code":"","title":"homepage","sub":"marquee + works grid","meta":"open ->","href":"./ui_kits/homepage/"},{"code":"","title":"project page","sub":"hero receipt install changelog","meta":"open ->","href":"./ui_kits/project_page/"},{"code":"","title":"docs","sub":"long-form prose chrome","meta":"open ->","href":"./ui_kits/docs/"},{"code":"","title":"blog","sub":"dated index + reading view","meta":"open ->","href":"./ui_kits/blog/"},{"code":"","title":"chat","sub":"message thread + composer","meta":"open ->","href":"./ui_kits/chat/"},{"code":"","title":"aicat","sub":"ai assistant with cat persona","meta":"open ->","href":"./ui_kits/aicat/"},{"code":"","title":"file browser","sub":"rails by file type drop preview","meta":"open ->","href":"./ui_kits/file_browser/"},{"code":"","title":"dashboard","sub":"kpis tables receipts changelog","meta":"open ->","href":"./ui_kits/dashboard/"},{"code":"","title":"terminal","sub":"cli prompt command lines log view","meta":"open ->","href":"./ui_kits/terminal/"},{"code":"","title":"settings","sub":"sectioned forms toggles save bar","meta":"open ->","href":"./ui_kits/settings/"},{"code":"","title":"signin","sub":"auth providers magic link","meta":"open ->","href":"./ui_kits/signin/"},{"code":"","title":"search","sub":"topbar query faceted filters rows","meta":"open ->","href":"./ui_kits/search/"},{"code":"","title":"404","sub":"empty-state hero suggested routes","meta":"open ->","href":"./ui_kits/error_404/"},{"code":"","title":"gallery","sub":"visual grid tonal cards lightbox","meta":"open ->","href":"./ui_kits/gallery/"}]},{"id":"file_browser","title":"file browser","count":"primitives","items":[{"code":"fb","title":"file_browser kit","sub":"drop, list, preview, dialogs","meta":"open ->","href":"./ui_kits/file_browser/"},{"code":"fb","title":"FileRow","sub":"rail icon name meta","meta":"open ->","href":"./preview/file-row.html"},{"code":"fb","title":"FileGrid","sub":"stack of rows in a panel","meta":"open ->","href":"./preview/file-grid.html"},{"code":"fb","title":"DropZone","sub":"tonal upload target","meta":"open ->","href":"./preview/dropzone.html"},{"code":"fb","title":"FileViewer","sub":"modal preview keyed head","meta":"open ->","href":"./preview/file-viewer.html"},{"code":"fb","title":"FileToolbar","sub":"actions breadcrumb upload","meta":"open ->","href":"./preview/file-toolbar.html"},{"code":"fb","title":"fsbrowse","sub":"Express + busboy backend","meta":"source","href":"https://github.com/AnEntrypoint/fsbrowse"}]},{"id":"desktop_os","title":"desktop os shell","count":"in-page wm","items":[{"code":"os","title":"createDesktopShell","sub":"menubar apps launcher taskbar window manager","meta":"shell.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/shell.js"},{"code":"os","title":"icons set","sub":"svg glyphs for menubar + taskbar","meta":"icons.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/icons.js"},{"code":"os","title":"theme.css","sub":"os chrome tokens menubar launcher wm","meta":"theme.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/desktop/theme.css"},{"code":"os","title":"import path","sub":"anentrypoint-design/desktop","meta":"exports","href":"https://github.com/AnEntrypoint/design/blob/main/package.json"}]},{"id":"web_components","title":"web components","count":"1 element","items":[{"code":"wc","title":"\u003cds-chat>","sub":"auto-registers when the sdk loads in a browser","meta":"ds-chat.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/web-components/ds-chat.js"},{"code":"wc","title":"registerChatElement","sub":"manual register helper","meta":"source","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js"}]},{"id":"api_exports","title":"public api","count":"sdk surface","items":[{"code":"api","title":"h / applyDiff","sub":"webjsx createElement + diff","meta":"index.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/index.js"},{"code":"api","title":"installStyles / scope","sub":"ds-247420 css scope + bootstrap","meta":"styles.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js"},{"code":"api","title":"loadCss","sub":"fetch the bundled css string","meta":"styles.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/styles.js"},{"code":"api","title":"mount / mountKit","sub":"ds shell + ui_kit bootstrap","meta":"bootstrap.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/bootstrap.js"},{"code":"api","title":"registerDeckStage / getDeckStage","sub":"16:9 deck stage api","meta":"deck-stage.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/deck-stage.js"},{"code":"api","title":"renderMarkdown","sub":"marked v15 + dompurify lazy stack","meta":"markdown.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/markdown.js"},{"code":"api","title":"ensurePrism / highlightAllUnder","sub":"prism core + per-language","meta":"highlight.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/highlight.js"},{"code":"api","title":"renderPageHtml","sub":"static page html template","meta":"page-html.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/page-html.js"},{"code":"api","title":"components / motion / debug","sub":"namespaces from the default export","meta":"components.js","href":"https://github.com/AnEntrypoint/design/blob/main/src/components.js"}]},{"id":"decks","title":"decks","count":1,"items":[{"code":"","title":"deck template","sub":"16:9 stage with auto-fit","meta":"open ->","href":"./slides/"}]},{"id":"docs","title":"docs","count":5,"items":[{"code":"md","title":"readme","sub":"overview, manifesto, conventions","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/README.md"},{"code":"md","title":"skill","sub":"authoring rules for the agent","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/SKILL.md"},{"code":"css","title":"tokens","sub":"colors, type, panel surface tokens","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"code":"md","title":"component props","sub":"generated prop reference","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/docs/component-props.md"},{"code":"md","title":"changelog","sub":"release history","meta":"open ->","href":"https://github.com/AnEntrypoint/design/blob/main/CHANGELOG.md"}]},{"id":"features","title":"why design","count":4,"items":[{"code":"","title":"layered surfaces","sub":"panel-on-panel rhythm; loud content sits inside quiet chrome.","meta":"panel-row.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/css/app-shell/panel-row.css"},{"code":"","title":"monospace labels","sub":"mono only for codes/labels/CLI; sans for everything legible.","meta":"colors_and_type.css","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"},{"code":"","title":"indicator rails","sub":"color-coded inset rails for category separation, never borders.","meta":"panel-row.css","href":"https://github.com/AnEntrypoint/design/blob/main/src/css/app-shell/panel-row.css#L126"},{"code":"","title":"tokens-only","sub":"every surface, type ramp, accent driven by --panel-* / --fs-* tokens.","meta":"colors_and_type.css","href":"https://github.com/AnEntrypoint/design/blob/main/colors_and_type.css"}]},{"id":"previews","title":"previews","count":25,"items":[{"code":"","title":"buttons","sub":"preview · buttons.html","meta":"open ->","href":"./preview/buttons.html"},{"code":"","title":"colors core","sub":"preview · colors-core.html","meta":"open ->","href":"./preview/colors-core.html"},{"code":"","title":"colors lore","sub":"preview · colors-lore.html","meta":"open ->","href":"./preview/colors-lore.html"},{"code":"","title":"colors semantic","sub":"preview · colors-semantic.html","meta":"open ->","href":"./preview/colors-semantic.html"},{"code":"","title":"dateline","sub":"preview · dateline.html","meta":"open ->","href":"./preview/dateline.html"},{"code":"","title":"dropzone","sub":"preview · dropzone.html","meta":"open ->","href":"./preview/dropzone.html"},{"code":"","title":"file grid","sub":"preview · file-grid.html","meta":"open ->","href":"./preview/file-grid.html"},{"code":"","title":"file row","sub":"preview · file-row.html","meta":"open ->","href":"./preview/file-row.html"},{"code":"","title":"file toolbar","sub":"preview · file-toolbar.html","meta":"open ->","href":"./preview/file-toolbar.html"},{"code":"","title":"file viewer","sub":"preview · file-viewer.html","meta":"open ->","href":"./preview/file-viewer.html"},{"code":"","title":"header","sub":"preview · header.html","meta":"open ->","href":"./preview/header.html"},{"code":"","title":"icons unicode","sub":"preview · icons-unicode.html","meta":"open ->","href":"./preview/icons-unicode.html"},{"code":"","title":"index row","sub":"preview · index-row.html","meta":"open ->","href":"./preview/index-row.html"},{"code":"","title":"inputs","sub":"preview · inputs.html","meta":"open ->","href":"./preview/inputs.html"},{"code":"","title":"manifesto","sub":"preview · manifesto.html","meta":"open ->","href":"./preview/manifesto.html"},{"code":"","title":"rules","sub":"preview · rules.html","meta":"open ->","href":"./preview/rules.html"},{"code":"","title":"spacing","sub":"preview · spacing.html","meta":"open ->","href":"./preview/spacing.html"},{"code":"","title":"stamps","sub":"preview · stamps.html","meta":"open ->","href":"./preview/stamps.html"},{"code":"","title":"stamps lore","sub":"preview · stamps-lore.html","meta":"open ->","href":"./preview/stamps-lore.html"},{"code":"","title":"theme ink","sub":"preview · theme-ink.html","meta":"open ->","href":"./preview/theme-ink.html"},{"code":"","title":"type display","sub":"preview · type-display.html","meta":"open ->","href":"./preview/type-display.html"},{"code":"","title":"type mono","sub":"preview · type-mono.html","meta":"open ->","href":"./preview/type-mono.html"},{"code":"","title":"type prose","sub":"preview · type-prose.html","meta":"open ->","href":"./preview/type-prose.html"},{"code":"","title":"type scale","sub":"preview · type-scale.html","meta":"open ->","href":"./preview/type-scale.html"},{"code":"","title":"wordmarks","sub":"preview · wordmarks.html","meta":"open ->","href":"./preview/wordmarks.html"}]}],"quickstart":{"heading":"quick start","lines":[{"kind":"cmt","text":"# install via importmap (no bundler)"},{"kind":"cmd","text":"\u003cscript type='importmap'>{\"imports\":{\"anentrypoint-design\":\"https://unpkg.com/anentrypoint-design@latest/dist/247420.js\"}}\u003c/script>"},{"kind":"cmt","text":"# or clone the source"},{"kind":"cmd","text":"git clone https://github.com/AnEntrypoint/design.git"}]},"statusLeft":["main","utf-8","lf"],"statusRight":["anentrypoint-design@latest","14 kits"],"seoAuthor":"247420 · a design system by AnEntrypoint"}</script>
|
|
120
120
|
<style>html,body{margin:0;padding:0}body{background:var(--bg,#F6F5F1);color:var(--fg,#131318);font-family:var(--ff-body,system-ui,sans-serif)}</style>
|
|
121
121
|
</head>
|
|
122
122
|
<body>
|
|
123
123
|
<div id="app"></div>
|
|
124
124
|
<script type="module">
|
|
125
125
|
import { mount, components as C, h } from 'anentrypoint-design';
|
|
126
|
-
|
|
126
|
+
let data;
|
|
127
|
+
try {
|
|
128
|
+
data = JSON.parse(document.getElementById('__site__').textContent);
|
|
129
|
+
} catch (e) {
|
|
130
|
+
console.error('[page-html] failed to parse #__site__ bootstrap data:', e);
|
|
131
|
+
document.getElementById('app').textContent = 'This page failed to load correctly. Please refresh, or contact support if the problem persists.';
|
|
132
|
+
throw e;
|
|
133
|
+
}
|
|
127
134
|
|
|
128
135
|
function heroNode(hero) {
|
|
129
136
|
if (!hero) return null;
|
|
@@ -150,11 +157,13 @@ function heroNode(hero) {
|
|
|
150
157
|
);
|
|
151
158
|
}
|
|
152
159
|
|
|
160
|
+
function __esc(s) { return String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>'); }
|
|
161
|
+
|
|
153
162
|
function sectionNode(sec, idx) {
|
|
154
163
|
const features = sec.features || sec.items || [];
|
|
155
164
|
const rows = features.map((f, i) => {
|
|
156
165
|
const kids = [h('div', { key: 't', class: 'ds-feature-title' }, String(f.name || ''))];
|
|
157
|
-
if (f.desc) kids.push(h('div', { key: 'd', class: 'ds-feature-desc', innerHTML: String(f.desc).replace(/`([^`]+)`/g, '<code>$1</code>') }));
|
|
166
|
+
if (f.desc) kids.push(h('div', { key: 'd', class: 'ds-feature-desc', innerHTML: __esc(String(f.desc)).replace(/`([^`]+)`/g, '<code>$1</code>') }));
|
|
158
167
|
if (f.benefit) kids.push(h('div', { key: 'b', class: 'ds-feature-benefit' }, String(f.benefit)));
|
|
159
168
|
return h('div', { key: i, class: 'ds-feature' }, ...kids);
|
|
160
169
|
});
|
|
@@ -185,9 +194,64 @@ function examplesNode(examples) {
|
|
|
185
194
|
});
|
|
186
195
|
}
|
|
187
196
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
197
|
+
// Category glyph per homepage panel id — the same line-icon vocabulary
|
|
198
|
+
// icons.js already provides, so kits/previews/decks/docs read as distinct
|
|
199
|
+
// categories at a glance instead of by text label alone. Falls back to no
|
|
200
|
+
// icon for panel ids outside this table (e.g. one-off feature panels).
|
|
201
|
+
const PANEL_ICON = {
|
|
202
|
+
kits: 'grid',
|
|
203
|
+
file_browser: 'folder',
|
|
204
|
+
desktop_os: 'square',
|
|
205
|
+
web_components: 'page',
|
|
206
|
+
api_exports: 'link',
|
|
207
|
+
decks: 'screen',
|
|
208
|
+
docs: 'file-text',
|
|
209
|
+
previews: 'eye',
|
|
210
|
+
features: 'info',
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Filter state for the kits search box above the "ui kits" panel. Reuses
|
|
214
|
+
// ui_kits/search's own query-bar pattern (plain module-level state object,
|
|
215
|
+
// mutated on input, driving a re-render) rather than inventing a second
|
|
216
|
+
// filtering mechanism -- this homepage already ships that kit, so the
|
|
217
|
+
// homepage's own kit listing gets the same affordance instead of being the
|
|
218
|
+
// one surface on the site without a way to search kits by name.
|
|
219
|
+
const kitsFilterState = { q: '' };
|
|
220
|
+
|
|
221
|
+
function panelNode(panel, idx, rerender) {
|
|
222
|
+
let items = Array.isArray(panel.items) ? panel.items : [];
|
|
223
|
+
const isKits = panel.id === 'kits';
|
|
224
|
+
const q = isKits ? kitsFilterState.q.trim().toLowerCase() : '';
|
|
225
|
+
if (isKits && q) {
|
|
226
|
+
items = items.filter((it) => {
|
|
227
|
+
const hay = (String(it.title || it.name || '') + ' ' + String(it.sub || it.desc || '')).toLowerCase();
|
|
228
|
+
return hay.includes(q);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
const iconName = panel.id && PANEL_ICON[panel.id];
|
|
232
|
+
const titleText = panel.title || panel.name || '';
|
|
233
|
+
const titleNode = iconName && titleText
|
|
234
|
+
? h('span', { class: 'ds-panel-title-glyph' }, C.Icon(iconName, { size: 15 }), h('span', {}, titleText))
|
|
235
|
+
: titleText;
|
|
236
|
+
const filterInput = isKits && rerender ? h('div', { class: 'ds-kits-filter' },
|
|
237
|
+
h('input', {
|
|
238
|
+
type: 'search', class: 'input ds-kits-filter-input',
|
|
239
|
+
placeholder: 'filter kits by name or description…',
|
|
240
|
+
value: kitsFilterState.q,
|
|
241
|
+
'aria-label': 'filter ui kits',
|
|
242
|
+
oninput: (e) => { kitsFilterState.q = e.target.value; rerender(); },
|
|
243
|
+
})) : null;
|
|
244
|
+
if (!items.length) {
|
|
245
|
+
if (isKits && q) {
|
|
246
|
+
return h('div', { class: 'ds-kits-panel-wrap' }, filterInput,
|
|
247
|
+
C.Panel({ id: panel.id || null, title: titleNode, count: 0, children:
|
|
248
|
+
h('div', { class: 'ds-empty-state' },
|
|
249
|
+
h('div', { class: 'ds-empty-state-glyph' }, '( )'),
|
|
250
|
+
h('p', { class: 'ds-empty-state-msg' }, 'no kits match ', h('code', {}, '"' + kitsFilterState.q.trim() + '"')),
|
|
251
|
+
) }));
|
|
252
|
+
}
|
|
253
|
+
return filterInput ? h('div', { class: 'ds-kits-panel-wrap' }, filterInput) : null;
|
|
254
|
+
}
|
|
191
255
|
const rows = items.map((it, i) => {
|
|
192
256
|
const code = it.code == null ? '' : String(it.code).trim();
|
|
193
257
|
const kids = [];
|
|
@@ -197,7 +261,8 @@ function panelNode(panel, idx) {
|
|
|
197
261
|
kids.push(h('span', { key: 'a', class: 'ds-row-arrow' }, it.meta || '->'));
|
|
198
262
|
return h('a', { key: i, class: 'row', href: it.href || '#' }, ...kids);
|
|
199
263
|
});
|
|
200
|
-
|
|
264
|
+
const panelEl = C.Panel({ id: panel.id || null, title: titleNode, count: items.length, children: rows });
|
|
265
|
+
return filterInput ? h('div', { class: 'ds-kits-panel-wrap' }, filterInput, panelEl) : panelEl;
|
|
201
266
|
}
|
|
202
267
|
|
|
203
268
|
function marqueeNode(marquee) {
|
|
@@ -301,8 +366,14 @@ const bodyNode = data.bodyHtml ? C.Section({ children: h('div', { class: 'page-b
|
|
|
301
366
|
function footerNode() {
|
|
302
367
|
const year = new Date().getFullYear();
|
|
303
368
|
const links = (data.navItems || []).filter(([, href]) => /^https?:/.test(String(href)));
|
|
369
|
+
// Names the actual maintaining entity, not just the project's numeric
|
|
370
|
+
// brand. This is a personal/community project (MIT, copyright holder
|
|
371
|
+
// "AnEntrypoint" per LICENSE) with no separate legal org behind it, so the
|
|
372
|
+
// footer says that plainly instead of leaving "247420" to stand in for an
|
|
373
|
+
// entity it isn't.
|
|
374
|
+
const entity = (data.seoAuthor || '247420 · a design system by AnEntrypoint').toLowerCase();
|
|
304
375
|
return h('footer', { class: 'ds-page-footer' },
|
|
305
|
-
h('span', { class: 'ds-page-footer-copy' }, String(year) + ' · ' +
|
|
376
|
+
h('span', { class: 'ds-page-footer-copy' }, String(year) + ' · ' + entity),
|
|
306
377
|
links.length ? h('nav', { class: 'ds-page-footer-links', 'aria-label': 'footer' },
|
|
307
378
|
...links.map(([label, href], i) => h('a', { key: i, href }, String(label).replace(' ->', '')))
|
|
308
379
|
) : null,
|
|
@@ -320,40 +391,46 @@ function tierNode(tier, children) {
|
|
|
320
391
|
return h('section', { key: tier.key, class: 'ds-tier ds-tier-' + tier.key, id: tier.key, 'aria-labelledby': labelId }, head, ...kids);
|
|
321
392
|
}
|
|
322
393
|
|
|
323
|
-
const panelsById = new Map((data.panels || []).map((p) => [p.id || p.title || p.name || '', p]));
|
|
324
|
-
const takePanel = (id) => { const p = panelsById.get(id); if (p) panelsById.delete(id); return p ? panelNode(p) : null; };
|
|
325
|
-
|
|
326
394
|
const TIERS = [
|
|
327
395
|
{ key: 'open', label: 'open', lede: 'browse and try the system running.', ids: ['kits', 'previews', 'decks'], extra: () => [examplesNode(data.examples)] },
|
|
328
396
|
{ key: 'ships', label: 'ships', lede: 'what the package contains.', ids: ['file_browser', 'desktop_os', 'web_components', 'api_exports'], extra: () => [] },
|
|
329
397
|
{ key: 'read', label: 'read', lede: 'understand the rules behind it.', ids: ['docs', 'features'], extra: () => [quickstartNode(data.quickstart)] },
|
|
330
398
|
];
|
|
331
399
|
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
return
|
|
339
|
-
});
|
|
340
|
-
const leftoverPanels = [...panelsById.values()].map(panelNode);
|
|
400
|
+
// Builds the whole main-content tree fresh each render so the kits filter
|
|
401
|
+
// (module-level kitsFilterState) can drive a real re-render via mount()'s
|
|
402
|
+
// own returned render callback -- same reactive shape mountKit() gives every
|
|
403
|
+
// other kit on the site, applied here to the static-page renderer.
|
|
404
|
+
function buildMainChildren(rerender) {
|
|
405
|
+
const panelsById = new Map((data.panels || []).map((p) => [p.id || p.title || p.name || '', p]));
|
|
406
|
+
const takePanel = (id) => { const p = panelsById.get(id); if (p) panelsById.delete(id); return p ? panelNode(p, 0, rerender) : null; };
|
|
341
407
|
|
|
342
|
-
const
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
].
|
|
408
|
+
const tierNodes = TIERS.map((t) => {
|
|
409
|
+
const kids = [...t.ids.map(takePanel), ...t.extra()].filter(Boolean);
|
|
410
|
+
if (t.key === 'open' && kids.length) {
|
|
411
|
+
const lead = kids[0];
|
|
412
|
+
if (lead.props) lead.props.class = (lead.props.class || '') + ' ds-tier-lead';
|
|
413
|
+
}
|
|
414
|
+
return tierNode(t, kids);
|
|
415
|
+
});
|
|
416
|
+
const leftoverPanels = [...panelsById.values()].map((p) => panelNode(p, 0, rerender));
|
|
417
|
+
|
|
418
|
+
return [
|
|
419
|
+
heroNode(data.hero),
|
|
420
|
+
marqueeNode(data.marquee),
|
|
421
|
+
...data.sections.map(sectionNode),
|
|
422
|
+
...tierNodes,
|
|
423
|
+
...leftoverPanels,
|
|
424
|
+
bodyNode,
|
|
425
|
+
footerNode(),
|
|
426
|
+
].filter(Boolean);
|
|
427
|
+
}
|
|
351
428
|
|
|
352
|
-
mount(document.getElementById('app'), () => C.AppShell({
|
|
429
|
+
mount(document.getElementById('app'), (rerender) => C.AppShell({
|
|
353
430
|
topbar: C.Topbar({ brand: data.siteName, items: data.navItems, active: data.title }),
|
|
354
431
|
crumb: C.Crumb({ leaf: data.title }),
|
|
355
432
|
side: sideNode(data.sidebar),
|
|
356
|
-
main: h('div', { class: 'app-stage' }, ...
|
|
433
|
+
main: h('div', { class: 'app-stage' }, ...buildMainChildren(rerender)),
|
|
357
434
|
status: C.Status({
|
|
358
435
|
left: data.statusLeft || [data.siteName.toLowerCase(), data.slug],
|
|
359
436
|
right: data.statusRight || ['live'],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anentrypoint-design",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.478",
|
|
4
4
|
"description": "247420 design system SDK — webjsx + modified ripple-ui, single-file ESM bundle for reproducible use of the AnEntrypoint design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/247420.js",
|
|
@@ -99,13 +99,20 @@ export function Marquee({ items = [], sep = '/' }) {
|
|
|
99
99
|
if (!items.length) return null;
|
|
100
100
|
// Two identical runs make the -50% translate loop seamless. Each text and
|
|
101
101
|
// separator is a keyed span so webjsx applyDiff never sees a primitive
|
|
102
|
-
// sibling beside a keyed VElement.
|
|
102
|
+
// sibling beside a keyed VElement. Run 'a' is the real, assistive-tech-
|
|
103
|
+
// visible content; run 'b' is a purely visual duplicate for the seamless
|
|
104
|
+
// loop and must not be exposed to screen readers as doubled text, so it
|
|
105
|
+
// is wrapped in its own aria-hidden container (standard seamless-marquee
|
|
106
|
+
// technique).
|
|
103
107
|
const run = (runKey) => items.flatMap((it, i) => [
|
|
104
108
|
h('span', { class: 'ds-marquee-item', key: `${runKey}-i${i}` }, it),
|
|
105
109
|
h('span', { class: 'ds-marquee-sep', key: `${runKey}-s${i}`, 'aria-hidden': 'true' }, sep),
|
|
106
110
|
]);
|
|
107
111
|
return h('div', { class: 'ds-marquee', role: 'marquee' },
|
|
108
|
-
h('div', { class: 'ds-marquee-track' },
|
|
112
|
+
h('div', { class: 'ds-marquee-track' },
|
|
113
|
+
h('span', { class: 'ds-marquee-run ds-marquee-run-a' }, ...run('a')),
|
|
114
|
+
h('span', { class: 'ds-marquee-run ds-marquee-run-b', 'aria-hidden': 'true' }, ...run('b')),
|
|
115
|
+
)
|
|
109
116
|
);
|
|
110
117
|
}
|
|
111
118
|
|
|
@@ -90,7 +90,7 @@ export const themePage = makePage((ctx) => {
|
|
|
90
90
|
return [
|
|
91
91
|
PageHeader({ title: 'theme', lede: 'theme preference' }),
|
|
92
92
|
section('current', Table({ headers: ['setting', 'value'], rows: [
|
|
93
|
-
['theme', (typeof window !== 'undefined' && document.
|
|
93
|
+
['theme', (typeof window !== 'undefined' && document.documentElement.getAttribute('data-theme')) || 'github-dark'],
|
|
94
94
|
['density', (typeof window !== 'undefined' && document.documentElement.getAttribute('data-density')) || 'compact'],
|
|
95
95
|
['accent', (typeof window !== 'undefined' && document.documentElement.getAttribute('data-accent')) || 'default'],
|
|
96
96
|
] })),
|
|
@@ -7,9 +7,14 @@ import * as webjsx from '../../../vendor/webjsx/index.js';
|
|
|
7
7
|
import { trapTab } from '../overlay-primitives.js';
|
|
8
8
|
import { Brand, Glyph } from './atoms.js';
|
|
9
9
|
import { Icon } from './icons.js';
|
|
10
|
+
import { ThemeToggle } from '../theme-toggle.js';
|
|
10
11
|
const h = webjsx.createElement;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
// `themeToggle` defaults on: every Topbar consumer (homepage included) gets a
|
|
14
|
+
// real, working light/dark/auto control in the shell chrome instead of each
|
|
15
|
+
// call site having to remember to wire ThemeToggle() in by hand. Pass
|
|
16
|
+
// `themeToggle: false` to opt a shell out (e.g. a kit that renders its own).
|
|
17
|
+
export function Topbar({ brand = '247420', leaf = '', items = [], active = '', onNav, search, themeToggle = true } = {}) {
|
|
13
18
|
return h('header', { class: 'app-topbar', role: 'banner' },
|
|
14
19
|
Brand({ name: brand, leaf }),
|
|
15
20
|
search ? h('label', { class: 'app-search' },
|
|
@@ -50,7 +55,8 @@ export function Topbar({ brand = '247420', leaf = '', items = [], active = '', o
|
|
|
50
55
|
}
|
|
51
56
|
}
|
|
52
57
|
}, label);
|
|
53
|
-
}))
|
|
58
|
+
})),
|
|
59
|
+
themeToggle ? h('div', { class: 'app-topbar-theme' }, ThemeToggle({ compact: true })) : null
|
|
54
60
|
);
|
|
55
61
|
}
|
|
56
62
|
|
|
@@ -208,9 +214,14 @@ export function AppShell({ topbar, crumb, side, main, status, narrow } = {}) {
|
|
|
208
214
|
// brand + nav (topbar) and breadcrumb + right slot (crumb) share a single
|
|
209
215
|
// band so the chrome reads as one bar, not two. Either prop alone still
|
|
210
216
|
// renders on its own (consumers that pass only a topbar are unaffected).
|
|
217
|
+
// Landmark wrapper: topbar/crumb are opaque children with no semantics of
|
|
218
|
+
// their own, so screen-reader users landmark-navigating a page saw no
|
|
219
|
+
// "banner"/"navigation" region at all above <main>. <header role="banner">
|
|
220
|
+
// names the brand+nav band; the app-side-shell aside below already exists
|
|
221
|
+
// as a real <aside>, so this closes the missing landmark for the top band.
|
|
211
222
|
const chrome = (topbar && crumb)
|
|
212
|
-
? h('
|
|
213
|
-
: (topbar || crumb || null
|
|
223
|
+
? h('header', { class: 'app-chrome', role: 'banner' }, topbar, crumb)
|
|
224
|
+
: (topbar || crumb) ? h('header', { class: 'app-chrome', role: 'banner' }, topbar || crumb) : null;
|
|
214
225
|
return h('div', { class: 'app', ref: syncAppSide },
|
|
215
226
|
h('a', { href: '#app-main', class: 'skip-link' }, 'skip to main content'),
|
|
216
227
|
hasSide ? h('button', {
|
package/src/copy-code.js
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// copy-code.js -- vanilla-JS "copy" button injector for <pre><code> blocks.
|
|
2
|
+
//
|
|
3
|
+
// Standalone module, no dependencies, no framework assumptions: include it
|
|
4
|
+
// with a plain <script src="…/copy-code.js"></script> (or type="module") on
|
|
5
|
+
// any page rendering doc/code blocks and it wires itself up on
|
|
6
|
+
// DOMContentLoaded, finding every `pre > code` element and injecting a small
|
|
7
|
+
// button that copies the block's text to the clipboard.
|
|
8
|
+
//
|
|
9
|
+
// Self-invoking so a page can include it more than once without double-
|
|
10
|
+
// registering handlers or double-injecting buttons (guarded per-element via
|
|
11
|
+
// a data attribute).
|
|
12
|
+
(function () {
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
const COPY_LABEL = 'copy';
|
|
16
|
+
const COPIED_LABEL = 'copied';
|
|
17
|
+
const FAILED_LABEL = 'copy failed';
|
|
18
|
+
const RESET_MS = 1500;
|
|
19
|
+
const MARK_ATTR = 'data-copy-code-wired';
|
|
20
|
+
|
|
21
|
+
function copyText(text) {
|
|
22
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
23
|
+
return navigator.clipboard.writeText(text);
|
|
24
|
+
}
|
|
25
|
+
// Fallback for non-secure contexts / browsers without navigator.clipboard.
|
|
26
|
+
return new Promise((resolve, reject) => {
|
|
27
|
+
try {
|
|
28
|
+
const ta = document.createElement('textarea');
|
|
29
|
+
ta.value = text;
|
|
30
|
+
ta.style.position = 'fixed';
|
|
31
|
+
ta.style.opacity = '0';
|
|
32
|
+
document.body.appendChild(ta);
|
|
33
|
+
ta.focus();
|
|
34
|
+
ta.select();
|
|
35
|
+
const ok = document.execCommand('copy');
|
|
36
|
+
document.body.removeChild(ta);
|
|
37
|
+
ok ? resolve() : reject(new Error('execCommand copy failed'));
|
|
38
|
+
} catch (err) {
|
|
39
|
+
reject(err);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function makeButton(codeEl) {
|
|
45
|
+
const btn = document.createElement('button');
|
|
46
|
+
btn.type = 'button';
|
|
47
|
+
btn.className = 'copy-code-btn';
|
|
48
|
+
btn.textContent = COPY_LABEL;
|
|
49
|
+
btn.setAttribute('aria-label', 'copy code to clipboard');
|
|
50
|
+
|
|
51
|
+
let resetTimer = null;
|
|
52
|
+
btn.addEventListener('click', () => {
|
|
53
|
+
copyText(codeEl.textContent || '').then(
|
|
54
|
+
() => setLabel(true),
|
|
55
|
+
() => setLabel(false)
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
function setLabel(ok) {
|
|
60
|
+
btn.textContent = ok ? COPIED_LABEL : FAILED_LABEL;
|
|
61
|
+
clearTimeout(resetTimer);
|
|
62
|
+
resetTimer = setTimeout(() => { btn.textContent = COPY_LABEL; }, RESET_MS);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return btn;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function wireBlock(codeEl) {
|
|
69
|
+
const pre = codeEl.parentElement;
|
|
70
|
+
if (!pre || pre.tagName !== 'PRE') return;
|
|
71
|
+
if (pre.hasAttribute(MARK_ATTR)) return;
|
|
72
|
+
pre.setAttribute(MARK_ATTR, '1');
|
|
73
|
+
// Position context for an absolutely-positioned button; harmless no-op
|
|
74
|
+
// if the page's own CSS already sets a position on <pre>.
|
|
75
|
+
if (!pre.style.position) pre.style.position = 'relative';
|
|
76
|
+
pre.appendChild(makeButton(codeEl));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function wireAll(root) {
|
|
80
|
+
(root || document).querySelectorAll('pre > code').forEach(wireBlock);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (document.readyState === 'loading') {
|
|
84
|
+
document.addEventListener('DOMContentLoaded', () => wireAll(document));
|
|
85
|
+
} else {
|
|
86
|
+
wireAll(document);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Minimal default styling, injected once, so the button is usable even on
|
|
90
|
+
// pages with no bespoke .copy-code-btn rule of their own. A page that wants
|
|
91
|
+
// its own look can simply define .copy-code-btn in its own stylesheet --
|
|
92
|
+
// this only runs if that class isn't already styled to be visible.
|
|
93
|
+
if (!document.getElementById('copy-code-btn-style')) {
|
|
94
|
+
const style = document.createElement('style');
|
|
95
|
+
style.id = 'copy-code-btn-style';
|
|
96
|
+
style.textContent =
|
|
97
|
+
'.copy-code-btn{position:absolute;top:.5em;right:.5em;font:inherit;' +
|
|
98
|
+
'font-size:.75em;line-height:1;padding:.35em .6em;border:1px solid currentColor;' +
|
|
99
|
+
'border-radius:4px;background:transparent;color:inherit;cursor:pointer;opacity:.6}' +
|
|
100
|
+
'.copy-code-btn:hover{opacity:1}';
|
|
101
|
+
document.head.appendChild(style);
|
|
102
|
+
}
|
|
103
|
+
})();
|
|
@@ -41,6 +41,12 @@
|
|
|
41
41
|
.ds-demo-label { font-size: var(--fs-xs); font-weight: 500; margin: 0 0 var(--space-1); }
|
|
42
42
|
.ds-demo-desc { font-size: var(--fs-tiny); color: var(--fg-3); margin: 0 0 var(--space-2); }
|
|
43
43
|
|
|
44
|
+
/* Per-preview backlink to the full token map/doc — names which token
|
|
45
|
+
families the specimen above it demonstrates, then links out to the
|
|
46
|
+
generated theme-map for the resolved values. */
|
|
47
|
+
.tokens-backlink { font-family: var(--ff-mono); font-size: var(--fs-xs); color: var(--fg-3); margin-top: 2px; }
|
|
48
|
+
.tokens-backlink a { color: inherit; }
|
|
49
|
+
|
|
44
50
|
@media (max-width: 768px) {
|
|
45
51
|
.ds-catalog { flex-direction: column; }
|
|
46
52
|
.ds-catalog-side { width: 100%; height: auto; position: static; border-right: 0; border-bottom: var(--bw-hair) solid var(--rule); }
|
|
@@ -263,6 +263,12 @@
|
|
|
263
263
|
display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
|
|
264
264
|
gap: var(--space-3); align-items: start;
|
|
265
265
|
}
|
|
266
|
+
/* Mobile fallback: auto-fill can still pack 2 cramped columns down to ~320px
|
|
267
|
+
viewports; force a single column below the shared mobile breakpoint
|
|
268
|
+
(docs/responsive.md) so thumbnails and file rails always read as a list. */
|
|
269
|
+
@media (max-width: 480px) {
|
|
270
|
+
.ds-file-grid-thumb { grid-template-columns: 1fr; }
|
|
271
|
+
}
|
|
266
272
|
.ds-file-cell {
|
|
267
273
|
position: relative;
|
|
268
274
|
background: var(--bg); border: var(--bw-hair) solid var(--rule); border-radius: var(--r-2);
|
|
@@ -88,6 +88,18 @@
|
|
|
88
88
|
display: flex; gap: var(--space-2, 10px); flex-wrap: wrap;
|
|
89
89
|
justify-content: flex-start; margin-top: var(--space-hair, 4px);
|
|
90
90
|
}
|
|
91
|
+
/* Hero CTA labels are content-driven (e.g. "GitHub", proper nouns from
|
|
92
|
+
home.yaml) and the site's voice is deliberately all-lowercase everywhere
|
|
93
|
+
else. Force the rendered case here rather than hand-lowercasing every
|
|
94
|
+
proper-noun label at the content layer, so a future CTA label doesn't
|
|
95
|
+
silently reintroduce Title Case. */
|
|
96
|
+
.ds-hero-actions .btn { text-transform: lowercase; }
|
|
97
|
+
/* Filter input above the homepage's "ui kits" panel — reuses the same
|
|
98
|
+
.input token the search kit's own topbar query box uses, just placed
|
|
99
|
+
inline above the panel instead of in a topbar slot. */
|
|
100
|
+
.ds-kits-panel-wrap { display: flex; flex-direction: column; gap: var(--space-2, 10px); }
|
|
101
|
+
.ds-kits-filter { display: flex; }
|
|
102
|
+
.ds-kits-filter-input { width: 100%; max-width: 32ch; }
|
|
91
103
|
/* Below this width the aside card's own internal rhythm (stat rows still
|
|
92
104
|
stacked vertically at full width) is already correct for a narrow column —
|
|
93
105
|
no separate breakpoint override needed now that .ds-hero is always a
|
|
@@ -167,6 +179,7 @@
|
|
|
167
179
|
white-space: nowrap; will-change: transform;
|
|
168
180
|
animation: ds-marquee-run 28s linear infinite;
|
|
169
181
|
}
|
|
182
|
+
.ds-marquee-run { display: inline-flex; align-items: center; gap: var(--space-5); }
|
|
170
183
|
.ds-marquee-item { display: inline-flex; align-items: center; gap: var(--space-5); }
|
|
171
184
|
.ds-marquee-sep { color: var(--accent-ink); }
|
|
172
185
|
.ds-marquee:hover .ds-marquee-track,
|
|
@@ -451,6 +451,11 @@
|
|
|
451
451
|
.ds-btn-row-tight { gap: var(--space-1-75, 6px); }
|
|
452
452
|
.ds-key-input { flex: 1 1 160px; min-width: 0; font-family: var(--ff-mono); }
|
|
453
453
|
.ds-toggle-btn { min-width: 78px; }
|
|
454
|
+
/* Side-by-side checked/unchecked reference pair (settings kit theme panel) --
|
|
455
|
+
documents the visual difference between states in one static, non-live
|
|
456
|
+
spot rather than requiring a viewer to toggle a real control back and
|
|
457
|
+
forth to compare. */
|
|
458
|
+
.ds-toggle-state-sample { display: flex; align-items: center; gap: var(--space-1-5, 6px); }
|
|
454
459
|
.ds-toggle-label { margin-left: var(--space-2, 8px); color: inherit; opacity: 0.7; }
|
|
455
460
|
.ds-btn-warn { color: var(--warn); }
|
|
456
461
|
/* Raw --mascot text measures 3.11:1 on paper (fails 4.5:1); --mascot-deep is
|
|
@@ -593,6 +598,14 @@
|
|
|
593
598
|
display: flex; flex-direction: column; gap: 0;
|
|
594
599
|
background: var(--ink); border-radius: var(--r-1);
|
|
595
600
|
font-family: var(--ff-mono); font-size: var(--fs-micro); line-height: 1.65;
|
|
601
|
+
/* Responsive strategy for long logs: cap the scrollback height and scroll
|
|
602
|
+
vertically rather than growing the page indefinitely; long command/output
|
|
603
|
+
lines wrap (see .cli .cmd's overflow-wrap: anywhere below) instead of
|
|
604
|
+
scrolling horizontally, so wrapping is the chosen default over
|
|
605
|
+
horizontal scroll for this kit. */
|
|
606
|
+
max-height: 60vh;
|
|
607
|
+
overflow-y: auto;
|
|
608
|
+
overflow-wrap: anywhere;
|
|
596
609
|
}
|
|
597
610
|
/* .cli is authored in hero-content.css as a STANDALONE hero code block --
|
|
598
611
|
20px/24px padding, --fs-lg type, --r-3 radius and its own --ink background
|
|
@@ -73,6 +73,13 @@
|
|
|
73
73
|
margin: 0; font: inherit; font-size: inherit; font-weight: inherit;
|
|
74
74
|
letter-spacing: inherit; text-transform: inherit; color: inherit;
|
|
75
75
|
}
|
|
76
|
+
/* Category glyph beside a panel title (kits / previews / decks / docs on the
|
|
77
|
+
homepage) — same inline-svg vocabulary as icons.js, sized to sit on the
|
|
78
|
+
text baseline rather than dominating it. */
|
|
79
|
+
.ds-panel-title-glyph {
|
|
80
|
+
display: inline-flex; align-items: center; gap: var(--space-1-5, 6px);
|
|
81
|
+
}
|
|
82
|
+
.ds-panel-title-glyph .ds-icon { flex-shrink: 0; color: var(--fg-3); }
|
|
76
83
|
.panel-body { padding: var(--space-2) var(--space-3) var(--space-3); }
|
|
77
84
|
.panel-body > * { margin: 0; }
|
|
78
85
|
/* One-line explanatory caption under a panel's title — e.g. distinguishing
|
|
@@ -113,6 +120,14 @@
|
|
|
113
120
|
transition: background var(--dur-snap) var(--ease), box-shadow var(--dur-base) var(--ease-spring);
|
|
114
121
|
}
|
|
115
122
|
.row + .row { margin-top: 2px; }
|
|
123
|
+
/* Mobile tap-target floor: at compact/comfortable density on a touch
|
|
124
|
+
viewport the padding-only row height can fall under the 44px effective
|
|
125
|
+
tap target (WCAG 2.5.5), especially at [data-density="compact"] (0.75x).
|
|
126
|
+
Force a min-height on narrow/coarse-pointer viewports only, so the dense
|
|
127
|
+
desktop mono/list layout (file-row, index-row) is untouched above 640px. */
|
|
128
|
+
@media (max-width: 640px), (pointer: coarse) {
|
|
129
|
+
.row, a.row, button.row, .row[role="button"] { min-height: 44px; }
|
|
130
|
+
}
|
|
116
131
|
/* Interactive rows (anchor/button wrappers) get a hairline lift on hover,
|
|
117
132
|
matching the btn/panel elevation language — non-interactive rows (plain
|
|
118
133
|
divs used as static list items) are unaffected since the selector needs a
|