@felloinnovations/brand-kit 0.4.0 → 0.5.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/AGENTS.md +198 -24
- package/CHANGELOG.md +197 -0
- package/README.md +34 -7
- package/design-system/01-how-claude-decides.md +26 -17
- package/design-system/02-principles.md +11 -6
- package/design-system/03-colour.md +134 -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 +357 -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 +52 -16
- package/design-system/components/Skeleton/preview.html +35 -23
- package/design-system/components/Skeleton/style.css +22 -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 +4091 -744
- package/design-system/tokens.json +1314 -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 +110 -11
- 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 +174 -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 +1292 -62
- package/tokens/tokens.md +588 -61
- package/tokens/tokens.root.css +1298 -62
- package/tokens/tokens.ts +1677 -64
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Data" height=
|
|
1
|
+
<!-- @dsCard group="Data" height=760 -->
|
|
2
2
|
<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
@@ -8,59 +8,175 @@
|
|
|
8
8
|
<link rel="stylesheet" href="../bundle.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
|
-
<div class="ws-stage ws-stage--grey">
|
|
12
|
-
<div class="ws-kanban-board" role="region" aria-label="Pipeline stages" tabindex="0">
|
|
11
|
+
<div class="ws-stage ws-stage--grey ws-stage--column">
|
|
13
12
|
|
|
14
|
-
<div class="ws-
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
13
|
+
<div class="ws-stack">
|
|
14
|
+
<span class="ws-muted">Stages as equal 280 px columns: a held card floats, the column under it darkens a step, an empty stage says so, a stage still loading shows ghost cards; the far edge fades while stages are hidden past it</span>
|
|
15
|
+
<div class="ws-kanban-board" role="region" aria-label="Pipeline stages" tabindex="0">
|
|
16
|
+
|
|
17
|
+
<section class="ws-kanban-board__column" aria-labelledby="kb-new">
|
|
18
|
+
<div class="ws-kanban-board__head">
|
|
19
|
+
<h3 class="ws-kanban-board__title" id="kb-new">New leads <span class="ws-kanban-board__count">3</span></h3>
|
|
20
|
+
</div>
|
|
21
|
+
<a class="ws-card ws-kanban-board__card" href="#priya">
|
|
22
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">PN</span><span class="ws-row__title">Priya Nair</span></span>
|
|
23
|
+
<span class="ws-kanban-board__meta">6 days here, cold call</span>
|
|
24
|
+
</a>
|
|
25
|
+
<a class="ws-card ws-kanban-board__card" href="#marco">
|
|
26
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">MD</span><span class="ws-row__title">Marco Diaz-Fernandez de la Vega</span></span>
|
|
27
|
+
<span class="ws-kanban-board__meta">2 days here, referral from a past client who bought on Elm Street</span>
|
|
28
|
+
</a>
|
|
29
|
+
<a class="ws-card ws-kanban-board__card" href="#nellie">
|
|
30
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">NP</span><span class="ws-row__title">Nellie Park</span></span>
|
|
31
|
+
<span class="ws-kanban-board__meta">Just added</span>
|
|
32
|
+
</a>
|
|
33
|
+
</section>
|
|
34
|
+
|
|
35
|
+
<section class="ws-kanban-board__column ws-kanban-board__column--over" aria-labelledby="kb-show">
|
|
36
|
+
<div class="ws-kanban-board__head">
|
|
37
|
+
<h3 class="ws-kanban-board__title" id="kb-show">Showing scheduled <span class="ws-kanban-board__count">2</span></h3>
|
|
38
|
+
</div>
|
|
39
|
+
<a class="ws-card ws-kanban-board__card ws-kanban-board__card--dragging" href="#sam" aria-grabbed="true">
|
|
40
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">SO</span><span class="ws-row__title">Sam Okafor</span></span>
|
|
41
|
+
<span class="ws-kanban-board__meta">Waiting on showing confirmation</span>
|
|
42
|
+
</a>
|
|
43
|
+
<a class="ws-card ws-kanban-board__card" href="#theo">
|
|
44
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">TL</span><span class="ws-row__title">Theo Lang</span></span>
|
|
45
|
+
<span class="ws-kanban-board__meta">Link expires in 2 days</span>
|
|
46
|
+
</a>
|
|
47
|
+
</section>
|
|
48
|
+
|
|
49
|
+
<section class="ws-kanban-board__column" aria-labelledby="kb-offer">
|
|
50
|
+
<div class="ws-kanban-board__head">
|
|
51
|
+
<h3 class="ws-kanban-board__title" id="kb-offer">Offer made <span class="ws-kanban-board__count">1</span></h3>
|
|
52
|
+
</div>
|
|
53
|
+
<a class="ws-card ws-kanban-board__card" href="#dana">
|
|
54
|
+
<span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">DA</span><span class="ws-row__title">Dana Alvarez</span></span>
|
|
55
|
+
<span class="ws-kanban-board__meta">Waiting on her answer</span>
|
|
56
|
+
</a>
|
|
57
|
+
</section>
|
|
58
|
+
|
|
59
|
+
<section class="ws-kanban-board__column" aria-labelledby="kb-contract">
|
|
60
|
+
<div class="ws-kanban-board__head">
|
|
61
|
+
<h3 class="ws-kanban-board__title" id="kb-contract">Under contract <span class="ws-kanban-board__count">0</span></h3>
|
|
62
|
+
</div>
|
|
63
|
+
<p class="ws-kanban-board__empty">Nobody here yet</p>
|
|
64
|
+
</section>
|
|
65
|
+
|
|
66
|
+
<section class="ws-kanban-board__column" aria-labelledby="kb-closed" aria-busy="true">
|
|
67
|
+
<div class="ws-kanban-board__head">
|
|
68
|
+
<h3 class="ws-kanban-board__title" id="kb-closed">Closed</h3>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="ws-kanban-board__ghost ws-shimmer"></div>
|
|
71
|
+
<div class="ws-kanban-board__ghost ws-shimmer"></div>
|
|
72
|
+
</section>
|
|
31
73
|
|
|
32
|
-
<div class="ws-kanban-board__column" aria-label="Showing scheduled">
|
|
33
|
-
<div class="ws-kanban-board__head">
|
|
34
|
-
<h3 class="ws-eyebrow">Showing scheduled <span class="ws-tnum">(2)</span></h3>
|
|
35
|
-
</div>
|
|
36
|
-
<div class="ws-card ws-kanban-board__card ws-kanban-board__card--dragging" aria-grabbed="true">
|
|
37
|
-
<div class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">SO</span><span class="ws-row__title">Sam Okafor</span></div>
|
|
38
|
-
<span class="ws-kanban-board__meta">Waiting on showing confirmation</span>
|
|
39
|
-
</div>
|
|
40
|
-
<div class="ws-card ws-kanban-board__card">
|
|
41
|
-
<div class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">TL</span><span class="ws-row__title">Theo Lang</span></div>
|
|
42
|
-
<span class="ws-kanban-board__meta">Link expires in 2 days</span>
|
|
43
74
|
</div>
|
|
44
75
|
</div>
|
|
45
76
|
|
|
46
|
-
<div class="ws-
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
77
|
+
<div class="ws-stack">
|
|
78
|
+
<span class="ws-muted">--fill, a board page: the board takes the rest of a height-bound column, each stage scrolls on its own with its head stuck, so the sideways bar stays on screen (shown here in a 320 px frame)</span>
|
|
79
|
+
<div style="height: 320px; display: flex; flex-direction: column;">
|
|
80
|
+
<div class="ws-kanban-board ws-kanban-board--fill" role="region" aria-label="Pipeline stages, fill" tabindex="0">
|
|
81
|
+
<section class="ws-kanban-board__column" aria-labelledby="kf-new">
|
|
82
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="kf-new">New leads <span class="ws-kanban-board__count">5</span></h3></div>
|
|
83
|
+
<a class="ws-card ws-kanban-board__card" href="#a1"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">PN</span><span class="ws-row__title">Priya Nair</span></span><span class="ws-kanban-board__meta">6 days here</span></a>
|
|
84
|
+
<a class="ws-card ws-kanban-board__card" href="#a2"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">MD</span><span class="ws-row__title">Marco Diaz</span></span><span class="ws-kanban-board__meta">2 days here</span></a>
|
|
85
|
+
<a class="ws-card ws-kanban-board__card" href="#a3"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">NP</span><span class="ws-row__title">Nellie Park</span></span><span class="ws-kanban-board__meta">Just added</span></a>
|
|
86
|
+
<a class="ws-card ws-kanban-board__card" href="#a4"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">JW</span><span class="ws-row__title">Jo Whitfield</span></span><span class="ws-kanban-board__meta">Just added</span></a>
|
|
87
|
+
<a class="ws-card ws-kanban-board__card" href="#a5"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">RB</span><span class="ws-row__title">Ravi Bose</span></span><span class="ws-kanban-board__meta">Just added</span></a>
|
|
88
|
+
</section>
|
|
89
|
+
<section class="ws-kanban-board__column" aria-labelledby="kf-show">
|
|
90
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="kf-show">Showing scheduled <span class="ws-kanban-board__count">1</span></h3></div>
|
|
91
|
+
<a class="ws-card ws-kanban-board__card" href="#b1"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">SO</span><span class="ws-row__title">Sam Okafor</span></span><span class="ws-kanban-board__meta">Saturday, 11:00</span></a>
|
|
92
|
+
</section>
|
|
93
|
+
<section class="ws-kanban-board__column" aria-labelledby="kf-offer">
|
|
94
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="kf-offer">Offer made <span class="ws-kanban-board__count">0</span></h3></div>
|
|
95
|
+
<p class="ws-kanban-board__empty">Nobody here yet</p>
|
|
96
|
+
</section>
|
|
97
|
+
</div>
|
|
53
98
|
</div>
|
|
54
99
|
</div>
|
|
55
100
|
|
|
56
|
-
<div class="ws-
|
|
57
|
-
<
|
|
58
|
-
|
|
101
|
+
<div class="ws-stack">
|
|
102
|
+
<span class="ws-muted">Moving: click a card to send it to the next stage. It glides there and the cards it leaves close up, on North's list rows reorder spring (reorder(), a View Transition)</span>
|
|
103
|
+
<div class="ws-kanban-board" id="kb-move" role="region" aria-label="Pipeline stages, moving" tabindex="0">
|
|
104
|
+
<section class="ws-kanban-board__column" aria-labelledby="km-new">
|
|
105
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="km-new">New leads <span class="ws-kanban-board__count">2</span></h3></div>
|
|
106
|
+
<a class="ws-card ws-kanban-board__card" href="#m1" data-key="m1"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">PN</span><span class="ws-row__title">Priya Nair</span></span><span class="ws-kanban-board__meta">6 days here, cold call</span></a>
|
|
107
|
+
<a class="ws-card ws-kanban-board__card" href="#m2" data-key="m2"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">NP</span><span class="ws-row__title">Nellie Park</span></span><span class="ws-kanban-board__meta">Just added</span></a>
|
|
108
|
+
</section>
|
|
109
|
+
<section class="ws-kanban-board__column" aria-labelledby="km-show">
|
|
110
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="km-show">Showing scheduled <span class="ws-kanban-board__count">1</span></h3></div>
|
|
111
|
+
<a class="ws-card ws-kanban-board__card" href="#m3" data-key="m3"><span class="ws-kanban-board__who"><span class="ws-avatar ws-avatar--sm" aria-hidden="true">SO</span><span class="ws-row__title">Sam Okafor</span></span><span class="ws-kanban-board__meta">Waiting on showing confirmation</span></a>
|
|
112
|
+
</section>
|
|
113
|
+
<section class="ws-kanban-board__column" aria-labelledby="km-offer">
|
|
114
|
+
<div class="ws-kanban-board__head"><h3 class="ws-kanban-board__title" id="km-offer">Offer made <span class="ws-kanban-board__count">0</span></h3></div>
|
|
115
|
+
<p class="ws-kanban-board__empty">Nobody here yet</p>
|
|
116
|
+
</section>
|
|
59
117
|
</div>
|
|
60
|
-
<p class="ws-kanban-board__empty">Nobody here yet</p>
|
|
61
118
|
</div>
|
|
62
119
|
|
|
63
120
|
</div>
|
|
64
|
-
|
|
121
|
+
<script>
|
|
122
|
+
/* The demo's wiring. reorder() is the kit's helper (import { reorder } from '@felloinnovations/brand-kit'), copied here
|
|
123
|
+
because a preview loads no script: it names each card for a View Transition, runs the move, and eases every card's
|
|
124
|
+
flight on North's reorder spring (.4 / 0, 750 ms), read from the tokens (--ws-spring-reorder). Without View Transitions, or under reduced motion, the card lands. */
|
|
125
|
+
const ids = new WeakMap();
|
|
126
|
+
let count = 0;
|
|
127
|
+
function inView(el) {
|
|
128
|
+
const r = el.getBoundingClientRect();
|
|
129
|
+
if (r.bottom < 0 || r.right < 0 || r.top > innerHeight || r.left > innerWidth) return false;
|
|
130
|
+
for (let p = el.parentElement; p; p = p.parentElement) {
|
|
131
|
+
const s = getComputedStyle(p);
|
|
132
|
+
if (s.overflowX === 'visible' && s.overflowY === 'visible') continue;
|
|
133
|
+
const c = p.getBoundingClientRect(), top = c.top + p.clientTop, left = c.left + p.clientLeft;
|
|
134
|
+
if (r.top < top - 1 || r.left < left - 1 || r.bottom > top + p.clientHeight + 1 || r.right > left + p.clientWidth + 1) return false;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
function reorder(update, within = document, rows = '.ws-kanban-board__card, .ws-list-detail__rows > li, .ws-side-list__picks > li') {
|
|
139
|
+
if (!document.startViewTransition || matchMedia('(prefers-reduced-motion: reduce)').matches) return Promise.resolve(update()).then(() => {});
|
|
140
|
+
const kept = new Map(), from = new Map(), raised = [];
|
|
141
|
+
const name = (after) => within.querySelectorAll(rows).forEach((el) => {
|
|
142
|
+
if (!kept.has(el)) kept.set(el, el.style.viewTransitionName);
|
|
143
|
+
if (!ids.has(el)) ids.set(el, `ws-row-${el.dataset.key || el.id || `auto-${++count}`}`);
|
|
144
|
+
const id = CSS.escape(ids.get(el));
|
|
145
|
+
el.style.viewTransitionName = inView(el) ? id : kept.get(el);
|
|
146
|
+
if (!after) from.set(id, el.parentElement);
|
|
147
|
+
else if (from.has(id) && from.get(id) !== el.parentElement) raised.push(id);
|
|
148
|
+
});
|
|
149
|
+
name(false);
|
|
150
|
+
const t = document.startViewTransition(async () => { await update(); name(true); });
|
|
151
|
+
t.ready.then(() => {
|
|
152
|
+
const s = getComputedStyle(document.documentElement), timing = { duration: parseFloat(s.getPropertyValue('--ws-spring-reorder-duration')), easing: s.getPropertyValue('--ws-spring-reorder').trim() };
|
|
153
|
+
for (const a of document.getAnimations()) {
|
|
154
|
+
const p = a.effect && a.effect.pseudoElement;
|
|
155
|
+
if (p && p.startsWith('::view-transition-group(') && p !== '::view-transition-group(root)') a.effect.updateTiming(timing);
|
|
156
|
+
}
|
|
157
|
+
for (const id of raised) document.documentElement.animate({ zIndex: [1, 1] }, { duration: timing.duration, pseudoElement: `::view-transition-group(${id})` });
|
|
158
|
+
}, () => {});
|
|
159
|
+
const restore = () => kept.forEach((v, el) => { el.style.viewTransitionName = v; });
|
|
160
|
+
t.finished.then(restore, restore);
|
|
161
|
+
return t.updateCallbackDone;
|
|
162
|
+
}
|
|
163
|
+
document.getElementById('kb-move').addEventListener('click', (e) => {
|
|
164
|
+
const card = e.target.closest('.ws-kanban-board__card');
|
|
165
|
+
if (!card) return;
|
|
166
|
+
e.preventDefault();
|
|
167
|
+
const board = e.currentTarget, cols = [...board.querySelectorAll('.ws-kanban-board__column')];
|
|
168
|
+
const to = cols[(cols.indexOf(card.closest('.ws-kanban-board__column')) + 1) % cols.length];
|
|
169
|
+
reorder(() => {
|
|
170
|
+
to.append(card);
|
|
171
|
+
for (const c of cols) {
|
|
172
|
+
const n = c.querySelectorAll('.ws-kanban-board__card').length;
|
|
173
|
+
c.querySelector('.ws-kanban-board__count').textContent = n;
|
|
174
|
+
let empty = c.querySelector('.ws-kanban-board__empty');
|
|
175
|
+
if (n && empty) empty.remove();
|
|
176
|
+
if (!n && !empty) { empty = document.createElement('p'); empty.className = 'ws-kanban-board__empty'; empty.textContent = 'Nobody here yet'; c.append(empty); }
|
|
177
|
+
}
|
|
178
|
+
}, board);
|
|
179
|
+
});
|
|
180
|
+
</script>
|
|
65
181
|
</body>
|
|
66
182
|
</html>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/* ---- KanbanBoard: stages as equal 280 px columns on the sunk plate; the board scrolls sideways inside itself, a stage
|
|
2
|
+
at a time on touch, the next stage peeking in; --fill makes it the page's remaining height with each column scrolling,
|
|
3
|
+
so the sideways bar sits at the foot of the window (K16) ---- */
|
|
4
|
+
/* 4 px of room on every side (pulled back by the margin) so a focused card's 2 px ring, 2 px out, is never clipped. */
|
|
5
|
+
.ws-kanban-board { --ws-kanban-board-ground: var(--ws-surface-sunk); display: flex; align-items: flex-start; gap: var(--space-sm); max-width: 100%; overflow-x: auto; padding: var(--space-xxs); margin: calc(var(--space-xxs) * -1); scroll-snap-type: x proximity; scroll-padding-inline: var(--space-xxs); overscroll-behavior-x: contain; scrollbar-width: thin; }
|
|
6
|
+
.ws-kanban-board:focus-visible { outline-offset: calc(var(--ws-focus-width) * -1); }
|
|
7
|
+
.ws-kanban-board__column { flex: 0 0 auto; width: min(calc(var(--space-9xl) + var(--space-5xl)), calc(100% - var(--space-2xl))); display: flex; flex-direction: column; gap: var(--space-xs); padding: var(--space-xs); border-radius: var(--ws-radius-card); background: var(--ws-kanban-board-ground); scroll-snap-align: start; transition: background-color var(--ws-duration-hover) var(--ws-ease-soft); }
|
|
8
|
+
/* In dark the sunk cream is lighter than a card, so the cards would read as holes: the column takes the well, darker
|
|
9
|
+
than the cards, as a well behind rows does. */
|
|
10
|
+
[data-theme="dark"] .ws-kanban-board { --ws-kanban-board-ground: var(--ws-well); }
|
|
11
|
+
@media (prefers-color-scheme: dark) { [data-theme="system"] .ws-kanban-board { --ws-kanban-board-ground: var(--ws-well); } }
|
|
12
|
+
/* The column a dragged card is over: one step darker, nothing moves. In dark that step is lighter than a card (the
|
|
13
|
+
holes again), so the column keeps the well and takes the card edge round it, as a drop zone marks its edge. */
|
|
14
|
+
.ws-kanban-board__column--over { --ws-kanban-board-ground: var(--ws-surface-press); background: var(--ws-kanban-board-ground); }
|
|
15
|
+
[data-theme="dark"] .ws-kanban-board__column--over { --ws-kanban-board-ground: var(--ws-well); box-shadow: inset 0 0 0 var(--ws-line) var(--ws-edge-card); }
|
|
16
|
+
@media (prefers-color-scheme: dark) { [data-theme="system"] .ws-kanban-board__column--over { --ws-kanban-board-ground: var(--ws-well); box-shadow: inset 0 0 0 var(--ws-line) var(--ws-edge-card); } }
|
|
17
|
+
/* Head: the stage in 13 / 18 medium navy, its count muted beside it (sentence case, D6), flush with the cards. */
|
|
18
|
+
.ws-kanban-board__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-xs); min-height: var(--ws-control-h); }
|
|
19
|
+
.ws-kanban-board__title { display: flex; align-items: baseline; gap: var(--space-xs); min-width: 0; font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; color: var(--color-text-heading); }
|
|
20
|
+
.ws-kanban-board__count { font-weight: 500; color: var(--color-text-muted); font-variant-numeric: tabular-nums; }
|
|
21
|
+
/* A card is a ws-card (a link or a button when it opens the thing); two classes, so it stays a column as a link too. */
|
|
22
|
+
.ws-kanban-board__column > .ws-kanban-board__card { display: flex; flex-direction: column; gap: var(--space-xxs); padding: var(--ws-card-padding); }
|
|
23
|
+
/* Hover and press: North's wash over the card's cream. The card's own hover, the sunk cream, is the column's ground, so
|
|
24
|
+
the card would sink into it. */
|
|
25
|
+
.ws-kanban-board__column > .ws-kanban-board__card:is(:hover, :active) { background-color: var(--color-bg-page); }
|
|
26
|
+
@media (hover: hover) { .ws-kanban-board__column > .ws-kanban-board__card:hover { background-image: linear-gradient(var(--ws-hover), var(--ws-hover)); } }
|
|
27
|
+
.ws-kanban-board__column > .ws-kanban-board__card:active { background-image: linear-gradient(var(--ws-hover-strong), var(--ws-hover-strong)); }
|
|
28
|
+
/* A held card floats: North's floating shadow (it carries the dark rim), a slight tilt. */
|
|
29
|
+
.ws-kanban-board__card--dragging { box-shadow: var(--ws-shadow-pop); transform: rotate(-1deg); }
|
|
30
|
+
.ws-kanban-board__who { display: flex; align-items: center; gap: var(--space-xs); min-width: 0; }
|
|
31
|
+
.ws-kanban-board__meta { font-size: var(--ws-text-control); line-height: var(--ws-leading-control); color: var(--color-text-muted); }
|
|
32
|
+
.ws-kanban-board__empty { padding: var(--space-md) var(--space-xs); text-align: center; font-size: var(--ws-text-control); line-height: var(--ws-leading-control); color: var(--color-text-muted); }
|
|
33
|
+
/* Loading: a ghost the height of a card, in the chart colours' sweep (add ws-shimmer). */
|
|
34
|
+
.ws-kanban-board__ghost { display: block; height: calc(var(--ws-card-padding) * 2 + var(--ws-control-h-sm) + var(--space-xxs) + var(--ws-leading-control)); border-radius: var(--ws-radius-card); background: var(--ws-track); }
|
|
35
|
+
.ws-kanban-board__ghost.ws-shimmer { background: var(--ws-shimmer); background-size: 300% 100%; }
|
|
36
|
+
/* A board page (K16): the board takes the rest of a height-bound column (the shell's body, a fill page), every column
|
|
37
|
+
runs its full height and scrolls on its own with its head stuck, so the sideways bar is always on screen. */
|
|
38
|
+
.ws-kanban-board--fill { flex: 1; min-height: 0; align-items: stretch; }
|
|
39
|
+
.ws-kanban-board--fill .ws-kanban-board__column { min-height: 0; overflow-y: auto; overscroll-behavior-y: contain; scrollbar-width: thin; scroll-padding-block: calc(var(--ws-control-h) + var(--space-xs) + var(--space-xxs)) var(--space-xxs); }
|
|
40
|
+
/* The stuck head covers the column's 8 px padding too (its top 8 is that padding, so the title sits where the plain
|
|
41
|
+
board's does); sticky edges are measured inside the padding, so it sticks 8 above it, and no card shows over it. */
|
|
42
|
+
.ws-kanban-board--fill .ws-kanban-board__head { position: sticky; top: calc(var(--space-xs) * -1); z-index: 1; min-height: calc(var(--ws-control-h) + var(--space-xs)); margin: calc(var(--space-xs) * -1) calc(var(--space-xs) * -1) 0; padding: var(--space-xs) var(--space-xs) 0; background: inherit; }
|
|
43
|
+
/* The far edge fades while stages are hidden past it, and the fade lifts at the end (a scroll-driven fade). */
|
|
44
|
+
@supports (animation-timeline: scroll()) {
|
|
45
|
+
.ws-kanban-board { mask-image: linear-gradient(to left, transparent, var(--ws-mask) var(--space-lg)); mask-size: calc(100% + var(--space-lg)) 100%; mask-repeat: no-repeat; animation: ws-kanban-board-end linear both; animation-timeline: scroll(self inline); animation-range: calc(100% - var(--space-lg)) 100%; }
|
|
46
|
+
/* The fade would wash out the focus ring's far side: a focused board drops it, the ring saying it scrolls. */
|
|
47
|
+
.ws-kanban-board:focus-visible { mask-image: none; }
|
|
48
|
+
/* A --fill column that holds more than it shows says so, as ListDetail's list does: its last 24 px fade into the
|
|
49
|
+
column's ground while cards are hidden below, lifting at the end. A column that fits shows none (no scroll, no fade). */
|
|
50
|
+
.ws-kanban-board--fill .ws-kanban-board__column::after { content: ""; position: sticky; bottom: calc(var(--space-xs) * -1); flex: none; height: var(--space-lg); margin: calc((var(--space-lg) + var(--space-xs)) * -1) calc(var(--space-xs) * -1) 0; background: linear-gradient(to bottom, transparent, var(--ws-kanban-board-ground)); opacity: 0; pointer-events: none; animation: ws-kanban-board-more linear both; animation-timeline: scroll(nearest block); animation-range: calc(100% - var(--space-lg)) 100%; }
|
|
51
|
+
}
|
|
52
|
+
@keyframes ws-kanban-board-end { from { mask-position: calc(var(--space-lg) * -1) 0; } to { mask-position: 0 0; } }
|
|
53
|
+
@keyframes ws-kanban-board-more { from { opacity: 1; } to { opacity: 0; } }
|
|
@@ -14,11 +14,12 @@ A key as it is printed on the keyboard ("Esc", "Enter", "⌘K"), shown beside th
|
|
|
14
14
|
|
|
15
15
|
## Anatomy
|
|
16
16
|
|
|
17
|
-
- Box:
|
|
18
|
-
|
|
19
|
-
- Ground: the
|
|
20
|
-
- Words:
|
|
21
|
-
browser draws `<kbd>` in a monospace face by default; the class puts it back in Instrument Sans.
|
|
17
|
+
- Box: 18 px tall (`--space-md` + `--space-3xs`) and at least as wide, 4 px sides (`--space-xxs`), 4 px corners
|
|
18
|
+
(`--ws-radius-control`), North's key cap.
|
|
19
|
+
- Ground: the surface (`--color-surface`, white) with the 0.5 px card edge (`--ws-edge-card`) drawn inside.
|
|
20
|
+
- Words: 11 px (`--ws-text-micro`) medium navy (`--color-text-heading`) in the house face (`--font-body`), even
|
|
21
|
+
numerals, one line. The browser draws `<kbd>` in a monospace face by default; the class puts it back in Instrument Sans.
|
|
22
|
+
- In a sentence it sits on the line's baseline.
|
|
22
23
|
|
|
23
24
|
## Variants and sizes
|
|
24
25
|
|
|
@@ -39,6 +40,7 @@ reference implementation draws it, not a row of separate caps.
|
|
|
39
40
|
until then the key is left out rather than shown as "Ctrl" and flipped to "⌘".
|
|
40
41
|
- **Empty:** a shortcut with no key is not listed.
|
|
41
42
|
- **Long label:** stays on one line and grows sideways; a sequence longer than two keys is a sign the shortcut is too long.
|
|
43
|
+
- **Dark:** the surface, the edge and the words take their dark values.
|
|
42
44
|
- **Narrow:** the cap never wraps; in a tight row the act's words truncate first.
|
|
43
45
|
- **Touch:** shown as it is, or left out on a screen with no keyboard; nothing depends on it.
|
|
44
46
|
|
|
@@ -62,8 +64,7 @@ reference implementation draws it, not a row of separate caps.
|
|
|
62
64
|
|
|
63
65
|
## Rules
|
|
64
66
|
|
|
65
|
-
- Tokens only;
|
|
66
|
-
`.ws-kbd-list__row` rows.
|
|
67
|
+
- Tokens only; a shortcut list is a `<dl class="ws-kbd-list">` of `.ws-kbd-list__row` rows, each at least 24 tall.
|
|
67
68
|
- One cap per shortcut, holding the whole label.
|
|
68
69
|
- A shortcut never replaces a visible control: it is a faster way to the same act.
|
|
69
70
|
- Single-key shortcuts never fire while someone types in a field or while a dialog is open over the page; a shortcut with
|
|
@@ -72,5 +73,20 @@ reference implementation draws it, not a row of separate caps.
|
|
|
72
73
|
## Source
|
|
73
74
|
|
|
74
75
|
**Precedent**: the first product built on the system (`Kbd` in its workspace shortcuts: the "?" list, the command
|
|
75
|
-
palette's Enter and Esc, and a coach view's help line). **Derived from**:
|
|
76
|
-
|
|
76
|
+
palette's Enter and Esc, and a coach view's help line). **Derived from**: Seth's North key cap (style1.css:601: 18 tall,
|
|
77
|
+
4 px corners, a 0.5 px edge, white, 11 / 500 navy), which replaces the 0.4.0 pill (1 px edge, sunk ground, 12 / 600).
|
|
78
|
+
North's 5 px sides snap to the 4 step.
|
|
79
|
+
|
|
80
|
+
## Markup
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<p class="ws-body">Press <kbd class="ws-kbd">?</kbd> anywhere to see every shortcut.</p>
|
|
84
|
+
<dl class="ws-kbd-list ws-body">
|
|
85
|
+
<div class="ws-kbd-list__row"><dt>Open the command palette</dt><dd><kbd class="ws-kbd">⌘K</kbd></dd></div>
|
|
86
|
+
<div class="ws-kbd-list__row"><dt>Go to the pipeline</dt><dd><kbd class="ws-kbd">G then P</kbd></dd></div>
|
|
87
|
+
</dl>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Styles
|
|
91
|
+
|
|
92
|
+
`design-system/components/Kbd/style.css`: `ws-kbd`, `ws-kbd-list` and `__row`. It restates the house's `.ws-kbd`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Navigation" height=
|
|
1
|
+
<!-- @dsCard group="Navigation" height=250 -->
|
|
2
2
|
<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
@@ -11,18 +11,22 @@
|
|
|
11
11
|
<div class="ws-stage ws-stage--column">
|
|
12
12
|
|
|
13
13
|
<div class="ws-stack">
|
|
14
|
-
<span class="ws-muted">Keys as printed: one key, a modifier, a sequence</span>
|
|
14
|
+
<span class="ws-muted">Keys as printed: one key, a modifier, a sequence, each one cap (18 px, 11 px medium navy)</span>
|
|
15
15
|
<div class="ws-cluster ws-cluster--loose">
|
|
16
16
|
<kbd class="ws-kbd">Esc</kbd>
|
|
17
17
|
<kbd class="ws-kbd">Enter</kbd>
|
|
18
18
|
<kbd class="ws-kbd">S</kbd>
|
|
19
19
|
<kbd class="ws-kbd">←</kbd>
|
|
20
|
+
</div>
|
|
21
|
+
<div class="ws-cluster ws-cluster--loose">
|
|
20
22
|
<kbd class="ws-kbd">⌘K</kbd>
|
|
21
23
|
<kbd class="ws-kbd">Ctrl K</kbd>
|
|
22
24
|
<kbd class="ws-kbd">G then P</kbd>
|
|
23
25
|
</div>
|
|
24
26
|
</div>
|
|
25
27
|
|
|
28
|
+
<p class="ws-body">Press <kbd class="ws-kbd">?</kbd> anywhere to see every shortcut.</p>
|
|
29
|
+
|
|
26
30
|
<div class="ws-stack" style="max-width: 320px;">
|
|
27
31
|
<span class="ws-eyebrow">Anywhere</span>
|
|
28
32
|
<dl class="ws-kbd-list ws-body">
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/* ---- Kbd: a key as printed, North's (0.5.0, D1; style1.css:601): 18 px tall and at least as wide, 4 px corners, the
|
|
2
|
+
surface with the 0.5 px card edge drawn inside, 11 px medium navy in the house face (a <kbd> is monospace by default).
|
|
3
|
+
Restates the house's Kbd, so that copy can go. ---- */
|
|
4
|
+
.ws-kbd { display: inline-flex; align-items: center; justify-content: center; min-width: calc(var(--space-md) + var(--space-3xs)); height: calc(var(--space-md) + var(--space-3xs)); padding: 0 var(--space-xxs); border: 0; border-radius: var(--ws-radius-control); background: var(--color-surface); box-shadow: var(--ws-shadow-hairline-in); color: var(--color-text-heading); font-family: var(--font-body); font-size: var(--ws-text-micro); line-height: var(--ws-leading-micro); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
5
|
+
/* A shortcut list: each act at the left and its keys at the right. */
|
|
6
|
+
.ws-kbd-list { display: flex; flex-direction: column; gap: var(--space-xxs); margin: 0; }
|
|
7
|
+
.ws-kbd-list__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); min-height: var(--space-lg); }
|
|
8
|
+
.ws-kbd-list dt { min-width: 0; }
|
|
9
|
+
.ws-kbd-list dd { flex-shrink: 0; margin: 0; }
|
|
@@ -19,90 +19,124 @@ The kit's one button: a click that sells, in one of five themes, for a landing p
|
|
|
19
19
|
|
|
20
20
|
## Anatomy
|
|
21
21
|
|
|
22
|
-
- Box: `--radius-
|
|
22
|
+
- Box: `--ws-radius-card` (8px) corners at large and medium, `--ws-radius-row` (6px) at small. Buttons stay at 8px while
|
|
23
23
|
the kit's cards cap at 4px: two different ceilings, both decided on purpose.
|
|
24
|
-
- Height: 45px large, 36px medium, 28px small.
|
|
25
|
-
|
|
26
|
-
- Words:
|
|
27
|
-
- Sides: 20px large, 16px (`--space-md`) medium, 12px small. `clean` has none.
|
|
28
|
-
-
|
|
29
|
-
-
|
|
24
|
+
- Height: 45px large, 36px medium, 28px small. These are floors (`min-height`), so a label too long for its column
|
|
25
|
+
wraps to a second, balanced line and the button grows with it.
|
|
26
|
+
- Words: 16/20 semibold at large, 14/18 semibold at medium, 12/16 medium at small (`--font-size-md`, `-sm`, `-2xs`).
|
|
27
|
+
- Sides: 20px large, 16px (`--space-md`) medium, 12px (`--space-sm`) small. `clean` has none.
|
|
28
|
+
- Top and bottom room for a wrapped label: 8px large, 6px medium, 4px small. On one line the height floor wins.
|
|
29
|
+
- Icon: 16px (`--ws-icon`) at large and medium, 12px (`--ws-icon-sm`) at small, `--space-xs` (8px) from the words.
|
|
30
|
+
- The lift: `primary` and `navy` carry a 3px bottom border. The words centre on the face above it.
|
|
30
31
|
|
|
31
32
|
## Variants and sizes
|
|
32
33
|
|
|
33
|
-
| Variant | Fill | Words | Edge | Where |
|
|
34
|
-
| --- | --- | --- | --- | --- |
|
|
35
|
-
| `primary` | the salmon gradient
|
|
36
|
-
| `secondary` | `--color-
|
|
37
|
-
| `navy` | a
|
|
38
|
-
| `tertiary` | transparent | `--color-
|
|
39
|
-
| `clean` | transparent, no padding | `--color-
|
|
34
|
+
| Variant | Fill | Words | Edge | Hover | Where |
|
|
35
|
+
| --- | --- | --- | --- | --- | --- |
|
|
36
|
+
| `primary` | the salmon gradient (`--gradient-btn-primary`) | white, in every theme (2.44 to 2.65:1: the one logged exception to D2, Amit 4 Nov 2026) | 3px `--color-button-border` lift | 4% brighter | the page's one conversion act |
|
|
37
|
+
| `secondary` | `--color-bg-page` (the page cream) | `--color-text-interactive` (mid blue) | 1px `--color-border-hairline` | the `--color-nav-hover-bg` tint over the cream | a second act beside primary |
|
|
38
|
+
| `navy` | a mid blue to navy gradient, `--shadow-btn` | white (6.98:1) | 3px `--color-brand-navy` lift | 4% brighter, and the shadow deepens to `--shadow-btn-hover` | a second strong CTA, e.g. "Start free trial" beside "Book a demo" |
|
|
39
|
+
| `tertiary` | transparent | `--color-text-heading` | 1px `--color-text-heading` | fills with the heading colour, words in `--ws-on-act` | an outlined act; placeholder per-state colours (see Rules) |
|
|
40
|
+
| `clean` | transparent, no side padding | `--color-text-heading` | none | underlines | a plain act inside a sentence or a footnote |
|
|
40
41
|
|
|
41
|
-
Sizes: `small` (28px), `medium` (36px), `large` (45px, the default
|
|
42
|
+
Sizes: `small` (28px), `medium` (36px), `large` (45px, the default). `--shadow` adds `--shadow-btn` under any variant
|
|
43
|
+
and deepens it on hover. `--full` stretches the button to its container.
|
|
44
|
+
|
|
45
|
+
Classes: `ws-kit-button` plus one size (`ws-kit-button--large`, `--medium`, `--small`) and one variant
|
|
46
|
+
(`ws-kit-button--primary`, `--secondary`, `--navy`, `--tertiary`, `--clean`); `ws-kit-button--shadow` and
|
|
47
|
+
`ws-kit-button--full` go on top of any of them. The CSS has no default size or variant, so name both.
|
|
42
48
|
|
|
43
49
|
## States
|
|
44
50
|
|
|
45
51
|
- **Default:** as the table above.
|
|
46
|
-
- **Hover:**
|
|
47
|
-
`
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- **
|
|
53
|
-
|
|
54
|
-
- **Disabled:** 50% opacity, no pointer events,
|
|
55
|
-
- **
|
|
56
|
-
- **Long label:**
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(28px) "miss the 44px tap target. Use Large for any mobile CTA or form submit."
|
|
52
|
+
- **Hover:** a colour change, never a lift: primary and navy brighten 4%, secondary tints, tertiary fills, clean
|
|
53
|
+
underlines. A button that already casts a shadow (navy, or `--shadow`) also deepens it; in dark that shadow does not
|
|
54
|
+
show, the brighter fill does. Only on a pointer that hovers (`@media (hover: hover)`), so a tap on a phone leaves nothing behind. `.is-hover` draws it in a static
|
|
55
|
+
preview on any device.
|
|
56
|
+
- **Focus:** the house ring on `:focus-visible`: 2px `--ws-focus-color` (navy; light in dark), 2px out. It shows on
|
|
57
|
+
the salmon fill and on the cream alike. `.is-focus` draws it in a static preview.
|
|
58
|
+
- **Pressed (the lift):** `primary` and `navy` drop 2px and their bottom border disappears, so the button physically
|
|
59
|
+
presses into the page (`:active`, or `.is-pressed`). Navy and `--shadow` lose their shadow while pressed.
|
|
60
|
+
- **Disabled:** 50% opacity, no pointer events, on `disabled` or `aria-disabled="true"`.
|
|
61
|
+
- **Selected / pending / error / empty:** not applicable.
|
|
62
|
+
- **Long label:** wraps to a second line, balanced (`text-wrap: balance`), centred; the button grows to fit. It never
|
|
63
|
+
runs out of its box or past the screen.
|
|
64
|
+
- **Touch:** every act on a public page is a 44px target (`--ws-touch-public`). Large is 45. Medium and small keep
|
|
65
|
+
their look and take a 44px hit area (an `::after` above and below) on a coarse pointer.
|
|
61
66
|
|
|
62
67
|
## Behaviour
|
|
63
68
|
|
|
64
|
-
- Keyboard: a real `<button
|
|
65
|
-
|
|
66
|
-
-
|
|
67
|
-
|
|
68
|
-
- Motion:
|
|
69
|
-
|
|
69
|
+
- Keyboard: a real `<button>` (or an `<a>` for a CTA that goes to a page); Enter or Space activates it; Tab order
|
|
70
|
+
follows the DOM.
|
|
71
|
+
- Pointer: hover changes the colour; `:active` presses primary and navy down 2px.
|
|
72
|
+
- Touch: medium and small grow their hit area to 44px; nothing about their look changes.
|
|
73
|
+
- Motion: colour, shadow, filter and the press move over 150ms ease-out (`--transition-fast`), only under
|
|
74
|
+
`prefers-reduced-motion: no-preference`. With reduced motion the state changes at once.
|
|
70
75
|
|
|
71
76
|
## Content
|
|
72
77
|
|
|
73
78
|
- Sentence case, an imperative verb ("Book a demo", "Start free trial"), never a question.
|
|
74
79
|
- No em dashes.
|
|
75
80
|
- One `primary` or `navy` CTA per section; everything else is `secondary`, `tertiary` or `clean`.
|
|
81
|
+
- Keep it short. A label that wraps is a fallback for a narrow column, not a style.
|
|
76
82
|
|
|
77
83
|
## Props
|
|
78
84
|
|
|
85
|
+
The React `Button` (`@felloinnovations/brand-kit`) renders this button with Tailwind utilities on the same tokens.
|
|
86
|
+
|
|
79
87
|
| Name | Type | Meaning |
|
|
80
88
|
| --- | --- | --- |
|
|
81
89
|
| `variant` | `'primary' \| 'secondary' \| 'navy' \| 'tertiary' \| 'clean'` | the theme, default `primary` |
|
|
82
|
-
| `size` | `'large' \| 'medium' \| 'small'` | the height, default `large` |
|
|
83
|
-
| `shadow` | `boolean` | adds `--shadow-btn` under `primary`, `secondary`, `navy` and `tertiary
|
|
90
|
+
| `size` | `'large' \| 'medium' \| 'small'` | the height floor, default `large` |
|
|
91
|
+
| `shadow` | `boolean` | adds `--shadow-btn` under `primary`, `secondary`, `navy` and `tertiary`, deeper on hover |
|
|
84
92
|
| `fullWidth` | `boolean` | stretches the button to its container |
|
|
85
93
|
| `leadingIcon` | `React.ReactNode` | rendered before the label |
|
|
86
94
|
| `trailingIcon` | `React.ReactNode` | rendered after the label |
|
|
87
95
|
| ...rest | native `<button>` props | passed through (`onClick`, `type`, `disabled`) |
|
|
88
96
|
|
|
97
|
+
`buttonVariants({ variant, size })` gives the same classes for an `<a>`.
|
|
98
|
+
|
|
89
99
|
## Rules
|
|
90
100
|
|
|
91
101
|
- The 3px bottom border on `primary` is "not decoration. It is the lift, and `:active` collapses it so the button
|
|
92
102
|
physically presses" (the kit's own doc comment on `buttonVariants`).
|
|
93
|
-
-
|
|
94
|
-
|
|
103
|
+
- **Every act on a public page is 44px** (`14-accessibility.md`, targets). Large is the only size whose box clears it;
|
|
104
|
+
medium and small clear it with their touch hit area. Use large for a phone's main act and set it `--full`.
|
|
105
|
+
- **Kit-owned corners** (4 Nov 2026): the corners read `--ws-radius-*`, not Tailwind's `--radius-*`. A shadcn host
|
|
106
|
+
derives `--radius-sm` to `--radius-lg` from its own `--radius` in `@layer theme`, which beats the kit, so in a
|
|
107
|
+
shadcn app a large button drew 10px corners. The `--ws-radius-*` lengths are the kit's alone.
|
|
108
|
+
- Focus is the house ring (D8, 4 Nov 2026). The old salmon halo (`--shadow-focus-ring` at 20%) was 1.21:1 on the
|
|
109
|
+
cream and is gone. Nothing here sets `outline: none`.
|
|
110
|
+
- Hover is a colour change (D7). The old `clean` hover turned the words salmon, 2.7:1 on white; it underlines now.
|
|
111
|
+
- **`clean` has no sides in React too** (4 Nov 2026): tailwind-merge dropped the variant's `px-0` and `min-w-0` for the
|
|
112
|
+
size's padding and width floor, so a React `clean` button had 20px sides and a 100px floor. They are a compound variant
|
|
113
|
+
now, as `.ws-kit-button--clean` draws it.
|
|
95
114
|
- `tertiary` and `clean` are flagged placeholders: "the design capture never drilled into per-state colours for
|
|
96
|
-
them" (`AGENTS.md`, provisional values
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
them" (`AGENTS.md`, provisional values).
|
|
116
|
+
- **Navy words on the salmon** (4 Nov 2026, D2, open to Amit's veto): white words on the gradient were 2.44 to
|
|
117
|
+
2.65:1, under AA for 16px semibold, at every size and in every theme. Brand navy on the same gradient is 4.79 to
|
|
118
|
+
5.21:1, the pair Ignite already ships and tests (`onAccent`). The fill is literal salmon in every theme, so the
|
|
119
|
+
words are literal `--color-brand-navy`, not the heading word, which turns light in dark.
|
|
120
|
+
- The product's `Button` is solid navy, flat, 4px corners, 36px large. The two stand side by side on purpose: this
|
|
121
|
+
one for a public page, the product's for everything inside a signed-in workspace.
|
|
101
122
|
|
|
102
123
|
## Source
|
|
103
124
|
|
|
104
125
|
- **Derived from**: the kit's own `buttonVariants` and `Button` (house rules and known gaps in `AGENTS.md`,
|
|
105
|
-
`tokens/tokens.md`),
|
|
106
|
-
`--gradient-btn-primary` and `--shadow-btn-hover` carry no token in this system.
|
|
126
|
+
`tokens/tokens.md`), the house focus ring (D8) and touch floors (`14-accessibility.md`).
|
|
107
127
|
- **Precedent**: the first product built on the system, whose own `Button` stands apart from this one for every
|
|
108
128
|
signed-in screen.
|
|
129
|
+
|
|
130
|
+
## Markup
|
|
131
|
+
|
|
132
|
+
```html
|
|
133
|
+
<button class="ws-kit-button ws-kit-button--large ws-kit-button--primary">Book a demo</button>
|
|
134
|
+
<a class="ws-kit-button ws-kit-button--large ws-kit-button--secondary" href="/how-it-works">See how it works</a>
|
|
135
|
+
<button class="ws-kit-button ws-kit-button--small ws-kit-button--tertiary">Compare plans</button>
|
|
136
|
+
<button class="ws-kit-button ws-kit-button--medium ws-kit-button--navy">
|
|
137
|
+
Start free trial
|
|
138
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M5 11 11 5M5.5 5h5.5v5.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
139
|
+
</button>
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Styles: the `KitButton` block (`components/KitButton/style.css`), in `fello.css`. Nothing else.
|