@humanforest/nuxt-layer 0.1.0
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/LICENSE +67 -0
- package/README.md +208 -0
- package/app.config.ts +10 -0
- package/assets/icons/forest/bike-asterisk.svg +21 -0
- package/assets/icons/forest/bike-down.svg +19 -0
- package/assets/icons/forest/bike-off.svg +20 -0
- package/assets/icons/forest/bike-up.svg +19 -0
- package/assets/icons/forest/bike-x.svg +19 -0
- package/assets/icons/forest/bike.svg +18 -0
- package/assets/icons/forest/mark-fill.svg +6 -0
- package/assets/icons/forest/mark.svg +6 -0
- package/assets/icons/forest/parking.svg +3 -0
- package/assets/icons/forest/star-fill.svg +4 -0
- package/assets/icons/forest/star.svg +4 -0
- package/assets/icons/forest/traffic-light-caution.svg +8 -0
- package/assets/icons/forest/traffic-light-go.svg +8 -0
- package/assets/icons/forest/traffic-light-lit.svg +8 -0
- package/assets/icons/forest/traffic-light-stop.svg +8 -0
- package/assets/icons/forest/traffic-light.svg +8 -0
- package/nuxt.config.ts +81 -0
- package/package.json +35 -0
- package/packages/charts/src/FBoroughShape.vue +52 -0
- package/packages/charts/src/FCalendarGrid.vue +332 -0
- package/packages/charts/src/FCellLegend.vue +54 -0
- package/packages/charts/src/FChartFrame.vue +201 -0
- package/packages/charts/src/FChartFrameSingle.vue +91 -0
- package/packages/charts/src/FChartLegend.vue +26 -0
- package/packages/charts/src/FDistributionBar.vue +224 -0
- package/packages/charts/src/FDottedMap.vue +335 -0
- package/packages/charts/src/FLondonMap.vue +399 -0
- package/packages/charts/src/FSparkline.vue +198 -0
- package/packages/charts/src/FStatusTrack.vue +151 -0
- package/packages/charts/src/cellSize.ts +46 -0
- package/packages/charts/src/distribution.ts +99 -0
- package/packages/charts/src/engine.ts +15 -0
- package/packages/charts/src/forestTooltip.ts +110 -0
- package/packages/charts/src/fromCategories.ts +43 -0
- package/packages/charts/src/index.ts +87 -0
- package/packages/charts/src/londonAreas.ts +75 -0
- package/packages/charts/src/londonGrid.ts +67 -0
- package/packages/charts/src/motionDuration.ts +49 -0
- package/packages/charts/src/presets.ts +143 -0
- package/packages/charts/src/resolveVar.ts +21 -0
- package/packages/charts/src/snapTooltip.ts +154 -0
- package/packages/charts/src/tooltipStandIn.ts +58 -0
- package/packages/charts/src/useCellScale.ts +155 -0
- package/packages/charts/src/useChartPalette.ts +61 -0
- package/packages/charts/src/useChartRepaintKey.ts +22 -0
- package/packages/charts/src/useThemeVersion.ts +17 -0
- package/packages/frames/src/FBrowserFrame.vue +53 -0
- package/packages/frames/src/FDeviceFrame.vue +242 -0
- package/packages/frames/src/FFitFrame.vue +83 -0
- package/packages/frames/src/art/iphone-11.svg +124 -0
- package/packages/frames/src/art/iphone-12.svg +601 -0
- package/packages/frames/src/art/iphone-13-pro.svg +820 -0
- package/packages/frames/src/art/iphone-13.svg +849 -0
- package/packages/frames/src/art/iphone-14.svg +681 -0
- package/packages/frames/src/art/iphone-15-pro.svg +633 -0
- package/packages/frames/src/art/iphone-15.svg +713 -0
- package/packages/frames/src/art/iphone-16-plus.svg +685 -0
- package/packages/frames/src/art/iphone-16-pro-max.svg +611 -0
- package/packages/frames/src/art/iphone-16-pro.svg +631 -0
- package/packages/frames/src/art/iphone-16.svg +713 -0
- package/packages/frames/src/art/iphone-17-pro-max.svg +355 -0
- package/packages/frames/src/art/iphone-17.svg +305 -0
- package/packages/frames/src/art/iphone-air.svg +389 -0
- package/packages/frames/src/art/iphone-se-3.svg +473 -0
- package/packages/frames/src/art/iphone-x.svg +652 -0
- package/packages/frames/src/art/pixel-10-pro-xl.svg +32 -0
- package/packages/frames/src/art/pixel-10-pro.svg +32 -0
- package/packages/frames/src/art/pixel-10.svg +32 -0
- package/packages/frames/src/art/pixel-8-pro.svg +208 -0
- package/packages/frames/src/art/pixel-8.svg +208 -0
- package/packages/frames/src/art/pixel-8a.svg +8 -0
- package/packages/frames/src/art/pixel-9-pro-xl.svg +32 -0
- package/packages/frames/src/art/pixel-9-pro.svg +34 -0
- package/packages/frames/src/art/pixel-9a.svg +25 -0
- package/packages/frames/src/art.ts +29 -0
- package/packages/frames/src/devices.ts +337 -0
- package/packages/frames/src/index.ts +15 -0
- package/packages/tokens/geo/london-boroughs.json +1 -0
- package/packages/tokens/geo/london-dots-coarse.json +1 -0
- package/packages/tokens/geo/london-dots-fine.json +1 -0
- package/packages/tokens/geo/london-dots-medium.json +1 -0
- package/packages/tokens/geo/london-dots-ultra.json +1 -0
- package/packages/tokens/geo/london-wards.json +1 -0
- package/packages/tokens/glyphs/glyphs.json +1 -0
- package/packages/tokens/logos/f-rot.svg +4 -0
- package/packages/tokens/logos/f.svg +4 -0
- package/packages/tokens/logos/favicon-c2w.svg +9 -0
- package/packages/tokens/logos/favicon-console.svg +9 -0
- package/packages/tokens/logos/favicon-ds.svg +9 -0
- package/packages/tokens/logos/favicon-fleet.svg +9 -0
- package/packages/tokens/logos/favicon-flex.svg +9 -0
- package/packages/tokens/logos/favicon-plus.svg +9 -0
- package/packages/tokens/logos/favicon-radar.svg +9 -0
- package/packages/tokens/logos/favicon-tower.svg +9 -0
- package/packages/tokens/logos/lockup-horizontal.svg +17 -0
- package/packages/tokens/logos/lockup-vertical.svg +17 -0
- package/packages/tokens/logos/mark-mono.svg +4 -0
- package/packages/tokens/logos/mark.svg +7 -0
- package/packages/tokens/logos/wordmark.svg +9 -0
- package/packages/tokens/src/colourEngine.ts +604 -0
- package/packages/tokens/src/glyphs.ts +127 -0
- package/packages/tokens/src/logo.ts +50 -0
- package/packages/tokens/src/subbrands.ts +44 -0
- package/packages/tokens/src/sublogo.ts +80 -0
- package/packages/ui/icons/forest/map/forest-place-count.svg +21 -0
- package/packages/ui/icons/forest/map/forest-place-marker.svg +17 -0
- package/packages/ui/icons/forest/map/forest-vehicle-marker.svg +73 -0
- package/packages/ui/icons/forest/map/manifest.json +373 -0
- package/packages/ui/icons/forest/map/place-count-manifest.json +83 -0
- package/packages/ui/icons/forest/map/place-manifest.json +74 -0
- package/packages/ui/src/address/address.ts +125 -0
- package/packages/ui/src/address/autofill.ts +78 -0
- package/packages/ui/src/address/geocode.ts +55 -0
- package/packages/ui/src/address/index.ts +31 -0
- package/packages/ui/src/address/validate.ts +91 -0
- package/packages/ui/src/canvas/FCanvasCard.vue +97 -0
- package/packages/ui/src/canvas/FCanvasControl.vue +121 -0
- package/packages/ui/src/canvas/FCanvasControlGroup.vue +100 -0
- package/packages/ui/src/canvas/FCanvasFlyout.vue +216 -0
- package/packages/ui/src/canvas/FCanvasHud.vue +402 -0
- package/packages/ui/src/canvas/canvasSurface.ts +39 -0
- package/packages/ui/src/canvas/index.ts +17 -0
- package/packages/ui/src/contexts/ForestContext.vue +53 -0
- package/packages/ui/src/contexts/contexts.ts +153 -0
- package/packages/ui/src/contexts/index.ts +23 -0
- package/packages/ui/src/contexts/marketing-theme.ts +214 -0
- package/packages/ui/src/contexts/mobile-theme.ts +402 -0
- package/packages/ui/src/filter/FFilterBar.vue +72 -0
- package/packages/ui/src/filter/FFilterChip.vue +362 -0
- package/packages/ui/src/filter/FFilterClauses.vue +104 -0
- package/packages/ui/src/filter/FFilterTrigger.vue +183 -0
- package/packages/ui/src/filter/filter.theme.ts +27 -0
- package/packages/ui/src/filter/filterClause.ts +265 -0
- package/packages/ui/src/filter/filterPredicate.ts +134 -0
- package/packages/ui/src/filter/filterSchema.ts +82 -0
- package/packages/ui/src/filter/index.ts +36 -0
- package/packages/ui/src/forest-preset.ts +68 -0
- package/packages/ui/src/icons.ts +79 -0
- package/packages/ui/src/index.ts +17 -0
- package/packages/ui/src/kpi/FKpi.vue +253 -0
- package/packages/ui/src/kpi/FKpiGroup.vue +161 -0
- package/packages/ui/src/kpi/index.ts +20 -0
- package/packages/ui/src/kpi/kpi.theme.ts +168 -0
- package/packages/ui/src/kpi/kpiDelta.ts +82 -0
- package/packages/ui/src/kpi/kpiFormat.ts +72 -0
- package/packages/ui/src/kpi/kpiGroupState.ts +63 -0
- package/packages/ui/src/logo/FLogo.vue +52 -0
- package/packages/ui/src/logo/FSubLogo.vue +214 -0
- package/packages/ui/src/logo/index.ts +8 -0
- package/packages/ui/src/map/FMap.vue +355 -0
- package/packages/ui/src/map/FMapCompass.vue +154 -0
- package/packages/ui/src/map/FMapCoordinates.vue +134 -0
- package/packages/ui/src/map/FMapDrawTools.vue +116 -0
- package/packages/ui/src/map/FMapFullscreen.vue +92 -0
- package/packages/ui/src/map/FMapGeolocate.vue +208 -0
- package/packages/ui/src/map/FMapLayers.vue +75 -0
- package/packages/ui/src/map/FMapLegend.vue +45 -0
- package/packages/ui/src/map/FMapPopup.vue +129 -0
- package/packages/ui/src/map/FMapRamp.vue +69 -0
- package/packages/ui/src/map/FMapRegion.vue +77 -0
- package/packages/ui/src/map/FMapScale.vue +107 -0
- package/packages/ui/src/map/FMapSearch.vue +362 -0
- package/packages/ui/src/map/FMapTilt.vue +87 -0
- package/packages/ui/src/map/FMapTools.vue +61 -0
- package/packages/ui/src/map/FMapZoom.vue +81 -0
- package/packages/ui/src/map/FMarker.vue +218 -0
- package/packages/ui/src/map/FTrackScrubber.vue +94 -0
- package/packages/ui/src/map/FVehicleLegend.vue +72 -0
- package/packages/ui/src/map/FVehicleMark.vue +166 -0
- package/packages/ui/src/map/bin.ts +196 -0
- package/packages/ui/src/map/coordinates.ts +83 -0
- package/packages/ui/src/map/density.ts +401 -0
- package/packages/ui/src/map/draw.ts +356 -0
- package/packages/ui/src/map/ease.ts +67 -0
- package/packages/ui/src/map/fullscreen.ts +59 -0
- package/packages/ui/src/map/heat.ts +160 -0
- package/packages/ui/src/map/index.ts +351 -0
- package/packages/ui/src/map/liveMarkers.ts +60 -0
- package/packages/ui/src/map/map.css +116 -0
- package/packages/ui/src/map/mapColor.ts +31 -0
- package/packages/ui/src/map/mapContext.ts +12 -0
- package/packages/ui/src/map/mapLayers.ts +55 -0
- package/packages/ui/src/map/mapLegend.ts +70 -0
- package/packages/ui/src/map/mapSearch.theme.ts +79 -0
- package/packages/ui/src/map/mapSearch.ts +279 -0
- package/packages/ui/src/map/mapUrl.ts +117 -0
- package/packages/ui/src/map/markerAsset.ts +3 -0
- package/packages/ui/src/map/padding.ts +39 -0
- package/packages/ui/src/map/place.ts +192 -0
- package/packages/ui/src/map/ramp.ts +95 -0
- package/packages/ui/src/map/regionSelect.ts +163 -0
- package/packages/ui/src/map/route.ts +167 -0
- package/packages/ui/src/map/scale.ts +329 -0
- package/packages/ui/src/map/scaleBar.ts +67 -0
- package/packages/ui/src/map/selectionModel.ts +50 -0
- package/packages/ui/src/map/sources/coordinates.ts +58 -0
- package/packages/ui/src/map/sources/mapboxPlaces.ts +71 -0
- package/packages/ui/src/map/style.ts +14 -0
- package/packages/ui/src/map/track.ts +279 -0
- package/packages/ui/src/map/useFeatureSelect.ts +230 -0
- package/packages/ui/src/map/useLiveMarkers.ts +84 -0
- package/packages/ui/src/map/useMap.ts +150 -0
- package/packages/ui/src/map/useMapDraw.ts +776 -0
- package/packages/ui/src/map/useMapOverlay.ts +421 -0
- package/packages/ui/src/map/useMapTableSelection.ts +101 -0
- package/packages/ui/src/map/useMapUrlState.ts +155 -0
- package/packages/ui/src/map/useMarkerSource.ts +163 -0
- package/packages/ui/src/map/useRegionSelect.ts +309 -0
- package/packages/ui/src/map/useTokenMode.ts +61 -0
- package/packages/ui/src/map/useTrackPlayback.ts +131 -0
- package/packages/ui/src/map/useVehicleFilter.ts +51 -0
- package/packages/ui/src/map/useVisibleFeatures.ts +124 -0
- package/packages/ui/src/map/vehicle.ts +807 -0
- package/packages/ui/src/map/vehicleFilter.ts +284 -0
- package/packages/ui/src/map/vehicleLegend.ts +155 -0
- package/packages/ui/src/map/visibleFeatures.ts +192 -0
- package/packages/ui/src/map/zone.ts +291 -0
- package/packages/ui/src/shell/FAppNavbar.vue +68 -0
- package/packages/ui/src/shell/FAppShell.vue +163 -0
- package/packages/ui/src/shell/FAppSidebar.vue +215 -0
- package/packages/ui/src/shell/FPageToolbar.vue +126 -0
- package/packages/ui/src/shell/FScrollShadow.vue +43 -0
- package/packages/ui/src/shell/FSidePanel.vue +258 -0
- package/packages/ui/src/shell/FToolbarActions.vue +32 -0
- package/packages/ui/src/shell/index.ts +33 -0
- package/packages/ui/src/shell/nav.ts +37 -0
- package/packages/ui/src/shell/pageToolbar.ts +69 -0
- package/packages/ui/src/shell/shell.ts +74 -0
- package/packages/ui/src/shell/sidePanel.ts +115 -0
- package/packages/ui/src/themes/accordion.ts +36 -0
- package/packages/ui/src/themes/alert.ts +16 -0
- package/packages/ui/src/themes/auth-form.ts +19 -0
- package/packages/ui/src/themes/avatar-group.ts +9 -0
- package/packages/ui/src/themes/avatar.ts +18 -0
- package/packages/ui/src/themes/badge.ts +51 -0
- package/packages/ui/src/themes/banner.ts +21 -0
- package/packages/ui/src/themes/breadcrumb.ts +10 -0
- package/packages/ui/src/themes/button.mechanics.ts +191 -0
- package/packages/ui/src/themes/button.ts +136 -0
- package/packages/ui/src/themes/calendar.ts +29 -0
- package/packages/ui/src/themes/card.ts +67 -0
- package/packages/ui/src/themes/carousel.ts +41 -0
- package/packages/ui/src/themes/checkbox-group.ts +20 -0
- package/packages/ui/src/themes/checkbox.ts +47 -0
- package/packages/ui/src/themes/chip.ts +50 -0
- package/packages/ui/src/themes/collapsible.ts +26 -0
- package/packages/ui/src/themes/color-picker.ts +13 -0
- package/packages/ui/src/themes/command-palette.ts +37 -0
- package/packages/ui/src/themes/container.ts +14 -0
- package/packages/ui/src/themes/context-menu.ts +38 -0
- package/packages/ui/src/themes/dashboard-group.ts +11 -0
- package/packages/ui/src/themes/dashboard-navbar.ts +10 -0
- package/packages/ui/src/themes/dashboard-panel.ts +18 -0
- package/packages/ui/src/themes/dashboard-resize-handle.ts +35 -0
- package/packages/ui/src/themes/dashboard-sidebar-collapse.ts +7 -0
- package/packages/ui/src/themes/dashboard-sidebar-toggle.ts +7 -0
- package/packages/ui/src/themes/dashboard-sidebar.ts +58 -0
- package/packages/ui/src/themes/dashboard-toolbar.ts +15 -0
- package/packages/ui/src/themes/drawer.ts +45 -0
- package/packages/ui/src/themes/dropdown-menu.ts +38 -0
- package/packages/ui/src/themes/empty.ts +43 -0
- package/packages/ui/src/themes/field-group.ts +52 -0
- package/packages/ui/src/themes/file-upload.ts +38 -0
- package/packages/ui/src/themes/footer-columns.ts +13 -0
- package/packages/ui/src/themes/footer.ts +9 -0
- package/packages/ui/src/themes/form-field.ts +25 -0
- package/packages/ui/src/themes/form.ts +22 -0
- package/packages/ui/src/themes/header.ts +12 -0
- package/packages/ui/src/themes/icon.ts +61 -0
- package/packages/ui/src/themes/index.ts +99 -0
- package/packages/ui/src/themes/input-date.ts +73 -0
- package/packages/ui/src/themes/input-menu.ts +66 -0
- package/packages/ui/src/themes/input-number.ts +58 -0
- package/packages/ui/src/themes/input-rating.ts +25 -0
- package/packages/ui/src/themes/input-tags.ts +63 -0
- package/packages/ui/src/themes/input-time.ts +70 -0
- package/packages/ui/src/themes/input.ts +148 -0
- package/packages/ui/src/themes/kbd.ts +27 -0
- package/packages/ui/src/themes/link.ts +27 -0
- package/packages/ui/src/themes/listbox.ts +48 -0
- package/packages/ui/src/themes/main.ts +6 -0
- package/packages/ui/src/themes/marquee.ts +45 -0
- package/packages/ui/src/themes/modal.ts +46 -0
- package/packages/ui/src/themes/navigation-menu.ts +80 -0
- package/packages/ui/src/themes/page-anchors.ts +7 -0
- package/packages/ui/src/themes/page-aside.ts +7 -0
- package/packages/ui/src/themes/page-card.ts +22 -0
- package/packages/ui/src/themes/page-cta.ts +18 -0
- package/packages/ui/src/themes/page-feature.ts +13 -0
- package/packages/ui/src/themes/page-header.ts +16 -0
- package/packages/ui/src/themes/page-hero.ts +15 -0
- package/packages/ui/src/themes/page-links.ts +12 -0
- package/packages/ui/src/themes/page-section.ts +14 -0
- package/packages/ui/src/themes/page.ts +7 -0
- package/packages/ui/src/themes/pagination.ts +17 -0
- package/packages/ui/src/themes/pin-input.ts +73 -0
- package/packages/ui/src/themes/popover.ts +30 -0
- package/packages/ui/src/themes/progress.ts +29 -0
- package/packages/ui/src/themes/prose.ts +45 -0
- package/packages/ui/src/themes/radio-group.ts +39 -0
- package/packages/ui/src/themes/scroll-area.ts +23 -0
- package/packages/ui/src/themes/select-menu.ts +71 -0
- package/packages/ui/src/themes/select.ts +72 -0
- package/packages/ui/src/themes/separator.ts +28 -0
- package/packages/ui/src/themes/sidebar.ts +127 -0
- package/packages/ui/src/themes/skeleton.ts +15 -0
- package/packages/ui/src/themes/slideover.ts +87 -0
- package/packages/ui/src/themes/slider.ts +48 -0
- package/packages/ui/src/themes/stepper.ts +41 -0
- package/packages/ui/src/themes/switch.ts +63 -0
- package/packages/ui/src/themes/table.ts +34 -0
- package/packages/ui/src/themes/tabs.ts +74 -0
- package/packages/ui/src/themes/textarea.ts +77 -0
- package/packages/ui/src/themes/timeline.ts +25 -0
- package/packages/ui/src/themes/toast.ts +29 -0
- package/packages/ui/src/themes/toaster.ts +66 -0
- package/packages/ui/src/themes/tooltip.ts +31 -0
- package/packages/ui/src/themes/tree.ts +41 -0
- package/packages/ui/src/themes/user.ts +28 -0
- package/styles.cdn.gen.css +2047 -0
- package/theme.gen.json +1 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UKbd (flat component, single `base` slot).
|
|
3
|
+
*
|
|
4
|
+
* Deltas only — the preset APPENDS to stock's base, so restating its layout classes would invite
|
|
5
|
+
* drift. Tokens:
|
|
6
|
+
* rounded-xs from stock rounded-sm — a tight corner so the cap reads as a physical key, not a
|
|
7
|
+
* pill/chip. Stock keeps the corner in `base` (not per size), so overriding it in base
|
|
8
|
+
* is clean. Contexts round it up (mobile/marketing).
|
|
9
|
+
* font-mono from stock font-sans — labels sit alongside code/token surfaces.
|
|
10
|
+
* px-2 from stock px-1 — a little breathing room, except sm keeps px-1: at 16px tall px-2
|
|
11
|
+
* is cramped.
|
|
12
|
+
*
|
|
13
|
+
* The sm padding exception lives in the SIZE VARIANT, not a `[&.h-4]` base hook — a preset/theme
|
|
14
|
+
* fragment can carry `variants` (tv deep-merges them; the size variant is applied after base, so
|
|
15
|
+
* `size.sm: 'px-1'` overrides base `px-2` at sm only). Stock's size variant holds no padding, so
|
|
16
|
+
* this ADDS one. (A CONTEXT can't do this — `<UTheme :ui>` carries slot/base classes only and
|
|
17
|
+
* silently ignores `variants` — which is why mobile/marketing keep an `[&.h-4]:` hook for their own
|
|
18
|
+
* per-size radius exception.)
|
|
19
|
+
*
|
|
20
|
+
* `font-medium`/`uppercase` and the colour/variant compounds are stock (already on the Forest
|
|
21
|
+
* ramps) — not Forest's to restate.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export const kbdTheme = {
|
|
25
|
+
base: 'rounded-xs font-mono px-2',
|
|
26
|
+
variants: { size: { sm: 'px-1' } },
|
|
27
|
+
} as const
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — ULink (styled router/anchor link, active states).
|
|
3
|
+
*
|
|
4
|
+
* Forest opinions applied:
|
|
5
|
+
* - `base` (the single root slot): the stock `focus-visible:outline-primary` is replaced with a
|
|
6
|
+
* ramp-pinned focus outline anchored to var(--color-forest-500) — 2px, 2px offset — so the
|
|
7
|
+
* focus ring tracks the brand scale in both light and dark mode exactly as keycap buttons do.
|
|
8
|
+
* - Active state: text-primary (maps to forest-500 via the semantic colour wiring) is retained from
|
|
9
|
+
* the generated default — it reads correctly against Forest surfaces. No override needed.
|
|
10
|
+
* - Inactive rest: text-muted is the Forest semantic level for navigation links at rest (softer
|
|
11
|
+
* than text-default, never as dim as text-dimmed). Stock default is text-muted so this is kept.
|
|
12
|
+
* - Disabled: the generated cursor-not-allowed + opacity-75 is correct; no override needed.
|
|
13
|
+
* - Hover (non-disabled, non-active): text-default is the stock value and matches Forest's reading
|
|
14
|
+
* hierarchy (link darkens on hover but doesn't jump to active/brand colour). Kept as-is.
|
|
15
|
+
* - transition-colors: stock, retained for smooth colour transitions on hover and active change.
|
|
16
|
+
*
|
|
17
|
+
* Only the focus ring is a genuine Forest override (pinning the outline to the ramp var rather than
|
|
18
|
+
* relying on the semantic `outline-primary` token, for determinism across every Forest surface).
|
|
19
|
+
* Everything else is in harmony with stock and intentionally left unchanged.
|
|
20
|
+
*
|
|
21
|
+
* Slot names sourced from: apps/docs/node_modules/.nuxt-ui/ui/link.ts
|
|
22
|
+
* Slots touched: base (root element).
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
export const linkTheme = {
|
|
26
|
+
base: 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-[var(--color-forest-500)]',
|
|
27
|
+
} as const;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UListbox (standalone selectable list, optional filter input).
|
|
3
|
+
*
|
|
4
|
+
* Deltas only (the preset appends to stock Nuxt UI):
|
|
5
|
+
* - label — font-bold + tracking-wide: group headings read with brand confidence; stock is
|
|
6
|
+
* font-semibold, a weight the two-weight type system does not carry.
|
|
7
|
+
*
|
|
8
|
+
* The shell radius runs STOCK (rounded-lg). The standard voice states no opinion on it: a listbox
|
|
9
|
+
* is sized by its own options rather than by a surface it belongs to, so there is no tier to pin it
|
|
10
|
+
* against. The expressive contexts do have an opinion — mobile and marketing round the shell to
|
|
11
|
+
* 24px and inset the rows to clear the arc (contexts/{mobile,marketing}-theme.ts).
|
|
12
|
+
*
|
|
13
|
+
* The `item` hover/select slab keeps the stock before:rounded-md (12px) — the standalone-row shape
|
|
14
|
+
* a sidebar nav row, a palette result and a tree node all carry. The 8px slab belongs to rows inside
|
|
15
|
+
* an anchored 12px menu panel (dropdown-menu, select-menu), which this is not.
|
|
16
|
+
*
|
|
17
|
+
* The filter `input` is a UInput carrying the listbox's own size, so it takes its touch rungs from
|
|
18
|
+
* themes/input.ts and needs nothing here. The avatar and chip sizes ride prop-valued slots
|
|
19
|
+
* (itemLeadingAvatarSize / itemLeadingChipSize), which a class variant cannot reach — they hold
|
|
20
|
+
* their fine-pointer step under the bump below.
|
|
21
|
+
*
|
|
22
|
+
* Everything else (density ladder, colour ring, virtualize/divider split, selected check, empty and
|
|
23
|
+
* loading states, transitions) is stock on the Forest ramps.
|
|
24
|
+
*
|
|
25
|
+
* Slots touched: root · label; size variant (touch).
|
|
26
|
+
* Slot names sourced from: apps/docs/node_modules/.nuxt-ui/ui/listbox.ts
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
export const listboxTheme = {
|
|
30
|
+
slots: {
|
|
31
|
+
// Group headings: bold weight + wide tracking — confident, readable at small size.
|
|
32
|
+
label: 'font-bold tracking-wide',
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
// Touch: under a coarse pointer each row promotes ONE size up — it borrows the next size's
|
|
36
|
+
// padding / gap / type / icon, so the tap slab scales as a unit (mirrors the menu family). xl is
|
|
37
|
+
// the ceiling. Deltas only: each size lists just the tokens that differ from its next step up
|
|
38
|
+
// (e.g. md→lg changes only padding + gap, so no type delta). `coarse:` carries the
|
|
39
|
+
// :not(.cut-fixed) escape, so a baked mobile cut opts out instead of promoting again.
|
|
40
|
+
variants: {
|
|
41
|
+
size: {
|
|
42
|
+
xs: { item: 'coarse:p-1.5 coarse:gap-1.5', label: 'coarse:p-1.5 coarse:gap-1.5' },
|
|
43
|
+
sm: { item: 'coarse:text-sm', label: 'coarse:text-xs', itemLeadingIcon: 'coarse:size-5', itemTrailingIcon: 'coarse:size-5' },
|
|
44
|
+
md: { item: 'coarse:p-2 coarse:gap-2', label: 'coarse:p-2 coarse:gap-2' },
|
|
45
|
+
lg: { item: 'coarse:text-base', label: 'coarse:text-sm', itemDescription: 'coarse:text-sm', itemLeadingIcon: 'coarse:size-6', itemTrailingIcon: 'coarse:size-6' },
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
} as const;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UMarquee (infinite scrolling strip).
|
|
3
|
+
*
|
|
4
|
+
* Forest opinions applied:
|
|
5
|
+
*
|
|
6
|
+
* root — the default `[--duration:20s]` is preserved (Nuxt UI default). We extend the root
|
|
7
|
+
* with a subtle `rounded-xl` so that when a Marquee is placed inside a bordered card or on a
|
|
8
|
+
* clipped surface the overflow boundary matches the Forest --ui-radius soft-corner vocabulary
|
|
9
|
+
* (0.5 rem base, rounded-xl ≈ 0.75 rem for container-level trim). This prevents the infinite
|
|
10
|
+
* strip from bleeding hard corners out of a soft-radius container.
|
|
11
|
+
*
|
|
12
|
+
* content — we set `gap-6` (both axes) so items (badges, cards, avatars) always have a tactile,
|
|
13
|
+
* tighter separation than the stock `--gap` (--spacing(16) ≈ 64px, too airy — especially for a
|
|
14
|
+
* vertical feed, where 64px reads as broken spacing). `gap-6` = 24px on row AND column, so a
|
|
15
|
+
* horizontal strip and a vertical feed are both comfortably dense. Note this overrides the
|
|
16
|
+
* `gap-(--gap)` shorthand, so a per-instance `--gap` override no longer applies — pass a `gap-*`
|
|
17
|
+
* utility via `ui.content` to retune. The `items-center` alignment (stock) keeps mixed-height
|
|
18
|
+
* children centred — Forest preserves this.
|
|
19
|
+
*
|
|
20
|
+
* The overlay gradient blends into `from-default` (the semantic surface token), which adapts
|
|
21
|
+
* automatically in dark mode — no Forest override needed; the stock `before:from-default /
|
|
22
|
+
* after:from-default` is already semantically correct.
|
|
23
|
+
*
|
|
24
|
+
* Slots NOT overridden:
|
|
25
|
+
* - Orientation variants — the flex-row / flex-col layout is correct as-is.
|
|
26
|
+
* - `pauseOnHover` variant — stock `group-hover:[animation-play-state:paused]` is correct.
|
|
27
|
+
* - `reverse` variant — stock `![animation-direction:reverse]` is correct.
|
|
28
|
+
* - overlay compoundVariants — gradient geometry does not need a Forest delta.
|
|
29
|
+
*
|
|
30
|
+
* Slots touched: `root`, `content`.
|
|
31
|
+
* Slot names sourced from: apps/docs/node_modules/.nuxt-ui/ui/marquee.ts
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
export const marqueeTheme = {
|
|
35
|
+
slots: {
|
|
36
|
+
// Soft-corner clip so the strip trims flush with Forest card/surface containers, paired with a
|
|
37
|
+
// small vertical inset (py-1.5): the rounded clip would otherwise shave the top/bottom of any
|
|
38
|
+
// item sitting flush to the strip edge (rounded-full pills read as flat-topped). The clip and its
|
|
39
|
+
// inset are one opinion. Override via `ui.root`/`class` for a deliberately full-bleed strip.
|
|
40
|
+
root: 'rounded-xl py-1.5',
|
|
41
|
+
// Tighter, tactile spacing on both axes (24px) vs the airy stock --gap (64px) — matters most
|
|
42
|
+
// for a vertical feed. Overrides gap-(--gap): retune via a gap-* utility on ui.content.
|
|
43
|
+
content: 'gap-6',
|
|
44
|
+
},
|
|
45
|
+
} as const;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UModal (centred dialog on Reka UI's Dialog primitive).
|
|
3
|
+
*
|
|
4
|
+
* Deltas only (the preset APPENDS to stock Nuxt UI):
|
|
5
|
+
* - `title`: font-display (MohrAlt Black, uppercase) at text-xl — the dialog heading is a moment
|
|
6
|
+
* of clear hierarchy; the display face makes it unmistakable. Stock sets `font-semibold`.
|
|
7
|
+
* - radius: rounded-xl (0.75 rem) on the non-fullscreen panel — one step softer than stock's
|
|
8
|
+
* rounded-lg. It rides `variants.fullscreen.false.content`, NOT the base `content` slot: stock
|
|
9
|
+
* puts the radius on that same size variant, so a base override loses the tailwind-merge race
|
|
10
|
+
* (the per-size seam — see the badge fragment). Overriding the variant is also what keeps the
|
|
11
|
+
* fullscreen panel square (its `inset-0` content carries no radius).
|
|
12
|
+
* - `transition`: the open/close keyframes move onto the shared motion tokens. Stock runs a flat
|
|
13
|
+
* 200 ms both ways and eases the EXIT with `ease-in`, which the doctrine bans — it starts slow at
|
|
14
|
+
* the exact moment the user has already decided to dismiss. Forest enters on --motion-base (the
|
|
15
|
+
* scale-in bucket the popover/menu family sits in) and exits on --motion-fast, both --motion-ease-out.
|
|
16
|
+
*
|
|
17
|
+
* Everything else — overlay tint, header/body/footer padding, divide rules, close button — is stock
|
|
18
|
+
* and needs no Forest opinion.
|
|
19
|
+
*
|
|
20
|
+
* Slot names + variants sourced from: apps/docs/node_modules/.nuxt-ui/ui/modal.ts
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const modalTheme = {
|
|
24
|
+
slots: {
|
|
25
|
+
// Display face for the dialog title — MohrAlt Black, uppercase (via .font-display).
|
|
26
|
+
title: 'font-display text-xl',
|
|
27
|
+
},
|
|
28
|
+
variants: {
|
|
29
|
+
// Same keyframes as stock, retimed and re-eased onto the tokens. Only the animate-* utilities are
|
|
30
|
+
// restated (tailwind-merge takes the last one in the concat); the variant carries nothing else.
|
|
31
|
+
transition: {
|
|
32
|
+
true: {
|
|
33
|
+
overlay:
|
|
34
|
+
'data-[state=open]:animate-[fade-in_var(--motion-base)_var(--motion-ease-out)] data-[state=closed]:animate-[fade-out_var(--motion-fast)_var(--motion-ease-out)]',
|
|
35
|
+
content:
|
|
36
|
+
'data-[state=open]:animate-[scale-in_var(--motion-base)_var(--motion-ease-out)] data-[state=closed]:animate-[scale-out_var(--motion-fast)_var(--motion-ease-out)]',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
fullscreen: {
|
|
40
|
+
// Softer brand radius on the standard centred panel; stock ring + shadow are retained.
|
|
41
|
+
false: {
|
|
42
|
+
content: 'rounded-xl',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
} as const;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — NavigationMenu
|
|
3
|
+
*
|
|
4
|
+
* Forest opinion:
|
|
5
|
+
* - `viewport` no Forest radius override (rounded-md matches stock already); motion-timing
|
|
6
|
+
* classes (duration/easing) are retained on this slot.
|
|
7
|
+
* - `arrow` rounded-sm to keep the caret consistent with the viewport
|
|
8
|
+
* - `label` text-xs uppercase tracking-wider text-dimmed — Forest's
|
|
9
|
+
* standard section-label treatment (same as docs headings, sidebar groups)
|
|
10
|
+
* - `childLink` before:rounded-sm (8 px) — concentric one step inside the 12 px viewport panel.
|
|
11
|
+
*
|
|
12
|
+
* Active treatment — the house nav look (mirrors AppSidebar's active link:
|
|
13
|
+
* `!bg-primary/10 !text-primary font-bold`): the active item is a soft primary-tint slab with
|
|
14
|
+
* primary text, bold. Inactive items stay neutral (stock text-muted). Colour intent still tints the
|
|
15
|
+
* active *text* per ramp (stock colour compounds untouched); only the slab wash + weight are set here.
|
|
16
|
+
* - pill active link: stock paints a grey before:bg-elevated slab, unweighted — retint to the soft
|
|
17
|
+
* primary wash and bold it. Matches for both highlight on/off (no highlight key ⇒ both).
|
|
18
|
+
* - link variant: no slab, just bold the active text (colour still from the ramp).
|
|
19
|
+
* - childLink active: stock sets before:bg-elevated + text-highlighted (NOT colour-driven) — give the
|
|
20
|
+
* vertical/flyout child items the same brand accent so they read like the sidebar's active row.
|
|
21
|
+
*
|
|
22
|
+
* Slots touched: viewport, arrow, label, childLink
|
|
23
|
+
* All other slots inherit Nuxt UI defaults; default colour stays primary (forest accent for a bare menu).
|
|
24
|
+
*/
|
|
25
|
+
export const navigationMenuTheme = {
|
|
26
|
+
slots: {
|
|
27
|
+
// Panel: rounded-md matches stock already; motion-timing (duration/ease) retained below.
|
|
28
|
+
viewport: 'duration-(--motion-slow) ease-(--motion-ease-in-out) data-[state=open]:animate-[scale-in_var(--motion-base)_var(--motion-ease-out)] data-[state=closed]:animate-[scale-out_var(--motion-fast)_var(--motion-ease-out)]',
|
|
29
|
+
// Arrow caret rounded-sm — consistent with the viewport
|
|
30
|
+
arrow: 'rounded-sm',
|
|
31
|
+
// Group labels: Forest section-header treatment — uppercase, wider tracking, dimmed weight
|
|
32
|
+
label: 'text-xs uppercase tracking-wider text-dimmed',
|
|
33
|
+
// Child link hover slab: before:rounded-sm (8 px) — concentric inside the 12 px viewport panel.
|
|
34
|
+
childLink: 'before:rounded-sm dark:focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2',
|
|
35
|
+
},
|
|
36
|
+
variants: {
|
|
37
|
+
active: {
|
|
38
|
+
true: {
|
|
39
|
+
// Vertical/flyout child active row → the house accent (stock: before:bg-elevated + text-highlighted).
|
|
40
|
+
childLink: 'before:bg-primary/10 text-primary font-bold',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
compoundVariants: [
|
|
45
|
+
// Top-level active pill: swap the grey slab for the soft primary wash + bold. text-primary already
|
|
46
|
+
// comes from the colour=primary active compound; no highlight key ⇒ applies with highlight on or off.
|
|
47
|
+
{
|
|
48
|
+
variant: 'pill',
|
|
49
|
+
active: true,
|
|
50
|
+
class: { link: 'before:bg-primary/10 font-bold' },
|
|
51
|
+
},
|
|
52
|
+
// link variant carries no slab — just bold the active text (colour stays from the ramp).
|
|
53
|
+
{
|
|
54
|
+
variant: 'link',
|
|
55
|
+
active: true,
|
|
56
|
+
class: { link: 'font-bold' },
|
|
57
|
+
},
|
|
58
|
+
// A VERTICAL menu is a sidebar's nav, and Forest groups it. Stock leaves consecutive sections
|
|
59
|
+
// touching, so the uppercase label alone has to carry the boundary; give it the group's own
|
|
60
|
+
// air instead. The reset is scoped to the first LI, not to `:first-child` — the label is always
|
|
61
|
+
// the first child of ITS li, so `[&:first-child]` would match every group and reset them all.
|
|
62
|
+
{
|
|
63
|
+
orientation: 'vertical',
|
|
64
|
+
collapsed: false,
|
|
65
|
+
class: { label: 'mt-6 [li:first-child>&]:mt-0' },
|
|
66
|
+
},
|
|
67
|
+
// Collapsed to the icon rail. Stock keeps the row full-width, so the active state reads as a
|
|
68
|
+
// wide pill in a narrow column rather than a button; square it and centre it on the rail.
|
|
69
|
+
// The separator is the only thing marking a group once the labels are hidden, so it is kept but
|
|
70
|
+
// shortened — a tick between groups, not a cut across the rail.
|
|
71
|
+
{
|
|
72
|
+
orientation: 'vertical',
|
|
73
|
+
collapsed: true,
|
|
74
|
+
class: {
|
|
75
|
+
link: 'size-8 p-0 justify-center mx-auto',
|
|
76
|
+
separator: 'w-5 mx-auto my-1.5 px-0',
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
} as const
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reviewed, no delta. UPageAnchors is link-list layout: `text-sm` on the link matches the ladder's
|
|
3
|
+
* small step, and the active `font-semibold` resolves to 700 through the @theme weight remap in
|
|
4
|
+
* styles/forest.css rather than to a cut the brand fonts lack.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const pageAnchorsTheme = {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reviewed, no delta. The `from-default` scroll-fade gradients read correctly on Forest's surfaces
|
|
3
|
+
* in both modes — `default` is the warm neutral-0 in light and Nuxt's neutral-900 card in dark, which
|
|
4
|
+
* is exactly what the aside sits on. Sticky offsets track --ui-header-height, which Forest owns.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const pageAsideTheme = {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageCard.
|
|
3
|
+
*
|
|
4
|
+
* ★ Forest's UCard delta does NOT reach this component — different DOM, different recipe, and the
|
|
5
|
+
* `forest-card` marker that drives the nested-surface and concentric-corner CSS is set by the UCard
|
|
6
|
+
* theme alone. So a UPageCard beside a UCard reads as a different system unless corrected here.
|
|
7
|
+
*
|
|
8
|
+
* Two deltas: the corner moves from `rounded-lg` to the card corner (xl / 24px, per the radius
|
|
9
|
+
* contract), and the title and description come off Tailwind's default scale onto the ladder.
|
|
10
|
+
* `text-[15px]` on the description is an arbitrary value with no token behind it at all.
|
|
11
|
+
*
|
|
12
|
+
* The nesting CSS is deliberately NOT extended to this component. It is coupled to UCard's DOM by
|
|
13
|
+
* design, and a second consumer would make it a shared contract that neither component states.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export const pageCardTheme = {
|
|
17
|
+
slots: {
|
|
18
|
+
root: 'rounded-xl',
|
|
19
|
+
title: 'type-heading-xs',
|
|
20
|
+
description: 'type-body',
|
|
21
|
+
},
|
|
22
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageCTA (ui key `pageCta`).
|
|
3
|
+
*
|
|
4
|
+
* Type only. Note what is NOT changed: `rounded-xl` on the root is already on-contract — the
|
|
5
|
+
* rounded-* utilities inline calc(var(--ui-radius) * N), so xl resolves to Forest's 24px card corner
|
|
6
|
+
* rather than a Tailwind literal. It looked like a bypass and is not.
|
|
7
|
+
*
|
|
8
|
+
* ★ It caps its own width (embedded UContainer), which matters most here: a CTA normally sits inside
|
|
9
|
+
* page content already, so nesting it in a well double-applies the gutters. Registered on
|
|
10
|
+
* /layout/well.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const pageCtaTheme = {
|
|
14
|
+
slots: {
|
|
15
|
+
title: 'type-headline',
|
|
16
|
+
description: 'type-body',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageFeature.
|
|
3
|
+
*
|
|
4
|
+
* `text-[15px]` on the description is an arbitrary value — not a step on any scale, Tailwind's or
|
|
5
|
+
* Forest's. Both slots move onto the ladder.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const pageFeatureTheme = {
|
|
9
|
+
slots: {
|
|
10
|
+
title: 'type-heading-xs',
|
|
11
|
+
description: 'type-body',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageHeader.
|
|
3
|
+
*
|
|
4
|
+
* Stock builds a whole type ladder of its own — `text-3xl sm:text-4xl` for the title, `text-lg` for
|
|
5
|
+
* the description, `text-sm font-semibold` for the headline. Forest already has those three steps
|
|
6
|
+
* named, and a second ladder drifts the moment the real one moves. Retyped onto the ladder; the
|
|
7
|
+
* responsive step is dropped with it, because `.type-display` owns its own scaling.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const pageHeaderTheme = {
|
|
11
|
+
slots: {
|
|
12
|
+
headline: 'type-overline',
|
|
13
|
+
title: 'type-display',
|
|
14
|
+
description: 'type-body',
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageHero.
|
|
3
|
+
*
|
|
4
|
+
* `text-5xl sm:text-7xl` is the largest of stock's off-ladder sizes and the one most likely to be
|
|
5
|
+
* noticed — a hero title two steps above anything Forest publishes. `.type-display` is the top of the
|
|
6
|
+
* ladder and is where a hero belongs; a louder treatment is the marketing context's job, not a
|
|
7
|
+
* bigger literal.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export const pageHeroTheme = {
|
|
11
|
+
slots: {
|
|
12
|
+
title: 'type-display',
|
|
13
|
+
description: 'type-subtitle',
|
|
14
|
+
},
|
|
15
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageLinks.
|
|
3
|
+
*
|
|
4
|
+
* One delta: the group title is `text-sm font-semibold`, off-ladder. `.type-label` is the step for a
|
|
5
|
+
* small heading over a list of controls.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const pageLinksTheme = {
|
|
9
|
+
slots: {
|
|
10
|
+
title: 'type-label',
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment for UPageSection.
|
|
3
|
+
*
|
|
4
|
+
* Stock steps `text-3xl sm:text-4xl lg:text-5xl` across three breakpoints. Forest's ladder handles
|
|
5
|
+
* its own scaling, so the section title takes `.type-headline` — one step below the page title, which
|
|
6
|
+
* is the relationship a section heading should have to the page it sits in.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export const pageSectionTheme = {
|
|
10
|
+
slots: {
|
|
11
|
+
title: 'type-headline',
|
|
12
|
+
description: 'type-body',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reviewed, no delta. UPage and its structural children (body, grid, columns, list) are flex/grid and
|
|
3
|
+
* spacing only — no type, colour or radius. They also set no width of their own, so unlike the
|
|
4
|
+
* page-CHROME family they nest inside a well safely.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const pageTheme = {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UPagination. Deltas over stock (stock `label: min-w-5 text-center`,
|
|
3
|
+
* `item: ''`). The page controls render as UButton, so their colour, size, radius and focus ring
|
|
4
|
+
* ride the button theme — nothing needed here for those, or for the touch (coarse) size step-up.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export const paginationTheme = {
|
|
8
|
+
slots: {
|
|
9
|
+
// Bold page numbers so the active page reads clearly on its solid face.
|
|
10
|
+
label: 'font-bold',
|
|
11
|
+
// Softer rounded-lg face on each page item.
|
|
12
|
+
item: 'rounded-lg',
|
|
13
|
+
// Ellipsis renders as an outline UButton (inherits the item variant); drop its ring so the
|
|
14
|
+
// gap marker reads as a plain glyph, not a bordered button. `as-child` lands this on the button.
|
|
15
|
+
ellipsis: 'ring-0',
|
|
16
|
+
},
|
|
17
|
+
} as const
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UPinInput (OTP / code entry). Deltas only; everything else inherited from
|
|
3
|
+
* stock Nuxt UI.
|
|
4
|
+
*
|
|
5
|
+
* A pin input is an input split into square cells, so it wears the SAME Forest identity as UInput
|
|
6
|
+
* (themes/input.ts): the recessed depth line, the colour-tracking focus halo, the per-size radius
|
|
7
|
+
* ladder, and the touch ladder. Stock UPinInput shares UInput's variant/colour/highlight
|
|
8
|
+
* set and the same responsive `md:text-*` shrink, so the deltas match — only the size axis differs
|
|
9
|
+
* (a square `size-*` cell rather than px/py), so the coarse step bumps the cell size + type.
|
|
10
|
+
*
|
|
11
|
+
* Slots touched: root, base.
|
|
12
|
+
* Slot names sourced from: apps/docs/node_modules/.nuxt-ui/ui/pin-input.ts
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
export const pinInputTheme = {
|
|
16
|
+
slots: {
|
|
17
|
+
// gap-2 → 8px between cells (stock gap-1.5) — a warmer, less grid-like row cadence.
|
|
18
|
+
root: 'gap-2',
|
|
19
|
+
// font-bold so a single digit fills the cell; plus the input identity: the box-shadow transition
|
|
20
|
+
// and the recessed depth line at rest + the depth line & soft colour halo on focus (same shared
|
|
21
|
+
// --forest-input-* / --forest-halo-* tokens as UInput). The old `focus:outline-none` is dropped —
|
|
22
|
+
// it suppressed the very focus outline UInput keeps; parity restores the shared treatment.
|
|
23
|
+
base: 'font-bold transition-[color,box-shadow] duration-(--motion-fast) shadow-[inset_0_calc(var(--forest-input-depth)_+_var(--forest-field-edge,0px))_0_0_var(--forest-input-recess)] focus-visible:shadow-[inset_0_var(--forest-input-depth)_0_0_var(--forest-input-recess),0_0_0_3px_var(--forest-input-halo,var(--forest-halo-primary))]',
|
|
24
|
+
},
|
|
25
|
+
// Touch ladder + per-size radius/depth — mirrors input.ts. Under a coarse pointer each
|
|
26
|
+
// cell grows one size up (a bigger square + type), so OTP entry gets a real tap target. The type
|
|
27
|
+
// bump targets the next size's RESPONSIVE-EFFECTIVE value (stock's `md:text-*` shrink, else the
|
|
28
|
+
// ladder inverts): sm→md `touch:text-sm`, lg→xl `touch:text-base`. sm also rounds up to rounded-md
|
|
29
|
+
// tracking its size-up. xl has a touch rung of its own (52). Depth line scales per size
|
|
30
|
+
// (2/2/3/3/4). PER-SIZE RADIUS:
|
|
31
|
+
// xs/sm rounded-sm (8px), md/lg/xl rounded-md (12px, inherited from stock base — not restated).
|
|
32
|
+
// The mobile cut needs no escape — it lands on the same rung a coarse pointer would.
|
|
33
|
+
variants: {
|
|
34
|
+
size: {
|
|
35
|
+
// touch 28: bigger cell (text/radius/depth unchanged)
|
|
36
|
+
xs: { base: 'rounded-sm [--forest-input-depth:2px] touch:size-7' },
|
|
37
|
+
// touch 36: bigger cell, larger type (md's effective 14), rounder, deeper recess
|
|
38
|
+
sm: { base: 'rounded-sm [--forest-input-depth:2px] touch:size-9 touch:text-sm touch:rounded-md touch:[--forest-input-depth:3px]' },
|
|
39
|
+
// touch 40: bigger cell
|
|
40
|
+
md: { base: '[--forest-input-depth:3px] touch:size-10 touch:text-sm' },
|
|
41
|
+
// touch 44: bigger cell, larger type (16), deepest recess
|
|
42
|
+
lg: { base: '[--forest-input-depth:3px] touch:size-11 touch:text-base touch:rounded-lg touch:[--forest-input-depth:4px]' },
|
|
43
|
+
// touch 52
|
|
44
|
+
xl: { base: '[--forest-input-depth:4px] touch:size-13 touch:text-lg touch:rounded-lg touch:[--forest-input-depth:4px]' },
|
|
45
|
+
},
|
|
46
|
+
// Focus halo tracks `color` — FLAT strings (stock's colour variant is flat; a `{ base: … }` shape
|
|
47
|
+
// would be dropped by the merge). Each colour re-points --forest-input-halo at its own 200 step.
|
|
48
|
+
color: {
|
|
49
|
+
primary: '[--forest-input-halo:var(--forest-halo-primary)]',
|
|
50
|
+
secondary: '[--forest-input-halo:var(--forest-halo-secondary)]',
|
|
51
|
+
success: '[--forest-input-halo:var(--forest-halo-success)]',
|
|
52
|
+
info: '[--forest-input-halo:var(--forest-halo-info)]',
|
|
53
|
+
warning: '[--forest-input-halo:var(--forest-halo-warning)]',
|
|
54
|
+
error: '[--forest-input-halo:var(--forest-halo-error)]',
|
|
55
|
+
forest: '[--forest-input-halo:var(--forest-halo-forest)]',
|
|
56
|
+
maple: '[--forest-input-halo:var(--forest-halo-maple)]',
|
|
57
|
+
river: '[--forest-input-halo:var(--forest-halo-river)]',
|
|
58
|
+
warm: '[--forest-input-halo:var(--forest-halo-warm)]',
|
|
59
|
+
acid: '[--forest-input-halo:var(--forest-halo-acid)]',
|
|
60
|
+
neutral: '[--forest-input-halo:var(--forest-halo-neutral)]',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
// Ghost drops the resting depth line (no fill/ring = nothing to recess into); it takes the line on
|
|
64
|
+
// hover/focus with the elevated fill. Same as input.
|
|
65
|
+
compoundVariants: [
|
|
66
|
+
{
|
|
67
|
+
variant: 'ghost',
|
|
68
|
+
class: {
|
|
69
|
+
base: 'shadow-none hover:shadow-[inset_0_calc(var(--forest-input-depth)_+_var(--forest-field-edge,0px))_0_0_var(--forest-input-recess)]',
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
} as const;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UPopover (floating contextual panel).
|
|
3
|
+
*
|
|
4
|
+
* Forest opinions applied:
|
|
5
|
+
*
|
|
6
|
+
* content — radius bumped from stock `rounded-md` to `rounded-xl` (the brand's warm, soft
|
|
7
|
+
* register — one step above the tooltip's `rounded-lg` since a popover carries richer
|
|
8
|
+
* content and warrants the extra breathing room). The shadow is stepped up from
|
|
9
|
+
* `shadow-lg` to `shadow-xl` to give the floating panel appropriate depth against the
|
|
10
|
+
* page surface.
|
|
11
|
+
*
|
|
12
|
+
* arrow — fill-bg already tracks the content background token; no Forest opinion needed beyond
|
|
13
|
+
* confirming stroke-default resolves correctly in both modes. Class unchanged.
|
|
14
|
+
*
|
|
15
|
+
* Result: a warmer, more tactile popover that sits confidently above the canvas without competing
|
|
16
|
+
* with deeper modals.
|
|
17
|
+
*
|
|
18
|
+
* Slots sourced from: apps/docs/node_modules/.nuxt-ui/ui/popover.ts
|
|
19
|
+
* Slots touched: content
|
|
20
|
+
* Slots NOT touched: arrow — stock values are semantically correct; no Forest override required.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export const popoverTheme = {
|
|
24
|
+
slots: {
|
|
25
|
+
// Softer brand radius + deeper shadow for comfortable floating-panel presence.
|
|
26
|
+
// All other classes (animation, origin, focus outline, pointer-events, ring) are inherited
|
|
27
|
+
// from the Nuxt UI base and are not restated here.
|
|
28
|
+
content: 'shadow-xl rounded-xl data-[state=open]:animate-[scale-in_var(--motion-base)_var(--motion-ease-out)] data-[state=closed]:animate-[scale-out_var(--motion-fast)_var(--motion-ease-out)]',
|
|
29
|
+
},
|
|
30
|
+
} as const;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forest theme fragment — UProgress (linear progress bar).
|
|
3
|
+
*
|
|
4
|
+
* Forest opinions applied:
|
|
5
|
+
*
|
|
6
|
+
* indicator — adds `will-change-transform` so the translate transition composites on the GPU
|
|
7
|
+
* across all browsers, giving a smooth scrub during rapid model-value updates (e.g. live
|
|
8
|
+
* telemetry feeds from the fleet API).
|
|
9
|
+
*
|
|
10
|
+
* Slots touched: `indicator`.
|
|
11
|
+
* Slot names sourced from: apps/docs/node_modules/.nuxt-ui/ui/progress.ts
|
|
12
|
+
*
|
|
13
|
+
* We do NOT override:
|
|
14
|
+
* - `base` (track) — stock `bg-accented` fill carries the groove; the coloured indicator is the
|
|
15
|
+
* signal. No border token reads consistently against the track in both modes, so no ring.
|
|
16
|
+
* - Colour variants — `bg-primary`, `bg-error`, etc. are already wired to the Forest OKLCH ramps
|
|
17
|
+
* via docs.css / forest-preset.ts; no per-slot colour class needed.
|
|
18
|
+
* - Size compound variants — the 2xs–2xl height/width ladder is suitable; Forest has no density
|
|
19
|
+
* opinion here beyond what `--ui-radius` (0.5 rem) already gives.
|
|
20
|
+
* - `status`, `steps`, `step` slots — stock text-dimmed + transition-[width] treatment is correct.
|
|
21
|
+
* - `root` — flex layout is correct for both orientations; no override needed.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export const progressTheme = {
|
|
25
|
+
slots: {
|
|
26
|
+
// Indicator: GPU-composited translate for smooth live-telemetry scrubbing.
|
|
27
|
+
indicator: 'duration-(--motion-slow) ease-(--motion-ease-out) will-change-transform',
|
|
28
|
+
},
|
|
29
|
+
} as const;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prose components (`ui.prose.*`) — the ones a docs surface actually renders.
|
|
3
|
+
*
|
|
4
|
+
* These run stock: `border-muted` around every code surface, `bg-default` on a filename header,
|
|
5
|
+
* `bg-muted` in the code body, `my-5` for rhythm. Only a measurable defect warrants an entry here.
|
|
6
|
+
*
|
|
7
|
+
* TWO CONSTRAINTS ON ANY ENTRY:
|
|
8
|
+
*
|
|
9
|
+
* 1. THE RAMP COLLAPSES A DIFFERENT PAIR IN EACH MODE. Light: `border-default` == `border-muted`
|
|
10
|
+
* (p3 0.903) == `bg-accented`. Dark: `border-muted` == `border-accented` (0.255), and
|
|
11
|
+
* `border-default` equals `bg-muted` — the code fill, which leaves a block no edge. A `dark:`
|
|
12
|
+
* split therefore holds in one mode and loses the edge in the other. Frame tokens take one
|
|
13
|
+
* token across both modes; never split them.
|
|
14
|
+
*
|
|
15
|
+
* 2. `codeIcon` STAYS STOCK. It maps a file to `i-vscode-icons-file-type-<ext>`, the brand marks an
|
|
16
|
+
* editor shows, which is what makes a file tree readable at a glance. They live in
|
|
17
|
+
* `@iconify-json/vscode-icons`, a devDependency alongside lucide; without that collection a tab
|
|
18
|
+
* with a filename renders an EMPTY slot. Lucide cannot tell a .ts from a .vue, so it is not a
|
|
19
|
+
* substitute. A file rendering blank means the extension is missing from stock's map
|
|
20
|
+
* (`UCodeIcon` resolves the FULL FILENAME first, then the extension) — add that one key.
|
|
21
|
+
*/
|
|
22
|
+
export const proseTheme = {
|
|
23
|
+
// `ed-demo` is a marker, not styling. The docs editorial grid opens a new section whenever a block
|
|
24
|
+
// contains a heading, and a specimen renders headings of its own (a UEmpty title, a dialog title).
|
|
25
|
+
// The marker excludes them, so section rhythm does not depend on which state a demo is showing.
|
|
26
|
+
codePreview: {
|
|
27
|
+
slots: {
|
|
28
|
+
preview: 'ed-demo',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
|
|
32
|
+
// Stock's collapsed root is `rounded-b-md` over an opaque `bg-muted` fill, so its square top
|
|
33
|
+
// corners paint into the 12px corners a filename header rounds — a hard right angle at each top
|
|
34
|
+
// corner, visible in dark where the fill clears the page. Rounding the closed root clips the
|
|
35
|
+
// children correctly: the root already carries `overflow-hidden`.
|
|
36
|
+
codeCollapse: {
|
|
37
|
+
variants: {
|
|
38
|
+
open: {
|
|
39
|
+
false: {
|
|
40
|
+
root: 'rounded-md',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|