@felloinnovations/brand-kit 0.4.0 → 0.5.1
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/AGENTS.md +198 -24
- package/CHANGELOG.md +221 -0
- package/README.md +38 -9
- package/design-system/01-how-claude-decides.md +26 -17
- package/design-system/02-principles.md +11 -6
- package/design-system/03-colour.md +135 -47
- package/design-system/04-type.md +45 -23
- package/design-system/05-space-and-layout.md +175 -52
- package/design-system/06-sizing-profiles.md +4 -4
- package/design-system/07-scrolling.md +66 -20
- package/design-system/08-choosing-components.md +50 -22
- package/design-system/09-charts.md +71 -28
- package/design-system/10-patterns.md +33 -10
- package/design-system/11-page-recipes.md +110 -23
- package/design-system/12-content.md +2 -1
- package/design-system/13-motion.md +330 -47
- package/design-system/14-accessibility.md +47 -24
- package/design-system/15-ai-experiences.md +11 -6
- package/design-system/16-creativity.md +1 -1
- package/design-system/17-decisions.md +367 -1
- package/design-system/18-checklist.md +79 -16
- package/design-system/19-public-pages.md +6 -4
- package/design-system/20-palettes.md +275 -0
- package/design-system/README.md +30 -17
- package/design-system/components/ActionList/README.md +96 -10
- package/design-system/components/ActionList/preview.html +52 -7
- package/design-system/components/ActionList/style.css +64 -0
- package/design-system/components/ActivityGrid/README.md +38 -2
- package/design-system/components/ActivityGrid/preview.html +1 -1
- package/design-system/components/ActivityGrid/style.css +35 -0
- package/design-system/components/AppShell/README.md +205 -75
- package/design-system/components/AppShell/preview.html +339 -58
- package/design-system/components/AppShell/style.css +154 -0
- package/design-system/components/Avatar/README.md +37 -10
- package/design-system/components/Avatar/preview.html +13 -4
- package/design-system/components/Avatar/style.css +14 -0
- package/design-system/components/Badge/README.md +41 -19
- package/design-system/components/Badge/preview.html +13 -10
- package/design-system/components/Badge/style.css +23 -0
- package/design-system/components/Banner/README.md +30 -9
- package/design-system/components/Banner/preview.html +1 -1
- package/design-system/components/Banner/style.css +19 -0
- package/design-system/components/Breadcrumb/README.md +58 -46
- package/design-system/components/Breadcrumb/preview.html +16 -16
- package/design-system/components/Breadcrumb/style.css +17 -0
- package/design-system/components/Button/README.md +113 -55
- package/design-system/components/Button/preview.html +98 -25
- package/design-system/components/Button/style.css +86 -0
- package/design-system/components/Card/README.md +158 -49
- package/design-system/components/Card/preview.html +141 -19
- package/design-system/components/Card/style.css +115 -0
- package/design-system/components/CardBoard/README.md +58 -37
- package/design-system/components/CardBoard/preview.html +26 -29
- package/design-system/components/ChatCard/README.md +115 -29
- package/design-system/components/ChatCard/preview.html +149 -32
- package/design-system/components/ChatCard/style.css +49 -0
- package/design-system/components/ChatShell/README.md +116 -0
- package/design-system/components/ChatShell/preview.html +201 -0
- package/design-system/components/ChatShell/style.css +86 -0
- package/design-system/components/ChatTurn/README.md +78 -35
- package/design-system/components/ChatTurn/preview.html +60 -28
- package/design-system/components/ChatTurn/style.css +50 -0
- package/design-system/components/CheckRow/README.md +141 -0
- package/design-system/components/CheckRow/preview.html +140 -0
- package/design-system/components/CheckRow/style.css +88 -0
- package/design-system/components/Checkbox/README.md +58 -22
- package/design-system/components/Checkbox/preview.html +112 -50
- package/design-system/components/Checkbox/style.css +45 -0
- package/design-system/components/Chip/README.md +78 -47
- package/design-system/components/Chip/preview.html +29 -4
- package/design-system/components/Chip/style.css +17 -0
- package/design-system/components/Combobox/README.md +44 -11
- package/design-system/components/Combobox/preview.html +35 -12
- package/design-system/components/Combobox/style.css +54 -0
- package/design-system/components/Composer/README.md +137 -35
- package/design-system/components/Composer/preview.html +115 -40
- package/design-system/components/Composer/style.css +81 -0
- package/design-system/components/ConfirmDialog/README.md +73 -52
- package/design-system/components/ConfirmDialog/preview.html +70 -26
- package/design-system/components/ConfirmDialog/style.css +5 -0
- package/design-system/components/Cover/preview.html +3 -3
- package/design-system/components/Cover/style.css +19 -0
- package/design-system/components/DateInput/README.md +77 -12
- package/design-system/components/DateInput/preview.html +27 -12
- package/design-system/components/DateInput/style.css +38 -0
- package/design-system/components/Dialog/README.md +112 -44
- package/design-system/components/Dialog/preview.html +141 -18
- package/design-system/components/Dialog/style.css +74 -0
- package/design-system/components/EmptyState/README.md +42 -12
- package/design-system/components/EmptyState/preview.html +11 -11
- package/design-system/components/EmptyState/style.css +9 -0
- package/design-system/components/EntryShell/README.md +73 -48
- package/design-system/components/EntryShell/preview.html +60 -27
- package/design-system/components/EntryShell/style.css +19 -0
- package/design-system/components/FeatureGrid/README.md +61 -39
- package/design-system/components/FeatureGrid/preview.html +2 -2
- package/design-system/components/FeatureGrid/style.css +20 -0
- package/design-system/components/FileUpload/README.md +33 -3
- package/design-system/components/FileUpload/preview.html +18 -4
- package/design-system/components/FileUpload/style.css +23 -0
- package/design-system/components/FilterBar/README.md +114 -0
- package/design-system/components/FilterBar/preview.html +82 -0
- package/design-system/components/FilterBar/style.css +22 -0
- package/design-system/components/Fold/README.md +84 -26
- package/design-system/components/Fold/preview.html +77 -34
- package/design-system/components/Fold/style.css +48 -0
- package/design-system/components/Footer/README.md +62 -39
- package/design-system/components/Footer/preview.html +5 -5
- package/design-system/components/Footer/style.css +30 -0
- package/design-system/components/FunnelBars/README.md +24 -3
- package/design-system/components/FunnelBars/preview.html +5 -5
- package/design-system/components/FunnelBars/style.css +13 -0
- package/design-system/components/GoalBars/README.md +54 -10
- package/design-system/components/GoalBars/preview.html +69 -28
- package/design-system/components/GoalBars/style.css +51 -0
- package/design-system/components/GoalTicks/README.md +74 -58
- package/design-system/components/GoalTicks/preview.html +41 -118
- package/design-system/components/GoalTicks/style.css +37 -0
- package/design-system/components/GoalTubes/README.md +29 -3
- package/design-system/components/GoalTubes/preview.html +6 -6
- package/design-system/components/GoalTubes/style.css +23 -0
- package/design-system/components/Heatmap/README.md +133 -0
- package/design-system/components/Heatmap/preview.html +168 -0
- package/design-system/components/Heatmap/style.css +119 -0
- package/design-system/components/Hero/README.md +58 -40
- package/design-system/components/Hero/preview.html +1 -1
- package/design-system/components/Hero/style.css +19 -0
- package/design-system/components/HoverCard/README.md +114 -0
- package/design-system/components/HoverCard/preview.html +107 -0
- package/design-system/components/HoverCard/style.css +59 -0
- package/design-system/components/IconButton/README.md +69 -38
- package/design-system/components/IconButton/preview.html +77 -43
- package/design-system/components/IconButton/style.css +45 -0
- package/design-system/components/Input/README.md +36 -11
- package/design-system/components/Input/preview.html +1 -1
- package/design-system/components/Input/style.css +23 -0
- package/design-system/components/KanbanBoard/README.md +93 -45
- package/design-system/components/KanbanBoard/preview.html +159 -43
- package/design-system/components/KanbanBoard/style.css +53 -0
- package/design-system/components/Kbd/README.md +25 -9
- package/design-system/components/Kbd/preview.html +6 -2
- package/design-system/components/Kbd/style.css +9 -0
- package/design-system/components/KitButton/README.md +81 -47
- package/design-system/components/KitButton/preview.html +35 -13
- package/design-system/components/KitButton/style.css +46 -0
- package/design-system/components/KitCard/README.md +75 -44
- package/design-system/components/KitCard/preview.html +18 -10
- package/design-system/components/KitCard/style.css +15 -0
- package/design-system/components/KitInput/README.md +54 -39
- package/design-system/components/KitInput/preview.html +7 -7
- package/design-system/components/KitInput/style.css +23 -0
- package/design-system/components/Leaderboard/README.md +76 -49
- package/design-system/components/Leaderboard/preview.html +61 -26
- package/design-system/components/Leaderboard/style.css +44 -0
- package/design-system/components/ListDetail/README.md +222 -0
- package/design-system/components/ListDetail/preview.html +213 -0
- package/design-system/components/ListDetail/style.css +148 -0
- package/design-system/components/LoadBar/README.md +79 -0
- package/design-system/components/LoadBar/preview.html +40 -0
- package/design-system/components/LoadBar/style.css +17 -0
- package/design-system/components/MarketingNav/README.md +76 -42
- package/design-system/components/MarketingNav/preview.html +37 -8
- package/design-system/components/MarketingNav/style.css +45 -0
- package/design-system/components/Matrix/README.md +129 -0
- package/design-system/components/Matrix/preview.html +99 -0
- package/design-system/components/Matrix/style.css +84 -0
- package/design-system/components/Menu/README.md +117 -41
- package/design-system/components/Menu/preview.html +85 -23
- package/design-system/components/Menu/style.css +61 -0
- package/design-system/components/Meter/README.md +39 -4
- package/design-system/components/Meter/preview.html +18 -1
- package/design-system/components/Meter/style.css +23 -0
- package/design-system/components/MetricTile/README.md +237 -0
- package/design-system/components/MetricTile/preview.html +241 -0
- package/design-system/components/MetricTile/style.css +129 -0
- package/design-system/components/Morph/README.md +106 -0
- package/design-system/components/Morph/preview.html +103 -0
- package/design-system/components/Morph/style.css +31 -0
- package/design-system/components/Motion/README.md +164 -0
- package/design-system/components/Motion/preview.html +2537 -0
- package/design-system/components/NumberInput/README.md +27 -8
- package/design-system/components/NumberInput/preview.html +21 -5
- package/design-system/components/NumberInput/style.css +34 -0
- package/design-system/components/PaceBar/README.md +75 -0
- package/design-system/components/PaceBar/preview.html +67 -0
- package/design-system/components/PaceBar/style.css +25 -0
- package/design-system/components/Page/README.md +57 -18
- package/design-system/components/Page/preview.html +15 -17
- package/design-system/components/Page/style.css +7 -0
- package/design-system/components/PageBar/README.md +90 -34
- package/design-system/components/PageBar/preview.html +60 -19
- package/design-system/components/PageBar/style.css +35 -0
- package/design-system/components/PageHero/README.md +87 -51
- package/design-system/components/PageHero/preview.html +35 -6
- package/design-system/components/PageHero/style.css +31 -0
- package/design-system/components/Pagination/README.md +70 -49
- package/design-system/components/Pagination/preview.html +24 -15
- package/design-system/components/Pagination/style.css +12 -0
- package/design-system/components/Panel/README.md +109 -51
- package/design-system/components/Panel/preview.html +118 -20
- package/design-system/components/Panel/style.css +51 -0
- package/design-system/components/PasswordInput/README.md +50 -18
- package/design-system/components/PasswordInput/preview.html +71 -21
- package/design-system/components/PasswordInput/style.css +31 -0
- package/design-system/components/Plate/README.md +75 -17
- package/design-system/components/Plate/preview.html +40 -7
- package/design-system/components/Plate/style.css +37 -0
- package/design-system/components/Popover/README.md +70 -49
- package/design-system/components/Popover/preview.html +44 -22
- package/design-system/components/Popover/style.css +41 -0
- package/design-system/components/PricingTable/README.md +69 -49
- package/design-system/components/PricingTable/preview.html +21 -21
- package/design-system/components/PricingTable/style.css +21 -0
- package/design-system/components/ProgressPetals/README.md +31 -3
- package/design-system/components/ProgressPetals/preview.html +14 -15
- package/design-system/components/ProgressPetals/style.css +27 -0
- package/design-system/components/README.md +151 -0
- package/design-system/components/Radio/README.md +40 -17
- package/design-system/components/Radio/preview.html +16 -1
- package/design-system/components/Radio/style.css +21 -0
- package/design-system/components/RankBar/README.md +29 -2
- package/design-system/components/RankBar/preview.html +14 -12
- package/design-system/components/RankBar/style.css +18 -0
- package/design-system/components/Ring/README.md +61 -11
- package/design-system/components/Ring/preview.html +55 -10
- package/design-system/components/Ring/style.css +49 -0
- package/design-system/components/ScoreHero/README.md +91 -0
- package/design-system/components/ScoreHero/preview.html +104 -0
- package/design-system/components/ScoreHero/style.css +32 -0
- package/design-system/components/Section/README.md +72 -33
- package/design-system/components/Section/preview.html +46 -16
- package/design-system/components/Section/style.css +18 -0
- package/design-system/components/Segmented/README.md +100 -55
- package/design-system/components/Segmented/preview.html +107 -26
- package/design-system/components/Segmented/style.css +94 -0
- package/design-system/components/SegmentedProgress/README.md +64 -0
- package/design-system/components/SegmentedProgress/preview.html +69 -0
- package/design-system/components/SegmentedProgress/style.css +11 -0
- package/design-system/components/Select/README.md +47 -12
- package/design-system/components/Select/preview.html +28 -2
- package/design-system/components/Select/style.css +22 -0
- package/design-system/components/ShareBar/README.md +69 -0
- package/design-system/components/ShareBar/preview.html +72 -0
- package/design-system/components/ShareBar/style.css +25 -0
- package/design-system/components/SideList/README.md +147 -0
- package/design-system/components/SideList/preview.html +139 -0
- package/design-system/components/SideList/style.css +94 -0
- package/design-system/components/Skeleton/README.md +53 -16
- package/design-system/components/Skeleton/preview.html +35 -23
- package/design-system/components/Skeleton/style.css +17 -0
- package/design-system/components/Slider/README.md +95 -0
- package/design-system/components/Slider/preview.html +49 -0
- package/design-system/components/Slider/style.css +13 -0
- package/design-system/components/Split/README.md +112 -0
- package/design-system/components/Split/preview.html +105 -0
- package/design-system/components/Split/style.css +30 -0
- package/design-system/components/Starter/README.md +21 -9
- package/design-system/components/Starter/preview.html +5 -5
- package/design-system/components/Stat/README.md +64 -43
- package/design-system/components/Stat/preview.html +3 -3
- package/design-system/components/Stat/style.css +15 -0
- package/design-system/components/StatTiles/README.md +88 -44
- package/design-system/components/StatTiles/preview.html +142 -71
- package/design-system/components/StatTiles/style.css +64 -0
- package/design-system/components/StatusLine/README.md +85 -0
- package/design-system/components/StatusLine/preview.html +49 -0
- package/design-system/components/StatusLine/style.css +14 -0
- package/design-system/components/StatusScreen/README.md +49 -35
- package/design-system/components/StatusScreen/preview.html +20 -5
- package/design-system/components/StatusScreen/style.css +9 -0
- package/design-system/components/StepLine/README.md +97 -0
- package/design-system/components/StepLine/preview.html +108 -0
- package/design-system/components/StepLine/style.css +62 -0
- package/design-system/components/Stepper/README.md +35 -13
- package/design-system/components/Stepper/style.css +13 -0
- package/design-system/components/StreakCalendar/README.md +22 -1
- package/design-system/components/StreakCalendar/preview.html +10 -10
- package/design-system/components/StreakCalendar/style.css +12 -0
- package/design-system/components/SuggestionChip/README.md +87 -0
- package/design-system/components/SuggestionChip/preview.html +42 -0
- package/design-system/components/SuggestionChip/style.css +20 -0
- package/design-system/components/Switch/README.md +44 -24
- package/design-system/components/Switch/preview.html +23 -8
- package/design-system/components/Switch/style.css +31 -0
- package/design-system/components/Table/README.md +129 -58
- package/design-system/components/Table/preview.html +106 -72
- package/design-system/components/Table/style.css +104 -0
- package/design-system/components/Tabs/README.md +71 -46
- package/design-system/components/Tabs/preview.html +56 -24
- package/design-system/components/Tabs/style.css +44 -0
- package/design-system/components/Testimonial/README.md +48 -32
- package/design-system/components/Testimonial/preview.html +14 -14
- package/design-system/components/Testimonial/style.css +12 -0
- package/design-system/components/TextArea/README.md +27 -11
- package/design-system/components/TextArea/preview.html +8 -2
- package/design-system/components/TextArea/style.css +12 -0
- package/design-system/components/ThemeSwitch/README.md +116 -0
- package/design-system/components/ThemeSwitch/preview.html +57 -0
- package/design-system/components/ThemeSwitch/style.css +6 -0
- package/design-system/components/TickRow/README.md +52 -36
- package/design-system/components/TickRow/preview.html +64 -41
- package/design-system/components/TickRow/style.css +23 -0
- package/design-system/components/TickStrip/README.md +95 -0
- package/design-system/components/TickStrip/preview.html +88 -0
- package/design-system/components/TickStrip/style.css +42 -0
- package/design-system/components/Tile/README.md +79 -18
- package/design-system/components/Tile/preview.html +91 -40
- package/design-system/components/Tile/style.css +36 -0
- package/design-system/components/Timeline/README.md +68 -48
- package/design-system/components/Timeline/preview.html +27 -15
- package/design-system/components/Timeline/style.css +25 -0
- package/design-system/components/Toast/README.md +70 -38
- package/design-system/components/Toast/preview.html +43 -8
- package/design-system/components/Toast/style.css +25 -0
- package/design-system/components/Tooltip/README.md +93 -35
- package/design-system/components/Tooltip/preview.html +69 -15
- package/design-system/components/Tooltip/style.css +78 -0
- package/design-system/components/TopBar/README.md +67 -53
- package/design-system/components/TopBar/preview.html +14 -27
- package/design-system/components/TopBar/style.css +35 -0
- package/design-system/components/TopicRail/README.md +108 -0
- package/design-system/components/TopicRail/preview.html +58 -0
- package/design-system/components/TopicRail/style.css +48 -0
- package/design-system/components/TrendBars/README.md +52 -14
- package/design-system/components/TrendBars/preview.html +65 -32
- package/design-system/components/TrendBars/style.css +25 -0
- package/design-system/components/TrendLine/README.md +164 -0
- package/design-system/components/TrendLine/preview.html +373 -0
- package/design-system/components/TrendLine/style.css +155 -0
- package/design-system/components/Well/README.md +64 -22
- package/design-system/components/Well/preview.html +14 -14
- package/design-system/components/Well/style.css +22 -0
- package/design-system/components/_house.css +324 -0
- package/design-system/components/bundle.css +4086 -744
- package/design-system/tokens.json +1310 -124
- package/dist/fello-core.css +2 -2
- package/dist/fello.css +6 -1369
- package/dist/fello.scoped.css +7 -0
- package/dist/index.d.ts +109 -10
- package/dist/index.js +781 -96
- package/dist/palettes.d.ts +464 -0
- package/dist/palettes.js +497 -0
- package/dist/scoped.d.ts +3 -0
- package/dist/scoped.js +16 -0
- package/dist/toast.d.ts +14 -0
- package/dist/toast.js +33 -29
- package/dist/tokens.d.ts +1686 -62
- package/dist/tokens.js +1668 -61
- package/package.json +20 -4
- package/scripts/check-palette.mjs +295 -0
- package/scripts/token-model.mjs +552 -0
- package/tokens/_dark.css +173 -0
- package/tokens/_palettes.css +46 -0
- package/tokens/_product.css +266 -53
- package/tokens/_source.hubl.css +39 -19
- package/tokens/design-tokens.json +319 -0
- package/tokens/palettes.ts +504 -0
- package/tokens/shadcn-compat.css +19 -19
- package/tokens/shadcn-compat.hsl.css +76 -0
- package/tokens/tokens.css +1287 -62
- package/tokens/tokens.md +587 -61
- package/tokens/tokens.root.css +1293 -62
- package/tokens/tokens.ts +1677 -64
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
A page's main column and its aside, side by side when both fit and stacked when they do not. It measures its own
|
|
2
|
+
width, so it is right in the shell's body, a page, a dialog or a pane.
|
|
3
|
+
|
|
4
|
+
## Use it when
|
|
5
|
+
|
|
6
|
+
- A page shows a list or a report and, beside it, the detail of the one thing picked (Seth's checks list and its
|
|
7
|
+
check drawer).
|
|
8
|
+
- A page needs a column of facts or acts beside its main content (a deal and its next steps).
|
|
9
|
+
- The two parts have different jobs and the aside has a natural width; the main column takes the rest.
|
|
10
|
+
|
|
11
|
+
## Not for
|
|
12
|
+
|
|
13
|
+
- A page of like cards: that is a board (`CardBoard`, `.ws-board`).
|
|
14
|
+
- Small cards one, two then four across: `.ws-board--4` (see `Page`).
|
|
15
|
+
- A drawer that covers the page: `Panel` or a `Dialog` drawer.
|
|
16
|
+
- A list and its detail joined into one surface: `ListDetail` (from WP-data).
|
|
17
|
+
|
|
18
|
+
## Anatomy
|
|
19
|
+
|
|
20
|
+
- `<div class="ws-split">`: a size container named `ws-split`, its two parts 24 apart (`--ws-gap-group`, Seth's gap
|
|
21
|
+
between a report and its drawer), tops on one line (nothing stretches).
|
|
22
|
+
- Main (`__main`): takes the width the aside leaves, never under 0 (its content wraps or scrolls inside itself).
|
|
23
|
+
- Aside (`__aside`): 440 wide (`--ws-thing-width`, Seth's drawer). A page that needs another width sets
|
|
24
|
+
`--ws-split-aside` on the split from a token (North's side columns run 320 to 420).
|
|
25
|
+
- From 60rem of the split's own width the two sit side by side; under it the aside goes under the main column, both
|
|
26
|
+
the full width, in DOM order (the phone's order is the reading order).
|
|
27
|
+
- `--sticky`: side by side, the aside stays in view while the main column scrolls past it (`position: sticky`), 16
|
|
28
|
+
under the scroller's top (`--ws-gap-component`), the same gap it had under the bar before it stuck.
|
|
29
|
+
- `--fill`: the split is the rest of a height-bound column (the shell's body, a pane), Seth's report and its check
|
|
30
|
+
drawer (`301:2011`). Side by side, both parts take its height: the main column scrolls on its own (with 4 px of room
|
|
31
|
+
at its sides, so a ring on a row's edge is never cut) and the aside runs to the foot, its last part (a `Panel`'s
|
|
32
|
+
foot, a card's band) on the bottom. In the shell's body the page then ends 24 above the stage's foot, as Seth draws
|
|
33
|
+
it. Stacked, the split scrolls the two together. Its parent must be a flex column with a height.
|
|
34
|
+
|
|
35
|
+
## Variants and sizes
|
|
36
|
+
|
|
37
|
+
| Width of the split | Shows |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| 60rem and up | Main (the rest) and aside (440) side by side, 24 apart |
|
|
40
|
+
| Under 60rem | Main, then the aside under it, each the full width, 24 apart |
|
|
41
|
+
|
|
42
|
+
| Class | Height | Use |
|
|
43
|
+
| --- | --- | --- |
|
|
44
|
+
| (default) | Each part its content's | A page that scrolls as a whole |
|
|
45
|
+
| `--sticky` | The aside its own, held in view | A long main column beside a short aside |
|
|
46
|
+
| `--fill` | Both the rest of the column, the main scrolling inside | Seth's report and its drawer, the drawer's acts on the stage foot |
|
|
47
|
+
|
|
48
|
+
## States
|
|
49
|
+
|
|
50
|
+
- **Default**: side by side or stacked by width, as above.
|
|
51
|
+
- **Long content**: the main column grows the page; the aside keeps its own height. With `--sticky` it stays in view;
|
|
52
|
+
with `--fill` the main column scrolls inside its part and the aside's foot stays on the bottom; while rows are
|
|
53
|
+
hidden below, its last 24 px fade out (a scroll-driven fade, as `ListDetail`'s list), so a cut on a row's edge never
|
|
54
|
+
reads as the end. The fade lifts at the end, a column that fits shows none, and a keyboard focus inside drops it.
|
|
55
|
+
- **Long words**: they wrap inside their part, never widening it past its column.
|
|
56
|
+
- **No aside**: leave the split out; the main content goes straight in the page.
|
|
57
|
+
- **Loading**: each part shows its own ghosts (`.ws-shimmer`) at the size of what is coming.
|
|
58
|
+
|
|
59
|
+
## Behaviour
|
|
60
|
+
|
|
61
|
+
- Order is DOM order at every width: put the part that matters first on a phone first in the markup.
|
|
62
|
+
- No motion of its own; the parts' content settles in. The `--fill` fade follows the scroll, not time, so it is the
|
|
63
|
+
same under reduced motion.
|
|
64
|
+
- It sizes from its own width, never the window's, so in a 720 px pane it stacks even on a wide screen.
|
|
65
|
+
|
|
66
|
+
## Content
|
|
67
|
+
|
|
68
|
+
- The main column holds the page's answer; the aside holds the detail of one picked thing or the page's next acts.
|
|
69
|
+
- The aside's head names what it is the detail of, once.
|
|
70
|
+
|
|
71
|
+
## Props
|
|
72
|
+
|
|
73
|
+
| Name | Type | Meaning |
|
|
74
|
+
| --- | --- | --- |
|
|
75
|
+
| `main` | `ReactNode` | The main column |
|
|
76
|
+
| `aside` | `ReactNode` | The aside |
|
|
77
|
+
| `asideWidth` | `string` | A token for `--ws-split-aside`; default `--ws-thing-width` |
|
|
78
|
+
| `sticky` | `boolean` | Keeps the aside in view while the main column scrolls |
|
|
79
|
+
| `fill` | `boolean` | The split is the rest of a height-bound column; the main column scrolls inside it |
|
|
80
|
+
|
|
81
|
+
## Rules
|
|
82
|
+
|
|
83
|
+
- **Size from the split, not the window** (K3): it is its own container.
|
|
84
|
+
- **Tops on one line**: the two parts start on the same edge; neither adds a margin.
|
|
85
|
+
- **DOM order is the phone's order**: never reorder the parts for a narrow screen.
|
|
86
|
+
|
|
87
|
+
## Source
|
|
88
|
+
|
|
89
|
+
**Derived from**: Seth's Grow report with its check drawer (Figma `301:1630`: report 886, gap 24, drawer 440 in a
|
|
90
|
+
1350 content box), North's side columns (`style1.css` 311, 446, 963, 1036: a chart and a 320 to 420 column, 24 apart)
|
|
91
|
+
and Revenue OS's missing "main plus aside" pattern (Aryan's `.mock-split`, which switched by window and left the main
|
|
92
|
+
column too narrow at 1280). New in 0.5.0, 4 Nov 2026.
|
|
93
|
+
|
|
94
|
+
## Markup
|
|
95
|
+
|
|
96
|
+
```html
|
|
97
|
+
<div class="ws-split ws-split--sticky">
|
|
98
|
+
<div class="ws-split__main">
|
|
99
|
+
<!-- the report or the list -->
|
|
100
|
+
</div>
|
|
101
|
+
<aside class="ws-split__aside" aria-labelledby="split-aside-title">
|
|
102
|
+
<h2 class="ws-title" id="split-aside-title">Local search</h2>
|
|
103
|
+
<!-- the detail of the picked thing -->
|
|
104
|
+
</aside>
|
|
105
|
+
</div>
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Styles
|
|
109
|
+
|
|
110
|
+
`Split/style.css`. Tokens: `--ws-gap-group`, `--ws-gap-component`, `--ws-thing-width`, `--ws-focus-width`,
|
|
111
|
+
`--ws-focus-offset`, `--ws-ink`; the page may set `--ws-split-aside`. With the shell, Seth's frame is
|
|
112
|
+
`<main class="ws-app-shell__body ws-app-shell__body--wide"><div class="ws-split ws-split--fill">`.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
<!-- @dsCard group="Layout" height=974 -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>Split</title>
|
|
7
|
+
<link rel="stylesheet" href="../../tokens.css">
|
|
8
|
+
<link rel="stylesheet" href="../bundle.css">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div class="ws-stage ws-stage--column">
|
|
12
|
+
|
|
13
|
+
<div class="ws-stack">
|
|
14
|
+
<span class="ws-muted">Side by side from 60rem of its own width: the main column takes the rest, the aside 440, 24 apart, tops on one line; --sticky keeps the aside in view</span>
|
|
15
|
+
<div class="ws-split ws-split--sticky">
|
|
16
|
+
<div class="ws-split__main ws-stack ws-stack--component">
|
|
17
|
+
<section class="ws-section-group" aria-labelledby="split-checks">
|
|
18
|
+
<div class="ws-section-group__head">
|
|
19
|
+
<div class="ws-section-group__words">
|
|
20
|
+
<h2 id="split-checks" class="ws-section-group__title">Your AI visibility checks</h2>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
<ul>
|
|
24
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Local search</span><span class="ws-figure ws-figure--row">39</span></li>
|
|
25
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Website</span><span class="ws-figure ws-figure--row">75</span></li>
|
|
26
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Social</span><span class="ws-figure ws-figure--row">92</span></li>
|
|
27
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Zillow</span><span class="ws-figure ws-figure--row">100</span></li>
|
|
28
|
+
</ul>
|
|
29
|
+
</section>
|
|
30
|
+
<section class="ws-card ws-card--inset ws-stack" aria-labelledby="split-more">
|
|
31
|
+
<h2 class="ws-title" id="split-more">Zillow is your strongest</h2>
|
|
32
|
+
<p class="ws-body">Start with Local search: buyers near you see you in five of nine spots, never in the top three.</p>
|
|
33
|
+
</section>
|
|
34
|
+
</div>
|
|
35
|
+
<aside class="ws-split__aside ws-card ws-card--inset ws-stack ws-stack--loose" aria-labelledby="split-aside">
|
|
36
|
+
<h2 class="ws-title" id="split-aside">Local search</h2>
|
|
37
|
+
<p class="ws-body">How often you show up on Google Maps when buyers search near you.</p>
|
|
38
|
+
<div class="ws-plate ws-stack ws-stack--tight">
|
|
39
|
+
<span class="ws-muted">Next fix, 1 of 2</span>
|
|
40
|
+
<span class="ws-section">Name the towns you serve in your Google Business Profile.</span>
|
|
41
|
+
</div>
|
|
42
|
+
<div class="ws-cluster">
|
|
43
|
+
<button type="button" class="ws-btn ws-btn--secondary">Send to my web person</button>
|
|
44
|
+
<button type="button" class="ws-btn ws-btn--primary">Review the rewrite</button>
|
|
45
|
+
</div>
|
|
46
|
+
</aside>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<div class="ws-stack">
|
|
51
|
+
<span class="ws-muted">--fill in a height-bound column (here a 280 px frame standing in for the shell's body): both parts take its height, the main column scrolls on its own, the aside's foot sits on the bottom</span>
|
|
52
|
+
<div style="height: 280px; display: flex; flex-direction: column;">
|
|
53
|
+
<div class="ws-split ws-split--fill">
|
|
54
|
+
<div class="ws-split__main">
|
|
55
|
+
<section class="ws-section-group" aria-labelledby="split-fill-checks">
|
|
56
|
+
<div class="ws-section-group__head">
|
|
57
|
+
<div class="ws-section-group__words">
|
|
58
|
+
<h2 id="split-fill-checks" class="ws-section-group__title">Your AI visibility checks <span class="ws-section-group__count">6 checks</span></h2>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
<ul>
|
|
62
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Local search</span><span class="ws-figure ws-figure--row">39</span></li>
|
|
63
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Website</span><span class="ws-figure ws-figure--row">75</span></li>
|
|
64
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Social</span><span class="ws-figure ws-figure--row">92</span></li>
|
|
65
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Zillow</span><span class="ws-figure ws-figure--row">100</span></li>
|
|
66
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Google profile</span><span class="ws-muted">Could not check</span></li>
|
|
67
|
+
<li class="ws-section-group__row"><span class="ws-row-name">AI answers</span><span class="ws-muted">Could not check</span></li>
|
|
68
|
+
<li class="ws-section-group__row"><span class="ws-row-name">Reviews</span><span class="ws-figure ws-figure--row">88</span></li>
|
|
69
|
+
</ul>
|
|
70
|
+
</section>
|
|
71
|
+
</div>
|
|
72
|
+
<aside class="ws-split__aside ws-card ws-card--compound" aria-labelledby="split-fill-aside">
|
|
73
|
+
<header class="ws-head"><div>
|
|
74
|
+
<h2 class="ws-title" id="split-fill-aside">Local search</h2>
|
|
75
|
+
<p class="ws-body ws-card__line">How often you show up on Google Maps when buyers search near you.</p>
|
|
76
|
+
</div></header>
|
|
77
|
+
<footer class="ws-band">
|
|
78
|
+
<div class="ws-band__words">
|
|
79
|
+
<p class="ws-band__title">Next fix, 1 of 2</p>
|
|
80
|
+
<p class="ws-band__how">Name the towns you serve</p>
|
|
81
|
+
</div>
|
|
82
|
+
<button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Review the rewrite</button>
|
|
83
|
+
</footer>
|
|
84
|
+
</aside>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="ws-stack" style="width: 720px; max-width: 100%;">
|
|
90
|
+
<span class="ws-muted">Under 60rem (here a 720 px column): the aside goes under the main column, both the full width, in DOM order</span>
|
|
91
|
+
<div class="ws-split">
|
|
92
|
+
<section class="ws-split__main ws-card ws-card--inset ws-stack" aria-labelledby="split-narrow-main">
|
|
93
|
+
<h2 class="ws-title" id="split-narrow-main">Three offers wait on you</h2>
|
|
94
|
+
<p class="ws-body">The oldest has waited two days. Call Dana Alvarez first, then Marco Diaz.</p>
|
|
95
|
+
</section>
|
|
96
|
+
<aside class="ws-split__aside ws-card ws-card--inset ws-stack" aria-labelledby="split-narrow-aside">
|
|
97
|
+
<h2 class="ws-section" id="split-narrow-aside">Dana Alvarez</h2>
|
|
98
|
+
<p class="ws-body">Offer out Monday on 14 Elm Street, a long label that wraps inside the aside rather than widening it past its column.</p>
|
|
99
|
+
</aside>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
|
|
103
|
+
</div>
|
|
104
|
+
</body>
|
|
105
|
+
</html>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* ---- Split: a page's main column and its aside (a check's drawer, a list's detail, a column of facts) side by side, 24
|
|
2
|
+
apart, tops on one line; the aside 440 wide (Seth's drawer, --ws-thing-width) unless the page sets --ws-split-aside.
|
|
3
|
+
It measures itself: under 60rem of its own width the two stack in DOM order, each the full width. --sticky keeps the
|
|
4
|
+
aside in view while the main column scrolls past it; --fill makes the split the rest of a height-bound column. ---- */
|
|
5
|
+
.ws-split { container: ws-split / inline-size; display: flex; flex-wrap: wrap; align-items: flex-start; gap: var(--ws-gap-group); }
|
|
6
|
+
.ws-split > * { flex: 1 1 100%; min-width: 0; }
|
|
7
|
+
/* Fill (Seth's report and its drawer, 301:2011): the split takes the rest of a height-bound column (the shell's body).
|
|
8
|
+
Side by side, both parts take its height: the main column scrolls on its own (4 px of room at its sides, so a ring on
|
|
9
|
+
a row's edge is never cut; its scroll edges stay on the aside's) and the aside runs to the foot, its last part (a
|
|
10
|
+
Panel's or a card's foot) on the bottom. Stacked, the split scrolls the two together. */
|
|
11
|
+
.ws-split--fill { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--ws-ink) 18%, transparent) transparent; }
|
|
12
|
+
@container ws-split (min-width: 60rem) {
|
|
13
|
+
.ws-split > .ws-split__main { flex: 1 1 0; }
|
|
14
|
+
.ws-split > .ws-split__aside { flex: 0 0 var(--ws-split-aside, var(--ws-thing-width)); }
|
|
15
|
+
.ws-split--sticky > .ws-split__aside { position: sticky; top: var(--ws-gap-component); }
|
|
16
|
+
.ws-split--fill > :is(.ws-split__main, .ws-split__aside) { align-self: stretch; max-height: 100%; min-height: 0; }
|
|
17
|
+
.ws-split--fill > .ws-split__main { --ws-split-room: calc(var(--ws-focus-width) + var(--ws-focus-offset)); margin-inline: calc(var(--ws-split-room) * -1); padding-inline: var(--ws-split-room); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; scrollbar-color: color-mix(in srgb, var(--ws-ink) 18%, transparent) transparent; }
|
|
18
|
+
.ws-split--fill > .ws-split__aside { overflow-y: auto; }
|
|
19
|
+
.ws-split--fill > .ws-split__aside > :last-child:not(:first-child) { margin-top: auto; }
|
|
20
|
+
}
|
|
21
|
+
/* The main column shows that it holds more (a cut on a row's edge reads as the list's end): while rows are hidden below,
|
|
22
|
+
its last 24 px fade out, and the fade lifts at the end. Scroll-driven, as ListDetail's list, so a column that fits
|
|
23
|
+
shows none and nothing moves under reduced motion. A keyboard focus inside drops it, so a ring is never faded. */
|
|
24
|
+
@supports (animation-timeline: scroll()) {
|
|
25
|
+
@container ws-split (min-width: 60rem) {
|
|
26
|
+
.ws-split--fill > .ws-split__main { mask-image: linear-gradient(to top, transparent, var(--ws-mask) var(--space-lg)); mask-size: 100% calc(100% + var(--space-lg)); mask-repeat: no-repeat; animation: ws-split-end linear both; animation-timeline: scroll(self block); animation-range: calc(100% - var(--space-lg)) 100%; }
|
|
27
|
+
.ws-split--fill > .ws-split__main:is(:focus-visible, :has(:focus-visible)) { mask-image: none; }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
@keyframes ws-split-end { from { mask-position: 0 calc(var(--space-lg) * -1); } to { mask-position: 0 0; } }
|
|
@@ -5,8 +5,8 @@ paste the CSS into the `<style>`, then replace the sample content with the real
|
|
|
5
5
|
## Use it when
|
|
6
6
|
|
|
7
7
|
- Starting any page on the system: a claude.ai artifact, a mockup, a one-off HTML page, a report or a dashboard.
|
|
8
|
-
- Starting from markup only: every class in it is the kit's (`fello-core.css` plus the `
|
|
9
|
-
CSS of its own.
|
|
8
|
+
- Starting from markup only: every class in it is the kit's (`fello-core.css` plus the `Page`, `PageBar`, `Card`,
|
|
9
|
+
`Button` and `Well` blocks), so the page needs no CSS of its own.
|
|
10
10
|
|
|
11
11
|
## Not for
|
|
12
12
|
|
|
@@ -20,11 +20,13 @@ paste the CSS into the `<style>`, then replace the sample content with the real
|
|
|
20
20
|
- `<head>`: charset, viewport, a title, the Google Fonts link for Instrument Sans (fello.css also imports it; the link
|
|
21
21
|
loads it sooner), and one `<style>` holding the kit's CSS.
|
|
22
22
|
- In a claude.ai artifact the CSS must be inlined (an artifact may load no stylesheet but Google Fonts): paste
|
|
23
|
-
`fello-core.css`, then the styles of each component the page uses (each component's card lists them;
|
|
24
|
-
`fello.css` is too big to paste).
|
|
25
|
-
`
|
|
26
|
-
|
|
27
|
-
-
|
|
23
|
+
`fello-core.css`, then the styles of each component the page uses (each component's card lists them; this page needs
|
|
24
|
+
`Page`, `PageBar`, `Card`, `Button` and `Well`; the whole `fello.css` is too big to paste). The buttons and the well
|
|
25
|
+
rows need their own blocks: `fello-core.css` holds only their 0.4 look. A plain page links the whole file instead,
|
|
26
|
+
pinned: `https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css`.
|
|
27
|
+
- `<main class="ws-page">`: the page (see `Page`), Seth's 32 gutter.
|
|
28
|
+
- `PageBar`: the page's 56 px header, its one `h1` (16 / 22 semibold) and a word of context beside it, and its acts
|
|
29
|
+
with the page's one navy primary last.
|
|
28
30
|
- `.ws-board` with two `Card`s, each `ws-card ws-card--compound`: a head (`.ws-head`, the 22 px title that answers the
|
|
29
31
|
question and one line), a body (`.ws-card__body`), and a footer band (`.ws-band`) whose act is secondary, since the
|
|
30
32
|
page's one primary is in the PageBar.
|
|
@@ -34,7 +36,7 @@ paste the CSS into the `<style>`, then replace the sample content with the real
|
|
|
34
36
|
|
|
35
37
|
- **Wide**: the two cards side by side, each up to 556.
|
|
36
38
|
- **Narrow** (under 976 of content): one column, the first card first.
|
|
37
|
-
- **Arriving**: the cards
|
|
39
|
+
- **Arriving**: the cards settle in (`ws-settle`, `--ws-i` 0 and 1), 22 ms apart; still with reduced motion.
|
|
38
40
|
|
|
39
41
|
## Behaviour
|
|
40
42
|
|
|
@@ -57,4 +59,14 @@ paste the CSS into the `<style>`, then replace the sample content with the real
|
|
|
57
59
|
## Source
|
|
58
60
|
|
|
59
61
|
**Derived from**: `Page`, `PageBar`, `CardBoard` and `Card` in this catalog, and the first product's dashboard
|
|
60
|
-
arrangement (a page bar, then tiles, then cards). Added 27 Oct 2026 so a page is built from markup only
|
|
62
|
+
arrangement (a page bar, then tiles, then cards). Added 27 Oct 2026 so a page is built from markup only; brought to
|
|
63
|
+
0.5.0 (Seth's thread header and gutter) 4 Nov 2026.
|
|
64
|
+
|
|
65
|
+
## Markup
|
|
66
|
+
|
|
67
|
+
The whole of `preview.html` is the markup to copy: the head, the one `<style>`, the page, its bar and the board.
|
|
68
|
+
|
|
69
|
+
## Styles
|
|
70
|
+
|
|
71
|
+
Starter has no `style.css`: it is `fello-core.css` (tokens and the house) plus the `Page`, `PageBar`, `Card`,
|
|
72
|
+
`Button` and `Well` blocks. Write no other CSS. A component added to the page brings its own block (its card says which).
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
<title>Starter</title>
|
|
8
8
|
<!-- In a claude.ai artifact, paste fello-core.css into the <style> below, then the styles of each component you use
|
|
9
9
|
(each component's card lists them): an artifact may load no stylesheet but Google Fonts. On a plain page, link the
|
|
10
|
-
whole kit instead, pinned: https://brand-kit-site-production.up.railway.app/v/0.
|
|
10
|
+
whole kit instead, pinned: https://brand-kit-site-production.up.railway.app/v/0.5.1/fello.css -->
|
|
11
11
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
12
12
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
13
13
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400..700&display=swap">
|
|
14
14
|
<style>
|
|
15
|
-
/* fello-core.css here, then each used component's styles (this page: PageBar, Card). Write no other CSS. */
|
|
15
|
+
/* fello-core.css here, then each used component's styles (this page: Page, PageBar, Card, Button, Well). Write no other CSS. */
|
|
16
16
|
</style>
|
|
17
17
|
</head>
|
|
18
18
|
<body>
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
<header class="ws-page-bar">
|
|
22
22
|
<div class="ws-page-bar__words">
|
|
23
23
|
<h1 class="ws-page-bar__title">Calls this month</h1>
|
|
24
|
-
<
|
|
24
|
+
<span class="ws-page-bar__context">Your team's calls since Oct 1</span>
|
|
25
25
|
</div>
|
|
26
26
|
<div class="ws-page-bar__acts">
|
|
27
27
|
<button type="button" class="ws-btn ws-btn--secondary">Share</button>
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
<div class="ws-board">
|
|
33
33
|
|
|
34
|
-
<section class="ws-card ws-card--compound ws-
|
|
34
|
+
<section class="ws-card ws-card--compound ws-settle" style="--ws-i: 0;" aria-labelledby="starter-pace">
|
|
35
35
|
<header class="ws-head">
|
|
36
36
|
<div>
|
|
37
37
|
<h2 class="ws-title" id="starter-pace">On pace for 40 calls by Oct 22</h2>
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
</footer>
|
|
57
57
|
</section>
|
|
58
58
|
|
|
59
|
-
<section class="ws-card ws-card--compound ws-
|
|
59
|
+
<section class="ws-card ws-card--compound ws-settle" style="--ws-i: 1;" aria-labelledby="starter-waiting">
|
|
60
60
|
<header class="ws-head">
|
|
61
61
|
<div>
|
|
62
62
|
<h2 class="ws-title" id="starter-waiting">Three leads are waiting</h2>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
The kit's marketing piece: for a public page, never a product screen.
|
|
2
2
|
|
|
3
|
-
A single figure with its label, built to be a marketing proof point, three of them in a
|
|
3
|
+
A single figure with its label, built to be a marketing proof point, three of them in a strip.
|
|
4
4
|
|
|
5
5
|
## Use it when
|
|
6
6
|
|
|
@@ -11,87 +11,108 @@ A single figure with its label, built to be a marketing proof point, three of th
|
|
|
11
11
|
|
|
12
12
|
## Not for
|
|
13
13
|
|
|
14
|
-
- Any product screen: use `StatTiles` or `GoalTicks`, which carry the product's
|
|
15
|
-
|
|
16
|
-
- A number that
|
|
17
|
-
different idea than this component carries.
|
|
14
|
+
- Any product screen: use `StatTiles` or `GoalTicks`, which carry the product's figure sizes and its "a card whose
|
|
15
|
+
data does not exist is left out" rule instead of a dash.
|
|
16
|
+
- A number that should be compared to a past value: that is a change chip beside a figure.
|
|
18
17
|
- Several related numbers that need their own chart: a bar or goal chart, not three `Stat`s side by side.
|
|
19
18
|
|
|
20
19
|
## Anatomy
|
|
21
20
|
|
|
22
|
-
- Label: `--font-size-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
21
|
+
- Label (`__label`): 12/16 (`--font-size-2xs`), semibold, uppercase, `--letter-spacing-overline` (1.2px),
|
|
22
|
+
`--color-text-muted`.
|
|
23
|
+
- Value (`__value`): `--space-xxs` (4px) under the label, 28/32 (`--ws-text-figure-row`, `--ws-leading-figure-row`)
|
|
24
|
+
semibold, tabular numerals, `--color-text-heading` by default.
|
|
25
|
+
- Note (`__note`): `--space-xxs` under the value, 12/16 `--color-text-muted`.
|
|
26
|
+
- Strip (`.ws-stat-strip`): the stats `--space-2xl` (40px) apart in a row, wrapping with `--space-lg` (24px) between
|
|
27
|
+
rows when they do not fit.
|
|
27
28
|
|
|
28
29
|
## Variants and sizes
|
|
29
30
|
|
|
30
|
-
One size. Four tones
|
|
31
|
+
One size. Four tones:
|
|
31
32
|
|
|
32
33
|
| Tone | Colour | Use |
|
|
33
34
|
| --- | --- | --- |
|
|
34
35
|
| `default` | `--color-text-heading` (navy) | the ordinary case |
|
|
35
36
|
| `positive` | `--color-stat-positive` (teal) | a number that is good news |
|
|
36
|
-
| `brand` | `--color-brand-
|
|
37
|
+
| `brand` | `--color-text-brand-strong` (salmon's word step) | a number that should draw the eye |
|
|
37
38
|
| `muted` | `--color-text-muted` | a secondary or softer number beside a stronger one |
|
|
38
39
|
|
|
40
|
+
Classes: the default is the bare `ws-stat__value`; the tones are `ws-stat__value--positive`, `--brand` and `--muted`.
|
|
41
|
+
`ws-stat__value--none` is the no-data state (muted, an en dash), not a tone.
|
|
42
|
+
|
|
39
43
|
## States
|
|
40
44
|
|
|
41
|
-
- **Value (default):** the number, in its tone
|
|
42
|
-
- **Pending:** a
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **No data (`value: null`):** an en dash in `--color-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- **Hover / focus / selected / pressed:** not applicable; `Stat` renders no interactive element.
|
|
50
|
-
- **Disabled / error:** not applicable.
|
|
45
|
+
- **Value (default):** the number, in its tone.
|
|
46
|
+
- **Pending:** a ghost the size of a number (80 by 32, `--ws-radius-row`) under the house shimmer (`ws-shimmer`), never a
|
|
47
|
+
zero. It is the figure's own height, so nothing shifts when the number lands. A screen reader hears "Loading".
|
|
48
|
+
Under reduced motion it is the still ghost.
|
|
49
|
+
- **No data (`value: null`):** an en dash in `--color-text-muted`, with "No data" read to a screen reader. "A zero is a
|
|
50
|
+
claim about the business that may be false; an X reads as 'this broke'; a dash reads as 'nothing here yet', which is
|
|
51
|
+
the only true one." This is not pending: it means nothing is wired up at all.
|
|
52
|
+
- **Hover / focus / selected / pressed / disabled / error:** not applicable; `Stat` renders nothing interactive.
|
|
51
53
|
- **Long label:** the label wraps; the value's size does not change to fit.
|
|
52
|
-
- **Narrow:**
|
|
53
|
-
tight column.
|
|
54
|
+
- **Narrow:** the strip wraps, so each stat keeps its words on its own lines instead of crushing into a third of a phone.
|
|
54
55
|
|
|
55
56
|
## Behaviour
|
|
56
57
|
|
|
57
58
|
- Keyboard: nothing to focus; this is read-only content.
|
|
58
59
|
- Pointer / touch: no interaction.
|
|
59
|
-
- Motion: the pending
|
|
60
|
-
a still block (`motion-reduce:animate-none`).
|
|
60
|
+
- Motion: the pending shimmer sweeps over 1.8s (`--ws-loop-shimmer`), only under `prefers-reduced-motion: no-preference`.
|
|
61
61
|
|
|
62
62
|
## Content
|
|
63
63
|
|
|
64
|
-
- Label: short,
|
|
64
|
+
- Label: short, written in sentence case ("Appointments booked"); the component shows it uppercase.
|
|
65
65
|
- Value: the real number, pre-formatted (with its "%", "$" or comma) by the caller; `Stat` does not format it.
|
|
66
66
|
- Note: one short line of context ("Last 30 days, across the team"), optional.
|
|
67
|
-
- No em dashes; the "no data" mark is an en dash, drawn by the component
|
|
67
|
+
- No em dashes; the "no data" mark is an en dash, drawn by the component.
|
|
68
68
|
|
|
69
69
|
## Props
|
|
70
70
|
|
|
71
|
+
The React `Stat` (`@felloinnovations/brand-kit`) renders this with Tailwind utilities on the same tokens.
|
|
72
|
+
|
|
71
73
|
| Name | Type | Meaning |
|
|
72
74
|
| --- | --- | --- |
|
|
73
75
|
| `label` | `string` | the small uppercase caption |
|
|
74
76
|
| `value` | `string \| null` | the figure; `null` means no source is connected, not zero |
|
|
75
77
|
| `note` | `string \| null` | optional context line under the value |
|
|
76
78
|
| `tone` | `'default' \| 'positive' \| 'brand' \| 'muted'` | the value's colour, default `default` |
|
|
77
|
-
| `pending` | `boolean` | shows the
|
|
79
|
+
| `pending` | `boolean` | shows the shimmer ghost instead of `value` |
|
|
78
80
|
|
|
79
81
|
## Rules
|
|
80
82
|
|
|
81
|
-
- "
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- **
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
is truth, but writes it as a calc on the 4px grid (`.ws-stat__value`: `calc(var(--space-lg) + var(--space-xxs))`;
|
|
90
|
-
the pending block 29 by 80, `.ws-stat__pending`); the mismatch is reported here, not silently fixed.
|
|
91
|
-
- `--color-feedback-*` and `--color-stat-positive` are themselves flagged provisional in `AGENTS.md`: "inherited
|
|
92
|
-
from the HubSpot boilerplate, awaiting design." `positive` carries this caveat along with it.
|
|
83
|
+
- "null means no source is connected. It does not mean zero." (`dist/index.d.ts`, doc comment on `value`.)
|
|
84
|
+
- **The figure is a type step now** (D6, 4 Nov 2026): 28/32, the kit's row figure. It was a 28px calc with a 1.05
|
|
85
|
+
line height, and the React export drew 26px; both are 28/32 now.
|
|
86
|
+
- **Brand takes salmon's word step** (D2): salmon itself is 2.7:1 on white, under the 3:1 a 28px figure needs.
|
|
87
|
+
- **Labels are 12px** (`06-sizing-profiles.md`, public web: "meta, labels 12 to 14"); they were 10px.
|
|
88
|
+
- **Pending is the shimmer** (D7, North): it was a grey block on the house pulse.
|
|
89
|
+
- The strip wraps (4 Nov 2026): at 320px the three stats were 74px each and their labels and values ran past their boxes.
|
|
90
|
+
- `--color-stat-positive` is still flagged provisional in `AGENTS.md`.
|
|
93
91
|
|
|
94
92
|
## Source
|
|
95
93
|
|
|
96
|
-
**Derived from**: the kit's own `Stat
|
|
97
|
-
the
|
|
94
|
+
**Derived from**: the kit's own `Stat`, its doc comments on null versus zero and pending, the type steps (D6), North's
|
|
95
|
+
loading shimmer (D7), the public web profile and the geometry check at 320. **Precedent**: marketing pages only.
|
|
96
|
+
|
|
97
|
+
## Markup
|
|
98
|
+
|
|
99
|
+
```html
|
|
100
|
+
<div class="ws-stat-strip">
|
|
101
|
+
<div class="ws-stat">
|
|
102
|
+
<div class="ws-stat__label">Appointments booked</div>
|
|
103
|
+
<div class="ws-stat__value ws-stat__value--positive">214</div>
|
|
104
|
+
<div class="ws-stat__note">Last 30 days, across the team</div>
|
|
105
|
+
</div>
|
|
106
|
+
<div class="ws-stat">
|
|
107
|
+
<div class="ws-stat__label">Calls this week</div>
|
|
108
|
+
<div class="ws-stat__value" aria-busy="true"><span class="ws-stat__pending ws-shimmer"><span class="ws-sr">Loading</span></span></div>
|
|
109
|
+
</div>
|
|
110
|
+
<div class="ws-stat">
|
|
111
|
+
<div class="ws-stat__label">Profile views</div>
|
|
112
|
+
<div class="ws-stat__value ws-stat__value--none"><span aria-hidden="true">–</span><span class="ws-sr">No data</span></div>
|
|
113
|
+
<div class="ws-stat__note">No source connected yet</div>
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Styles: the `Stat` block (`components/Stat/style.css`); `ws-shimmer` and `ws-sr` are in `fello-core.css`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<!-- @dsCard group="Marketing" height=247 -->
|
|
2
2
|
<!doctype html>
|
|
3
|
-
<html>
|
|
3
|
+
<html lang="en">
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="utf-8">
|
|
6
6
|
<title>Stat</title>
|
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
</div>
|
|
21
21
|
<div class="ws-stat">
|
|
22
22
|
<div class="ws-stat__label">Calls this week</div>
|
|
23
|
-
<div class="ws-stat__value
|
|
24
|
-
<span class="ws-stat__pending"><span class="ws-sr">Loading</span></span>
|
|
23
|
+
<div class="ws-stat__value" aria-busy="true">
|
|
24
|
+
<span class="ws-stat__pending ws-shimmer"><span class="ws-sr">Loading</span></span>
|
|
25
25
|
</div>
|
|
26
26
|
<div class="ws-stat__note">Still counting Monday's calls</div>
|
|
27
27
|
</div>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* ---- Stat: the kit's marketing figure, its label above and a note under, three to a strip that wraps on a phone ---- */
|
|
2
|
+
.ws-stat-strip { display: flex; flex-wrap: wrap; gap: var(--space-lg) var(--space-2xl); }
|
|
3
|
+
.ws-stat { min-width: 0; }
|
|
4
|
+
.ws-stat__label { font-size: var(--font-size-2xs); line-height: var(--space-md); font-weight: 600; text-transform: uppercase; letter-spacing: var(--letter-spacing-overline); color: var(--color-text-muted); }
|
|
5
|
+
/* The figure is the kit's 28 / 32 row step (D6), semibold because it is a marketing heading. */
|
|
6
|
+
.ws-stat__value { margin-top: var(--space-xxs); font-size: var(--ws-text-figure-row); line-height: var(--ws-leading-figure-row); font-weight: 600; font-variant-numeric: tabular-nums; color: var(--color-text-heading); }
|
|
7
|
+
.ws-stat__value--positive { color: var(--color-stat-positive); }
|
|
8
|
+
/* Salmon itself is 2.7:1 on white, under the 3:1 a 28 px figure needs; its word step carries the tone. */
|
|
9
|
+
.ws-stat__value--brand { color: var(--color-text-brand-strong); }
|
|
10
|
+
.ws-stat__value--muted, .ws-stat__value--none { color: var(--color-text-muted); }
|
|
11
|
+
/* Pending: the North shimmer over a ghost the size of a number, never a zero. Same height as the figure, so nothing shifts. */
|
|
12
|
+
.ws-stat__pending { display: block; height: var(--ws-leading-figure-row); width: var(--space-5xl); border-radius: var(--ws-radius-row); }
|
|
13
|
+
/* Markup from before 0.5.0 (no ws-shimmer) still shows its ghost. */
|
|
14
|
+
.ws-stat__pending:not(.ws-shimmer) { background: var(--ws-track); }
|
|
15
|
+
.ws-stat__note { margin-top: var(--space-xxs); font-size: var(--font-size-2xs); line-height: var(--space-md); color: var(--color-text-muted); }
|