@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
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
A card
|
|
2
|
-
holding its one act.
|
|
1
|
+
A card the agent brings into the chat (North's chat card: at most 556 px, 20 px inside, the 80 px tray): one kind or one
|
|
2
|
+
chart, one title, one sentence, its facts on a plate or a breakdown, and the tray holding its one act.
|
|
3
3
|
|
|
4
4
|
## Use it when
|
|
5
5
|
|
|
@@ -11,27 +11,39 @@ holding its one act.
|
|
|
11
11
|
|
|
12
12
|
- A simple fact already said in the words above it: say it once, in the chat's text or in the card, never both
|
|
13
13
|
(the system's rule).
|
|
14
|
-
- A
|
|
15
|
-
|
|
14
|
+
- A wide table or a long comparison: the chat card holds a chart and a short breakdown (North's chat chart card);
|
|
15
|
+
anything wider opens in the card's own full screen or the side panel, with "Open" left in the chat.
|
|
16
16
|
- A list of past suggestions: a card is for the one thing in front of the person now; Today's own list lives
|
|
17
17
|
beside the chat, not repeated here.
|
|
18
18
|
|
|
19
19
|
## Anatomy
|
|
20
20
|
|
|
21
|
-
- Shell: `ws-card`,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
-
|
|
28
|
-
|
|
29
|
-
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
- A
|
|
34
|
-
|
|
21
|
+
- Shell: `ws-card ws-chat-card`, at most 556 px (`--ws-chart-card-w`), 8 px corners, 20 px inside (`--ws-card-inset`),
|
|
22
|
+
its parts 8 px apart, flat. On the chat's glass it keeps North's 0.5 px card edge (`--ws-edge-card`), not the page's
|
|
23
|
+
tray rim. It measures itself (a size container), so a narrow chat gets the narrow tray.
|
|
24
|
+
- Head (`ws-chat-card__head`, 24 px tall at least, its parts spread): the kind (`ws-chat-card__kind`), a 24 px disc
|
|
25
|
+
(`ws-disc ws-chat-card__disc`) with a navy 12 px glyph, or salmon-tinted (`--needs`: `--ws-tint-needs` behind a `--ws-chart-under-half` glyph) while the
|
|
26
|
+
card waits on the person, and the kind next to it in the eyebrow style ("Suggestion", "Task", "Reminder").
|
|
27
|
+
- Title: `ws-section` (15 / 22 semibold navy) for a kind card; `ws-title` (22 / 28) for a chart answer. One sentence
|
|
28
|
+
under it, 14 / 20 in `--color-text-body`.
|
|
29
|
+
- Facts plate (`ws-plate ws-chat-card__facts`): `Plate` (14 / 16 inside), its facts side by side, 12 px words, 16
|
|
30
|
+
apart and 4 between lines, each name in semibold navy (`b`).
|
|
31
|
+
- A chart answer's drawing (`ws-chat-card__graph`): the dotted field runs to the card's edges and sits only behind the
|
|
32
|
+
drawing, 16 above and 24 under it.
|
|
33
|
+
- A breakdown (`ws-chat-card__rows`): rows edge to edge, 44 px tall, 0.5 px rules (`--ws-edge-slot`), the label 14 / 20
|
|
34
|
+
medium navy on the left, the figure semibold, tabular, at the right.
|
|
35
|
+
- The tray (`ws-band ws-chat-card__band`): the band across the card's foot, 80 px tall, 28 px sides, the darker cream
|
|
36
|
+
and its inset shade; the door on the left ("Open in the app", 24 px tall), the buttons in `ws-band__acts` at the
|
|
37
|
+
right, at `large` (36 px), every secondary first and the one navy primary last.
|
|
38
|
+
- Under 470 px (a narrow chat): the tray is 64 px, 12 / 20, its second line (`ws-band__how`) hides and the title steps
|
|
39
|
+
to 14 / 18 (it wraps, balanced, beside the acts); the acts stay on the title's line at their own width (North keeps
|
|
40
|
+
the docked card on one line) and drop under it together only when they cannot fit (a door and two buttons).
|
|
41
|
+
- A needs-you reminder adds a timer chip in the head (`ws-chat-card__timer`: a 12 px clock and the time left, 12 px
|
|
42
|
+
medium tabular navy on the sunk cream, 2 px corners) and a cross (`ws-icon-btn ws-icon-btn--sm ws-chat-card__close`,
|
|
43
|
+
a 40 px hit area on touch) in the top right corner, 8 px in, for "not now"; the head keeps 32 px clear of it, so the
|
|
44
|
+
timer ends 16 px short of the cross.
|
|
45
|
+
- 0.4 markup's act group, `ws-chat-card__acts`, still lays its buttons out at the band's end; new markup uses
|
|
46
|
+
`ws-band__acts`.
|
|
35
47
|
|
|
36
48
|
## Variants and sizes
|
|
37
49
|
|
|
@@ -46,8 +58,7 @@ holding its one act.
|
|
|
46
58
|
## States
|
|
47
59
|
|
|
48
60
|
- **Default**: the card as drawn above.
|
|
49
|
-
- **Waits on you**: the head's disc is salmon-tinted
|
|
50
|
-
(`ws-shine-once`).
|
|
61
|
+
- **Waits on you**: the head's disc is salmon-tinted (`ws-chat-card__disc--needs`).
|
|
51
62
|
- **Pending**: the pressed button keeps its colour and shows a working dot; the other buttons step out of the way
|
|
52
63
|
while the tap is in flight.
|
|
53
64
|
- **Done**: the band's primary becomes a quiet Undo for as long as the act can still be taken back.
|
|
@@ -55,7 +66,10 @@ holding its one act.
|
|
|
55
66
|
- **Empty**: a card whose data does not exist is never drawn, not even as a placeholder shell.
|
|
56
67
|
- **Long title**: a question's title is never clamped (the yes it leads to is in it); other kinds clamp to two
|
|
57
68
|
lines.
|
|
58
|
-
- **
|
|
69
|
+
- **Loading**: a `StatusLine` on top says what the agent is doing, the drawing is a `Skeleton` ghost, the tray holds a
|
|
70
|
+
`LoadBar`; the card is `aria-busy`.
|
|
71
|
+
- **Narrow**: under 470 px the tray goes to 64 px with its acts beside the title; nothing truncates.
|
|
72
|
+
- **Dark**: the edge, the tray and the dots follow the theme.
|
|
59
73
|
|
|
60
74
|
## Behaviour
|
|
61
75
|
|
|
@@ -64,10 +78,20 @@ holding its one act.
|
|
|
64
78
|
"Not now" is the backend's own dismissal where one exists, kept in the browser otherwise, with 5 seconds to
|
|
65
79
|
undo.
|
|
66
80
|
- Pointer and touch: a tap on a button answers at once through the route handler, never a page navigation; the
|
|
67
|
-
band's controls sit at the 36 px large size,
|
|
81
|
+
band's controls sit at the 36 px large size, 40 px on touch (the house touch floor).
|
|
68
82
|
No side popups: a card acts in place.
|
|
69
|
-
- Motion:
|
|
70
|
-
|
|
83
|
+
- Motion: a card the app marks `ws-settle` as it arrives rises 6 px out of a 3 px blur on the card spring
|
|
84
|
+
(`--ws-spring-card`, .5 / .08, North's "Chart card arrives"); a chart draws over `--ws-duration-draw-chat`; a card lit
|
|
85
|
+
by a "waiting on you" jump gets a brief ring (`--ws-card-ring-lit`), not a float.
|
|
86
|
+
- Full screen (`ws-chat-card--full`, North's cc-full): the card over the page, the stage inset from the window's edges,
|
|
87
|
+
16 px corners and the float drop, scrolling on its own. Toggle it inside `morph(update, { as: 'full', el: card })`
|
|
88
|
+
(see `Morph`): it flies there and back as itself over `--ws-duration-morph` (.45 s) on `--ws-ease-morph`, 32 ms late,
|
|
89
|
+
its words never scaling (North's "Full screen: open / close"). morph() lifts it into the top layer while it is full,
|
|
90
|
+
so it covers the window from inside the chat's glass, AppShell's stage or any ancestor with a transform, filter,
|
|
91
|
+
`contain` or `will-change` (a bare `position: fixed` would fill only that ancestor). Its toggle lives in its head
|
|
92
|
+
("Full screen", then "Back"); Escape closes it as well; focus stays inside it and comes back to the toggle.
|
|
93
|
+
- Reduced motion: it is simply there, and the full screen simply opens and closes.
|
|
94
|
+
- The preview's last stack is live: Arrive and Full screen.
|
|
71
95
|
|
|
72
96
|
## Content
|
|
73
97
|
|
|
@@ -94,8 +118,8 @@ view.
|
|
|
94
118
|
|
|
95
119
|
## Rules
|
|
96
120
|
|
|
97
|
-
- **A card sits flat on the chat**:
|
|
98
|
-
|
|
121
|
+
- **A card sits flat on the chat**: the cream, North's 0.5 px edge, 8 px corners, 20 px inside, at most 556 px; no
|
|
122
|
+
float, a lit card gets its ring instead.
|
|
99
123
|
- **Its acts sit on the footer band, laid out as a card's band (`ws-band`, see `Card`)** (26 Oct 2026): the door on the left, the buttons on
|
|
100
124
|
the right, the one primary navy and last, every other button cream with the fine edge.
|
|
101
125
|
- **Each needs-you card carries a timer and a cross** that means "not now", never a delete, with 5 seconds to
|
|
@@ -106,6 +130,68 @@ view.
|
|
|
106
130
|
|
|
107
131
|
## Source
|
|
108
132
|
|
|
109
|
-
**Derived from**:
|
|
110
|
-
|
|
111
|
-
first product built on the system.
|
|
133
|
+
**Derived from**: North's chat chart card (Figma 733:325166 "card 556 · inset 20 · tray 80"; style1.css:688-733,
|
|
134
|
+
:1154-1190, :2001-2004), the system's footer band for a door plus buttons, and the needs-you timer-and-cross pattern.
|
|
135
|
+
**Precedent**: the first product built on the system.
|
|
136
|
+
|
|
137
|
+
## Markup
|
|
138
|
+
|
|
139
|
+
```html
|
|
140
|
+
<div class="ws-card ws-chat-card">
|
|
141
|
+
<p class="ws-title">Calls this week, by agent</p>
|
|
142
|
+
<p class="ws-body">Sam is three behind the team.</p>
|
|
143
|
+
<div class="ws-chat-card__graph ws-dots" aria-hidden="true"><!-- the drawing --></div>
|
|
144
|
+
<ul class="ws-chat-card__rows" aria-label="Calls this week">
|
|
145
|
+
<li class="ws-chat-card__row"><span>Dana Okafor</span><b>12</b></li>
|
|
146
|
+
</ul>
|
|
147
|
+
<div class="ws-band ws-chat-card__band">
|
|
148
|
+
<a class="ws-chat-card__door" href="/team">Open in the app</a>
|
|
149
|
+
<div class="ws-band__acts">
|
|
150
|
+
<button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Not now</button>
|
|
151
|
+
<button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Line them up</button>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<!-- A chart answer that opens full screen: the toggle in its head, run through morph() (see Morph) -->
|
|
157
|
+
<div class="ws-card ws-chat-card">
|
|
158
|
+
<div class="ws-chat-card__head">
|
|
159
|
+
<span class="ws-eyebrow">Chart</span>
|
|
160
|
+
<button type="button" class="ws-btn ws-btn--secondary">Full screen</button><!-- "Back" while full -->
|
|
161
|
+
</div>
|
|
162
|
+
<p class="ws-title">Calls this week, by agent</p>
|
|
163
|
+
<div class="ws-chat-card__graph ws-dots" aria-hidden="true"><!-- the drawing --></div>
|
|
164
|
+
</div>
|
|
165
|
+
|
|
166
|
+
<!-- A needs-you reminder: the cross in the corner, the kind and the timer in the head -->
|
|
167
|
+
<div class="ws-card ws-chat-card">
|
|
168
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--sm ws-chat-card__close" aria-label="Not now: Call Priya back before her offer expires" title="Not now">
|
|
169
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
170
|
+
</button>
|
|
171
|
+
<div class="ws-chat-card__head">
|
|
172
|
+
<span class="ws-chat-card__kind">
|
|
173
|
+
<span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none"><!-- a bell --></svg></span>
|
|
174
|
+
<span class="ws-eyebrow">Reminder</span>
|
|
175
|
+
</span>
|
|
176
|
+
<span class="ws-chat-card__timer" title="2 hours left">
|
|
177
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3l2 1.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
178
|
+
2h left
|
|
179
|
+
</span>
|
|
180
|
+
</div>
|
|
181
|
+
<p class="ws-section">Call Priya back before her offer expires</p>
|
|
182
|
+
<p class="ws-body">She asked for a decision by end of day.</p>
|
|
183
|
+
<div class="ws-plate ws-chat-card__facts">
|
|
184
|
+
<span><b>Priya</b> · offer on Oak Street</span>
|
|
185
|
+
</div>
|
|
186
|
+
<div class="ws-band ws-chat-card__band">
|
|
187
|
+
<a class="ws-chat-card__door" href="/leads/priya">Open in the app</a>
|
|
188
|
+
<div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Mark done</button></div>
|
|
189
|
+
</div>
|
|
190
|
+
</div>
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Styles
|
|
194
|
+
|
|
195
|
+
`ChatCard/style.css`; the band and its acts are `Card`'s, the plate `Plate`'s. Tokens: `--ws-chart-card-w`,
|
|
196
|
+
`--ws-card-inset`, `--ws-edge-card`, `--ws-edge-card-1x`, `--ws-edge-slot`, `--ws-radius-card-inner`, `--ws-tint-needs`,
|
|
197
|
+
`--ws-surface-sunk`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Chat" height=
|
|
1
|
+
<!-- @dsCard group="Chat" height=1217 -->
|
|
2
2
|
<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
@@ -8,12 +8,11 @@
|
|
|
8
8
|
<link rel="stylesheet" href="../bundle.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
|
-
<div class="ws-stage" style="
|
|
12
|
-
<div class="ws-stack ws-stack--group" style="width: var(--ws-
|
|
13
|
-
|
|
11
|
+
<div class="ws-stage" style="background: var(--ws-frame);">
|
|
12
|
+
<div class="ws-stack ws-stack--group" style="width: var(--ws-chart-card-w);">
|
|
14
13
|
<div class="ws-stack">
|
|
15
14
|
<span class="ws-muted">Suggestion: a door on the left, Not now then the one navy act</span>
|
|
16
|
-
<div class="ws-card ws-chat-card ws-
|
|
15
|
+
<div class="ws-card ws-chat-card ws-settle">
|
|
17
16
|
<div class="ws-chat-card__head">
|
|
18
17
|
<span class="ws-chat-card__kind">
|
|
19
18
|
<span class="ws-disc ws-chat-card__disc" aria-hidden="true">
|
|
@@ -31,49 +30,167 @@
|
|
|
31
30
|
<div class="ws-band ws-chat-card__band">
|
|
32
31
|
<a class="ws-chat-card__door" href="#" onclick="return false;">
|
|
33
32
|
Open in the app
|
|
34
|
-
<svg viewBox="0 0 16 16" fill="none"><path d="M4 12l8-8M7 4h5v5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
33
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 12l8-8M7 4h5v5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
35
34
|
</a>
|
|
36
|
-
<
|
|
35
|
+
<div class="ws-band__acts">
|
|
37
36
|
<button type="button" class="ws-btn ws-btn--secondary ws-btn--lg">Not now</button>
|
|
38
37
|
<button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Send the nudge</button>
|
|
39
|
-
</
|
|
38
|
+
</div>
|
|
40
39
|
</div>
|
|
41
40
|
</div>
|
|
42
41
|
</div>
|
|
43
42
|
|
|
44
43
|
<div class="ws-stack">
|
|
45
|
-
<span class="ws-muted">
|
|
46
|
-
<div class="ws-card ws-chat-card
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
</span>
|
|
57
|
-
<span class="ws-chat-card__timer" title="2 hours left">
|
|
58
|
-
<svg viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3l2 1.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
59
|
-
2h left
|
|
60
|
-
</span>
|
|
44
|
+
<span class="ws-muted">A chart answer: the dots only behind the drawing, a breakdown edge to edge, the tray</span>
|
|
45
|
+
<div class="ws-card ws-chat-card">
|
|
46
|
+
<p class="ws-title">Calls this week, by agent</p>
|
|
47
|
+
<p class="ws-body">Sam is three behind the team; Dana is on pace.</p>
|
|
48
|
+
<div class="ws-chat-card__graph ws-dots" aria-hidden="true">
|
|
49
|
+
<div class="ws-card__bars">
|
|
50
|
+
<div class="ws-card__bar" style="height: 80%;"></div>
|
|
51
|
+
<div class="ws-card__bar" style="height: 55%;"></div>
|
|
52
|
+
<div class="ws-card__bar" style="height: 30%;"></div>
|
|
53
|
+
<div class="ws-card__bar" style="height: 65%;"></div>
|
|
54
|
+
</div>
|
|
61
55
|
</div>
|
|
62
|
-
<
|
|
63
|
-
|
|
56
|
+
<ul class="ws-chat-card__rows" aria-label="Calls this week">
|
|
57
|
+
<li class="ws-chat-card__row"><span>Dana Okafor</span><b>12</b></li>
|
|
58
|
+
<li class="ws-chat-card__row"><span>Priya Nair</span><b>9</b></li>
|
|
59
|
+
<li class="ws-chat-card__row"><span>Sam Rivera</span><b>4</b></li>
|
|
60
|
+
</ul>
|
|
64
61
|
<div class="ws-band ws-chat-card__band">
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
</
|
|
69
|
-
<
|
|
70
|
-
|
|
62
|
+
<div class="ws-band__words">
|
|
63
|
+
<p class="ws-band__title">Get Sam one more call</p>
|
|
64
|
+
<p class="ws-band__how">Coach lines up his next three</p>
|
|
65
|
+
</div>
|
|
66
|
+
<div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Line them up</button></div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="ws-stack">
|
|
72
|
+
<span class="ws-muted">Loading: what it is doing on top, a ghost drawing, the load bar in the tray</span>
|
|
73
|
+
<div class="ws-card ws-chat-card" aria-busy="true">
|
|
74
|
+
<p class="ws-status-line" role="status" title="Coach: building the chart, step 2 of 3">
|
|
75
|
+
<b class="ws-status-line__who">Coach</b>
|
|
76
|
+
<span class="ws-status-line__doing">Building the chart</span>
|
|
77
|
+
<span class="ws-status-line__step">2 of 3</span>
|
|
78
|
+
</p>
|
|
79
|
+
<div class="ws-skeleton ws-skeleton--title" style="width: 55%;" aria-hidden="true"></div>
|
|
80
|
+
<div class="ws-skeleton__chart" aria-hidden="true">
|
|
81
|
+
<i style="height: 70%;"></i><i style="height: 45%;"></i><i style="height: 25%;"></i><i style="height: 60%;"></i>
|
|
82
|
+
</div>
|
|
83
|
+
<div class="ws-band ws-chat-card__band">
|
|
84
|
+
<div class="ws-load-bar" style="flex: 1;">
|
|
85
|
+
<p class="ws-load-bar__words"><span class="ws-load-bar__dot" aria-hidden="true"></span>Reading this week’s calls</p>
|
|
86
|
+
<span class="ws-load-bar__track" role="progressbar" aria-label="Reading this week's calls"><span class="ws-load-bar__fill"></span></span>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
</div>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div class="ws-stack" style="width: 400px;">
|
|
94
|
+
<span class="ws-muted">Needs-you reminder in a narrow chat: a timer, a cross for not now; the tray goes to 64</span>
|
|
95
|
+
<div class="ws-card ws-chat-card">
|
|
96
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--sm ws-chat-card__close" aria-label="Not now: Call Priya back before her offer expires" title="Not now">
|
|
97
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
98
|
+
</button>
|
|
99
|
+
<div class="ws-chat-card__head">
|
|
100
|
+
<span class="ws-chat-card__kind">
|
|
101
|
+
<span class="ws-disc ws-chat-card__disc ws-chat-card__disc--needs" aria-hidden="true">
|
|
102
|
+
<svg viewBox="0 0 16 16" fill="none"><path d="M4.5 11.5V7.8a3.5 3.5 0 0 1 7 0v3.7l1 1.2h-9z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/><path d="M7 14a1.2 1.2 0 0 0 2 0" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/></svg>
|
|
71
103
|
</span>
|
|
104
|
+
<span class="ws-eyebrow">Reminder</span>
|
|
105
|
+
</span>
|
|
106
|
+
<span class="ws-chat-card__timer" title="2 hours left">
|
|
107
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="8" r="6" stroke="currentColor" stroke-width="1.5"/><path d="M8 5v3l2 1.2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
108
|
+
2h left
|
|
109
|
+
</span>
|
|
110
|
+
</div>
|
|
111
|
+
<p class="ws-section">Call Priya back before her offer expires</p>
|
|
112
|
+
<p class="ws-body">She asked for a decision by end of day. The last note on her file is three days old.</p>
|
|
113
|
+
<div class="ws-band ws-chat-card__band">
|
|
114
|
+
<div class="ws-band__words">
|
|
115
|
+
<p class="ws-band__title">Call her now</p>
|
|
116
|
+
<p class="ws-band__how">Her number is on file</p>
|
|
72
117
|
</div>
|
|
118
|
+
<div class="ws-band__acts"><button type="button" class="ws-btn ws-btn--primary ws-btn--lg">Mark done</button></div>
|
|
73
119
|
</div>
|
|
74
120
|
</div>
|
|
121
|
+
</div>
|
|
75
122
|
|
|
123
|
+
<div class="ws-stack" style="width: var(--ws-chart-card-w);" data-live>
|
|
124
|
+
<span class="ws-muted">Live: Arrive plays the card coming into the thread on the card spring (.5 / .08); Full screen in its head flies it to the window's full screen and back as itself on the morph curve (.45 s, Morph), lifted above the page; Back or Escape brings it home</span>
|
|
125
|
+
<div class="ws-cluster">
|
|
126
|
+
<button type="button" class="ws-btn ws-btn--secondary" id="cc-live-arrive">Arrive</button>
|
|
127
|
+
</div>
|
|
128
|
+
<div style="min-height: 260px;">
|
|
129
|
+
<div class="ws-card ws-chat-card ws-settle" id="cc-live">
|
|
130
|
+
<div class="ws-chat-card__head"><span class="ws-eyebrow">Chart</span><button type="button" class="ws-btn ws-btn--secondary" id="cc-live-full">Full screen</button></div>
|
|
131
|
+
<p class="ws-title">Calls this week, by agent</p>
|
|
132
|
+
<p class="ws-body">Sam is three behind the team; Dana is on pace.</p>
|
|
133
|
+
<ul class="ws-chat-card__rows" aria-label="Calls this week">
|
|
134
|
+
<li class="ws-chat-card__row"><span>Dana Okafor</span><b>12</b></li>
|
|
135
|
+
<li class="ws-chat-card__row"><span>Sam Rivera</span><b>4</b></li>
|
|
136
|
+
</ul>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
76
139
|
</div>
|
|
140
|
+
<script>
|
|
141
|
+
(() => {
|
|
142
|
+
// A copy of morph() from @felloinnovations/brand-kit (src/lib/motion.ts): a preview cannot import the package.
|
|
143
|
+
// `full` lifts the element into the top layer while it is fixed, so no ancestor (a transform, a filter, the glass,
|
|
144
|
+
// contain) can trap it; Escape runs the update again (a toggle) and focus comes back.
|
|
145
|
+
const morph = (() => {
|
|
146
|
+
const lifted = new WeakMap(), root = document.documentElement;
|
|
147
|
+
const FOCUSABLE = 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), summary, [tabindex]:not([tabindex="-1"])';
|
|
148
|
+
let last = 0;
|
|
149
|
+
const place = (el, close) => {
|
|
150
|
+
const was = lifted.get(el);
|
|
151
|
+
if (was) { lifted.delete(el); el.removeEventListener('keydown', was.onKey); if (el.matches(':popover-open')) el.hidePopover(); el.removeAttribute('popover'); delete el.dataset.wsLifted; }
|
|
152
|
+
if (getComputedStyle(el).position === 'fixed' && el.showPopover) {
|
|
153
|
+
const onKey = (e) => { if (e.key !== 'Escape' || e.defaultPrevented || el.querySelector(':popover-open, dialog[open]')) return; e.preventDefault(); morph(close, { as: 'full', el, close }); };
|
|
154
|
+
el.dataset.wsLifted = ''; el.popover = 'manual'; el.showPopover(); el.addEventListener('keydown', onKey);
|
|
155
|
+
lifted.set(el, { opener: was ? was.opener : document.activeElement, onKey });
|
|
156
|
+
if (!el.contains(document.activeElement)) { const to = el.querySelector('[autofocus]') || el.querySelector(FOCUSABLE) || el; if (to === el && !el.hasAttribute('tabindex')) el.tabIndex = -1; to.focus({ preventScroll: true }); }
|
|
157
|
+
} else if (was) { const o = was.opener, here = document.activeElement; if (o && o.isConnected && o !== here && (!here || here === document.body || el.contains(here))) o.focus({ preventScroll: true }); }
|
|
158
|
+
};
|
|
159
|
+
const morph = (update, { as = 'full', el, close } = {}) => {
|
|
160
|
+
const run = as === 'full' && el ? async () => { await update(); place(el, close || update); } : update;
|
|
161
|
+
if (!document.startViewTransition || matchMedia('(prefers-reduced-motion: reduce)').matches) return Promise.resolve(run()).then(() => {});
|
|
162
|
+
const id = ++last;
|
|
163
|
+
if (el) {
|
|
164
|
+
const s = getComputedStyle(el);
|
|
165
|
+
root.style.setProperty('--ws-morph-ground', s.backgroundColor);
|
|
166
|
+
root.style.setProperty('--ws-morph-radius', s.borderRadius);
|
|
167
|
+
root.style.setProperty('--ws-morph-backdrop', s.backdropFilter || 'none');
|
|
168
|
+
el.style.viewTransitionName = 'ws-morph';
|
|
169
|
+
}
|
|
170
|
+
root.dataset.wsMorph = as;
|
|
171
|
+
const move = document.startViewTransition(run);
|
|
172
|
+
move.ready.catch(() => {});
|
|
173
|
+
return move.finished.finally(() => {
|
|
174
|
+
if (el) el.style.viewTransitionName = '';
|
|
175
|
+
if (id !== last) return;
|
|
176
|
+
delete root.dataset.wsMorph;
|
|
177
|
+
for (const p of ['--ws-morph-ground', '--ws-morph-radius', '--ws-morph-backdrop']) root.style.removeProperty(p);
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
return morph;
|
|
181
|
+
})();
|
|
182
|
+
const card = document.getElementById('cc-live'), full = document.getElementById('cc-live-full');
|
|
183
|
+
document.getElementById('cc-live-arrive').addEventListener('click', () => {
|
|
184
|
+
card.classList.remove('ws-settle');
|
|
185
|
+
void card.offsetWidth;
|
|
186
|
+
card.classList.add('ws-settle');
|
|
187
|
+
});
|
|
188
|
+
full.addEventListener('click', () => morph(() => {
|
|
189
|
+
const on = card.classList.toggle('ws-chat-card--full');
|
|
190
|
+
full.textContent = on ? 'Back' : 'Full screen';
|
|
191
|
+
}, { as: 'full', el: card }));
|
|
192
|
+
})();
|
|
193
|
+
</script>
|
|
77
194
|
</div>
|
|
78
195
|
</body>
|
|
79
196
|
</html>
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* ---- ChatCard: a card the agent brings into the chat (North's chat card: at most 556, 20 inside, the 80 px tray): a door on the left of its band, its acts on the right ---- */
|
|
2
|
+
/* North's chat card keeps the 0.5 px card edge on the chat's glass (the page's tray rim is for page cards). It
|
|
3
|
+
measures itself, so a narrow chat gets the narrow band. */
|
|
4
|
+
.ws-chat-card { position: relative; container: ws-chat-card / inline-size; display: flex; flex-direction: column; gap: var(--space-xs); max-width: var(--ws-chart-card-w); padding: var(--ws-card-inset); border: var(--ws-hairline) solid var(--ws-edge-card); }
|
|
5
|
+
@media (max-resolution: 1.49dppx) { .ws-chat-card { border-color: var(--ws-edge-card-1x); } }
|
|
6
|
+
.ws-chat-card__head { display: flex; align-items: center; justify-content: space-between; gap: var(--space-xs); min-height: var(--space-lg); }
|
|
7
|
+
.ws-chat-card__kind { display: flex; align-items: center; gap: var(--space-xs); min-width: 0; }
|
|
8
|
+
.ws-chat-card__disc { width: var(--space-lg); height: var(--space-lg); }
|
|
9
|
+
.ws-chat-card__disc svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
10
|
+
.ws-chat-card__disc--needs { background: var(--ws-tint-needs); color: var(--ws-chart-under-half); }
|
|
11
|
+
.ws-chat-card__timer { display: inline-flex; align-items: center; gap: var(--space-xxs); padding: var(--space-xxs) var(--space-xs); border-radius: var(--ws-radius-chip); background: var(--ws-surface-sunk); color: var(--color-text-heading); font-size: var(--ws-text-dense); font-weight: 500; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
12
|
+
.ws-chat-card__timer svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
13
|
+
/* The close sits in the corner, 8 in; a head beside it keeps clear of it. */
|
|
14
|
+
.ws-chat-card > .ws-chat-card__close { position: absolute; top: var(--space-xs); right: var(--space-xs); color: var(--color-text-muted); }
|
|
15
|
+
.ws-chat-card:has(> .ws-chat-card__close) > .ws-chat-card__head { padding-right: var(--space-xl); }
|
|
16
|
+
.ws-chat-card__facts { display: flex; flex-wrap: wrap; gap: var(--space-xxs) var(--space-md); font-size: var(--ws-text-dense); color: var(--color-text-body); }
|
|
17
|
+
.ws-chat-card__facts b { font-weight: 600; color: var(--color-text-heading); }
|
|
18
|
+
/* A chart answer's drawing: the dotted field runs to the card's edges and sits only behind the drawing, 24 under it. */
|
|
19
|
+
.ws-chat-card__graph { margin: var(--space-xs) calc(var(--ws-card-inset) * -1) 0; padding: var(--space-md) var(--ws-card-inset) var(--space-lg); }
|
|
20
|
+
/* A breakdown under the answer: rows edge to edge, 44 tall, 0.5 px rules, the label left and the figure right. */
|
|
21
|
+
.ws-chat-card__rows { margin: 0 calc(var(--ws-card-inset) * -1); border-top: var(--ws-hairline) solid var(--ws-edge-slot); }
|
|
22
|
+
.ws-chat-card__row { display: flex; align-items: center; justify-content: space-between; gap: var(--space-sm); min-height: calc(var(--space-2xl) + var(--space-xxs)); padding: var(--space-xxs) var(--ws-card-inset); font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); font-weight: 500; color: var(--color-text-heading); }
|
|
23
|
+
.ws-chat-card__row + .ws-chat-card__row { border-top: var(--ws-hairline) solid var(--ws-edge-slot); }
|
|
24
|
+
.ws-chat-card__row > b { flex-shrink: 0; font-weight: 600; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
25
|
+
/* The tray (the band) runs edge to edge under the card's words, 80 tall at least. */
|
|
26
|
+
.ws-chat-card__band { margin: var(--space-xs) calc(var(--ws-card-inset) * -1) calc(var(--ws-card-inset) * -1); border-radius: 0 0 var(--ws-radius-card-inner) var(--ws-radius-card-inner); }
|
|
27
|
+
.ws-chat-card__door { display: inline-flex; align-items: center; gap: var(--space-xxs); min-height: var(--space-lg); margin-right: auto; font-size: var(--ws-text-body); font-weight: 500; color: var(--color-text-body); text-decoration: none; }
|
|
28
|
+
@media (hover: hover) { .ws-chat-card__door:hover { color: var(--color-text-heading); text-decoration: underline; } }
|
|
29
|
+
.ws-chat-card__door svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
30
|
+
.ws-chat-card__acts { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xs); margin-left: auto; }
|
|
31
|
+
/* A narrow chat (the card under 470): the tray goes to 64, 12 / 20, its second line hides and the title steps to
|
|
32
|
+
14 / 18. North keeps the docked card on one line, so the acts stay beside the title at their own width (the band's
|
|
33
|
+
share-the-line rule under 26rem made the tray 92 to 100 tall); they drop under it together only when they cannot fit. */
|
|
34
|
+
@container ws-chat-card (max-width: 470px) {
|
|
35
|
+
.ws-chat-card__band { min-height: var(--space-4xl); column-gap: var(--space-sm); padding: var(--space-sm) var(--ws-card-inset); }
|
|
36
|
+
.ws-chat-card__band .ws-band__how { display: none; }
|
|
37
|
+
.ws-chat-card__band .ws-band__words { min-width: min(100%, var(--space-7xl)); }
|
|
38
|
+
.ws-chat-card__band .ws-band__title { font-size: var(--ws-text-body); line-height: var(--ws-leading-control); text-wrap: balance; }
|
|
39
|
+
.ws-chat-card__band .ws-band__acts { width: auto; }
|
|
40
|
+
.ws-chat-card__band .ws-band__acts > * { flex: none; }
|
|
41
|
+
}
|
|
42
|
+
/* Full screen (North's cc-full, css:751): the card over the page, the stage inset from the window's edges, 16 px corners
|
|
43
|
+
(8 in the thread), the float drop; it scrolls on its own. morph() (Morph, `as: 'full'`) carries it there and back as
|
|
44
|
+
itself and lifts it into the top layer while it is full, so no ancestor with a transform, a filter, a backdrop-filter
|
|
45
|
+
(the glass stage, the chat's glass), contain or will-change can make "full screen" fill only that ancestor. */
|
|
46
|
+
.ws-chat-card--full { position: fixed; inset: var(--ws-stage-inset); z-index: var(--z-modal); width: auto; height: auto; max-width: none; margin: 0; overflow-y: auto; overscroll-behavior: contain; border-radius: var(--ws-radius-panel); box-shadow: var(--ws-shadow-float); }
|
|
47
|
+
/* Motion (D7, North's "Chart card arrives", the card spring .5 / .08): a card the app marks ws-settle as it arrives rises
|
|
48
|
+
6 px out of a 3 px blur on that spring. Reduced motion: it is simply there. */
|
|
49
|
+
@media (prefers-reduced-motion: no-preference) { .ws-chat-card.ws-settle { animation: ws-settle var(--ws-spring-card-duration) var(--ws-spring-card) backwards; animation-delay: calc(var(--ws-i, 0) * var(--ws-stagger-detail)); } }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
The chat's frame in three modes: a bar (only the field, over a veiled page), a column docked beside the page, and the
|
|
2
|
+
full screen with one centred reading column.
|
|
3
|
+
|
|
4
|
+
## Use it when
|
|
5
|
+
|
|
6
|
+
- An app has a chat with its agent that a person opens over, beside or instead of the page they are on.
|
|
7
|
+
- The chat should keep its place: the same thread moves between the bar, the docked column and the full screen.
|
|
8
|
+
|
|
9
|
+
## Not for
|
|
10
|
+
|
|
11
|
+
- A dialog that asks one thing: use `Dialog`.
|
|
12
|
+
- A side pane of detail: use `Panel`.
|
|
13
|
+
- A page's own ask field that opens the chat: that is a `Composer` on the page; it opens this.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
- The shell (`ws-chat-shell`): North's glass (`--ws-glass`, white at 59 % blurred 28 px, `--ws-glass-blur-chat`), a
|
|
18
|
+
1 px stage edge (`--ws-edge-stage`), 16 px corners; a column. It is not clipped (its parts are inset), so a menu
|
|
19
|
+
inside still shows.
|
|
20
|
+
- The head (`ws-chat-shell__head`): 52 px tall, 20 px in on the left and 12 on the right, 8 px apart: the title
|
|
21
|
+
(`ws-section`), where the chat is (`ws-muted`, cut with a title), then the mode buttons (`IconButton` small, 2 px
|
|
22
|
+
apart; 12 apart on touch, so their 40 px hit areas never overlap) at the end; a 0.5 px navy rule under it (navy at 8 %).
|
|
23
|
+
- The thread (`ws-chat-shell__thread`): the one scroller, 20 px down and 20 px in, the turns (`ChatTurn`) and topic
|
|
24
|
+
heads (`TopicRail`) in it, 64 px of room under the last item so it scrolls clear of the composer.
|
|
25
|
+
- The composer area (`ws-chat-shell__compose`): 8 px above, 12 px at the sides and under, round a `Composer`.
|
|
26
|
+
- The empty chat (`ws-chat-shell__empty`): low in the thread, a 26 / 32 semibold title (`ws-chat-shell__empty-title`),
|
|
27
|
+
one 14 / 20 line 8 px under it,
|
|
28
|
+
the starters (`SuggestionChip`, chat pills) 16 px under that.
|
|
29
|
+
|
|
30
|
+
## Variants and sizes
|
|
31
|
+
|
|
32
|
+
| Mode | Class | Look |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| Docked | `ws-chat-shell--dock` in a `ws-chat-dock` | A column 420 px wide (dragged between 340 and 560), no shadow, 12 px beside the page; a resize handle in the gap; AppShell's nav folded to its rail before it |
|
|
35
|
+
| Full screen | `ws-chat-shell--full` | The page card's frame, white at 94 %; the thread and the composer in one centred column at most 760 px, 28 px in at the least; items 24 px apart, 120 px of room under the last |
|
|
36
|
+
| Bar | `ws-chat-shell--bar` | No shell: the field 60 px tall with 8 px corners and the chat bar's drop (`--ws-shadow-bar`; a live call adds the composer's ring), the page starters 14 px under it, over a veil (`ws-chat-veil`) that blurs the page |
|
|
37
|
+
|
|
38
|
+
The resize handle (`ws-chat-shell__resize`): the 12 px gap at the column's right edge, a 3 x 40 grip (navy at 18 %, 36 % under the pointer and while dragged) at
|
|
39
|
+
its middle, a col-resize pointer; a `role="separator"` with its value, moved by the arrow keys in the app, which sets
|
|
40
|
+
`--ws-chat-dock-w` on the shell.
|
|
41
|
+
|
|
42
|
+
## States
|
|
43
|
+
|
|
44
|
+
- **Open** (North's chat, js@647700): the shell grows in from its mode's side (the bar from its top, the docked column
|
|
45
|
+
from its left edge, the full screen from 40 % down) out of .97 (`--ws-open-scale`) on the panel spring
|
|
46
|
+
(`--ws-spring-panel`, .42 / .12, "Opens / moves / docks"), fading in over `--ws-duration-hover` (.2 s) and out of an
|
|
47
|
+
8 px blur (`--ws-blur-panel`) over .24 s; its head fades in over `--ws-duration-text` (.25 s), .12 s after it.
|
|
48
|
+
- **Change of mode** (North's "Chat moves between full screen, dock and pop-out", .55 s on the shift curve): the app
|
|
49
|
+
swaps the mode class inside `morph(update, { as: 'shift', el: shell })` from the package (see `Morph`), so the shell
|
|
50
|
+
moves to its new place and size as itself over `--ws-duration-shift` on `--ws-ease-shift`: its words ride in its
|
|
51
|
+
corner at their own size, then the new mode's words fade in from 55 % of the way. The docked width shifts on the
|
|
52
|
+
same curve, never while the handle is dragged (`ws-chat-shell--resizing`). Without view transitions, or with
|
|
53
|
+
reduced motion, the mode simply changes.
|
|
54
|
+
- **Closing** (`data-leaving`): it goes to .97 into a 6 px blur, fading, over .16 s (js@674822), faster than it came;
|
|
55
|
+
remove it 160 ms later.
|
|
56
|
+
- **Empty**: the empty chat with its starters.
|
|
57
|
+
- **Busy**: the answer at work shows a `StatusLine`; nothing else in the shell changes.
|
|
58
|
+
- **Narrow** (a window under 60rem, North's 960): the docked chat takes the whole width and the page waits behind it;
|
|
59
|
+
the handle goes.
|
|
60
|
+
- **Reduced motion**: every mode is simply there.
|
|
61
|
+
- The preview's last stack is live: Full screen and Dock change the mode, Close and Open play the exit and the entrance.
|
|
62
|
+
- **Dark**: the glass, the edge, the veil and the rules follow the theme.
|
|
63
|
+
|
|
64
|
+
## Behaviour
|
|
65
|
+
|
|
66
|
+
- Keyboard: the head's mode buttons are real buttons with labels; Escape closes the bar; focus moves to the field when
|
|
67
|
+
the chat opens and back to what opened it when it closes.
|
|
68
|
+
- Screen reader: the shell is a labelled region (`aside aria-label="Chat with Coach"`), the thread a labelled list.
|
|
69
|
+
- Pointer: the docked column is resized by its handle; the full screen keeps one reading column at any width.
|
|
70
|
+
- Touch: the head's buttons have 40 px hit areas.
|
|
71
|
+
|
|
72
|
+
## Content
|
|
73
|
+
|
|
74
|
+
- The title is the agent's name; where it is says which page it reads from ("On Pipeline").
|
|
75
|
+
- The empty title asks what to work on, in the agent's voice, no em dash.
|
|
76
|
+
|
|
77
|
+
## Rules
|
|
78
|
+
|
|
79
|
+
- One thread, three modes: changing mode never reloads or reorders the chat.
|
|
80
|
+
- The page steps aside for a docked chat; it is never covered by it.
|
|
81
|
+
- In the full screen the reading column stays at most 760 px; a chart answer may break out wider.
|
|
82
|
+
|
|
83
|
+
## Source
|
|
84
|
+
|
|
85
|
+
**Derived from**: North's chat (style1.css:505-533, :584-591, :786-788, :1296-1300, :1362-1408, :1553-1560;
|
|
86
|
+
js@647700-675000: the glass shell, the 52 px head, 20 / 22 thread inset, 28 between items, the 8 / 12 / 12 composer
|
|
87
|
+
area, the bar's 60 px field and veil, the 420 docked column with its 3 x 40 grip, the 760 full-screen column, the
|
|
88
|
+
open, re-form and shift motions). The thread's sides are 20 here, on the head's edge, where North has 22 against an
|
|
89
|
+
18 px head (one content edge, D3).
|
|
90
|
+
|
|
91
|
+
## Markup
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<div class="ws-chat-dock">
|
|
95
|
+
<nav class="ws-app-shell__rail" aria-label="Main"><!-- AppShell's rail --></nav>
|
|
96
|
+
<aside class="ws-chat-shell ws-chat-shell--dock" aria-label="Chat with Coach">
|
|
97
|
+
<header class="ws-chat-shell__head">
|
|
98
|
+
<h2 class="ws-section">Coach</h2>
|
|
99
|
+
<span class="ws-muted ws-chat-shell__where" title="On Pipeline">On Pipeline</span>
|
|
100
|
+
<span class="ws-chat-shell__tools"><!-- small IconButtons: full screen, close --></span>
|
|
101
|
+
</header>
|
|
102
|
+
<ol class="ws-chat-shell__thread" aria-label="Messages"><!-- ChatTurn and topic heads --></ol>
|
|
103
|
+
<div class="ws-chat-shell__compose"><!-- a Composer --></div>
|
|
104
|
+
<button type="button" class="ws-chat-shell__resize" role="separator" aria-orientation="vertical" aria-label="Resize the chat" aria-valuemin="340" aria-valuemax="560" aria-valuenow="420"></button>
|
|
105
|
+
</aside>
|
|
106
|
+
<main><!-- the page --></main>
|
|
107
|
+
</div>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Styles
|
|
111
|
+
|
|
112
|
+
`ChatShell/style.css` (its keyframes `ws-chat-open` and `ws-chat-veil` live there). Tokens: `--ws-glass`,
|
|
113
|
+
`--ws-glass-blur-chat`, `--ws-edge-stage`, `--ws-radius-panel`, `--ws-ink`, `--ws-shade`, `--ws-float-rim`,
|
|
114
|
+
`--ws-page`, `--ws-blur-panel`, `--color-surface`, `--ws-hover`, `--ws-duration-calm`, `--ws-duration-shift`,
|
|
115
|
+
`--ws-ease-settle`, `--ws-ease-shift`. The 760 column and the 420 width are component properties (`--ws-chat-col`,
|
|
116
|
+
`--ws-chat-dock-w`).
|