rizzo-css 0.0.81 → 0.0.83
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 +1 -1
- package/bin/rizzo-css.js +12 -0
- package/dist/rizzo.min.css +1 -1
- package/package.json +1 -1
- package/scaffold/astro/Settings.astro +3 -2
- package/scaffold/react/DocsSidebar.tsx +137 -28
- package/scaffold/react/ThemeIcon.tsx +57 -0
- package/scaffold/react/base/package.json +1 -1
- package/scaffold/react/themes.ts +54 -0
- package/scaffold/react/variants/full/README-RIZZO.md +35 -0
- package/scaffold/react/variants/full/package.json +24 -0
- package/scaffold/react/variants/full/src/App.tsx +41 -0
- package/scaffold/react/variants/full/src/config/componentCategories.ts +43 -0
- package/scaffold/react/variants/full/src/config/docsNav.ts +87 -0
- package/scaffold/react/variants/full/src/index.css +96 -0
- package/scaffold/react/variants/full/src/layouts/BlocksLayout.tsx +124 -0
- package/scaffold/react/variants/full/src/layouts/DocsLayout.tsx +93 -0
- package/scaffold/react/variants/full/src/main.tsx +13 -0
- package/scaffold/react/variants/full/src/views/BlocksIndex.tsx +56 -0
- package/scaffold/react/variants/full/src/views/DocsComponents.tsx +56 -0
- package/scaffold/react/variants/full/src/views/DocsGettingStarted.tsx +27 -0
- package/scaffold/react/variants/full/src/views/DocsIndex.tsx +39 -0
- package/scaffold/react/variants/full/src/views/DocsOverview.tsx +39 -0
- package/scaffold/react/variants/full/src/views/Home.tsx +104 -0
- package/scaffold/react/variants/full/src/views/Themes.tsx +118 -0
- package/scaffold/svelte/Settings.svelte +30 -5
- package/scaffold/svelte/variants/full/src/config/docsNav.ts +213 -13
- package/scaffold/svelte/variants/full/src/routes/+layout.svelte +4 -1
- package/scaffold/svelte/variants/full/src/routes/blocks/+layout.svelte +4 -2
- package/scaffold/svelte/variants/full/src/routes/docs/+layout.svelte +3 -1
- package/scaffold/svelte/variants/full/src/routes/themes/+page.svelte +130 -69
- package/scaffold/vanilla/README-RIZZO.md +1 -1
- package/scaffold/vanilla/components/accordion.html +8 -0
- package/scaffold/vanilla/components/alert-dialog.html +8 -0
- package/scaffold/vanilla/components/alert.html +8 -0
- package/scaffold/vanilla/components/aspect-ratio.html +8 -0
- package/scaffold/vanilla/components/avatar.html +8 -0
- package/scaffold/vanilla/components/back-to-top.html +8 -0
- package/scaffold/vanilla/components/badge.html +8 -0
- package/scaffold/vanilla/components/breadcrumb.html +8 -0
- package/scaffold/vanilla/components/button-group.html +8 -0
- package/scaffold/vanilla/components/button.html +8 -0
- package/scaffold/vanilla/components/calendar.html +8 -0
- package/scaffold/vanilla/components/cards.html +8 -0
- package/scaffold/vanilla/components/carousel.html +8 -0
- package/scaffold/vanilla/components/chart.html +8 -0
- package/scaffold/vanilla/components/collapsible.html +8 -0
- package/scaffold/vanilla/components/command.html +8 -0
- package/scaffold/vanilla/components/context-menu.html +8 -0
- package/scaffold/vanilla/components/copy-to-clipboard.html +8 -0
- package/scaffold/vanilla/components/dashboard.html +8 -0
- package/scaffold/vanilla/components/direction.html +8 -0
- package/scaffold/vanilla/components/divider.html +8 -0
- package/scaffold/vanilla/components/docs-sidebar.html +8 -0
- package/scaffold/vanilla/components/dropdown.html +8 -0
- package/scaffold/vanilla/components/empty.html +8 -0
- package/scaffold/vanilla/components/font-switcher.html +8 -0
- package/scaffold/vanilla/components/footer.html +8 -0
- package/scaffold/vanilla/components/forms.html +8 -0
- package/scaffold/vanilla/components/hover-card.html +8 -0
- package/scaffold/vanilla/components/icons.html +8 -0
- package/scaffold/vanilla/components/index.html +8 -0
- package/scaffold/vanilla/components/input-group.html +8 -0
- package/scaffold/vanilla/components/input-otp.html +8 -0
- package/scaffold/vanilla/components/kbd.html +8 -0
- package/scaffold/vanilla/components/label.html +8 -0
- package/scaffold/vanilla/components/menubar.html +8 -0
- package/scaffold/vanilla/components/modal.html +8 -0
- package/scaffold/vanilla/components/navbar.html +8 -0
- package/scaffold/vanilla/components/pagination.html +8 -0
- package/scaffold/vanilla/components/popover.html +8 -0
- package/scaffold/vanilla/components/progress-bar.html +8 -0
- package/scaffold/vanilla/components/range-calendar.html +8 -0
- package/scaffold/vanilla/components/resizable.html +8 -0
- package/scaffold/vanilla/components/scroll-area.html +8 -0
- package/scaffold/vanilla/components/search.html +8 -0
- package/scaffold/vanilla/components/separator.html +8 -0
- package/scaffold/vanilla/components/settings.html +8 -0
- package/scaffold/vanilla/components/sheet.html +8 -0
- package/scaffold/vanilla/components/skeleton.html +8 -0
- package/scaffold/vanilla/components/slider.html +8 -0
- package/scaffold/vanilla/components/sound-effects.html +8 -0
- package/scaffold/vanilla/components/spinner.html +8 -0
- package/scaffold/vanilla/components/switch.html +8 -0
- package/scaffold/vanilla/components/table.html +8 -0
- package/scaffold/vanilla/components/tabs.html +8 -0
- package/scaffold/vanilla/components/theme-switcher.html +8 -0
- package/scaffold/vanilla/components/toast.html +8 -0
- package/scaffold/vanilla/components/toggle-group.html +8 -0
- package/scaffold/vanilla/components/toggle.html +8 -0
- package/scaffold/vanilla/components/tooltip.html +8 -0
- package/scaffold/vanilla/index.html +8 -0
- package/scaffold/vue/DocsSidebar.vue +138 -4
- package/scaffold/vue/ThemeIcon.vue +50 -0
- package/scaffold/vue/base/package.json +1 -1
- package/scaffold/vue/themes.ts +54 -0
- package/scaffold/vue/variants/full/README-RIZZO.md +35 -0
- package/scaffold/vue/variants/full/package.json +22 -0
- package/scaffold/vue/variants/full/src/App.vue +17 -0
- package/scaffold/vue/variants/full/src/config/componentCategories.ts +43 -0
- package/scaffold/vue/variants/full/src/config/docsNav.ts +87 -0
- package/scaffold/vue/variants/full/src/layouts/BlocksLayout.vue +136 -0
- package/scaffold/vue/variants/full/src/layouts/DocsLayout.vue +145 -0
- package/scaffold/vue/variants/full/src/main.ts +6 -0
- package/scaffold/vue/variants/full/src/router/index.ts +38 -0
- package/scaffold/vue/variants/full/src/views/BlocksIndex.vue +111 -0
- package/scaffold/vue/variants/full/src/views/DocsComponents.vue +115 -0
- package/scaffold/vue/variants/full/src/views/DocsGettingStarted.vue +45 -0
- package/scaffold/vue/variants/full/src/views/DocsIndex.vue +69 -0
- package/scaffold/vue/variants/full/src/views/DocsOverview.vue +66 -0
- package/scaffold/vue/variants/full/src/views/Home.vue +240 -0
- package/scaffold/vue/variants/full/src/views/Themes.vue +257 -0
package/README.md
CHANGED
|
@@ -72,7 +72,7 @@ import 'rizzo-css';
|
|
|
72
72
|
**Without a bundler (plain HTML):** Use a CDN. Both unpkg and jsDelivr resolve the package root to the built CSS (via the `unpkg` / `jsdelivr` fields in this package). For reliability or to pin a version, use the explicit path:
|
|
73
73
|
|
|
74
74
|
```html
|
|
75
|
-
<!-- unpkg (pin version: replace @latest with @0.0.
|
|
75
|
+
<!-- unpkg (pin version: replace @latest with @0.0.83 or any version) -->
|
|
76
76
|
<link rel="stylesheet" href="https://unpkg.com/rizzo-css@latest/dist/rizzo.min.css" />
|
|
77
77
|
|
|
78
78
|
<!-- or jsDelivr -->
|
package/bin/rizzo-css.js
CHANGED
|
@@ -2036,6 +2036,12 @@ function copyReactComponents(projectDir, selectedNames, opts) {
|
|
|
2036
2036
|
}
|
|
2037
2037
|
const iconsSrc = join(scaffoldDir, 'icons');
|
|
2038
2038
|
if (existsSync(iconsSrc) && (toCopy.length > 0 || copyIconsOnly)) copyDirRecursive(iconsSrc, join(targetDir, 'icons'));
|
|
2039
|
+
if (toCopy.includes('ThemeSwitcher') || toCopy.includes('ThemeIcon')) {
|
|
2040
|
+
const themesSrc = join(scaffoldDir, 'themes.ts');
|
|
2041
|
+
if (existsSync(themesSrc)) {
|
|
2042
|
+
copyFileSync(themesSrc, join(targetDir, 'themes.ts'));
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2039
2045
|
if (toCopy.includes('Settings')) {
|
|
2040
2046
|
const configDir = getScaffoldConfigDir();
|
|
2041
2047
|
const fontsSrc = join(configDir, 'fonts.ts');
|
|
@@ -2098,6 +2104,12 @@ function copyVueComponents(projectDir, selectedNames, opts) {
|
|
|
2098
2104
|
}
|
|
2099
2105
|
const iconsSrc = join(scaffoldDir, 'icons');
|
|
2100
2106
|
if (existsSync(iconsSrc) && (toCopy.length > 0 || copyIconsOnly)) copyDirRecursive(iconsSrc, join(targetDir, 'icons'));
|
|
2107
|
+
if (toCopy.includes('ThemeSwitcher') || toCopy.includes('ThemeIcon')) {
|
|
2108
|
+
const themesSrc = join(scaffoldDir, 'themes.ts');
|
|
2109
|
+
if (existsSync(themesSrc)) {
|
|
2110
|
+
copyFileSync(themesSrc, join(targetDir, 'themes.ts'));
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2101
2113
|
if (toCopy.includes('Settings')) {
|
|
2102
2114
|
const configDir = getScaffoldConfigDir();
|
|
2103
2115
|
const fontsSrc = join(configDir, 'fonts.ts');
|
package/dist/rizzo.min.css
CHANGED
|
@@ -126,7 +126,7 @@ div.navbar__link{background:none;border:none;color:inherit;cursor:pointer;font:i
|
|
|
126
126
|
.theme-switcher__option--active:hover{background-color:var(--theme-bg,var(--background));border-left:var(--border-width-accent) solid var(--accent);border-radius:var(--radius);color:var(--text);font-weight:var(--font-weight-medium);padding-left:calc(var(--spacing-4) - var(--border-width-accent))}.theme-switcher__option--active:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}@media (width <= 768px){.theme-switcher,.theme-switcher__menu{max-width:100%;width:100%}.theme-switcher__menu{box-sizing:border-box;left:0;min-width:0;right:auto}}@media (width <= 640px){.theme-switcher__menu{left:0;right:auto}}.font-switcher{display:inline-block;position:relative;width:var(--theme-switcher-width)}.font-switcher__trigger{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-3);justify-content:space-between;min-width:0;padding:var(--spacing-3) var(--spacing-4);transition:background-color var(--transition-base),border-color var(--transition-base);width:100%}.font-switcher__label{flex:1;min-width:0;overflow:hidden;text-align:left;text-overflow:ellipsis;white-space:nowrap}.font-switcher__trigger:hover{background-color:var(--background);border-color:var(--accent);color:var(--text)}.font-switcher__trigger:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.font-switcher__trigger[aria-expanded="true"] .font-switcher__icon{transform:rotate(180deg)}.font-switcher__icon{color:var(--icon);flex-shrink:0;transition:transform var(--transition-base),color var(--transition-base)}.font-switcher__menu{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);display:flex;flex-direction:row;gap:0;left:0;max-height:var(--spacing-100);min-width:var(--theme-switcher-width);opacity:0;overflow-y:auto;position:absolute;top:calc(100% + var(--spacing-2));transform:translateY(calc(var(--spacing-2)*-1));transition:opacity var(--transition-base),visibility var(--transition-base),transform var(--transition-base);visibility:hidden;width:var(--theme-switcher-width);z-index:var(--z-dropdown)}.font-switcher__menu--open{opacity:1;transform:translateY(0);visibility:visible}.font-switcher__menu-options{flex:1 1 auto;min-width:0;overflow-y:auto}.font-switcher__preview{background-color:var(--background);display:flex;flex:0 0 auto;flex-direction:column;gap:var(--spacing-2);justify-content:flex-start;min-width:var(--spacing-32);padding:var(--spacing-4);pointer-events:none;width:var(--spacing-32)}.font-switcher__preview-title{color:var(--text);font-size:var(--font-size-sm);font-weight:var(--font-weight-bold);line-height:1.2;margin:0 0 var(--spacing-1) 0;padding:0}.font-switcher__preview-sample{color:var(--text);font-size:var(--font-size-lg);line-height:1.3;margin:0}.font-switcher__preview-mono{color:var(--text-dim);font-family:var(--font-family-mono);font-size:var(--font-size-sm);margin:0}@media (width <= 480px){.font-switcher__preview{display:none}}@media (width >= 481px){.font-switcher__menu-options{border-right:var(--border-width) solid var(--border)}}.font-switcher__option{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:transparent;border:none;color:var(--text);cursor:pointer;display:flex;font:inherit;font-family:var(--font-family);font-size:var(--font-size-base);padding:var(--spacing-2) var(--spacing-4);position:relative;text-align:left;transition:background-color var(--transition-fast),color var(--transition-fast);-webkit-user-select:none;-moz-user-select:none;user-select:none;width:100%}
|
|
127
127
|
.font-switcher__option:focus-visible,.font-switcher__option:hover{background-color:var(--background);color:var(--text);outline:none}.font-switcher__option:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}.font-switcher__option--active,
|
|
128
128
|
.font-switcher__option--active:focus-visible,
|
|
129
|
-
.font-switcher__option--active:hover{background-color:var(--background);border-left:var(--border-width-accent) solid var(--accent);border-radius:var(--radius);color:var(--text);font-weight:var(--font-weight-medium);padding-left:calc(var(--spacing-4) - var(--border-width-accent))}.font-switcher__option--active:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}@media (width <= 768px){.font-switcher,.font-switcher__menu{max-width:100%;width:100%}.font-switcher__menu{box-sizing:border-box;left:0;min-width:0;right:auto}}.settings__control .font-switcher{max-width:100%;width:100%}.settings__control .font-switcher__menu{box-sizing:border-box;max-width:100%;min-width:0;width:100%}.settings{inset:0;pointer-events:none;position:fixed;z-index:var(--z-settings)}.settings[aria-hidden="true"]{display:none}.settings__overlay{backdrop-filter:blur(var(--blur-sm));background-color:var(--overlay);inset:0;opacity:0;pointer-events:all;position:absolute;transition:opacity var(--transition-ease-out);z-index:1}.settings[aria-hidden="false"] .settings__overlay[aria-hidden="false"],.settings__overlay[aria-hidden="false"]{opacity:1}.settings__panel{background-color:var(--background-alt);border-left:var(--border-width) solid var(--border);box-shadow:calc(var(--spacing-1)*-1) 0 var(--spacing-3) calc(var(--spacing-0-125)*-1) oklch(from var(--shadow-color) l c h/15%);display:flex;flex-direction:column;height:100%;max-height:100vh;max-height:100dvh;max-width:var(--spacing-105);overflow:hidden;pointer-events:all;position:absolute;right:0;top:0;transform:translateX(100%);transition:transform var(--transition-ease-out);width:100%;z-index:2}.settings__panel[data-open="true"]{transform:translateX(0)}.settings[aria-hidden="false"] .settings__panel:not([data-open]){transform:translateX(100%)}@media (prefers-reduced-motion:reduce){.settings__overlay,.settings__panel{transition:none}}.settings__header{align-items:center;background-color:var(--background-alt);border-bottom:var(--border-width) solid var(--border);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--spacing-6);position:sticky;top:0;z-index:var(--z-dropdown)}.settings__title{color:var(--text);font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);margin:0}.settings__close{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;height:var(--spacing-8);justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:0;transition:background-color var(--transition-base),color var(--transition-base),border-color var(--transition-base);width:var(--spacing-8)}.settings__close:hover{background-color:var(--background-alt);border-color:var(--accent);color:var(--accent)}.settings__close:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__content{background-color:var(--background);display:flex;flex:1 1 0;flex-direction:column;gap:var(--spacing-8);min-height:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior-y:contain;padding:var(--spacing-6);-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}@media (width >= 641px){.settings__content{max-height:calc(100dvh - 4.5rem);max-height:calc(100vh - 4.5rem)}}.settings__section{display:flex;flex-direction:column;gap:var(--spacing-4)}.settings__section-title{color:var(--text);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);margin:0 0 var(--spacing-4)}.settings__control{display:flex;flex-direction:column;gap:var(--spacing-3)}.settings__control .theme-switcher{max-width:100%;width:100%}.settings__control .theme-switcher__menu{box-sizing:border-box;max-width:100%;min-width:0;width:100%}.settings__label{align-items:center;color:var(--text);display:flex;font-weight:var(--font-weight-medium);justify-content:space-between;margin-bottom:var(--spacing-3)}.settings__label-text{font-size:var(--font-size-base)}.settings__label-value{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold)}.settings__slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);cursor:pointer;height:var(--spacing-2);outline:none;width:100%}.settings__slider::-webkit-slider-runnable-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-moz-range-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);margin-top:calc(var(--spacing-2)*-1);-webkit-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-webkit-slider-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider::-moz-range-thumb{background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);-moz-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-moz-range-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__slider-labels{color:var(--text-dim);display:flex;font-size:var(--font-size-xs);justify-content:space-between;margin-top:var(--spacing-1)}.settings__checkbox-label{align-items:center;color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-medium);gap:var(--spacing-3);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__checkbox-label:hover{color:var(--accent)}.settings__checkbox{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__radio-group{display:flex;flex-direction:column;gap:var(--spacing-2)}.settings__radio-label{align-items:center;border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-normal);gap:var(--spacing-2);padding:var(--spacing-2);transition:background-color var(--transition-base),color var(--transition-base);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__radio-label:hover{background-color:var(--background-alt);color:var(--accent)}.settings__radio{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__help-text{color:var(--text-dim);font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);margin:0}.back-to-top{bottom:var(--spacing-6);opacity:0;position:fixed;right:var(--spacing-6);transform:translateY(var(--spacing-2));transition:opacity var(--transition-base),visibility var(--transition-base),transform var(--transition-base);visibility:hidden;z-index:var(--z-fixed)}.back-to-top[data-visible="true"]{opacity:1;transform:translateY(0);visibility:visible}.back-to-top__btn{align-items:center;background-color:var(--accent);border:none;border-radius:var(--radius-md);box-shadow:var(--shadow-lg);color:var(--accent-text);cursor:pointer;display:flex;height:var(--spacing-10);justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:0;transition:background-color var(--transition-base),transform var(--transition-base);width:var(--spacing-10)}.back-to-top__btn:hover{background-color:var(--accent-hover)}.back-to-top__btn:focus-visible{outline:var(--outline-width) solid var(--accent-text);outline-offset:var(--outline-offset)}.back-to-top__icon{flex-shrink:0}@media (prefers-reduced-motion:reduce){.back-to-top,
|
|
129
|
+
.font-switcher__option--active:hover{background-color:var(--background);border-left:var(--border-width-accent) solid var(--accent);border-radius:var(--radius);color:var(--text);font-weight:var(--font-weight-medium);padding-left:calc(var(--spacing-4) - var(--border-width-accent))}.font-switcher__option--active:focus-visible{box-shadow:inset 0 0 0 var(--outline-width) var(--accent)}@media (width <= 768px){.font-switcher,.font-switcher__menu{max-width:100%;width:100%}.font-switcher__menu{box-sizing:border-box;left:0;min-width:0;right:auto}}.settings__control .font-switcher{max-width:100%;width:100%}.settings__control .font-switcher__menu{box-sizing:border-box;max-width:100%;min-width:0;width:100%}.settings{inset:0;pointer-events:none;position:fixed;z-index:var(--z-settings)}.settings[aria-hidden="true"]{display:none}.settings__overlay{backdrop-filter:blur(var(--blur-sm));background-color:var(--overlay);inset:0;opacity:0;pointer-events:all;position:absolute;transition:opacity var(--transition-ease-out);z-index:1}.settings[aria-hidden="false"] .settings__overlay[aria-hidden="false"],.settings__overlay[aria-hidden="false"]{opacity:1}.settings__panel{background-color:var(--background-alt);border-left:var(--border-width) solid var(--border);box-shadow:calc(var(--spacing-1)*-1) 0 var(--spacing-3) calc(var(--spacing-0-125)*-1) oklch(from var(--shadow-color) l c h/15%);display:flex;flex-direction:column;height:100%;max-height:100vh;max-height:100dvh;max-width:var(--spacing-105);overflow:hidden;pointer-events:all;position:absolute;right:0;top:0;transform:translateX(100%);transition:transform var(--transition-ease-out);width:100%;z-index:2}.settings__panel[data-open="true"]{transform:translateX(0)}.settings[aria-hidden="false"] .settings__panel:not([data-open]){transform:translateX(100%)}@media (prefers-reduced-motion:reduce){.settings__overlay,.settings__panel{transition:none}}.reduced-motion .settings__overlay,.reduced-motion .settings__panel{transition:none}.settings__header{align-items:center;background-color:var(--background-alt);border-bottom:var(--border-width) solid var(--border);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--spacing-6);position:sticky;top:0;z-index:var(--z-dropdown)}.settings__title{color:var(--text);font-size:var(--font-size-xl);font-weight:var(--font-weight-bold);margin:0}.settings__close{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;height:var(--spacing-8);justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:0;transition:background-color var(--transition-base),color var(--transition-base),border-color var(--transition-base);width:var(--spacing-8)}.settings__close:hover{background-color:var(--background-alt);border-color:var(--accent);color:var(--accent)}.settings__close:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__content{background-color:var(--background);display:flex;flex:1 1 0;flex-direction:column;gap:var(--spacing-8);min-height:0;overflow-x:hidden;overflow-y:auto;overscroll-behavior-y:contain;padding:var(--spacing-6);-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}@media (width >= 641px){.settings__content{max-height:calc(100dvh - 4.5rem);max-height:calc(100vh - 4.5rem)}}.settings__section{display:flex;flex-direction:column;gap:var(--spacing-4)}.settings__section-title{color:var(--text);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);margin:0 0 var(--spacing-4)}.settings__control{display:flex;flex-direction:column;gap:var(--spacing-3)}.settings__control .theme-switcher{max-width:100%;width:100%}.settings__control .theme-switcher__menu{box-sizing:border-box;max-width:100%;min-width:0;width:100%}.settings__label{align-items:center;color:var(--text);display:flex;font-weight:var(--font-weight-medium);justify-content:space-between;margin-bottom:var(--spacing-3)}.settings__label-text{font-size:var(--font-size-base)}.settings__label-value{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold)}.settings__slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);cursor:pointer;height:var(--spacing-2);outline:none;width:100%}.settings__slider::-webkit-slider-runnable-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-moz-range-track{background:linear-gradient(to right,var(--accent) 0,var(--accent) var(--slider-progress,50%),var(--background-alt) var(--slider-progress,50%),var(--background-alt) 100%);border:var(--border-width) solid var(--border);border-radius:var(--radius);box-shadow:inset 0 var(--spacing-0-125) var(--spacing-0-125) oklch(from var(--shadow-color) l c h/10%);height:var(--spacing-2);width:100%}.settings__slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);margin-top:calc(var(--spacing-2)*-1);-webkit-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-webkit-slider-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider::-moz-range-thumb{background-color:var(--accent);border:var(--outline-width) solid var(--background);border-radius:var(--radius-circle);box-shadow:0 0 0 var(--spacing-0-125) var(--border);cursor:pointer;height:var(--spacing-5);-moz-transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);transition:background-color var(--transition-base),transform var(--transition-base),border-color var(--transition-base);width:var(--spacing-5)}.settings__slider::-moz-range-thumb:hover{background-color:var(--accent-hover);transform:scale(1.1)}.settings__slider:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.settings__slider-labels{color:var(--text-dim);display:flex;font-size:var(--font-size-xs);justify-content:space-between;margin-top:var(--spacing-1)}.settings__checkbox-label{align-items:center;color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-medium);gap:var(--spacing-3);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__checkbox-label:hover{color:var(--accent)}.settings__checkbox{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__radio-group{display:flex;flex-direction:column;gap:var(--spacing-2)}.settings__radio-label{align-items:center;border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:flex;font-size:var(--font-size-base);font-weight:var(--font-weight-normal);gap:var(--spacing-2);padding:var(--spacing-2);transition:background-color var(--transition-base),color var(--transition-base);-webkit-user-select:none;-moz-user-select:none;user-select:none}.settings__radio-label:hover{background-color:var(--background-alt);color:var(--accent)}.settings__radio{accent-color:var(--accent);cursor:pointer;height:var(--spacing-5);margin:0;width:var(--spacing-5)}.settings__help-text{color:var(--text-dim);font-size:var(--font-size-sm);line-height:var(--line-height-relaxed);margin:0}.back-to-top{bottom:var(--spacing-6);opacity:0;position:fixed;right:var(--spacing-6);transform:translateY(var(--spacing-2));transition:opacity var(--transition-base),visibility var(--transition-base),transform var(--transition-base);visibility:hidden;z-index:var(--z-fixed)}.back-to-top[data-visible="true"]{opacity:1;transform:translateY(0);visibility:visible}.back-to-top__btn{align-items:center;background-color:var(--accent);border:none;border-radius:var(--radius-md);box-shadow:var(--shadow-lg);color:var(--accent-text);cursor:pointer;display:flex;height:var(--spacing-10);justify-content:center;min-height:var(--touch-target-min);min-width:var(--touch-target-min);padding:0;transition:background-color var(--transition-base),transform var(--transition-base);width:var(--spacing-10)}.back-to-top__btn:hover{background-color:var(--accent-hover)}.back-to-top__btn:focus-visible{outline:var(--outline-width) solid var(--accent-text);outline-offset:var(--outline-offset)}.back-to-top__icon{flex-shrink:0}@media (prefers-reduced-motion:reduce){.back-to-top,
|
|
130
130
|
.back-to-top[data-visible="true"]{transition:none}}@media (width <= 640px){.settings__panel{max-width:100%;width:100%}}.modal-root{inset:0;pointer-events:none;position:fixed;z-index:var(--z-modal)}.modal-root > .modal__overlay{backdrop-filter:blur(var(--blur-sm));background-color:oklch(from var(--shadow-color) l c h/60%);bottom:0;left:0;opacity:0;pointer-events:none;position:fixed;right:0;top:0;transition:opacity var(--transition-slow) ease;z-index:0}.modal-root > .modal__overlay[aria-hidden="false"]{opacity:1;pointer-events:auto}.modal-root > .modal{pointer-events:none;z-index:1}.modal-root > .modal[aria-hidden="false"]{pointer-events:auto}.modal__overlay{backdrop-filter:blur(var(--blur-sm));background-color:oklch(from var(--shadow-color) l c h/60%);bottom:0;left:0;opacity:0;pointer-events:none;position:fixed;right:0;top:0;transition:opacity var(--transition-slow) ease;z-index:var(--z-modal-backdrop)}.modal__overlay[aria-hidden="false"]{opacity:1;pointer-events:auto}.modal{background-color:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-xl);display:flex;flex-direction:column;left:50%;max-height:var(--vh-90);max-width:var(--max-height-modal);opacity:0;pointer-events:none;position:fixed;top:50%;transform:translate(-50%,-50%);transition:opacity var(--transition-slow) ease,transform var(--transition-slow) ease;width:100%;z-index:var(--z-modal)}.modal[aria-hidden="false"]{opacity:1;pointer-events:auto}.modal__header{align-items:center;border-bottom:var(--border-width) solid var(--border);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--spacing-6)}.modal__title{color:var(--text);font-size:var(--font-size-xl);font-weight:var(--font-weight-semibold);margin:0}.modal__close{align-items:center;background:none;border:none;border-radius:var(--radius);color:var(--text-dim);cursor:pointer;display:flex;flex-shrink:0;justify-content:center;padding:var(--spacing-2);transition:background-color var(--transition-base),color var(--transition-base)}.modal__close:hover{background-color:var(--background-alt);color:var(--text)}.modal__close:focus{box-shadow:0 0 0 3px oklch(from var(--accent) l c h/10%);outline:none}.modal__body{flex:1;min-height:0;overflow-y:auto;padding:var(--spacing-6)}.modal__footer{border-top:var(--border-width) solid var(--border);display:flex;flex-shrink:0;gap:var(--spacing-3);justify-content:flex-end;padding:var(--spacing-6)}.modal__footer:empty{display:none}.modal--sm{max-width:var(--spacing-96)}.modal--md{max-width:var(--max-height-modal)}.modal--lg{max-width:var(--max-width-modal-lg)}
|
|
131
131
|
.reduced-motion .modal,.reduced-motion .modal__overlay{transition:none}@media (width <= 640px){.modal{bottom:auto;left:auto;margin:var(--spacing-4);max-height:95vh;max-width:95vw;right:auto;top:auto}.modal,.modal[aria-hidden="false"]{transform:none}
|
|
132
132
|
.modal__body,
|
package/package.json
CHANGED
|
@@ -277,9 +277,10 @@ const { open = false } = Astro.props;
|
|
|
277
277
|
// Remove data-open first to trigger close animation
|
|
278
278
|
panel.removeAttribute('data-open');
|
|
279
279
|
|
|
280
|
-
// Wait for animation to complete before hiding
|
|
280
|
+
// Wait for animation to complete before hiding (respect system preference and user toggle)
|
|
281
281
|
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
282
|
-
const
|
|
282
|
+
const reducedMotionClass = html.classList.contains('reduced-motion');
|
|
283
|
+
const animationDuration = (prefersReducedMotion || reducedMotionClass) ? 0 : 300;
|
|
283
284
|
|
|
284
285
|
setTimeout(() => {
|
|
285
286
|
settings.setAttribute('aria-hidden', 'true');
|
|
@@ -1,46 +1,155 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import type { HTMLAttributes } from 'react';
|
|
2
3
|
|
|
3
|
-
export interface
|
|
4
|
+
export interface DocsNavSection {
|
|
5
|
+
id: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface DocsNavLink {
|
|
4
10
|
href: string;
|
|
5
11
|
label: string;
|
|
6
|
-
|
|
12
|
+
frameworkOnly?: boolean;
|
|
13
|
+
absolute?: boolean;
|
|
14
|
+
sections?: DocsNavSection[];
|
|
15
|
+
/** When true, open in new tab (external to main site). */
|
|
16
|
+
external?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DocsNavGroup {
|
|
20
|
+
label: string;
|
|
21
|
+
links: DocsNavLink[];
|
|
7
22
|
}
|
|
8
23
|
|
|
9
24
|
export interface DocsSidebarProps extends HTMLAttributes<HTMLElement> {
|
|
10
|
-
|
|
11
|
-
|
|
25
|
+
/** Current URL pathname (e.g. location.pathname or useLocation().pathname). */
|
|
26
|
+
currentPath: string;
|
|
27
|
+
/** Path prefix for framework-specific links (e.g. /docs). */
|
|
28
|
+
pathPrefix?: string;
|
|
29
|
+
/** When true, omit the aside id to avoid duplicate ids when used inside a demo box. */
|
|
30
|
+
omitId?: boolean;
|
|
31
|
+
/** Nav config (when not provided, sidebar renders minimal placeholder for base template). */
|
|
32
|
+
nav?: DocsNavGroup[];
|
|
12
33
|
className?: string;
|
|
13
34
|
}
|
|
14
35
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
|
|
36
|
+
function fullHref(link: { href: string; frameworkOnly?: boolean; absolute?: boolean }, pathPrefix: string): string {
|
|
37
|
+
if (link.absolute && link.href) return link.href;
|
|
38
|
+
const base = link.frameworkOnly ? pathPrefix : '/docs';
|
|
39
|
+
return `${base}/${link.href}`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function isActive(link: DocsNavLink, currentPath: string, pathPrefix: string): boolean {
|
|
43
|
+
const path = currentPath.replace(/\/$/, '');
|
|
44
|
+
const href = fullHref(link, pathPrefix);
|
|
45
|
+
return path === href;
|
|
46
|
+
}
|
|
20
47
|
|
|
21
48
|
export function DocsSidebar({
|
|
22
|
-
|
|
23
|
-
|
|
49
|
+
currentPath,
|
|
50
|
+
pathPrefix = '/docs',
|
|
51
|
+
omitId = false,
|
|
52
|
+
nav = [],
|
|
24
53
|
className = '',
|
|
25
54
|
...rest
|
|
26
55
|
}: DocsSidebarProps) {
|
|
56
|
+
const [activeSectionId, setActiveSectionId] = useState<string | null>(null);
|
|
57
|
+
|
|
58
|
+
useEffect(() => {
|
|
59
|
+
function setActiveFromHash() {
|
|
60
|
+
setActiveSectionId(window.location.hash.slice(1) || null);
|
|
61
|
+
}
|
|
62
|
+
setActiveFromHash();
|
|
63
|
+
window.addEventListener('hashchange', setActiveFromHash);
|
|
64
|
+
|
|
65
|
+
let io: IntersectionObserver | null = null;
|
|
66
|
+
const content = document.querySelector('.docs__content');
|
|
67
|
+
if (content) {
|
|
68
|
+
const headings = content.querySelectorAll<HTMLHeadingElement>('h2[id]');
|
|
69
|
+
if (headings.length) {
|
|
70
|
+
io = new IntersectionObserver(
|
|
71
|
+
(entries: IntersectionObserverEntry[]) => {
|
|
72
|
+
for (const e of entries) {
|
|
73
|
+
if (!e.isIntersecting) continue;
|
|
74
|
+
const id = (e.target as HTMLElement).id;
|
|
75
|
+
if (id) setActiveSectionId(id);
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
{ rootMargin: '-80px 0px -60% 0px', threshold: 0 }
|
|
80
|
+
);
|
|
81
|
+
headings.forEach((h) => io!.observe(h));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return () => {
|
|
85
|
+
window.removeEventListener('hashchange', setActiveFromHash);
|
|
86
|
+
io?.disconnect();
|
|
87
|
+
};
|
|
88
|
+
}, []);
|
|
89
|
+
|
|
90
|
+
const hasNav = nav && nav.length > 0;
|
|
91
|
+
|
|
27
92
|
return (
|
|
28
|
-
<aside
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
93
|
+
<aside
|
|
94
|
+
id={omitId ? undefined : 'docs-sidebar'}
|
|
95
|
+
className={`docs-sidebar ${className}`.trim()}
|
|
96
|
+
aria-label="Documentation navigation"
|
|
97
|
+
{...rest}
|
|
98
|
+
>
|
|
99
|
+
{hasNav ? (
|
|
100
|
+
<nav className="docs-sidebar__nav">
|
|
101
|
+
{nav.map((group) => (
|
|
102
|
+
<div key={group.label} className="docs-sidebar__group">
|
|
103
|
+
<h2 className="docs-sidebar__group-label">{group.label}</h2>
|
|
104
|
+
<ul className="docs-sidebar__list">
|
|
105
|
+
{group.links.map((link) => {
|
|
106
|
+
const href = fullHref(link, pathPrefix);
|
|
107
|
+
const active = isActive(link, currentPath, pathPrefix);
|
|
108
|
+
const sections = link.sections ?? [];
|
|
109
|
+
return (
|
|
110
|
+
<li key={link.href + link.label} className="docs-sidebar__item">
|
|
111
|
+
<a
|
|
112
|
+
href={href}
|
|
113
|
+
className={`docs-sidebar__link ${active && (sections.length === 0 || activeSectionId == null) ? 'docs-sidebar__link--active' : ''}`.trim()}
|
|
114
|
+
aria-current={active && (sections.length === 0 || activeSectionId == null) ? 'page' : undefined}
|
|
115
|
+
target={link.external ? '_blank' : undefined}
|
|
116
|
+
rel={link.external ? 'noopener noreferrer' : undefined}
|
|
117
|
+
>
|
|
118
|
+
{link.label}
|
|
119
|
+
</a>
|
|
120
|
+
{sections.length > 0 && (
|
|
121
|
+
<ul className="docs-sidebar__sublist" aria-label={`Sections in ${link.label}`}>
|
|
122
|
+
{sections.map((section) => {
|
|
123
|
+
const sublinkHref = `${href}#${section.id}`;
|
|
124
|
+
const sublinkActive = !link.external && activeSectionId === section.id && currentPath.replace(/\/$/, '') === href.split('#')[0];
|
|
125
|
+
return (
|
|
126
|
+
<li key={section.id} className="docs-sidebar__subitem">
|
|
127
|
+
<a
|
|
128
|
+
href={sublinkHref}
|
|
129
|
+
className={`docs-sidebar__sublink ${sublinkActive ? 'docs-sidebar__sublink--active' : ''}`.trim()}
|
|
130
|
+
aria-current={sublinkActive ? 'location' : undefined}
|
|
131
|
+
target={link.external ? '_blank' : undefined}
|
|
132
|
+
rel={link.external ? 'noopener noreferrer' : undefined}
|
|
133
|
+
>
|
|
134
|
+
{section.label}
|
|
135
|
+
</a>
|
|
136
|
+
</li>
|
|
137
|
+
);
|
|
138
|
+
})}
|
|
139
|
+
</ul>
|
|
140
|
+
)}
|
|
141
|
+
</li>
|
|
142
|
+
);
|
|
143
|
+
})}
|
|
144
|
+
</ul>
|
|
145
|
+
</div>
|
|
146
|
+
))}
|
|
147
|
+
</nav>
|
|
148
|
+
) : (
|
|
149
|
+
<div className="docs-sidebar__nav docs-sidebar__nav--placeholder">
|
|
150
|
+
<p className="docs-sidebar__placeholder">Docs sidebar — add <code>nav</code> prop with DOCS_NAV for full nav.</p>
|
|
151
|
+
</div>
|
|
152
|
+
)}
|
|
44
153
|
</aside>
|
|
45
154
|
);
|
|
46
155
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'react';
|
|
2
|
+
|
|
3
|
+
const THEME_ICON_SVG: Record<string, string> = {
|
|
4
|
+
'github-dark-classic':
|
|
5
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M16 7h.01" /><path d="M3.4 18H12a8 8 0 0 0 8-8V7a4 4 0 0 0-7.28-2.3L2 20" /><path d="m20 7 2 .5-2 .5" /><path d="M10 18v3" /><path d="M14 17.75V21" /><path d="M7 18a6 6 0 0 0 3.84-10.61" /></svg>',
|
|
6
|
+
'github-light':
|
|
7
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4" /><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" /></svg>',
|
|
8
|
+
'red-velvet-cupcake':
|
|
9
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M20 21v-8a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8" /><path d="M4 16s1-1 4-1 5 2 8 2 4-1 4-1V4" /><path d="M2 16v4M22 16v4M8 8h.01M16 8h.01M8 12h.01M16 12h.01" /></svg>',
|
|
10
|
+
'orangy-one-light':
|
|
11
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M15.5 6.5c.5-2.5 2.5-4 5-4 1.5 0 2.5.5 3 1" /><path d="M12 12c-2 2-3 4-3 6 0 3 2 5 5 5 2 0 4-1 6-3" /><path d="M18 12c2 2 3 4 3 6 0 3-2 5-5 5-2 0-4-1-6-3" /></svg>',
|
|
12
|
+
sunflower:
|
|
13
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M22 17a10 10 0 0 0-20 0" /><path d="M6 17a6 6 0 0 1 12 0" /><path d="M10 17a2 2 0 0 1 4 0" /></svg>',
|
|
14
|
+
'shades-of-purple':
|
|
15
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 21a9 9 0 0 1 0 -18c4.97 0 9 3.582 9 8c0 1.06 -.474 2.078 -1.318 2.828c-.844 .75 -1.989 1.172 -3.182 1.172h-2.5a2 2 0 0 0 -1 3.75a1.3 1.3 0 0 1 -1 2.25"/><path d="M7.5 10.5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/><path d="M11.5 7.5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/><path d="M15.5 10.5a1 1 0 1 0 2 0a1 1 0 1 0 -2 0"/></svg>',
|
|
16
|
+
'sandstorm-classic':
|
|
17
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z" /></svg>',
|
|
18
|
+
'rocky-blood-orange':
|
|
19
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 10V2M4.93 10.93l1.41 1.41M2 18h2M20 18h2M17.66 10.93l1.41-1.41M22 22H2M8 6l4-4 4 4M16 18a4 4 0 0 0-8 0" /><path d="M12 22v-4" /></svg>',
|
|
20
|
+
'minimal-dark-neon-yellow':
|
|
21
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z" /></svg>',
|
|
22
|
+
'hack-the-box':
|
|
23
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" /></svg>',
|
|
24
|
+
'green-breeze-light':
|
|
25
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M11 20A7 7 0 0 1 9.8 6.1C15.5 5 17 4.48 19 2c1 2 2 4.18 2 8 0 5.5-4.78 10-10 10Z" /><path d="M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12" /></svg>',
|
|
26
|
+
'pink-cat-boo':
|
|
27
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M19.5 12.572l-7.5 7.428l-7.5 -7.428a5 5 0 1 1 7.5 -6.566a5 5 0 1 1 7.5 6.572" /></svg>',
|
|
28
|
+
'cute-pink':
|
|
29
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="M9 18c0-2 1.5-4 4-4s4 2 4 4c0 2-1.5 4-4 4s-4-2-4-4Z" /><path d="M15 18c0-2 1.5-4 4-4s4 2 4 4c0 2-1.5 4-4 4s-4-2-4-4Z" /><path d="M12 8v4M10 10l-2 2M14 10l2 2" /></svg>',
|
|
30
|
+
'semi-light-purple':
|
|
31
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true"><path d="m9.06 11.9 8.07-8.06a2.85 2.85 0 1 1 4.03 4.03l-8.06 8.08" /><path d="M7.87 14.14c-.32.32-.67.68-1.06 1.06a5.04 5.04 0 0 1-2.17 1.22c-.47.15-.85.2-1.15.2-.16 0-.3-.02-.41-.03a1 1 0 0 1-.63-.97c-.01-.14.02-.31.07-.51.1-.41.3-.95.6-1.59.3-.64.67-1.33 1.08-2.05" /></svg>',
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export interface ThemeIconProps extends HTMLAttributes<HTMLSpanElement> {
|
|
35
|
+
themeId: string;
|
|
36
|
+
size?: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function ThemeIcon({ themeId, size = 24, className = '', ...rest }: ThemeIconProps) {
|
|
40
|
+
const iconSvg = THEME_ICON_SVG[themeId] ?? null;
|
|
41
|
+
const sizedSvg = iconSvg
|
|
42
|
+
? iconSvg.replace(/width="16"/, `width="${size}"`).replace(/height="16"/, `height="${size}"`)
|
|
43
|
+
: null;
|
|
44
|
+
|
|
45
|
+
if (!sizedSvg) return null;
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<span
|
|
49
|
+
className={className}
|
|
50
|
+
style={{ display: 'inline-flex', verticalAlign: 'middle' }}
|
|
51
|
+
dangerouslySetInnerHTML={{ __html: sizedSvg }}
|
|
52
|
+
{...rest}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export default ThemeIcon;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single source of truth for theme id, label, type, icon, and preview colors.
|
|
3
|
+
* Used by ThemeSwitcher and Navbar so theme icons and labels stay consistent.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type ThemeIconKey =
|
|
7
|
+
| 'gear'
|
|
8
|
+
| 'owl'
|
|
9
|
+
| 'palette'
|
|
10
|
+
| 'flame'
|
|
11
|
+
| 'sunset'
|
|
12
|
+
| 'zap'
|
|
13
|
+
| 'shield'
|
|
14
|
+
| 'heart'
|
|
15
|
+
| 'sun'
|
|
16
|
+
| 'cake'
|
|
17
|
+
| 'lemon'
|
|
18
|
+
| 'rainbow'
|
|
19
|
+
| 'leaf'
|
|
20
|
+
| 'cherry'
|
|
21
|
+
| 'brush';
|
|
22
|
+
|
|
23
|
+
export interface ThemeEntry {
|
|
24
|
+
value: string;
|
|
25
|
+
label: string;
|
|
26
|
+
type: 'dark' | 'light';
|
|
27
|
+
iconKey: ThemeIconKey;
|
|
28
|
+
/** OKLCH background for ThemeSwitcher preview */
|
|
29
|
+
bg: string;
|
|
30
|
+
/** OKLCH accent for ThemeSwitcher preview */
|
|
31
|
+
accent: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const THEMES_DARK: ThemeEntry[] = [
|
|
35
|
+
{ value: 'github-dark-classic', label: 'GitHub Dark Classic', type: 'dark', iconKey: 'owl', bg: 'oklch(18% 0.012 264deg)', accent: 'oklch(72% 0.12 250deg)' },
|
|
36
|
+
{ value: 'shades-of-purple', label: 'Shades of Purple', type: 'dark', iconKey: 'palette', bg: 'oklch(18% 0.08 290deg)', accent: 'oklch(65% 0.25 290deg)' },
|
|
37
|
+
{ value: 'sandstorm-classic', label: 'Sandstorm Classic', type: 'dark', iconKey: 'flame', bg: 'oklch(16% 0.025 25deg)', accent: 'oklch(58% 0.18 25deg)' },
|
|
38
|
+
{ value: 'rocky-blood-orange', label: 'Rocky Blood Orange', type: 'dark', iconKey: 'sunset', bg: 'oklch(16% 0.03 45deg)', accent: 'oklch(62% 0.16 55deg)' },
|
|
39
|
+
{ value: 'minimal-dark-neon-yellow', label: 'Minimal Dark Neon Yellow', type: 'dark', iconKey: 'zap', bg: 'oklch(14% 0.01 95deg)', accent: 'oklch(88% 0.18 95deg)' },
|
|
40
|
+
{ value: 'hack-the-box', label: 'Hack The Box', type: 'dark', iconKey: 'shield', bg: 'oklch(16% 0.03 255deg)', accent: 'oklch(88% 0.22 130deg)' },
|
|
41
|
+
{ value: 'pink-cat-boo', label: 'Pink Cat Boo', type: 'dark', iconKey: 'heart', bg: 'oklch(18% 0.03 280deg)', accent: 'oklch(78% 0.12 350deg)' },
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
export const THEMES_LIGHT: ThemeEntry[] = [
|
|
45
|
+
{ value: 'github-light', label: 'GitHub Light', type: 'light', iconKey: 'sun', bg: 'oklch(100% 0 0deg)', accent: 'oklch(55% 0.18 255deg)' },
|
|
46
|
+
{ value: 'red-velvet-cupcake', label: 'Red Velvet Cupcake', type: 'light', iconKey: 'cake', bg: 'oklch(99% 0.005 25deg)', accent: 'oklch(55% 0.17 25deg)' },
|
|
47
|
+
{ value: 'orangy-one-light', label: 'Orangy One Light', type: 'light', iconKey: 'lemon', bg: 'oklch(99% 0.008 70deg)', accent: 'oklch(58% 0.16 55deg)' },
|
|
48
|
+
{ value: 'sunflower', label: 'Sunflower', type: 'light', iconKey: 'rainbow', bg: 'oklch(98% 0.03 95deg)', accent: 'oklch(75% 0.16 95deg)' },
|
|
49
|
+
{ value: 'green-breeze-light', label: 'Green Breeze Light', type: 'light', iconKey: 'leaf', bg: 'oklch(98% 0.008 140deg)', accent: 'oklch(48% 0.16 155deg)' },
|
|
50
|
+
{ value: 'cute-pink', label: 'Cute Pink', type: 'light', iconKey: 'cherry', bg: 'oklch(98% 0.025 350deg)', accent: 'oklch(62% 0.22 350deg)' },
|
|
51
|
+
{ value: 'semi-light-purple', label: 'Semi Light Purple', type: 'light', iconKey: 'brush', bg: 'oklch(96% 0.02 290deg)', accent: 'oklch(52% 0.2 290deg)' },
|
|
52
|
+
];
|
|
53
|
+
|
|
54
|
+
export const ALL_THEMES = [...THEMES_DARK, ...THEMES_LIGHT];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Rizzo CSS — React Full Template
|
|
2
|
+
|
|
3
|
+
This project was generated with the **Full** template (React + React Router). It mirrors the structure of the Rizzo docs site: home, docs (overview, getting started, components), blocks, and themes.
|
|
4
|
+
|
|
5
|
+
## Project structure
|
|
6
|
+
|
|
7
|
+
- **Home** (`/`) — Hero, features, add-command, doc cards.
|
|
8
|
+
- **Docs** (`/docs`, `/docs/overview`, `/docs/getting-started`, `/docs/components`) — Docs layout with sidebar (Introduction, Components, Blocks, Themes). Uses `DocsSidebar` with `DOCS_NAV` from `src/config/docsNav.ts`.
|
|
9
|
+
- **Blocks** (`/blocks`) — Blocks layout with sidebar and index of block links (main site).
|
|
10
|
+
- **Themes** (`/themes`) — Theme picker with ThemeSwitcher, Dark/Light theme cards (Card + ThemeIcon), and code snippet.
|
|
11
|
+
|
|
12
|
+
Config used by the full template:
|
|
13
|
+
|
|
14
|
+
- `src/config/docsNav.ts` — Sidebar nav (matches main site structure).
|
|
15
|
+
- `src/config/componentCategories.ts` — Component categories for the components page.
|
|
16
|
+
|
|
17
|
+
## Scripts
|
|
18
|
+
|
|
19
|
+
- `pnpm dev` — Start dev server (Vite).
|
|
20
|
+
- `pnpm build` — Build for production.
|
|
21
|
+
- `pnpm preview` — Preview production build.
|
|
22
|
+
|
|
23
|
+
## Adding components
|
|
24
|
+
|
|
25
|
+
From the project root:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx rizzo-css add <ComponentName>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Example: `npx rizzo-css add Modal` adds the Modal component to `src/components/rizzo`.
|
|
32
|
+
|
|
33
|
+
## Settings panel
|
|
34
|
+
|
|
35
|
+
The Settings panel (gear in the navbar) includes Theme (ThemeSwitcher), Font Size, Font (FontSwitcher), Sound (SoundEffects), and Accessibility options. Preferences are stored in `localStorage`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{PROJECT_NAME}}",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc -b && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"react": "^18.3.1",
|
|
13
|
+
"react-dom": "^18.3.1",
|
|
14
|
+
"react-router-dom": "^6.28.0"
|
|
15
|
+
},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"@types/react": "^18.3.12",
|
|
18
|
+
"@types/react-dom": "^18.3.1",
|
|
19
|
+
"@vitejs/plugin-react": "^4.3.3",
|
|
20
|
+
"rizzo-css": "^0.0.83",
|
|
21
|
+
"typescript": "~5.6.2",
|
|
22
|
+
"vite": "^6.0.1"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { Routes, Route } from 'react-router-dom';
|
|
2
|
+
import Navbar from '@/components/rizzo/Navbar';
|
|
3
|
+
import Footer from '@/components/rizzo/Footer';
|
|
4
|
+
import Settings from '@/components/rizzo/Settings';
|
|
5
|
+
import BackToTop from '@/components/rizzo/BackToTop';
|
|
6
|
+
import Home from './views/Home';
|
|
7
|
+
import BlocksLayout from './layouts/BlocksLayout';
|
|
8
|
+
import BlocksIndex from './views/BlocksIndex';
|
|
9
|
+
import DocsLayout from './layouts/DocsLayout';
|
|
10
|
+
import DocsIndex from './views/DocsIndex';
|
|
11
|
+
import DocsOverview from './views/DocsOverview';
|
|
12
|
+
import DocsGettingStarted from './views/DocsGettingStarted';
|
|
13
|
+
import DocsComponents from './views/DocsComponents';
|
|
14
|
+
import Themes from './views/Themes';
|
|
15
|
+
|
|
16
|
+
export default function App() {
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
<a href="#main-content" className="skip-link">Skip to main content</a>
|
|
20
|
+
<Navbar siteName="Rizzo CSS" />
|
|
21
|
+
<main id="main-content">
|
|
22
|
+
<Routes>
|
|
23
|
+
<Route path="/" element={<Home />} />
|
|
24
|
+
<Route path="/blocks" element={<BlocksLayout />}>
|
|
25
|
+
<Route index element={<BlocksIndex />} />
|
|
26
|
+
</Route>
|
|
27
|
+
<Route path="/docs" element={<DocsLayout />}>
|
|
28
|
+
<Route index element={<DocsIndex />} />
|
|
29
|
+
<Route path="overview" element={<DocsOverview />} />
|
|
30
|
+
<Route path="getting-started" element={<DocsGettingStarted />} />
|
|
31
|
+
<Route path="components" element={<DocsComponents />} />
|
|
32
|
+
</Route>
|
|
33
|
+
<Route path="/themes" element={<Themes />} />
|
|
34
|
+
</Routes>
|
|
35
|
+
</main>
|
|
36
|
+
<Footer />
|
|
37
|
+
<BackToTop />
|
|
38
|
+
<Settings />
|
|
39
|
+
</>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal component categories for the full template components page.
|
|
3
|
+
* Same structure as main site for consistent layout.
|
|
4
|
+
*/
|
|
5
|
+
export interface CategoryItem {
|
|
6
|
+
href: string;
|
|
7
|
+
title: string;
|
|
8
|
+
description: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface CategoryWithItems {
|
|
12
|
+
id: string;
|
|
13
|
+
label: string;
|
|
14
|
+
items: CategoryItem[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function slugToTitle(slug: string): string {
|
|
18
|
+
return slug
|
|
19
|
+
.split('-')
|
|
20
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
21
|
+
.join(' ');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const CATEGORIES: { id: string; label: string; slugs: string[] }[] = [
|
|
25
|
+
{ id: 'layout', label: 'Layout', slugs: ['navbar', 'docs-sidebar', 'dashboard', 'resizable', 'footer'] },
|
|
26
|
+
{ id: 'forms', label: 'Forms & inputs', slugs: ['button', 'button-group', 'forms', 'switch', 'slider', 'toggle', 'toggle-group', 'divider', 'separator', 'label', 'kbd'] },
|
|
27
|
+
{ id: 'data', label: 'Data display', slugs: ['cards', 'table', 'badge', 'pagination', 'aspect-ratio', 'empty', 'scroll-area', 'alert', 'skeleton', 'spinner', 'progress-bar', 'toast'] },
|
|
28
|
+
{ id: 'overlay', label: 'Overlay', slugs: ['modal', 'sheet', 'popover', 'dropdown', 'tooltip', 'accordion', 'collapsible', 'tabs'] },
|
|
29
|
+
{ id: 'other', label: 'Other', slugs: ['avatar', 'copy-to-clipboard', 'theme-switcher', 'font-switcher', 'settings', 'search', 'breadcrumb', 'back-to-top'] },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
export function getComponentsByCategory(): CategoryWithItems[] {
|
|
33
|
+
const pathPrefix = '/docs/components';
|
|
34
|
+
return CATEGORIES.map((cat) => ({
|
|
35
|
+
id: cat.id,
|
|
36
|
+
label: cat.label,
|
|
37
|
+
items: cat.slugs.map((slug) => ({
|
|
38
|
+
href: `${pathPrefix}/${slug}`,
|
|
39
|
+
title: slugToTitle(slug),
|
|
40
|
+
description: `Accessible, themeable ${slugToTitle(slug).toLowerCase()} component.`,
|
|
41
|
+
})),
|
|
42
|
+
}));
|
|
43
|
+
}
|