@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
|
@@ -9,13 +9,13 @@
|
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
11
|
<div class="ws-stage ws-stage--grey">
|
|
12
|
-
<div style="display: grid; grid-template-columns: repeat(
|
|
12
|
+
<div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 240px), 1fr)); gap: var(--ws-gap-component); width: 100%;">
|
|
13
13
|
|
|
14
14
|
<div class="ws-combobox">
|
|
15
15
|
<span class="ws-muted">Closed, with a value</span>
|
|
16
16
|
<label class="ws-label" for="cb-closed">Lead source</label>
|
|
17
|
-
<span class="ws-combobox__field"
|
|
18
|
-
<input type="text" value="Referral" readonly role="combobox" aria-expanded="false">
|
|
17
|
+
<span class="ws-combobox__field">
|
|
18
|
+
<input id="cb-closed" type="text" value="Referral" readonly role="combobox" aria-expanded="false">
|
|
19
19
|
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
20
20
|
</span>
|
|
21
21
|
</div>
|
|
@@ -23,27 +23,28 @@
|
|
|
23
23
|
<div class="ws-combobox">
|
|
24
24
|
<span class="ws-muted">Open, with matches (typed part navy medium, rest body grey)</span>
|
|
25
25
|
<label class="ws-label" for="cb-open">Street address</label>
|
|
26
|
-
<span class="ws-combobox__field ws-combobox__field--focus"
|
|
27
|
-
<input type="text" value="pine" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-1">
|
|
26
|
+
<span class="ws-combobox__field ws-combobox__field--focus">
|
|
27
|
+
<input id="cb-open" type="text" value="pine" role="combobox" aria-expanded="true" aria-controls="cb-list" aria-activedescendant="cb-opt-1">
|
|
28
28
|
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
29
29
|
</span>
|
|
30
30
|
<div class="ws-menu ws-combobox__panel" role="listbox" id="cb-list">
|
|
31
31
|
<div class="ws-combobox__option" role="option" id="cb-opt-0"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest">wood Drive</span></div>
|
|
32
32
|
<div class="ws-combobox__option ws-combobox__option--active" role="option" id="cb-opt-1" aria-selected="true"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Street</span></div>
|
|
33
33
|
<div class="ws-combobox__option" role="option" id="cb-opt-2"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Hollow Court</span></div>
|
|
34
|
+
<div class="ws-combobox__option" role="option" id="cb-opt-3"><span class="ws-combobox__match">Pine</span><span class="ws-combobox__rest"> Hollow Court, Building 4, Unit 1207, Lakeview Estates North</span></div>
|
|
34
35
|
</div>
|
|
35
36
|
</div>
|
|
36
37
|
|
|
37
38
|
<div class="ws-combobox">
|
|
38
39
|
<span class="ws-muted">No matches, with a create act</span>
|
|
39
40
|
<label class="ws-label" for="cb-empty">Street address</label>
|
|
40
|
-
<span class="ws-combobox__field ws-combobox__field--focus"
|
|
41
|
-
<input type="text" value="cedar harbor" role="combobox" aria-expanded="true">
|
|
41
|
+
<span class="ws-combobox__field ws-combobox__field--focus">
|
|
42
|
+
<input id="cb-empty" type="text" value="cedar harbor" role="combobox" aria-expanded="true" aria-controls="cb-list-empty">
|
|
42
43
|
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
43
44
|
</span>
|
|
44
|
-
<div class="ws-menu ws-combobox__panel">
|
|
45
|
-
<div class="ws-combobox__empty">No matches</div>
|
|
46
|
-
<div class="ws-combobox__create">
|
|
45
|
+
<div class="ws-menu ws-combobox__panel" role="listbox" id="cb-list-empty">
|
|
46
|
+
<div class="ws-combobox__empty" aria-hidden="true">No matches</div>
|
|
47
|
+
<div class="ws-combobox__create" role="option" id="cb-create">
|
|
47
48
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>
|
|
48
49
|
Create "Cedar Harbor"
|
|
49
50
|
</div>
|
|
@@ -53,10 +54,32 @@
|
|
|
53
54
|
<div class="ws-combobox">
|
|
54
55
|
<span class="ws-muted">Multi-select: chosen values as chips (TagInput behaviour)</span>
|
|
55
56
|
<label class="ws-label" for="cb-multi">Call kinds</label>
|
|
56
|
-
<span class="ws-combobox__field"
|
|
57
|
+
<span class="ws-combobox__field">
|
|
57
58
|
<span class="ws-combobox__chip">Cold calls<button type="button" aria-label="Remove Cold calls"><svg viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M2 2l6 6M8 2l-6 6"/></svg></button></span>
|
|
58
59
|
<span class="ws-combobox__chip">Live transfers<button type="button" aria-label="Remove Live transfers"><svg viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M2 2l6 6M8 2l-6 6"/></svg></button></span>
|
|
59
|
-
<input type="text" placeholder="Add another" role="combobox" aria-expanded="false">
|
|
60
|
+
<input id="cb-multi" type="text" placeholder="Add another" role="combobox" aria-expanded="false">
|
|
61
|
+
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<div class="ws-combobox">
|
|
66
|
+
<span class="ws-muted">Error: nothing chosen, with what to do</span>
|
|
67
|
+
<label class="ws-label" for="cb-error">Listing</label>
|
|
68
|
+
<span class="ws-combobox__field">
|
|
69
|
+
<input id="cb-error" type="text" placeholder="Search your listings" role="combobox" aria-expanded="false" aria-invalid="true" aria-describedby="cb-error-msg">
|
|
70
|
+
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
71
|
+
</span>
|
|
72
|
+
<p class="ws-field-msg ws-field-msg--error" id="cb-error-msg">
|
|
73
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 2.3 14.6 13.5H1.4L8 2.3Z"/><path d="M8 6.4v3"/><path d="M8 11.5v.05"/></svg>
|
|
74
|
+
Choose the listing this showing is for
|
|
75
|
+
</p>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div class="ws-combobox">
|
|
79
|
+
<span class="ws-muted">Disabled, with a long chosen value (it is cut inside the field)</span>
|
|
80
|
+
<label class="ws-label" for="cb-disabled">Street address</label>
|
|
81
|
+
<span class="ws-combobox__field">
|
|
82
|
+
<input id="cb-disabled" type="text" value="Pine Hollow Court, Building 4, Unit 1207, Lakeview Estates North" role="combobox" aria-expanded="false" disabled>
|
|
60
83
|
<svg class="ws-combobox__chevron" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M4 6l4 4 4-4"/></svg>
|
|
61
84
|
</span>
|
|
62
85
|
</div>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/* ---- Combobox: a field you type in with a menu of matches under it; chosen values as chips when several. The field
|
|
2
|
+
is Input's (edge inside, darker under the pointer, the focus ring while typing, since its own input draws none). ---- */
|
|
3
|
+
.ws-combobox { position: relative; display: flex; min-width: 0; flex-direction: column; gap: var(--space-xxs); }
|
|
4
|
+
.ws-combobox__field { position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-xxs); min-height: var(--ws-control-h); padding: var(--space-3xs) var(--space-xl) var(--space-3xs) var(--space-sm); border: 0; border-radius: var(--ws-radius-control); background: var(--ws-field); box-shadow: var(--ws-shadow-hairline-in); font-size: var(--ws-text-body); color: var(--ws-field-ink); transition: box-shadow var(--ws-duration-hover) var(--ws-ease-soft); }
|
|
5
|
+
@media (hover: hover) { .ws-combobox__field:hover { box-shadow: inset 0 0 0 var(--ws-hairline) var(--ws-edge-hover); } }
|
|
6
|
+
.ws-combobox__field:has(input:focus-visible), .ws-combobox__field--focus { outline: var(--ws-focus-width) solid var(--ws-focus-color); outline-offset: var(--ws-focus-offset); }
|
|
7
|
+
.ws-combobox__field:has(input[aria-invalid="true"]) { box-shadow: inset 0 0 0 var(--ws-line) var(--ws-word-needs); }
|
|
8
|
+
.ws-combobox__chevron { position: absolute; right: var(--space-xs); top: 50%; width: var(--ws-icon); height: var(--ws-icon); transform: translateY(-50%); color: var(--ws-field-mark, var(--color-text-heading)); pointer-events: none; }
|
|
9
|
+
.ws-combobox__field input { flex: 1; min-width: calc(var(--space-4xl) - var(--space-xxs)); height: calc(var(--ws-control-h) - var(--space-xxs)); padding: 0; border: 0; outline: none; background: transparent; font: inherit; line-height: calc(var(--space-md) + var(--space-xxs)); color: inherit; }
|
|
10
|
+
.ws-combobox__field input::placeholder { color: var(--color-text-placeholder); }
|
|
11
|
+
/* The menu of matches: the menu, 8 options tall before it scrolls (and never taller than the window, as every menu),
|
|
12
|
+
growing from its top left, under the field's left edge; the option under the keyboard on the sunk cream. Written on
|
|
13
|
+
.ws-menu so it outweighs Menu's own height and corner. */
|
|
14
|
+
.ws-menu.ws-combobox__panel { --ws-combobox-row: var(--ws-control-h); margin-top: var(--space-xxs); max-height: min(calc(var(--ws-combobox-row) * 8 + var(--space-xxs) * 2), calc(100dvh - var(--space-xl))); overflow-y: auto; transform-origin: top left; }
|
|
15
|
+
/* An option is one run of text, so the typed part and the rest flow as one line and a long one wraps inside the panel
|
|
16
|
+
(never cut, never scrolled sideways); one line is 32 tall. */
|
|
17
|
+
.ws-combobox__option { display: block; padding: calc((var(--ws-combobox-row, var(--ws-control-h)) - var(--space-md) - var(--space-xxs)) / 2) var(--space-sm); border-radius: var(--ws-radius-row); font-size: var(--ws-text-body); line-height: calc(var(--space-md) + var(--space-xxs)); cursor: pointer; }
|
|
18
|
+
@media (hover: hover) { .ws-combobox__option:hover { background: var(--ws-hover); } }
|
|
19
|
+
.ws-combobox__option--active, .ws-combobox__option[aria-selected="true"] { background: var(--ws-surface-sunk); }
|
|
20
|
+
.ws-combobox__match { font-weight: 500; color: var(--color-text-heading); }
|
|
21
|
+
/* pre-wrap keeps the rest's leading space (" Street") and still wraps a long one. */
|
|
22
|
+
.ws-combobox__rest { color: var(--color-text-body); white-space: pre-wrap; }
|
|
23
|
+
.ws-combobox__empty { display: flex; align-items: center; min-height: var(--ws-control-h); padding: 0 var(--space-sm); color: var(--color-text-muted); font-size: var(--ws-text-body); }
|
|
24
|
+
.ws-combobox__create { display: flex; align-items: center; gap: var(--space-xxs-plus); width: 100%; min-height: var(--ws-control-h); padding: 0 var(--space-sm); border: 0; border-radius: var(--ws-radius-row); background: none; font-size: var(--ws-text-body); font-weight: 500; color: var(--color-text-heading); text-align: start; cursor: pointer; }
|
|
25
|
+
@media (hover: hover) { .ws-combobox__create:hover { background: var(--ws-hover); } }
|
|
26
|
+
.ws-combobox__create svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
27
|
+
/* A chosen value: Chip's tag on the sunk cream, its remove x a 24 px target (a hit area round the 12 px mark; 40 on
|
|
28
|
+
touch, below). */
|
|
29
|
+
/* On the navy ground the field stays white, so a chip there takes the light grey tag and the field's own ink (the
|
|
30
|
+
ground's dark sunk tag read inverted on the white field). */
|
|
31
|
+
.ws-combobox { --ws-combobox-chip: var(--ws-surface-sunk); --ws-combobox-chip-ink: var(--color-text-body); --ws-combobox-chip-hover: var(--ws-hover-strong); }
|
|
32
|
+
[data-theme="dark"][data-ground="navy"] .ws-combobox { --ws-combobox-chip: var(--color-gray-2); --ws-combobox-chip-ink: var(--ws-field-ink); --ws-combobox-chip-hover: color-mix(in srgb, var(--ws-field-ink) 8%, transparent); }
|
|
33
|
+
@media (prefers-color-scheme: dark) { [data-theme="system"][data-ground="navy"] .ws-combobox { --ws-combobox-chip: var(--color-gray-2); --ws-combobox-chip-ink: var(--ws-field-ink); --ws-combobox-chip-hover: color-mix(in srgb, var(--ws-field-ink) 8%, transparent); } }
|
|
34
|
+
.ws-combobox__chip { display: inline-flex; align-items: center; gap: var(--space-xxs); max-width: 100%; height: var(--space-lg); padding: 0 var(--space-xxs) 0 var(--space-xs); border-radius: var(--ws-radius-control); background: var(--ws-combobox-chip); color: var(--ws-combobox-chip-ink); font-size: var(--ws-text-control); line-height: var(--ws-leading-control); font-weight: 500; white-space: nowrap; }
|
|
35
|
+
.ws-combobox__chip button { position: relative; display: inline-flex; align-items: center; justify-content: center; width: var(--space-md); height: var(--space-md); padding: 0; border: 0; border-radius: var(--ws-radius-control); background: none; color: var(--ws-field-mark, var(--color-text-heading)); cursor: pointer; }
|
|
36
|
+
.ws-combobox__chip button::after { content: ""; position: absolute; inset: calc((var(--space-md) - var(--space-lg)) / 2); }
|
|
37
|
+
.ws-combobox__chip button:focus-visible { outline-color: var(--ws-field-mark, var(--ws-focus-color)); outline-offset: 0; }
|
|
38
|
+
@media (hover: hover) { .ws-combobox__chip button:hover { background: var(--ws-combobox-chip-hover); } }
|
|
39
|
+
.ws-combobox__chip svg { width: var(--ws-icon-sm); height: var(--ws-icon-sm); }
|
|
40
|
+
/* Disabled: Input's sunk ground and muted words, no pointer. */
|
|
41
|
+
.ws-combobox__field:has(input:disabled) { background: var(--ws-surface-sunk); color: var(--color-text-muted); cursor: not-allowed; }
|
|
42
|
+
.ws-combobox__field:has(input:disabled) .ws-combobox__chevron { color: var(--color-text-muted); }
|
|
43
|
+
/* Touch: the field is Input's 40 (its words 16, so a phone does not zoom into it), and every row of the menu, the
|
|
44
|
+
create act and the empty line with it, is 40 too (so the panel's 8 rows are 40s). A chip's remove x keeps its 16 px
|
|
45
|
+
mark and gets the 40 px hit area an icon act asks (14-accessibility.md); chips sit 8 apart so that area never reaches
|
|
46
|
+
the next chip. */
|
|
47
|
+
@media (pointer: coarse) {
|
|
48
|
+
.ws-combobox__field { column-gap: var(--space-xs); min-height: var(--ws-touch); font-size: var(--ws-text-value); }
|
|
49
|
+
.ws-combobox__field input { height: calc(var(--ws-touch) - var(--space-xxs)); }
|
|
50
|
+
.ws-menu.ws-combobox__panel { --ws-combobox-row: var(--ws-touch); }
|
|
51
|
+
.ws-combobox__create, .ws-combobox__empty { min-height: var(--ws-touch); }
|
|
52
|
+
.ws-combobox__chip button { min-height: 0; }
|
|
53
|
+
.ws-combobox__chip button::after { inset: calc((var(--space-md) - var(--ws-touch)) / 2); }
|
|
54
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
The one chat box, drawn once for the home screen and every chat:
|
|
2
|
-
|
|
1
|
+
The one chat box (North's), drawn once for the home screen and every chat: a square-cornered field that grows upward
|
|
2
|
+
with what is typed, its tools on the bottom line at the right, and what the question is about riding on top as a tab.
|
|
3
3
|
|
|
4
4
|
## Use it when
|
|
5
5
|
|
|
6
6
|
- A person writes to an app's assistant or agent from a home screen or a chat.
|
|
7
7
|
- The same box must also become a live call's: the words field turns into the call's line without changing shape.
|
|
8
|
+
- A question is about something on screen (a chart, a person): the context tab says so above the field.
|
|
9
|
+
- A pane needs its own small ask line (Seth's "Ask Grow about Local search"): the `field` look.
|
|
8
10
|
|
|
9
11
|
## Not for
|
|
10
12
|
|
|
@@ -14,50 +16,74 @@ it goes to at its left, and the round action at its right.
|
|
|
14
16
|
|
|
15
17
|
## Anatomy
|
|
16
18
|
|
|
17
|
-
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
- The area round it, in a chat (`ChatShell`): 8 px above, 12 px at the sides and under (North's 8 / 12 / 12).
|
|
20
|
+
- The field: white (`--ws-field`), the 0.5 px card edge drawn inside (an inset hairline, so nothing clips it), 4 px
|
|
21
|
+
corners (`--ws-radius-control`), 52 px tall at least (`--ws-composer-h`), 8 px inside and 16 px on the left of the
|
|
22
|
+
words. It grows with the words; the tools stay on the bottom line.
|
|
23
|
+
- The tools' line is 36 px (40 on touch); the words, the lead and the rule all centre on it.
|
|
24
|
+
- Words (`ws-composer__words`, a `textarea` that sizes to its content, or an `input`): 16 / 24 in `--ws-field-ink`,
|
|
25
|
+
growing to six lines and then scrolling; the placeholder in `--color-text-muted`.
|
|
26
|
+
- Tools (`ws-composer__trail`, 2 px apart): plus and mic as 36 px square tools (4 px corners, navy 16 px icons, the
|
|
27
|
+
navy 6 % wash under the pointer; a tool that is on, `aria-pressed`, turns into the navy round), then the one round
|
|
28
|
+
navy act: Talk while the box is empty, Send once there are words. A product draws only the tools it supports.
|
|
29
|
+
- The context tab (`ws-composer__context`): what the question is about, riding on the field: 6 / 6 / 6 / 12 inside, the
|
|
30
|
+
field's edge on its top and sides, 4 px top corners, navy at 5 % over white, 13 / 18 words in `--color-text-body` cut
|
|
31
|
+
with a title, a 16 px navy mark and a 24 px close. The field gives up its top corners; tabs stack, split by a 0.5 px
|
|
32
|
+
line.
|
|
33
|
+
- The lead (`ws-composer__lead`, the home screen): the app's 20 px face (`ws-disc ws-composer__face`, a 12 px glyph)
|
|
34
|
+
and short name (`ws-composer__name`, 14 px medium navy), then a 1 px rule (`ws-composer__rule`) 12 px either side,
|
|
35
|
+
before the words.
|
|
36
|
+
- During a call the same box takes the selected ring and the words show what is heard, one line: the lead holds the
|
|
37
|
+
working dot (`ws-dot ws-working ws-composer__dot`), the name and the timer, and the words are a status line
|
|
38
|
+
(`ws-composer__words--empty`, muted, "Listening…") until something is heard.
|
|
39
|
+
- The field look (`--field`): the agent's own 20 px face as a bare `svg.ws-composer__face` (no disc: the face is the
|
|
40
|
+
mark), the words an `input` whose placeholder and value are cut with an ellipsis, never mid-letter, and a plain
|
|
41
|
+
send arrow.
|
|
26
42
|
|
|
27
43
|
## Variants and sizes
|
|
28
44
|
|
|
29
45
|
| Variant | What it looks like | Where |
|
|
30
46
|
| --- | --- | --- |
|
|
31
|
-
| Default |
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
35
|
-
|
|
47
|
+
| Default | The words flush left, the tools at the right | every chat (North's) |
|
|
48
|
+
| With a context tab | A tab on top naming the chart, card or person asked about | a question about something on screen |
|
|
49
|
+
| Lead | The app's face and name at the left, a rule, then the words | the home screen, which addresses one of several apps |
|
|
50
|
+
| Live (`--live`) | The selected ring, the call's timer in the lead, what is heard in the words | a live voice call |
|
|
51
|
+
| Field (`--field`) | 40 px, the tray grey, 8 px corners, 12 px inside, 10 between, the agent's bare 20 px face, 14 / 20 words cut with an ellipsis, a plain send arrow | a pane's own ask line |
|
|
36
52
|
|
|
37
53
|
## States
|
|
38
54
|
|
|
39
|
-
- **Empty
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- **
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- **
|
|
46
|
-
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
51
|
-
|
|
55
|
+
- **Empty**: the placeholder names who it reaches ("Message Coach"); the round act is Talk, unless voice is not set
|
|
56
|
+
up, in which case there is no Talk at all.
|
|
57
|
+
- **With words**: the round act becomes Send (an upward arrow), enabled once there is a trimmed value.
|
|
58
|
+
- **Focus**: the kit's 2 px navy ring on the box's own edge, drawn inside it, while the words have focus (North draws
|
|
59
|
+
none; the kit needs a visible one, D8). Its tools take their own ring.
|
|
60
|
+
- **Tool on** (dictating): the tool turns into the navy round with its icon in `--ws-on-act`.
|
|
61
|
+
- **Live (talking)**: the ring, the timer at the left; what is heard is one line, cut at the end.
|
|
62
|
+
- **Disabled**: not a state of the box; offline, the words stay and Send is refused, not greyed.
|
|
63
|
+
- **Long words**: the box grows up to six lines, then scrolls inside; nothing is cut off.
|
|
64
|
+
- **Narrow**: on a phone the box is the full width; the tools keep their size.
|
|
65
|
+
- **Touch**: the tools' line is 40 px, so every tool is 40 px; the field look's words go to 16 px, so iOS never zooms in.
|
|
66
|
+
- **Dark**: the field, the edge, the tab and the tools follow the theme. On the navy ground the field stays white, so
|
|
67
|
+
its words, tools, washes, edges and focus ring take the field's navy ink (`--ws-field-ink`), the muted words the
|
|
68
|
+
placeholder grey; the pane field (`--field`) sits on the tray and keeps the ground's own words.
|
|
52
69
|
|
|
53
70
|
## Behaviour
|
|
54
71
|
|
|
55
72
|
- Keyboard: Enter sends (unless Shift is held, which inserts a new line); Alt+T starts Talk from the keyboard.
|
|
56
73
|
- Pointer / touch: tapping the box focuses the words field; the box grows upward as more is typed, up to its cap, then
|
|
57
74
|
scrolls.
|
|
58
|
-
- Motion: the
|
|
59
|
-
|
|
60
|
-
|
|
75
|
+
- Motion: the tools' wash eases over `--ws-duration-hover`; the live round act pulses on the working beat (`ws-working`,
|
|
76
|
+
1 s). Focus glow (North's "Focus glow", the glow spring .3 / 0, css:2120): while something in the box has focus a
|
|
77
|
+
soft drop gathers under it (0 4 16, the shade at 7 %) on `--ws-spring-glow`; its edge stays its own and the keyboard
|
|
78
|
+
ring is still the kit's (D8). The pane field, a live call and the chat bar keep their own look.
|
|
79
|
+
- Placeholder roll (North's "Placeholder roll", the roll spring .45 / .05): put the words and a `ws-composer__roll` of a
|
|
80
|
+
few questions in a `ws-composer__slot`, keep the first question as the words' `placeholder` (what a screen reader
|
|
81
|
+
reads; the roll paints it clear), and run `rollPlaceholder(roll)` from the package (it returns a stop, a React
|
|
82
|
+
effect's cleanup). Every 3.4 s the next question rolls up out of 12 px (`--ws-drop`) and a 3 px blur
|
|
83
|
+
(`--ws-blur-arrive`) on `--ws-spring-roll`, the last rolling on up into the blur; the roll goes once there are words.
|
|
84
|
+
Without the script, without `:has()`, or with reduced motion, the first question holds. The main field only.
|
|
85
|
+
Under reduced motion nothing pulses or rolls and the glow simply appears; the state is said in words.
|
|
86
|
+
- The preview's last stack is live: watch the placeholder roll, then click in.
|
|
61
87
|
|
|
62
88
|
## Content
|
|
63
89
|
|
|
@@ -77,7 +103,8 @@ There is one size: 52px, fixed regardless of how many lines the words expand to
|
|
|
77
103
|
|
|
78
104
|
## Rules
|
|
79
105
|
|
|
80
|
-
- One chat box, drawn once, for the home screen and every chat, never redrawn per screen
|
|
106
|
+
- One chat box, drawn once, for the home screen and every chat, never redrawn per screen; a pane's ask line is its
|
|
107
|
+
`field` look, not a new box.
|
|
81
108
|
- The placeholder always names who it reaches ("Message your assistant"); the header already names the app or agent,
|
|
82
109
|
so the box itself never repeats that name a second time.
|
|
83
110
|
- The plus and mic are the designed trail; a product shows only the controls it actually supports (no file upload, no
|
|
@@ -86,5 +113,80 @@ There is one size: 52px, fixed regardless of how many lines the words expand to
|
|
|
86
113
|
|
|
87
114
|
## Source
|
|
88
115
|
|
|
89
|
-
**Derived from**:
|
|
90
|
-
|
|
116
|
+
**Derived from**: North's composer (style1.css:1376-1392, :1553-1560: 8 / 12 / 12 round a 52 px square-cornered field
|
|
117
|
+
that grows, + · mic · voice on the right, the context tab riding on top) and Seth's pane field (Grow 301:2104-2105).
|
|
118
|
+
The focus ring is the kit's own (D8). **Precedent**: the first product built on the system.
|
|
119
|
+
|
|
120
|
+
## Markup
|
|
121
|
+
|
|
122
|
+
```html
|
|
123
|
+
<div class="ws-composer__context" title="Calls this week, by agent">
|
|
124
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- a 16 px mark --></svg>
|
|
125
|
+
<span>Calls this week, by agent</span>
|
|
126
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--xs" aria-label="Remove the chart from your question"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M5 5l6 6M11 5l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg></button>
|
|
127
|
+
</div>
|
|
128
|
+
<div class="ws-composer">
|
|
129
|
+
<label class="ws-sr" for="ask">Message Coach</label>
|
|
130
|
+
<textarea id="ask" class="ws-composer__words" rows="1" placeholder="Message Coach"></textarea>
|
|
131
|
+
<div class="ws-composer__trail">
|
|
132
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Add a file"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- plus --></svg></button>
|
|
133
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Dictate"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- mic --></svg></button>
|
|
134
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Talk with Coach"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- voice --></svg></button>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
<!-- With a lead (the home screen) -->
|
|
139
|
+
<div class="ws-composer">
|
|
140
|
+
<div class="ws-composer__lead">
|
|
141
|
+
<span class="ws-disc ws-composer__face" aria-hidden="true"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- the app's mark --></svg></span>
|
|
142
|
+
<span class="ws-composer__name">Coach</span>
|
|
143
|
+
</div>
|
|
144
|
+
<span class="ws-composer__rule" aria-hidden="true"></span>
|
|
145
|
+
<label class="ws-sr" for="ask-home">Message Coach</label>
|
|
146
|
+
<input id="ask-home" class="ws-composer__words" type="text" placeholder="Message Coach">
|
|
147
|
+
<div class="ws-composer__trail"><!-- Talk, the round navy act --></div>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<!-- Live: a call with Coach -->
|
|
151
|
+
<div class="ws-composer ws-composer--live">
|
|
152
|
+
<div class="ws-composer__lead">
|
|
153
|
+
<span class="ws-dot ws-working ws-composer__dot" aria-hidden="true"></span>
|
|
154
|
+
<span class="ws-composer__name">Coach</span>
|
|
155
|
+
<span class="ws-muted ws-tnum">0:42</span>
|
|
156
|
+
</div>
|
|
157
|
+
<span class="ws-composer__rule" aria-hidden="true"></span>
|
|
158
|
+
<div class="ws-composer__words ws-composer__words--empty" role="status" title="Listening">Listening…</div>
|
|
159
|
+
<div class="ws-composer__trail"><!-- Mute, then End as the round navy act --></div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<!-- The field look, in a pane -->
|
|
163
|
+
<div class="ws-composer ws-composer--field">
|
|
164
|
+
<svg class="ws-composer__face" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 16.5V9l6.5-5.5L16.5 9v7.5Z"/><path d="M8 16.5v-4h4v4"/></svg>
|
|
165
|
+
<label class="ws-sr" for="ask-pane">Ask Grow about Local search</label>
|
|
166
|
+
<input id="ask-pane" class="ws-composer__words" type="text" placeholder="Ask Grow about Local search">
|
|
167
|
+
<div class="ws-composer__trail">
|
|
168
|
+
<button type="button" class="ws-icon-btn" aria-label="Send"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><!-- send arrow --></svg></button>
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<!-- The rolling placeholder: the words and the roll share a slot; rollPlaceholder(roll) moves it on every 3.4 s -->
|
|
173
|
+
<div class="ws-composer">
|
|
174
|
+
<label class="ws-sr" for="ask-roll">Message Coach</label>
|
|
175
|
+
<span class="ws-composer__slot">
|
|
176
|
+
<textarea id="ask-roll" class="ws-composer__words" rows="1" placeholder="Who should I call first?"></textarea>
|
|
177
|
+
<span class="ws-composer__roll" aria-hidden="true"><span>Who should I call first?</span><span>Why did calls drop?</span><span>Who needs a nudge?</span></span>
|
|
178
|
+
</span>
|
|
179
|
+
<div class="ws-composer__trail"><!-- Talk, the round navy act --></div>
|
|
180
|
+
</div>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
import { rollPlaceholder } from '@felloinnovations/brand-kit';
|
|
185
|
+
useEffect(() => rollPlaceholder(rollRef.current!), []); // returns the stop
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Styles
|
|
189
|
+
|
|
190
|
+
`Composer/style.css`; the tools are `IconButton`s reshaped inside the trail. Tokens: `--ws-composer-h`, `--ws-field`,
|
|
191
|
+
`--ws-field-ink`, `--ws-edge-card`, `--ws-hairline`, `--ws-radius-control`, `--ws-control-h-md`, `--ws-touch`,
|
|
192
|
+
`--ws-leading-message`, `--ws-hover`, `--ws-hover-strong`, `--ws-on-act`, `--ws-tray`, `--ws-focus-*`.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- @dsCard group="Chat" height=
|
|
1
|
+
<!-- @dsCard group="Chat" height=648 -->
|
|
2
2
|
<!doctype html>
|
|
3
3
|
<html>
|
|
4
4
|
<head>
|
|
@@ -8,80 +8,155 @@
|
|
|
8
8
|
<link rel="stylesheet" href="../bundle.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
11
|
-
<div class="ws-stage ws-stage--column">
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
<span class="ws-muted">Empty: the app or agent chip, the placeholder, plus and mic, Talk</span>
|
|
11
|
+
<div class="ws-stage ws-stage--column" style="background: var(--ws-frame);">
|
|
12
|
+
<div class="ws-stack" style="max-width: 440px;">
|
|
13
|
+
<span class="ws-muted">Empty: the words flush left, plus and mic as square tools, Talk as the round navy act</span>
|
|
15
14
|
<div class="ws-composer">
|
|
16
|
-
<
|
|
17
|
-
|
|
18
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4.5h10a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H7l-2.5 2v-2H3a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1z"/></svg>
|
|
19
|
-
</span>
|
|
20
|
-
<span class="ws-composer__name">Assistant</span>
|
|
21
|
-
</div>
|
|
22
|
-
<span class="ws-composer__rule" aria-hidden="true"></span>
|
|
23
|
-
<label class="ws-sr" for="composer-empty">Message your assistant</label>
|
|
24
|
-
<input id="composer-empty" class="ws-composer__words" type="text" placeholder="Message your assistant">
|
|
15
|
+
<label class="ws-sr" for="composer-empty">Message Coach</label>
|
|
16
|
+
<textarea id="composer-empty" class="ws-composer__words" rows="1" placeholder="Message Coach"></textarea>
|
|
25
17
|
<div class="ws-composer__trail">
|
|
26
|
-
<button class="ws-icon-btn" aria-label="Add a file" title="Add a file">
|
|
27
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M8 3v10M3 8h10"/></svg>
|
|
18
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Add a file" title="Add a file">
|
|
19
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>
|
|
28
20
|
</button>
|
|
29
|
-
<button class="ws-icon-btn" aria-label="
|
|
30
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2" width="4" height="7" rx="2"/><path d="M4 7.5a4 4 0 0 0 8 0M8 13.5V15M6 15h4"/></svg>
|
|
21
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Dictate" title="Dictate">
|
|
22
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="2" width="4" height="7" rx="2"/><path d="M4 7.5a4 4 0 0 0 8 0M8 13.5V15M6 15h4"/></svg>
|
|
31
23
|
</button>
|
|
32
|
-
<button class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Talk with
|
|
33
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.
|
|
24
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Talk with Coach" title="Talk (Alt+T)">
|
|
25
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M3 6.5v3M5.5 4.5v7M8 2.5v11M10.5 4.5v7M13 6.5v3"/></svg>
|
|
34
26
|
</button>
|
|
35
27
|
</div>
|
|
36
28
|
</div>
|
|
37
29
|
</div>
|
|
38
30
|
|
|
39
|
-
<div class="ws-stack">
|
|
40
|
-
<span class="ws-muted">With words
|
|
31
|
+
<div class="ws-stack" style="max-width: 440px;">
|
|
32
|
+
<span class="ws-muted">With words and a context tab: what the question is about rides on top; Send replaces Talk</span>
|
|
33
|
+
<div>
|
|
34
|
+
<div class="ws-composer__context" title="Calls this week, by agent">
|
|
35
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M2 13.5h12M4 11V7.5M8 11V4M12 11V8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
36
|
+
<span>Calls this week, by agent</span>
|
|
37
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--xs" aria-label="Remove the chart from your question">
|
|
38
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M5 5l6 6M11 5l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
39
|
+
</button>
|
|
40
|
+
</div>
|
|
41
|
+
<div class="ws-composer__context" title="Sam Rivera">
|
|
42
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><circle cx="8" cy="5.5" r="2.5" stroke="currentColor" stroke-width="1.5"/><path d="M3 13c0-2.5 2.2-4 5-4s5 1.5 5 4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
43
|
+
<span>Sam Rivera</span>
|
|
44
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--xs" aria-label="Remove Sam Rivera from your question">
|
|
45
|
+
<svg viewBox="0 0 16 16" fill="none" aria-hidden="true"><path d="M5 5l6 6M11 5l-6 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/></svg>
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
<div class="ws-composer">
|
|
49
|
+
<label class="ws-sr" for="composer-words">Message Coach</label>
|
|
50
|
+
<textarea id="composer-words" class="ws-composer__words" rows="1">Why is Sam so far behind this week, and what would get him one more cold call before Friday?</textarea>
|
|
51
|
+
<div class="ws-composer__trail">
|
|
52
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Add a file" title="Add a file">
|
|
53
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 3v10M3 8h10"/></svg>
|
|
54
|
+
</button>
|
|
55
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Dictate" aria-pressed="true" title="Dictating">
|
|
56
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="6" y="2" width="4" height="7" rx="2"/><path d="M4 7.5a4 4 0 0 0 8 0M8 13.5V15M6 15h4"/></svg>
|
|
57
|
+
</button>
|
|
58
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Send" title="Send">
|
|
59
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 13V3M4 7l4-4 4 4"/></svg>
|
|
60
|
+
</button>
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div class="ws-stack" style="max-width: 440px;">
|
|
67
|
+
<span class="ws-muted">With a lead (the home screen): the app's face and name, a rule, then the words</span>
|
|
41
68
|
<div class="ws-composer">
|
|
42
69
|
<div class="ws-composer__lead">
|
|
43
70
|
<span class="ws-disc ws-composer__face" aria-hidden="true">
|
|
44
71
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 4.5h10a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1H7l-2.5 2v-2H3a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1z"/></svg>
|
|
45
72
|
</span>
|
|
46
|
-
<span class="ws-composer__name">
|
|
73
|
+
<span class="ws-composer__name">Coach</span>
|
|
47
74
|
</div>
|
|
48
75
|
<span class="ws-composer__rule" aria-hidden="true"></span>
|
|
49
|
-
<
|
|
76
|
+
<label class="ws-sr" for="composer-lead">Message Coach</label>
|
|
77
|
+
<input id="composer-lead" class="ws-composer__words" type="text" placeholder="Message Coach">
|
|
50
78
|
<div class="ws-composer__trail">
|
|
51
|
-
<button class="ws-icon-btn" aria-label="
|
|
52
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.
|
|
53
|
-
</button>
|
|
54
|
-
<button class="ws-icon-btn" aria-label="Talk with your assistant, by voice" title="Talk">
|
|
55
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="2" width="4" height="7" rx="2"/><path d="M4 7.5a4 4 0 0 0 8 0M8 13.5V15M6 15h4"/></svg>
|
|
56
|
-
</button>
|
|
57
|
-
<button class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Send" title="Send">
|
|
58
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M8 13V3M4 7l4-4 4 4"/></svg>
|
|
79
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Talk with Coach" title="Talk (Alt+T)">
|
|
80
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M3 6.5v3M5.5 4.5v7M8 2.5v11M10.5 4.5v7M13 6.5v3"/></svg>
|
|
59
81
|
</button>
|
|
60
82
|
</div>
|
|
61
83
|
</div>
|
|
62
84
|
</div>
|
|
63
85
|
|
|
64
|
-
<div class="ws-stack">
|
|
65
|
-
<span class="ws-muted">Live: talking with the
|
|
86
|
+
<div class="ws-stack" style="max-width: 440px;">
|
|
87
|
+
<span class="ws-muted">Live: talking with Coach, the same box ringed, what is heard in the words</span>
|
|
66
88
|
<div class="ws-composer ws-composer--live">
|
|
67
89
|
<div class="ws-composer__lead">
|
|
68
90
|
<span class="ws-dot ws-working ws-composer__dot" aria-hidden="true"></span>
|
|
69
|
-
<span class="ws-composer__name">
|
|
91
|
+
<span class="ws-composer__name">Coach</span>
|
|
70
92
|
<span class="ws-muted ws-tnum">0:42</span>
|
|
71
93
|
</div>
|
|
72
94
|
<span class="ws-composer__rule" aria-hidden="true"></span>
|
|
73
|
-
<div class="ws-composer__words ws-composer__words--empty" role="status">Listening
|
|
95
|
+
<div class="ws-composer__words ws-composer__words--empty" role="status" title="Listening">Listening…</div>
|
|
74
96
|
<div class="ws-composer__trail">
|
|
75
|
-
<button class="ws-icon-btn" aria-label="Mute"
|
|
76
|
-
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3l10 10M9.8 9.9A4 4 0 0 1 4 7.5m4-5.2a2 2 0 0 1 2 2V8M6 6V4.3a2 2 0 0 1 .3-1M8 13.5V15M6 15h4"/></svg>
|
|
97
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--lg" aria-label="Mute" title="Mute">
|
|
98
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3l10 10M9.8 9.9A4 4 0 0 1 4 7.5m4-5.2a2 2 0 0 1 2 2V8M6 6V4.3a2 2 0 0 1 .3-1M8 13.5V15M6 15h4"/></svg>
|
|
77
99
|
</button>
|
|
78
|
-
<button class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="End the call with
|
|
79
|
-
<svg
|
|
100
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="End the call with Coach" title="End the call">
|
|
101
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>
|
|
102
|
+
</button>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div class="ws-stack" style="max-width: 440px;">
|
|
108
|
+
<span class="ws-muted">Field look, in a pane: the tray grey, 40 tall, the agent's face and a send arrow</span>
|
|
109
|
+
<div class="ws-composer ws-composer--field">
|
|
110
|
+
<svg class="ws-composer__face" viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 16.5V9l6.5-5.5L16.5 9v7.5Z"/><path d="M8 16.5v-4h4v4"/></svg>
|
|
111
|
+
<label class="ws-sr" for="composer-field">Ask Grow about Local search</label>
|
|
112
|
+
<input id="composer-field" class="ws-composer__words" type="text" placeholder="Ask Grow about Local search">
|
|
113
|
+
<div class="ws-composer__trail">
|
|
114
|
+
<button type="button" class="ws-icon-btn" aria-label="Send" title="Send">
|
|
115
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M8 13V3M4 7l4-4 4 4"/></svg>
|
|
80
116
|
</button>
|
|
81
117
|
</div>
|
|
82
118
|
</div>
|
|
83
119
|
</div>
|
|
84
120
|
|
|
121
|
+
<div class="ws-stack" style="max-width: 440px;" data-live>
|
|
122
|
+
<span class="ws-muted">Live: the placeholder rolls to the next question every 3.4 s on the roll spring, up out of 12 px and a 3 px blur (rollPlaceholder); click in and the focus glow gathers under the box on the glow spring</span>
|
|
123
|
+
<div class="ws-composer">
|
|
124
|
+
<label class="ws-sr" for="composer-live">Message Coach</label>
|
|
125
|
+
<span class="ws-composer__slot">
|
|
126
|
+
<textarea id="composer-live" class="ws-composer__words" rows="1" placeholder="Who should I call first?"></textarea>
|
|
127
|
+
<span class="ws-composer__roll" aria-hidden="true" id="composer-live-roll">
|
|
128
|
+
<span>Who should I call first?</span>
|
|
129
|
+
<span>Why did calls drop?</span>
|
|
130
|
+
<span>Who needs a nudge?</span>
|
|
131
|
+
</span>
|
|
132
|
+
</span>
|
|
133
|
+
<div class="ws-composer__trail">
|
|
134
|
+
<button type="button" class="ws-icon-btn ws-icon-btn--primary ws-icon-btn--lg" aria-label="Talk with Coach" title="Talk (Alt+T)">
|
|
135
|
+
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" aria-hidden="true"><path d="M3 6.5v3M5.5 4.5v7M8 2.5v11M10.5 4.5v7M13 6.5v3"/></svg>
|
|
136
|
+
</button>
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
<script>
|
|
141
|
+
(() => {
|
|
142
|
+
// A copy of rollPlaceholder() from @felloinnovations/brand-kit (src/lib/motion.ts): a preview cannot import the package.
|
|
143
|
+
const roll = document.getElementById('composer-live-roll'), lines = [...roll.children];
|
|
144
|
+
let at = 0;
|
|
145
|
+
lines[0].setAttribute('data-on', '');
|
|
146
|
+
if (matchMedia('(prefers-reduced-motion: reduce)').matches) return;
|
|
147
|
+
setInterval(() => {
|
|
148
|
+
const was = lines[at];
|
|
149
|
+
at = (at + 1) % lines.length;
|
|
150
|
+
const next = lines[at];
|
|
151
|
+
for (const l of lines) l.removeAttribute('data-off');
|
|
152
|
+
next.removeAttribute('data-on');
|
|
153
|
+
void next.offsetWidth;
|
|
154
|
+
was.removeAttribute('data-on');
|
|
155
|
+
was.setAttribute('data-off', '');
|
|
156
|
+
next.setAttribute('data-on', '');
|
|
157
|
+
}, 3400);
|
|
158
|
+
})();
|
|
159
|
+
</script>
|
|
85
160
|
</div>
|
|
86
161
|
</body>
|
|
87
162
|
</html>
|