@thewhatmatters/wmds 0.4.0 → 0.4.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/CHANGELOG.md +68 -0
- package/CONSUMING.md +8 -4
- package/dist/collapse.css +9 -1
- package/dist/colors.css +7 -0
- package/dist/components/atoms/Badge/Badge.d.ts +16 -4
- package/dist/components/atoms/Badge/Badge.d.ts.map +1 -1
- package/dist/components/atoms/Badge/Badge.js +54 -42
- package/dist/components/atoms/Badge/badgeStyles.d.ts +12 -2
- package/dist/components/atoms/Badge/badgeStyles.d.ts.map +1 -1
- package/dist/components/atoms/Badge/badgeStyles.js +24 -13
- package/dist/components/atoms/Button/Button.d.ts +11 -3
- package/dist/components/atoms/Button/Button.d.ts.map +1 -1
- package/dist/components/atoms/Button/Button.js +118 -98
- package/dist/components/atoms/Button/ButtonStatusButton.d.ts +3 -1
- package/dist/components/atoms/Button/ButtonStatusButton.d.ts.map +1 -1
- package/dist/components/atoms/Button/ButtonStatusButton.js +19 -18
- package/dist/components/atoms/Button/ButtonStatusContent.d.ts +7 -1
- package/dist/components/atoms/Button/ButtonStatusContent.d.ts.map +1 -1
- package/dist/components/atoms/Button/ButtonStatusContent.js +9 -6
- package/dist/components/atoms/Button/buttonStatusStyles.d.ts +5 -0
- package/dist/components/atoms/Button/buttonStatusStyles.d.ts.map +1 -1
- package/dist/components/atoms/Button/buttonStatusStyles.js +10 -10
- package/dist/components/atoms/Button/buttonStyles.d.ts +2 -0
- package/dist/components/atoms/Button/buttonStyles.d.ts.map +1 -1
- package/dist/components/atoms/Button/buttonStyles.js +12 -12
- package/dist/components/atoms/Checkbox/Checkbox.d.ts +7 -0
- package/dist/components/atoms/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/atoms/Checkbox/Checkbox.js +86 -69
- package/dist/components/atoms/Checkbox/checkboxStyles.d.ts +6 -0
- package/dist/components/atoms/Checkbox/checkboxStyles.d.ts.map +1 -1
- package/dist/components/atoms/Checkbox/checkboxStyles.js +11 -11
- package/dist/components/atoms/IconButton/IconButton.d.ts +5 -0
- package/dist/components/atoms/IconButton/IconButton.d.ts.map +1 -1
- package/dist/components/atoms/IconButton/IconButton.js +73 -68
- package/dist/components/atoms/IconButton/iconButtonStyles.d.ts +5 -0
- package/dist/components/atoms/IconButton/iconButtonStyles.d.ts.map +1 -1
- package/dist/components/atoms/IconButton/iconButtonStyles.js +4 -4
- package/dist/components/atoms/Kbd/useKbdChoiceKeys.d.ts +13 -4
- package/dist/components/atoms/Kbd/useKbdChoiceKeys.d.ts.map +1 -1
- package/dist/components/atoms/Kbd/useKbdChoiceKeys.js +32 -13
- package/dist/components/atoms/Prose/Prose.d.ts +23 -0
- package/dist/components/atoms/Prose/Prose.d.ts.map +1 -0
- package/dist/components/atoms/Prose/Prose.js +15 -0
- package/dist/components/atoms/Prose/proseStyles.d.ts +17 -0
- package/dist/components/atoms/Prose/proseStyles.d.ts.map +1 -0
- package/dist/components/atoms/Prose/proseStyles.js +16 -0
- package/dist/components/atoms/SectionCaption/SectionCaption.d.ts +26 -0
- package/dist/components/atoms/SectionCaption/SectionCaption.d.ts.map +1 -0
- package/dist/components/atoms/SectionCaption/SectionCaption.js +25 -0
- package/dist/components/atoms/SectionCaption/sectionCaptionStyles.d.ts +11 -0
- package/dist/components/atoms/SectionCaption/sectionCaptionStyles.d.ts.map +1 -0
- package/dist/components/atoms/SectionCaption/sectionCaptionStyles.js +12 -0
- package/dist/components/atoms/TextLink/TextLink.d.ts +10 -2
- package/dist/components/atoms/TextLink/TextLink.d.ts.map +1 -1
- package/dist/components/atoms/TextLink/TextLink.js +15 -15
- package/dist/components/atoms/TextLink/textLinkStyles.d.ts +13 -0
- package/dist/components/atoms/TextLink/textLinkStyles.d.ts.map +1 -1
- package/dist/components/atoms/TextLink/textLinkStyles.js +7 -3
- package/dist/components/molecules/Accordion/Accordion.d.ts +6 -1
- package/dist/components/molecules/Accordion/Accordion.d.ts.map +1 -1
- package/dist/components/molecules/Accordion/Accordion.js +57 -50
- package/dist/components/molecules/Accordion/accordionStyles.d.ts +9 -0
- package/dist/components/molecules/Accordion/accordionStyles.d.ts.map +1 -1
- package/dist/components/molecules/Accordion/accordionStyles.js +2 -2
- package/dist/components/molecules/CheckboxGroup/CheckboxGroupItem.d.ts +5 -1
- package/dist/components/molecules/CheckboxGroup/CheckboxGroupItem.d.ts.map +1 -1
- package/dist/components/molecules/CheckboxGroup/CheckboxGroupItem.js +12 -10
- package/dist/components/molecules/DescriptionList/DescriptionList.d.ts +37 -0
- package/dist/components/molecules/DescriptionList/DescriptionList.d.ts.map +1 -0
- package/dist/components/molecules/DescriptionList/DescriptionList.js +50 -0
- package/dist/components/molecules/DescriptionList/descriptionListStyles.d.ts +21 -0
- package/dist/components/molecules/DescriptionList/descriptionListStyles.d.ts.map +1 -0
- package/dist/components/molecules/DescriptionList/descriptionListStyles.js +27 -0
- package/dist/components/molecules/IndexList/IndexList.d.ts +58 -0
- package/dist/components/molecules/IndexList/IndexList.d.ts.map +1 -0
- package/dist/components/molecules/IndexList/IndexList.js +96 -0
- package/dist/components/molecules/IndexList/indexListStyles.d.ts +29 -0
- package/dist/components/molecules/IndexList/indexListStyles.d.ts.map +1 -0
- package/dist/components/molecules/IndexList/indexListStyles.js +24 -0
- package/dist/components/molecules/PromptBar/promptBarStyles.d.ts +3 -2
- package/dist/components/molecules/PromptBar/promptBarStyles.d.ts.map +1 -1
- package/dist/components/molecules/PromptBar/promptBarStyles.js +1 -1
- package/dist/components/organisms/ChatDock/ChatDock.d.ts +120 -10
- package/dist/components/organisms/ChatDock/ChatDock.d.ts.map +1 -1
- package/dist/components/organisms/ChatDock/ChatDock.js +654 -212
- package/dist/components/organisms/ChatDock/ChatDockGate.d.ts +52 -0
- package/dist/components/organisms/ChatDock/ChatDockGate.d.ts.map +1 -0
- package/dist/components/organisms/ChatDock/ChatDockGate.js +161 -0
- package/dist/components/organisms/ChatDock/chatDockGateStyles.d.ts +16 -0
- package/dist/components/organisms/ChatDock/chatDockGateStyles.d.ts.map +1 -0
- package/dist/components/organisms/ChatDock/chatDockGateStyles.js +8 -0
- package/dist/components/organisms/ChatDock/chatDockStyles.d.ts +60 -10
- package/dist/components/organisms/ChatDock/chatDockStyles.d.ts.map +1 -1
- package/dist/components/organisms/ChatDock/chatDockStyles.js +15 -9
- package/dist/components/organisms/ChatDock/chatDockViewport.d.ts +21 -0
- package/dist/components/organisms/ChatDock/chatDockViewport.d.ts.map +1 -0
- package/dist/components/organisms/ChatDock/chatDockViewport.js +46 -0
- package/dist/components/organisms/Toast/Toast.js +5 -5
- package/dist/index.d.ts +7 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +122 -112
- package/dist/lib/compositionAudit.d.ts.map +1 -1
- package/dist/lib/typography.d.ts +2 -2
- package/dist/lib/typography.d.ts.map +1 -1
- package/dist/lib/typography.js +27 -1
- package/dist/styles.css +1 -1
- package/dist/theme.css +1 -0
- package/dist/typography.css +34 -0
- package/docs/README.md +1 -1
- package/docs/component-contracts.md +15 -0
- package/docs/components.md +15 -11
- package/docs/exports.json +69 -4
- package/docs/patterns/components-accordion--flush.tsx +29 -0
- package/docs/patterns/components-avatar--dropdown-row.tsx +1 -1
- package/docs/patterns/components-badge--outline-tags.tsx +25 -0
- package/docs/patterns/components-badge--with-avatar.tsx +1 -1
- package/docs/patterns/components-button-button--copy-button.tsx +39 -0
- package/docs/patterns/components-button-button--destructive-action.tsx +1 -1
- package/docs/patterns/components-button-button--external-link.tsx +30 -0
- package/docs/patterns/components-button-button--ghost-action.tsx +1 -1
- package/docs/patterns/components-button-button--inverse-action.tsx +1 -1
- package/docs/patterns/components-button-button--link-render.tsx +1 -1
- package/docs/patterns/components-button-button--multi-state-badge.tsx +1 -1
- package/docs/patterns/components-button-button--outline-mono.tsx +1 -1
- package/docs/patterns/components-button-button--primary-action.tsx +1 -1
- package/docs/patterns/components-button-button--row-hug.tsx +1 -1
- package/docs/patterns/components-button-button--row-layout.tsx +1 -1
- package/docs/patterns/components-button-button--secondary-action.tsx +1 -1
- package/docs/patterns/components-button-button--suggestion-pills.tsx +1 -1
- package/docs/patterns/components-button-button--with-count.tsx +1 -1
- package/docs/patterns/components-button-button--with-icon.tsx +1 -1
- package/docs/patterns/components-button-floatingactionbutton--vertical-actions.tsx +1 -1
- package/docs/patterns/components-calembed--pattern-skip-in-footer.tsx +1 -1
- package/docs/patterns/components-card-card--body-slot-occupancy-history.tsx +1 -1
- package/docs/patterns/components-card-card--headerless-media.tsx +1 -1
- package/docs/patterns/components-card-card--outlined-layout.tsx +1 -1
- package/docs/patterns/components-card-card--pinned-height.tsx +1 -1
- package/docs/patterns/components-card-selectablecard--selectable-cards-pattern.tsx +1 -1
- package/docs/patterns/components-chart--audience-activity-heatmap.tsx +1 -1
- package/docs/patterns/components-chart--cartesian-no-data-gaps.tsx +1 -1
- package/docs/patterns/components-chart--occupancy-history-in-card.tsx +1 -1
- package/docs/patterns/components-chart--occupancy-in-card.tsx +1 -1
- package/docs/patterns/components-chart--post-reach-distribution.tsx +1 -1
- package/docs/patterns/components-chart--ranked-audience-breakdown.tsx +1 -1
- package/docs/patterns/components-chart--unit-grid-composition.tsx +1 -1
- package/docs/patterns/components-chatdock--pattern-chat-dock.tsx +101 -11
- package/docs/patterns/components-chatdock--pattern-start-project-gate.tsx +180 -0
- package/docs/patterns/components-chatqa--pattern-qa-with-reply.tsx +1 -1
- package/docs/patterns/components-checkbox-checkbox--default.tsx +1 -1
- package/docs/patterns/components-checkbox-checkbox--with-count.tsx +19 -0
- package/docs/patterns/components-checkbox-checkbox--with-description.tsx +1 -1
- package/docs/patterns/components-checkbox-checkboxgroup--default.tsx +1 -1
- package/docs/patterns/components-checkbox-checkboxgroup--option-counts.tsx +17 -0
- package/docs/patterns/components-descriptionlist--details.tsx +21 -0
- package/docs/patterns/components-descriptionlist--post-metadata.tsx +52 -0
- package/docs/patterns/components-dialog--alert-dialog-destructive.tsx +1 -1
- package/docs/patterns/components-dialog--default-dialog.tsx +1 -1
- package/docs/patterns/components-dialog--form-dialog.tsx +1 -1
- package/docs/patterns/components-displaycontrols--page-utilities.tsx +1 -1
- package/docs/patterns/components-field--horizontal-input.tsx +1 -1
- package/docs/patterns/components-field--horizontal-text-area.tsx +1 -1
- package/docs/patterns/components-field--multi-control.tsx +1 -1
- package/docs/patterns/components-footerreveal--marketing-hero-pattern.tsx +1 -1
- package/docs/patterns/components-footerreveal--marketing-hero-ruled-pattern.tsx +1 -1
- package/docs/patterns/components-footerreveal--marketing-hero-with-gallery-intro.tsx +1 -1
- package/docs/patterns/components-footerreveal--marketing-page-pattern.tsx +1 -1
- package/docs/patterns/components-footerreveal--ruled-grid-footer-pattern.tsx +1 -1
- package/docs/patterns/components-footerreveal--sequenced-marketing-hero.tsx +1 -1
- package/docs/patterns/components-herointro--two-line-intro.tsx +1 -1
- package/docs/patterns/components-herotilestack--marketing-hero-pattern.tsx +1 -1
- package/docs/patterns/components-herotilestack--marketing-hero-text-sequence.tsx +1 -1
- package/docs/patterns/components-herotilestack--marketing-hero-with-gallery-intro.tsx +1 -1
- package/docs/patterns/components-indexlist--post-index.tsx +36 -0
- package/docs/patterns/components-intakeconfirmation--booked-pattern.tsx +1 -1
- package/docs/patterns/components-intakeconfirmation--emailed-pattern.tsx +1 -1
- package/docs/patterns/components-intakeform--about-you-pattern.tsx +1 -1
- package/docs/patterns/components-intakemodal--intake-modal-pattern.tsx +1 -1
- package/docs/patterns/components-kbd--command-row.tsx +1 -1
- package/docs/patterns/components-kbd--numbered-choices.tsx +1 -1
- package/docs/patterns/components-kbd--shortcut.tsx +1 -1
- package/docs/patterns/components-moremenu--action-menu.tsx +1 -1
- package/docs/patterns/components-moremenu--in-card-header.tsx +1 -1
- package/docs/patterns/components-navlist--side-nav-settings.tsx +1 -1
- package/docs/patterns/components-pageheader--app-header-pattern.tsx +1 -1
- package/docs/patterns/components-pageheader--page-section-header.tsx +1 -1
- package/docs/patterns/components-pageheader--toolbar-header.tsx +1 -1
- package/docs/patterns/components-panel--end-detail-rail.tsx +1 -1
- package/docs/patterns/components-pillgroup--pill-group-pattern.tsx +1 -1
- package/docs/patterns/components-promptbar--pattern-prompt-bar.tsx +1 -1
- package/docs/patterns/components-prose--article-body.tsx +11 -0
- package/docs/patterns/components-radio-radiogroup--default.tsx +1 -1
- package/docs/patterns/components-scrollhorizontal--project-gallery-pattern.tsx +1 -1
- package/docs/patterns/components-scrollhorizontal--with-intro.tsx +1 -1
- package/docs/patterns/components-sectioncaption--column-caption.tsx +16 -0
- package/docs/patterns/components-sectioncaption--with-action.tsx +19 -0
- package/docs/patterns/components-sheet--bottom-sheet.tsx +1 -1
- package/docs/patterns/components-sheet--end-sheet.tsx +1 -1
- package/docs/patterns/components-sitenav--brand-and-cta.tsx +1 -1
- package/docs/patterns/components-sitenav--centered-links.tsx +1 -1
- package/docs/patterns/components-sitenav--compact.tsx +1 -1
- package/docs/patterns/components-sitenav--marketing-header.tsx +1 -1
- package/docs/patterns/components-sitenav--mega-menu.tsx +1 -1
- package/docs/patterns/components-stat--insights-row.tsx +1 -1
- package/docs/patterns/components-stepprogress--step-progress-pattern.tsx +1 -1
- package/docs/patterns/components-switch--default.tsx +1 -1
- package/docs/patterns/components-switch--settings-row.tsx +1 -1
- package/docs/patterns/components-tab--settings-pages.tsx +1 -1
- package/docs/patterns/components-taskrows--action-details.tsx +1 -1
- package/docs/patterns/components-taskrows--capsules.tsx +1 -1
- package/docs/patterns/components-taskrows--card-with-status-rows.tsx +1 -1
- package/docs/patterns/components-taskrows--controlled-expand.tsx +1 -1
- package/docs/patterns/components-taskrows--custom-slots.tsx +1 -1
- package/docs/patterns/components-taskrows--status-list.tsx +1 -1
- package/docs/patterns/components-taskrows--tag-chips.tsx +1 -1
- package/docs/patterns/components-textlink--external-destination.tsx +1 -1
- package/docs/patterns/components-textlink--inline-prose.tsx +1 -1
- package/docs/patterns/components-textlink--quiet-title.tsx +15 -0
- package/docs/patterns/components-textlink--supporting-copy.tsx +1 -1
- package/docs/patterns/components-textsequence--default.tsx +1 -1
- package/docs/patterns/components-textsequence--reduced-motion.tsx +1 -1
- package/docs/patterns/components-textsequence--shapes.tsx +1 -1
- package/docs/patterns/components-toast--stacked-notifications.tsx +1 -1
- package/docs/patterns/components-tooltip--controlled.tsx +1 -1
- package/docs/patterns/components-tooltip--disabled-control.tsx +1 -1
- package/docs/patterns/components-tooltip--icon-action.tsx +1 -1
- package/docs/patterns/components-tooltip--keyboard-shortcut.tsx +1 -1
- package/docs/patterns/components-tooltip--placement.tsx +1 -1
- package/docs/patterns/foundations-scroll-fade--horizontal-rail.tsx +1 -1
- package/docs/patterns/foundations-scroll-fade--overflowing-list.tsx +1 -1
- package/docs/patterns/guides-chart-explorations--comparison-gallery.tsx +1 -1
- package/docs/patterns/guides-filter-panel--filtered-index.tsx +174 -0
- package/docs/patterns/guides-overlay-flows--notification-preferences.tsx +1 -1
- package/docs/patterns/guides-post-page--post-page.tsx +143 -0
- package/docs/patterns/guides-profile-typography--editorial-profile.tsx +1 -1
- package/docs/patterns/index.json +129 -1
- package/package.json +1 -1
package/dist/theme.css
CHANGED
|
@@ -90,6 +90,7 @@
|
|
|
90
90
|
--color-on-brand-hover: var(--color-on-brand-hover);
|
|
91
91
|
--color-brand-outline: var(--color-brand-outline);
|
|
92
92
|
--color-brand-soft: var(--color-brand-soft);
|
|
93
|
+
--color-brand-tint: var(--color-brand-tint);
|
|
93
94
|
--color-primary: var(--color-primary);
|
|
94
95
|
--color-primary-foreground: var(--color-on-primary);
|
|
95
96
|
--color-primary-hover: var(--color-primary-hover);
|
package/dist/typography.css
CHANGED
|
@@ -110,6 +110,24 @@
|
|
|
110
110
|
--text-code-weight: var(--font-weight-normal);
|
|
111
111
|
--text-code-leading: 1.4286;
|
|
112
112
|
|
|
113
|
+
/**
|
|
114
|
+
* WMDS extension — long-form reading text (**Prose** `size="lg"`): 17px at a 28px line. Article
|
|
115
|
+
* bodies at the 40rem reading measure; UI copy stays on `type-body`.
|
|
116
|
+
*/
|
|
117
|
+
--text-reading-size: var(--font-size-lg);
|
|
118
|
+
--text-reading-weight: var(--font-weight-normal);
|
|
119
|
+
--text-reading-leading: 1.6471;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* WMDS extension — small uppercase mono caption for editorial labels: column captions over index
|
|
123
|
+
* rows and filter panel titles ("/ Date", "/ Filters"). Write the text in sentence case; the
|
|
124
|
+
* utility sets the capitals.
|
|
125
|
+
*/
|
|
126
|
+
--text-eyebrow-size: var(--font-size-sm);
|
|
127
|
+
--text-eyebrow-weight: var(--font-weight-normal);
|
|
128
|
+
--text-eyebrow-leading: 1.3333;
|
|
129
|
+
--text-eyebrow-tracking: 0.05em;
|
|
130
|
+
|
|
113
131
|
/** WMDS extension — fixed-height control shells (Button, Chip, Input). Phase 4 migrates atoms here. */
|
|
114
132
|
--text-control-size: var(--font-size-base);
|
|
115
133
|
--text-control-weight: var(--font-weight-medium);
|
|
@@ -216,6 +234,22 @@
|
|
|
216
234
|
line-height: var(--text-code-leading);
|
|
217
235
|
}
|
|
218
236
|
|
|
237
|
+
@utility type-reading {
|
|
238
|
+
font-family: var(--font-family-body);
|
|
239
|
+
font-size: var(--text-reading-size);
|
|
240
|
+
font-weight: var(--text-reading-weight);
|
|
241
|
+
line-height: var(--text-reading-leading);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
@utility type-eyebrow {
|
|
245
|
+
font-family: var(--font-family-code);
|
|
246
|
+
font-size: var(--text-eyebrow-size);
|
|
247
|
+
font-weight: var(--text-eyebrow-weight);
|
|
248
|
+
line-height: var(--text-eyebrow-leading);
|
|
249
|
+
letter-spacing: var(--text-eyebrow-tracking);
|
|
250
|
+
text-transform: uppercase;
|
|
251
|
+
}
|
|
252
|
+
|
|
219
253
|
@utility type-control {
|
|
220
254
|
font-family: var(--font-family-body);
|
|
221
255
|
font-size: var(--text-control-size);
|
package/docs/README.md
CHANGED
|
@@ -6,7 +6,7 @@ These files ship in the npm package at `node_modules/@thewhatmatters/wmds/docs/`
|
|
|
6
6
|
|------|------------|
|
|
7
7
|
| `exports.json` | Every export with its tier, category, one-line summary, Storybook page, and the ids of its patterns. Also the CSS entries, peer dependencies, planned components, and lib helpers. |
|
|
8
8
|
| `components.md` | The component and token contracts: props, patterns, composition rules, and what not to do. |
|
|
9
|
-
| `component-contracts.md` | Long-form contracts for FooterReveal, HeroTileStack, TextSequence, ScrollHorizontal, RiveHand, and
|
|
9
|
+
| `component-contracts.md` | Long-form contracts for FooterReveal, HeroTileStack, TextSequence, ScrollHorizontal, RiveHand, PromptBar, and ChatDock. |
|
|
10
10
|
| `patterns/index.json` | One row per pattern: id, Storybook title, pattern name, file. |
|
|
11
11
|
| `patterns/<id>.tsx` | A pattern's Show code, exactly as Storybook shows it, with a header naming the pattern and the package version. |
|
|
12
12
|
| `consumer-agents.md` | A block to paste into a consuming repo's `AGENTS.md` / `CLAUDE.md`. |
|
|
@@ -25,3 +25,18 @@ decorative hand on the marketing hero headline, from `public/rive/interactive-ic
|
|
|
25
25
|
## PromptBar
|
|
26
26
|
|
|
27
27
|
wide prompt pill — inline **TextArea** (`rows={1}`, one line when empty, grows through **3 lines**, then scrolls) and an **IconButton** `sm` send control (Lucide **ArrowRight**) inset with even padding. The pill owns focus; the send control does not draw a second ring. Placeholder **Ask anything…**. Enter sends; Shift+Enter inserts a newline. Send stays disabled and muted until the draft has text, then uses **`--color-brand`** (`#011272` / `bg-brand`). No new Button role. Voice and attachments are not part of this version. Copy **Components/PromptBar → Pattern — prompt bar**. Optional `start` holds the brand mark (**Avatar** `size="md"`, the send circle's size) and `end` holds extra inset **IconButton** `sm` controls before send. On the marketing pages **PromptBar** appears inside **ChatDock** (**Components/ChatDock → Pattern — chat dock**): pinned to the bottom of the page grid (`--grid-max: 40rem`, above the safe area, under **SiteNav**), it opens into a non-modal chat window instead of handing off to a separate ask page. Do not hand-roll the pin, and do not restyle **SiteNav**.
|
|
28
|
+
|
|
29
|
+
## ChatDock
|
|
30
|
+
|
|
31
|
+
The site assistant. At rest, a **PromptBar** pinned to the bottom of the page grid (`--grid-max: 40rem`, above the safe area, under **SiteNav**), with the brand `mark` (**Avatar** `size="md"`) in its `start` slot. Hovering the bar shows the `suggestions` that carry a `prompt` as **Button** `secondary` pills above it, one `--motion-stagger` apart; touch never shows them. Focusing, clicking, or typing opens a non-modal window around the same composer, and Escape or **Close chat** folds it back. One **PromptBar** serves both states, so the composer is on screen every frame and never jumps. From `md` the window is an opaque card on the composer's bottom edge that grows up and out of it on the medium tier — height, 16px wider on each side, pill radius to the shell radius; the mark folds out of the composer (the header carries it), and the composer keeps its width, rising only by the `disclaimer` line that opens under it. The header, conversation, and rows fade in one `--motion-stagger` apart, a `--motion-beat` after the window starts; on close they fade first, the window folds back into the bar, and the hover pills return once it has folded. Below `md` the window fills the screen and rises from the bottom edge, and falls back on close. Escape while opening, or a click in the composer while closing, reverses from where it is. Reduced motion crossfades the window in place at full size; nothing slides, so the mark and the disclaimer line switch at once and the composer steps up by that line. The window is the shared overlay header (mark, `title`, `subtitle`, close only — no send or expand arrow), the conversation (`role="log"`: `greeting`, then `messages`; the visitor's turns sit on `bg-brand-tint`, replies are plain text; a **Status** dot thinking row while `thinking`), and the suggestion rows (**Button** `layout="row"`) until the first message — a row that sends moves focus to the composer, since the rows leave as the message lands, so Escape still closes the window; the composer and the `disclaimer` caption sit on top of it. The thread stays pinned to the end while the reader is there.
|
|
32
|
+
|
|
33
|
+
**Follow-ups.** `followUps` takes the same items as `suggestions` (`{ id, label, prompt? }`; an `icon` is not shown) for the latest reply only. They show while the last message is an assistant reply and `thinking` is off, and disappear the moment the visitor sends — ChatDock hides them itself before the app clears them, so they never sit beside a pending reply. Choosing one calls `onSuggestionSelect`, then `onSend` with its `prompt` when it has one; an item without a `prompt` (for example **Start a project**) only calls `onSuggestionSelect`. The press does not take focus from the composer, and a keyboard choice hands focus back to it. They rise in one `--motion-stagger` apart (fast tier) and leave at once. `followUpsPlacement="inline"` (default) renders them as **Button** `layout="row"` rows in the conversation, directly under the reply, each led by Lucide **CornerDownRight**, in a group named `labels.followUps` (**Suggested follow-ups**) — 44px targets below `md`, 36px from `md`. `followUpsPlacement="composer"` renders text-only **Button** `secondary` pills between the conversation and the composer; they wrap, so at 390 three take about 150px from the conversation. The app decides which replies get follow-ups; **Pattern — chat dock** holds the state (set from `ask`'s result, cleared on send).
|
|
34
|
+
|
|
35
|
+
**Reply row.** Under each finished reply, a row of up to three parts, each shown on its own: **Copy** when the message has `copyText` (it writes that text to the clipboard, swaps its icon to a check and its name to `labels.copied` for two seconds, and announces it in a status region); thumbs up and down when `onMessageFeedback` is passed and the message carries `feedback` (**IconButton** `pressed` toggles named `labels.helpful` / `labels.notHelpful`, one vote at a time; `feedback` is `"up" | "down" | null` — `null` until the visitor votes — and pressing the active thumb calls `onMessageFeedback(message, null)`; leave `feedback` out on replies that take no vote, such as a form's summary); and the score when the message has `meta` (`label` as muted caption text, not a control; `description` follows it for screen readers). Visitor turns and the greeting never have a row. Where the pointer can hover, the row shows while the reply is hovered or holds focus (fast tier); on touch screens it is always shown. Either way it keeps its height, so the thread never moves. While `thinking` is on, the latest reply is still arriving: its row keeps its place but shows nothing. Buttons are **IconButton** `md` (44px) below `md` and `sm` (36px) from `md`, pulled out so the first glyph lines up with the reply text. **Pattern — chat dock** holds the votes: `ask` resolves with `string | { reply, followUps?, meta?, copyText?, startProject? }` (`copyText` defaults to the reply; replies start with `feedback: null`), and each vote goes to its required `onFeedback` prop. It also holds Start a project: `startProject` / `onStartProjectChange` (a site button sets it; the Start a project suggestion and an `ask` result with `startProject` open it) and `renderStartProject`, which returns the gate.
|
|
36
|
+
|
|
37
|
+
**Gate.** `gate` puts a multi-step form in the composer's place — **ChatDock.Gate** (`ChatDockGate`), for Start a project. While it is set and the window is open, the composer, the suggestion rows, the follow-ups, and the disclaimer step aside; the conversation stays above it. Setting it opens the window (closed, or mid-conversation) and moves focus to the gate; clearing it brings the composer back and returns focus to it. The composer and the gate share one cell and crossfade (fast tier) while the area eases between their heights (medium tier); both stay mounted, so a gate keeps its progress when the visitor closes the window with it up, and it is there when the window reopens. The gate hugs each step up to a cap — the window less its header, 7rem of conversation, and the space under the gate, never below 12rem — so the last lines of the latest reply stay in view; past the cap its body scrolls. Escape belongs to the gate: **ChatDock.Gate** calls `onClose` on it, and ChatDock does not fold the window on Escape while a gate is up (a second Escape, at the composer, does). **ChatDock.Gate** is a **Card** (`as="section"`, `padding="none"`, `variant="surface"`): `title` (names the gate) and `subtitle`; at the end of the header **IconButton** previous (disabled on step 1), the progress (`labels.progress`, "2 of 4", announced politely), next (disabled without `onNext` or while `canContinue` is false), and close; the step in **Card.Body** on the inset well, sliding between steps (fast tier) while the body eases to the new height (medium tier); **Card.Footer** with `footerStart` (for example **CalEmbed.Skip**), Cancel, and the primary action (`continueLabel`, shown when `onNext` is passed). Controls are 44px below `md` and 36px from `md`. Number keys belong to the pattern through **useKbdChoiceKeys** with `scope` set to the gate, so digits act only while focus is in it. **Pattern — start a project gate** fills four steps — services as numbered **Checkbox** rows, budget as numbered **Radio** rows, **IntakeForm**, **CalEmbed** — and on booking or skipping calls `onSubmit`, fires confetti from the control used, and hands the conversation the answers (**ChatQa**) and a confirmation line.
|
|
38
|
+
|
|
39
|
+
**Phones.** Below `md` the window fills the part of the screen a keyboard leaves visible (`visualViewport`), and the composer and a gate sit at its bottom edge.
|
|
40
|
+
|
|
41
|
+
The app owns `messages`, `thinking`, `followUps`, the votes, the gate's open state, `onSend`, and `onSuggestionSelect`; ChatDock never fetches or parses Markdown (`content` is text or rendered Markdown). `placement="inline"` is for previews only. Copy **Components/ChatDock → Pattern — chat dock**. See **ADR-0039**.
|
|
42
|
+
|
package/docs/components.md
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
# @thewhatmatters/wmds — component contracts
|
|
2
2
|
|
|
3
|
-
Version 0.4.
|
|
3
|
+
Version 0.4.1. Generated from the WMDS repository's AGENTS.md (Storybook-first) by `scripts/generate-package-docs.mjs` — do not edit here.
|
|
4
4
|
|
|
5
5
|
Storybook paths such as **Components/Button/Button → Pattern — …** name a story; its Show code is in `patterns/` (see `patterns/index.json`). Longer contracts for FooterReveal, HeroTileStack, TextSequence, ScrollHorizontal, RiveHand, and PromptBar are in `component-contracts.md`. ADR numbers refer to decision records in the WMDS repository.
|
|
6
6
|
|
|
7
7
|
- **Theme** lives in `src/theme/` — `colors.css` (semantic roles) + `theme.css` (Tailwind `@theme` bridge). Storybook is the source of truth, not Paper.
|
|
8
8
|
- **Dark mode:** `[data-theme="dark"]` on `<html>` or any ancestor — same token names, swapped values in `colors.css`.
|
|
9
9
|
- **Consuming apps:** use exported components and typed props; `className` for layout only — not re-theming. Page layout utilities (`gap`, `grid`, `max-w`) are fine between components.
|
|
10
|
-
- **Theme tokens:** Semantic roles in **`src/theme/colors.css`**; typography in **`src/theme/typography.css`** (`type-*` utilities, geometric scale; **display-1/2/3** are fluid via `clamp` — display-1 hits **5rem** on desktop and scales down to **2.5rem** on mobile); motion in **`src/theme/motion.css`**; page spine in **`src/theme/grid.css`** (`--grid-*`, `grid-page` / `band`, `--leading-base`). **`--spacing` stays 4px** — do not re-scale; baseline is 8px. See **ADR-0007**, **ADR-0008**, **ADR-0009**, **ADR-0010**, **DESIGN.md → Grid**. Use **`typographyClass()`** — not raw `text-sm` in document copy.
|
|
10
|
+
- **Theme tokens:** Semantic roles in **`src/theme/colors.css`**; typography in **`src/theme/typography.css`** (`type-*` utilities, geometric scale; **display-1/2/3** are fluid via `clamp` — display-1 hits **5rem** on desktop and scales down to **2.5rem** on mobile); motion in **`src/theme/motion.css`**; page spine in **`src/theme/grid.css`** (`--grid-*`, `grid-page` / `band`, `--leading-base`). **`--spacing` stays 4px** — do not re-scale; baseline is 8px. See **ADR-0007**, **ADR-0008**, **ADR-0009**, **ADR-0010**, **DESIGN.md → Grid**. Use **`typographyClass()`** — not raw `text-sm` in document copy. **`type-eyebrow`** (`typographyClass("eyebrow")`) is the small uppercase mono caption for editorial labels — **SectionCaption**, **IndexList** captions, **DescriptionList** `variant="mono"` names; write the text in sentence case — the "/" marker comes from the component, `aria-hidden`. Not for app UI section labels (`overline`) or secondary text (`caption`). **`type-reading`** (`typographyClass("reading")`, 17px at a 28px line) is long-form article text — **Prose** sets it; UI copy stays on `type-body`. A dotted hairline is **DescriptionList** `rule="dotted"`. See **ADR-0040**, **ADR-0041**.
|
|
11
11
|
- **Page layout:** Every Storybook **Guides** page and consuming product page starts on **`grid-page`**; use **`band`** + responsive column spans for content alignment. Constrain a specific experience by overriding **`--grid-max`** on that wrapper (for example, `960px`) rather than replacing the grid with an arbitrary centered container.
|
|
12
12
|
- **Scroll fade:** use **`scroll-fade-y`** / **`scroll-fade-x`** on the element that owns overflow to hint at clipped list or rail content. The mask is scroll-aware, disappears when no overflow exists in supporting browsers, and follows inline direction for RTL. Keep the surface fill/border on a wrapper; customize with `--scroll-fade-size` only when the default 12% / 40px cap does not fit. Copy **Foundations → Scroll fade → Pattern — …**.
|
|
13
13
|
- **Motion:** Duration tiers in **`src/theme/motion.css`** — **fast** (hover/focus), **medium** (panels/layout), **slow** (rare). Single **`--ease-standard`**. CSS via `motionTransition()`; Motion via `motionTransitionProp()`. Choreography tokens `--motion-stagger`, `--motion-beat`, `--motion-blur-reveal` through `motionStaggerSeconds()`, `motionBeatSeconds(n)`, `motionBlurReveal(reduce)`, and `readMotionDurationSeconds(tier)` — Show code never hard-codes a blur, stagger, or duration. See **ADR-0008**. Storybook wraps `<MotionConfig reducedMotion="user">`.
|
|
14
14
|
- **Icons:** **[Lucide](https://lucide.dev/icons/) only** until further notice — import from **`lucide-react`** in components, stories, and examples. Peer dependency, not bundled; use `stroke-current` / `ButtonIcon` for sizing. See **Foundations → Icons**.
|
|
15
|
-
- **Button:** pill by default; **`layout="row"`** for flat full-width detail/settings lines (**`width="hug"`** sizes a row to its content with a tight gap — inline disclosure triggers); **`align="start"`** left-aligns a pill label and **`emphasis="quiet"`** puts `role="outline"` on the `border-border` hairline (full-width suggestion pills — **Pattern — suggestion pills**); **`layout="nav"`** for **NavList** rows (`selected`). Six **roles** (`primary`, `secondary`, `ghost`, `destructive`, **`inverse`** — surface fill and brand text, for a brand-blue field, **`outline`** — hairline border and transparent fill). Patterns: action, **`row`**, **`nav`**, `icon`, `count`, `status` morph, **`mono`** + **`endIcon`** (accent arrow square) — mutually exclusive where documented. No slots. [Motion reference](https://motion.dev/examples/react-multi-state-badge).
|
|
15
|
+
- **Button:** pill by default; **`layout="row"`** for flat full-width detail/settings lines (**`width="hug"`** sizes a row to its content with a tight gap — inline disclosure triggers); **`align="start"`** left-aligns a pill label and **`emphasis="quiet"`** puts `role="outline"` on the `border-border` hairline (full-width suggestion pills — **Pattern — suggestion pills**); **`layout="nav"`** for **NavList** rows (`selected`). Six **roles** (`primary`, `secondary`, `ghost`, `destructive`, **`inverse`** — surface fill and brand text, for a brand-blue field, **`outline`** — hairline border and transparent fill). Patterns: action, **`row`**, **`nav`**, `icon`, `count`, `status` morph, **`mono`** + **`endIcon`** (accent arrow square) — mutually exclusive where documented. **`status` with `icon`**: the icon morphs into the status glyph — **Pattern — copy button** (`icon={<Copy />}`, `statusLabels`, hold with **`buttonStatusHoldMs`**; the pill's live region announces the result). **`external`** with `render={<a href />}`: new tab, safe `rel`, spoken "(opens in a new tab)", **TextLink**'s trailing icon (`externalIcon={false}` drops it) — **Pattern — external link**; never hand-write `target` or the new-tab text. The shell sets its own case, so a caps-styled parent does not capitalize a label. No slots. [Motion reference](https://motion.dev/examples/react-multi-state-badge).
|
|
16
16
|
- **Avatar:** circular identity — required `name`, optional `src`, initials → **User** fallback; sizes `xsm` / `sm` / `md` (default) / `lg` / `xl` (20–128px). Optional `presence={{ tone, label, pulsing? }}` — rim dot via **Status** dot tokens (not the **Status** component). **`avatarSizeForCluster()`** for header rows; **`size="sm"`** in **Dropdown.Item** `start`. Not clickable — wrap at call site. Agents: copy **Components/Avatar → Pattern — …**; see **ADR-0017**.
|
|
17
|
-
- **IconButton:** circular icon-only control. Patterns: toolbar (ghost), `fab`, `loading`, native `title`, **`inset`** (compact dismiss inside Chip), **`render={<a/>}`** (circular brand / icon links). Compose **Tooltip** for tokenized hover/focus labels and pass `title=""` to avoid duplicate native UI. **`aria-label` required** — use `Button` when text is needed.
|
|
18
|
-
- **Kbd:** semantic keyboard keycap — one physical key per **Kbd**; compose multiple keycaps for shortcuts. Sizes `sm` | `md`; add `aria-label` when symbolic labels need spoken expansion. Display-only — never interactive on the keycap itself. Numbered choice rows pair trailing **Kbd** digits with **`useKbdChoiceKeys`** so `1`–`
|
|
19
|
-
- **TextLink:** inline anchor for navigation inside prose
|
|
17
|
+
- **IconButton:** circular icon-only control. Patterns: toolbar (ghost), `fab`, `loading`, native `title`, **`inset`** (compact dismiss inside Chip), **`render={<a/>}`** (circular brand / icon links), **`pressed`** (toggle — `aria-pressed`, pressed fill and a filled glyph while on; votes, stars). Compose **Tooltip** for tokenized hover/focus labels and pass `title=""` to avoid duplicate native UI. **`aria-label` required** — use `Button` when text is needed.
|
|
18
|
+
- **Kbd:** semantic keyboard keycap — one physical key per **Kbd**; compose multiple keycaps for shortcuts. Sizes `sm` | `md`; add `aria-label` when symbolic labels need spoken expansion. Display-only — never interactive on the keycap itself. Numbered choice rows pair trailing **Kbd** digits with **`useKbdChoiceKeys`** so `1`–`9` select the same way a click does while focus is not in text entry (a focused checkbox or radio still takes digits); pass `scope` (a ref) to act only while focus is inside that element, as in a chat gate (see **Pattern — numbered choice keys**). Copy **Components/Kbd → Pattern — keyboard shortcut**.
|
|
19
|
+
- **TextLink:** inline anchor for navigation — `variant="prose"` (default) inside prose: canonical solid underline, stronger hover decoration, and focus ring. **`variant="quiet"`** for headline-size text and list titles: no underline at rest, an underline scaled to the text on hover and focus, the same focus ring; inherits size and weight from the heading around it — never inside running prose. `external` opens a new tab and appends Lucide **SquareArrowOutUpRight** with spoken context. Inherits surrounding type size; `className` is layout only. Use **Button** for actions. Copy **Components/TextLink → Pattern — inline prose link** or **Pattern — quiet title link**.
|
|
20
20
|
- **Tooltip:** short supplemental label — **`Tooltip.Provider`** shares hover delay; **`Tooltip.Trigger render={...}`** composes a ref/DOM-prop-forwarding control; **`Tooltip.Content`** portals with collision-aware physical or logical placement. Opens on hover/focus, closes with Escape, and does not open on touch. No essential or interactive content. Disabled native controls need the documented focusable wrapper. Copy **Components/Tooltip → Pattern — …**.
|
|
21
|
-
- **Badge:** solid and **
|
|
21
|
+
- **Badge:** solid, **muted**, and **outline** (hairline, transparent fill) semantic fills. Patterns: label, **`emphasis="muted"`**, **`emphasis="outline"`** + **`mono`** (mono caps, as **Button** `mono` — author and category tags), **`render={<a href />}`** (a tag that navigates: hover underline, focus ring, 44px-tall hit area — **Pattern — outline tags**), `count`, `icon`, **`avatar`**, **`iconOnly`** — mutually exclusive where documented. Actions stay on **Button**. **`avatar={{ src, alt }}`** renders **Avatar** at the badge size (`badgeAvatarSize`: sm → 20px, md → 24px). **`BadgeSegmentCount`** for filter/tab segment totals (Chip trailing count). No **Status** dot inside Badge. See **ADR-0033**.
|
|
22
22
|
- **Chip:** filter/toggle molecule — composes **`BadgeIcon`** / **`ButtonIcon`**, **`IconButton inset`** (remove), **`BadgeSegmentCount`** (count). Patterns: **multi-select filter** (`ChipFilterGroup` + `value`), single-select group, standalone `selected`, **removable** (`onRemove`), **read-only**. Sizes `sm` | `md` | `lg`. Optional `icon`, `count` — not with `onRemove`. No slots.
|
|
23
23
|
- **SegmentedControl:** connected **segmented control** — one track, Motion sliding thumb, mutually exclusive **`SegmentedControl.Item`** segments (`role="radiogroup"`). Patterns: **shape/settings toggle** (`layout="hug"`), **view switcher** (`layout="stretch"`). Sizes **`sm` | `md` | `lg`** — cluster tiers (28 / 36 / 44px), **1:1 with Chip**; pair **Button** via `buttonSizeForCluster()` and **IconButton** via `iconButtonSizeForCluster()`. Not multi-select — use **ChipFilterGroup**; not many options — use **Select**. **Badge** `sm`/`md` is inline label scale, not cluster header pairing.
|
|
24
24
|
- **DisplayControls:** compact page-utility molecule — controlled grid visibility + theme mode (`auto` | `light` | `dark`); composes **Button** + **Kbd**. Global **G** toggles grid and **T** cycles theme. When paired with **GridOverlay**, set `keyboardShortcut={false}` on the overlay. `className` is placement only. Copy **Components/DisplayControls → Pattern — page display controls**.
|
|
@@ -34,18 +34,22 @@ Storybook paths such as **Components/Button/Button → Pattern — …** name a
|
|
|
34
34
|
- **Tab:** responsive peer-page/view navigation — **Tab.Group** + **Tab** (`tablist` / `tab`); inactive labels are regular-weight `text-muted`, active labels are medium-weight `text-fg` with the shared Motion bottom rule, and the muted pill fill is hover-only; optional `count`. Width overflow reserves a **More** Dropdown; selecting a hidden tab promotes it into the final visible slot before More. Not **SegmentedControl** (settings choice) or **Chip** (filter). See **ADR-0022**.
|
|
35
35
|
- **Stat:** at-a-glance metric tile — required `label`, `value`; optional `trend` (muted **Badge**), `start` / `end`, `loading`. **`Stat.Group`** — responsive grid (`columns` 2–4, 2-up mobile). **`size="sm"`** for insights rows; **`size="md"`** for hero KPI above charts. Inline mono trend (`chartKpiTrend*`) stays on **Chart**-paired KPIs — not **Badge**. Section heading + actions → **PageHeader** `variant="page"`.
|
|
36
36
|
- **TaskRows:** expandable task rows — composes **Accordion** for disclosure; adds status (**Badge**, **Status**), **meta**, detail rails, and **TaskRows.Detail**. Patterns: **status rows**; **capsules**; **action details** (`detailsLayout="actions"` + `TaskRows.Detail variant="button"` → **Button** `size="xs"`); **tag chips** (`detailsLayout="chips"` + read-only **Chip** `size="sm"`); **detail lines** (`TaskRows.Detail` + `onPress` → **Button** `layout="row"`). Optional **Card.Body**.
|
|
37
|
-
- **Accordion:** generic expand/collapse — **leading**, **label**, **trailing**, built-in chevron, `motion-collapse` panel. Variants: `list`, `capsule`, `plain
|
|
37
|
+
- **Accordion:** generic expand/collapse — **leading**, **label**, **trailing**, built-in chevron, `motion-collapse` panel. Variants: `list`, `capsule`, `plain`; **`flush`** (plain only) drops the inset so labels line up with surrounding text — filter side panels. A closed panel turns `visibility: hidden` once it folds, so Tab skips its controls. **TaskRows** is the task-status pattern on top.
|
|
38
|
+
- **DescriptionList:** a list of facts — `dl` > **DescriptionList.Item** (`div` > `dt` `name` + `dd` value). `layout` `inline` (value beside the name, 2 : 3 tracks, default) or `stacked` (value under it — tags, actions), per list or per item. `rule` `solid` (default) / `dotted` (quieter — beside caption rules) / `none`. `variant` `sans` (caption name, body value) or `mono` (eyebrow name, mono caps value, tabular figures — post metadata). Values take text, `<time>`, **Badge** tags, or **Button** actions; several wrap in a row. Not form fields (**Field**), metrics (**Stat**), or status rows (**TaskRows**). Paste **Components/DescriptionList → Pattern — post metadata** or **Pattern — details**. See **ADR-0041**.
|
|
39
|
+
- **SectionCaption:** the small uppercase mono caption over a page column ("/ Metadata", "/ Article", "/ Filters") — `type-eyebrow` on a `border-border-emphasized` rule; the "/" `marker` is `aria-hidden`. `as` `h2` (default — pair `id` with the region's `aria-labelledby`) or `p` (labels a column that has its own heading); `end` holds a **Button** `size="xs"` (Clear all) without growing the row; `rule` / `marker` can be turned off. Write `children` in sentence case. Copy **Components/SectionCaption → Pattern — column caption**. See **ADR-0041**.
|
|
40
|
+
- **Prose:** long-form content set from plain HTML elements (rendered markdown) — headings, paragraphs, lists, quotes, inline code, code blocks, rules, images, figures, and tables, with the spacing between them. `size` `lg` (default — `type-reading`, headings a step up) or `md` (`type-body`, denser notes); `measure` `reading` (40rem, default) or `none`; `as` `div` / `article` / `section`. Wide tables scroll in their own box. Map markdown `#` to `h2` under a page `h1`, and links to **TextLink** (`external` for other sites). Never add classes to the elements inside. Paste **Components/Prose → Pattern — article body**; the full page is **Guides/Post page → Pattern — post page**. See **ADR-0041**.
|
|
41
|
+
- **IndexList:** editorial index for list pages (blog, case studies) — **IndexList.Item** rows with `meta` (a `<time>`), a linked `title` (`href`; a quiet **TextLink** in an `h2` by default — `titleAs`), and an optional `preview` an **IconButton** disclosure expands under the title. Optional `captions={{ meta, title }}` in sentence case (`type-eyebrow`, the "/" marker and the **SectionCaption** rule, `aria-hidden`) share the rows' tracks. Two tracks (7.5rem meta, title) once the list is 32rem wide (container query); one column below, captions hidden. `size` `lg` (type-display-3, default) / `md` / `sm`. `empty` replaces the rows when there are none. `className` is layout only. Not tabular data — **Table** is planned. Paste **Components/IndexList → Pattern — post index**; with filters, **Guides/Filter panel → Pattern — filtered index**. See **ADR-0040**.
|
|
38
42
|
- **Card:** `Card.Header`, `Card.Body`, `Card.Footer`. Layout cards (`padding="none"`): header/footer on the shell; **`Card.Header`** is two horizontal slots (`start` | `end`) at **16px** (`px-4`). **`end` is always trailing** (`ml-auto`) — overflow / **MoreMenu** stays on the right even when `start` is omitted. **`Card.Body` is a square composition slot** with a **2px** horizontal gutter — no inner pad, no radius, **no default fill**. The **occupant** dictates how the body region looks; use **`cardLayoutBodyOccupantInsetXClasses`** (`px-3.5` / 14px) + **`cardLayoutBodyOccupantPadYClasses`** (`py-[16px]` / literal 16px vertical) when body content should align with header/footer (2px + 14px = 16px horizontal). Shape config lives in **`src/theme/shape.css`**: shell **`--radius-card-shell: 16px`**, body occupant **`--radius-card-body: 14px`**. Radius-only media → **`cardLayoutBodyOccupantRadiusClasses`**; inset gray/chart wells → **`cardLayoutBodyOccupantWellClasses`** or **`cardLayoutBodyOccupantDotGridWellClasses`**. A headerless layout **Card.Body** densifies the shell top to 2px (`pt-[2px]`) — same density as footerless / `bodyTerminal` bottom; **`headerless`** is only an override for wrapped slot composition. A direct terminal **`Card.Body`** automatically fills stretched cards and gets the 2px bottom shell inset; **`bodyTerminal`** is only an override for wrapped slot composition. Pin a layout height on the root (`className`) with Header + Body + Footer — Header/Footer stay put; **Card.Body** scrolls (2px gutter unchanged; no new variant). See **Components/Card/Card → Pattern — pinned height**. `variant="surface"` is elevated; **`variant="outlined"`** uses **`shadow-soft-card`** with no stroke (same elevation as layout `surface`). Radius stays **`--radius-card-shell`**. Default **`shape="rounded"`**. **`shape="flush"`** only when a parent owns outer chrome. Simple cards: `padding="md"`.
|
|
39
43
|
- **Input:** pill-only. Optional leading `icon`; trailing `endBadge` or status / `loading`. Hero search with inset button → **Search** molecule. See **ADR-0006**.
|
|
40
44
|
- **PromptBar:** wide prompt pill — inline **TextArea** (one line when empty, grows through 3 lines, then scrolls) and an inset **IconButton** `sm` send control. Enter sends; Shift+Enter inserts a newline; send stays disabled until the draft has text. Optional `start` (brand mark — **Avatar** `size="md"`) and `end` (extra inset **IconButton** `sm`) slots. No new Button role. Copy **Components/PromptBar → Pattern — prompt bar**. The site assistant on the marketing pages is **ChatDock**, not a hand-pinned PromptBar. Do not restyle **SiteNav**. Full contract: **docs/component-contracts.md → PromptBar**.
|
|
41
|
-
- **ChatDock:** the site assistant — a **PromptBar** pinned to the bottom of the page grid (`--grid-max: 40rem`, under **SiteNav**) with the brand `mark`; hovering shows `suggestions` that carry a `prompt` as **Button** `secondary` pills above it; focusing, clicking, or typing opens a non-modal chat window
|
|
45
|
+
- **ChatDock:** the site assistant — a **PromptBar** pinned to the bottom of the page grid (`--grid-max: 40rem`, under **SiteNav**) with the brand `mark`; hovering shows `suggestions` that carry a `prompt` as **Button** `secondary` pills above it; focusing, clicking, or typing opens a non-modal chat window around the same composer (shared overlay header with `title` / `subtitle` / close, `greeting`, `messages` (visitor turns on `bg-brand-tint`, replies as plain text), `thinking` row, suggestion rows — **Button** `layout="row"` — until the first message (a row that sends hands focus to the composer as the rows leave), `disclaimer` under the composer). One **PromptBar** serves both states: the window grows up out of the bar and Escape or close folds it back; either reverses the other midway. Below `md` it fills the screen, rising from the bottom edge. Reduced motion crossfades. `followUps` (same items as `suggestions`; `icon` not shown — inline rows lead with **CornerDownRight**, composer pills are text only) show under the latest reply only — hidden while `thinking`, gone the moment the visitor sends; `followUpsPlacement` is `inline` (default, rows in the thread, 44px on phones) or `composer` (pills above the composer). Under each finished reply, a row: **Copy** (`copyText`), thumbs (`onMessageFeedback`, on replies that carry `feedback` — `null` until the visitor votes; **IconButton** `pressed`), and a muted score (`meta: { label, description? }`, e.g. "Match 99%") — each part on its own; shown on hover or focus where the pointer can hover, always on touch; it keeps its place so the thread never moves, and stays empty while the latest reply is still arriving. Never put actions inside `content`. `gate` puts a multi-step form — **ChatDock.Gate** (header with previous · "2 of 4" · next · close, scrolling step body, footer with Cancel · Next) — in the composer's place, conversation above: setting it opens the window and takes focus; composer, suggestion rows, follow-ups, and disclaimer step aside; capped so the latest reply stays in view; Escape is the gate's; the window's close keeps it and its progress. Phones keep the window inside the area a keyboard leaves visible. Start a project runs as a gate, not a dialog — paste **Pattern — start a project gate** and return it from **Pattern — chat dock**'s `renderStartProject`. Never put a form inside `content`. The app owns `messages`, `followUps`, votes, the gate's open state, and `onSend`; suggestions without a `prompt` (for example **Start a project**) only call `onSuggestionSelect`. No full-page chat, no header send/expand arrow, no voice. `placement="inline"` is for previews only. Copy **Components/ChatDock → Pattern — chat dock** (it holds the follow-up state, the votes, and Start a project). See **ADR-0039**. Full contract: **docs/component-contracts.md → ChatDock**.
|
|
42
46
|
- **TextArea:** element-radius multiline — same optional `label`, `description`, `status`, `message`, and `loading` as **Input**; default `resize="vertical"`. See **ADR-0006**.
|
|
43
47
|
- **Field:** label/layout wrapper — `orientation="vertical" | "horizontal"`; never required. Validation stays on **Input** / **TextArea**. See **ADR-0006**.
|
|
44
|
-
- **Checkbox:** boolean toggle — label row + optional `description`, `indeterminate`, `status` / `message`, and `loading`. See **ADR-0006**.
|
|
48
|
+
- **Checkbox:** boolean toggle — label row + optional `description`, `indeterminate`, `status` / `message`, and `loading`. **`count`** puts a muted number at the row's end (filter results, styled like **NavList** counts); screen readers hear it after the label in parentheses — "Guides (2)", or "Guides (2 posts)" with `countLabel`. Never write the count into `label`. See **ADR-0006**.
|
|
45
49
|
- **Radio:** single option circle — same label row rhythm as **Checkbox**; compose in **RadioGroup**. See **ADR-0006**.
|
|
46
50
|
- **RadioGroup:** mutually exclusive options — `value` / `onValueChange`, vertical or horizontal layout, group validation band.
|
|
47
51
|
- **Switch:** instant on/off — pill track + sliding thumb; `layout="settings"` for label-left rows. See **ADR-0006**.
|
|
48
|
-
- **CheckboxGroup:** multi-select options — `values` / `onValuesChange`, vertical or horizontal layout, group validation band.
|
|
52
|
+
- **CheckboxGroup:** multi-select options — `values` / `onValuesChange`, vertical or horizontal layout, group validation band. **CheckboxGroup.Item** takes `count` / `countLabel` like **Checkbox**. A filter side panel — **Accordion** `flush` groups, counts, Clear all, a **Sheet** on phones — is **Guides/Filter panel → Pattern — filtered index**.
|
|
49
53
|
- **Select:** pill trigger matched to **Input** shell + floating listbox (**Dropdown.Menu** / **Dropdown.Item**). **`size="sm"`** in Card headers beside **Chip sm**. Options support **`start`** / **`end`** slots for icons and shortcuts. See **Components/Select**, **Components/Dropdown**.
|
|
50
54
|
- **Dropdown:** shared menu panel (`p-0.5` inset) + three-slot rows (`start` | label | `end`) — composed by **Select**; action menus via **MoreMenu**.
|
|
51
55
|
- **MoreMenu:** kebab **IconButton** + floating **Dropdown** action menu — **Card.Header** `end` (right) only; never left-align overflow. Menu right-aligns to trigger; expanded trigger retains the ghost hover surface; **`items`** + **`onAction`**. Sizes **`xs` | `sm` | `md` | `lg`** (**IconButton** scale). Not for single-select — **Select** / **SegmentedControl**.
|
package/docs/exports.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@thewhatmatters/wmds",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"import": "import { Button } from \"@thewhatmatters/wmds\";",
|
|
5
5
|
"styles": [
|
|
6
6
|
"@thewhatmatters/wmds/styles.css",
|
|
@@ -36,7 +36,9 @@
|
|
|
36
36
|
"title": "Components/Accordion",
|
|
37
37
|
"docs": "?path=/docs/components-accordion--docs"
|
|
38
38
|
},
|
|
39
|
-
"patterns": [
|
|
39
|
+
"patterns": [
|
|
40
|
+
"components-accordion--flush"
|
|
41
|
+
]
|
|
40
42
|
},
|
|
41
43
|
{
|
|
42
44
|
"name": "Avatar",
|
|
@@ -61,6 +63,7 @@
|
|
|
61
63
|
"docs": "?path=/docs/components-badge--docs"
|
|
62
64
|
},
|
|
63
65
|
"patterns": [
|
|
66
|
+
"components-badge--outline-tags",
|
|
64
67
|
"components-badge--with-avatar"
|
|
65
68
|
]
|
|
66
69
|
},
|
|
@@ -74,7 +77,9 @@
|
|
|
74
77
|
"docs": "?path=/docs/components-button-button--docs"
|
|
75
78
|
},
|
|
76
79
|
"patterns": [
|
|
80
|
+
"components-button-button--copy-button",
|
|
77
81
|
"components-button-button--destructive-action",
|
|
82
|
+
"components-button-button--external-link",
|
|
78
83
|
"components-button-button--ghost-action",
|
|
79
84
|
"components-button-button--inverse-action",
|
|
80
85
|
"components-button-button--link-render",
|
|
@@ -147,7 +152,8 @@
|
|
|
147
152
|
"docs": "?path=/docs/components-chatdock--docs"
|
|
148
153
|
},
|
|
149
154
|
"patterns": [
|
|
150
|
-
"components-chatdock--pattern-chat-dock"
|
|
155
|
+
"components-chatdock--pattern-chat-dock",
|
|
156
|
+
"components-chatdock--pattern-start-project-gate"
|
|
151
157
|
]
|
|
152
158
|
},
|
|
153
159
|
{
|
|
@@ -174,6 +180,7 @@
|
|
|
174
180
|
},
|
|
175
181
|
"patterns": [
|
|
176
182
|
"components-checkbox-checkbox--default",
|
|
183
|
+
"components-checkbox-checkbox--with-count",
|
|
177
184
|
"components-checkbox-checkbox--with-description"
|
|
178
185
|
]
|
|
179
186
|
},
|
|
@@ -187,7 +194,8 @@
|
|
|
187
194
|
"docs": "?path=/docs/components-checkbox-checkboxgroup--docs"
|
|
188
195
|
},
|
|
189
196
|
"patterns": [
|
|
190
|
-
"components-checkbox-checkboxgroup--default"
|
|
197
|
+
"components-checkbox-checkboxgroup--default",
|
|
198
|
+
"components-checkbox-checkboxgroup--option-counts"
|
|
191
199
|
]
|
|
192
200
|
},
|
|
193
201
|
{
|
|
@@ -212,6 +220,20 @@
|
|
|
212
220
|
},
|
|
213
221
|
"patterns": []
|
|
214
222
|
},
|
|
223
|
+
{
|
|
224
|
+
"name": "DescriptionList",
|
|
225
|
+
"tier": "molecule",
|
|
226
|
+
"category": "Table & list",
|
|
227
|
+
"summary": "Name-and-value rows (dl, dt, dd) with a solid or dotted rule; values take text, tags, or actions.",
|
|
228
|
+
"storybook": {
|
|
229
|
+
"title": "Components/DescriptionList",
|
|
230
|
+
"docs": "?path=/docs/components-descriptionlist--docs"
|
|
231
|
+
},
|
|
232
|
+
"patterns": [
|
|
233
|
+
"components-descriptionlist--details",
|
|
234
|
+
"components-descriptionlist--post-metadata"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
215
237
|
{
|
|
216
238
|
"name": "Dialog",
|
|
217
239
|
"tier": "organism",
|
|
@@ -336,6 +358,19 @@
|
|
|
336
358
|
},
|
|
337
359
|
"patterns": []
|
|
338
360
|
},
|
|
361
|
+
{
|
|
362
|
+
"name": "IndexList",
|
|
363
|
+
"tier": "molecule",
|
|
364
|
+
"category": "Table & list",
|
|
365
|
+
"summary": "Editorial index rows: a meta column, a large linked title, and an optional preview, under shared column captions.",
|
|
366
|
+
"storybook": {
|
|
367
|
+
"title": "Components/IndexList",
|
|
368
|
+
"docs": "?path=/docs/components-indexlist--docs"
|
|
369
|
+
},
|
|
370
|
+
"patterns": [
|
|
371
|
+
"components-indexlist--post-index"
|
|
372
|
+
]
|
|
373
|
+
},
|
|
339
374
|
{
|
|
340
375
|
"name": "Input",
|
|
341
376
|
"tier": "atom",
|
|
@@ -483,6 +518,19 @@
|
|
|
483
518
|
"components-promptbar--pattern-prompt-bar"
|
|
484
519
|
]
|
|
485
520
|
},
|
|
521
|
+
{
|
|
522
|
+
"name": "Prose",
|
|
523
|
+
"tier": "atom",
|
|
524
|
+
"category": "Content",
|
|
525
|
+
"summary": "Long-form article text set from plain HTML, with a reading measure.",
|
|
526
|
+
"storybook": {
|
|
527
|
+
"title": "Components/Prose",
|
|
528
|
+
"docs": "?path=/docs/components-prose--docs"
|
|
529
|
+
},
|
|
530
|
+
"patterns": [
|
|
531
|
+
"components-prose--article-body"
|
|
532
|
+
]
|
|
533
|
+
},
|
|
486
534
|
{
|
|
487
535
|
"name": "Radio",
|
|
488
536
|
"tier": "atom",
|
|
@@ -547,6 +595,20 @@
|
|
|
547
595
|
},
|
|
548
596
|
"patterns": []
|
|
549
597
|
},
|
|
598
|
+
{
|
|
599
|
+
"name": "SectionCaption",
|
|
600
|
+
"tier": "atom",
|
|
601
|
+
"category": "Content",
|
|
602
|
+
"summary": "Small uppercase mono caption over a page column, on a rule, with an optional action.",
|
|
603
|
+
"storybook": {
|
|
604
|
+
"title": "Components/SectionCaption",
|
|
605
|
+
"docs": "?path=/docs/components-sectioncaption--docs"
|
|
606
|
+
},
|
|
607
|
+
"patterns": [
|
|
608
|
+
"components-sectioncaption--column-caption",
|
|
609
|
+
"components-sectioncaption--with-action"
|
|
610
|
+
]
|
|
611
|
+
},
|
|
550
612
|
{
|
|
551
613
|
"name": "SegmentedControl",
|
|
552
614
|
"tier": "molecule",
|
|
@@ -730,6 +792,7 @@
|
|
|
730
792
|
"patterns": [
|
|
731
793
|
"components-textlink--external-destination",
|
|
732
794
|
"components-textlink--inline-prose",
|
|
795
|
+
"components-textlink--quiet-title",
|
|
733
796
|
"components-textlink--supporting-copy"
|
|
734
797
|
]
|
|
735
798
|
},
|
|
@@ -797,7 +860,9 @@
|
|
|
797
860
|
],
|
|
798
861
|
"guides": [
|
|
799
862
|
"Guides/Chart explorations",
|
|
863
|
+
"Guides/Filter panel",
|
|
800
864
|
"Guides/Overlay flows",
|
|
865
|
+
"Guides/Post page",
|
|
801
866
|
"Guides/Profile typography"
|
|
802
867
|
]
|
|
803
868
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — flush
|
|
2
|
+
// Storybook: Components/Accordion → Pattern — flush (?path=/story/components-accordion--flush)
|
|
3
|
+
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
|
+
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Accordion, CheckboxGroup, SectionCaption } from "@thewhatmatters/wmds";
|
|
7
|
+
|
|
8
|
+
export function TopicFilter() {
|
|
9
|
+
const [topics, setTopics] = useState<string[]>([]);
|
|
10
|
+
const [years, setYears] = useState<string[]>([]);
|
|
11
|
+
return (
|
|
12
|
+
<div className="flex w-64 flex-col">
|
|
13
|
+
<SectionCaption>Filters</SectionCaption>
|
|
14
|
+
<Accordion variant="plain" flush>
|
|
15
|
+
<Accordion.Item label="Topic" defaultOpen>
|
|
16
|
+
<CheckboxGroup label="Topic" labelHidden size="sm" values={topics} onValuesChange={setTopics}>
|
|
17
|
+
<CheckboxGroup.Item value="guides" label="Guides" count={2} />
|
|
18
|
+
<CheckboxGroup.Item value="notes" label="Notes" count={1} />
|
|
19
|
+
</CheckboxGroup>
|
|
20
|
+
</Accordion.Item>
|
|
21
|
+
<Accordion.Item label="Year">
|
|
22
|
+
<CheckboxGroup label="Year" labelHidden size="sm" values={years} onValuesChange={setYears}>
|
|
23
|
+
<CheckboxGroup.Item value="2026" label="2026" count={3} />
|
|
24
|
+
</CheckboxGroup>
|
|
25
|
+
</Accordion.Item>
|
|
26
|
+
</Accordion>
|
|
27
|
+
</div>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — dropdown row
|
|
2
2
|
// Storybook: Components/Avatar → Pattern — dropdown row (?path=/story/components-avatar--dropdown-row)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — outline tags
|
|
2
|
+
// Storybook: Components/Badge → Pattern — outline tags (?path=/story/components-badge--outline-tags)
|
|
3
|
+
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
|
+
|
|
5
|
+
import { Badge } from "@thewhatmatters/wmds";
|
|
6
|
+
|
|
7
|
+
export interface PostTag {
|
|
8
|
+
label: string;
|
|
9
|
+
href: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function PostTags({ author, categories }: { author: string; categories: PostTag[] }) {
|
|
13
|
+
return (
|
|
14
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
15
|
+
<Badge emphasis="outline" mono>
|
|
16
|
+
{author}
|
|
17
|
+
</Badge>
|
|
18
|
+
{categories.map((category) => (
|
|
19
|
+
<Badge key={category.href} emphasis="outline" mono render={<a href={category.href} />}>
|
|
20
|
+
{category.label}
|
|
21
|
+
</Badge>
|
|
22
|
+
))}
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — with avatar
|
|
2
2
|
// Storybook: Components/Badge → Pattern — with avatar (?path=/story/components-badge--with-avatar)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — copy button
|
|
2
|
+
// Storybook: Components/Button/Button → Pattern — copy button (?path=/story/components-button-button--copy-button)
|
|
3
|
+
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
|
+
|
|
5
|
+
import { useEffect, useState } from "react";
|
|
6
|
+
import { Copy } from "lucide-react";
|
|
7
|
+
import { Button, buttonStatusHoldMs, type ButtonStatus } from "@thewhatmatters/wmds";
|
|
8
|
+
|
|
9
|
+
export function CopyButton({ text, label }: { text: string; label: string }) {
|
|
10
|
+
const [status, setStatus] = useState<ButtonStatus>("idle");
|
|
11
|
+
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (status !== "success" && status !== "error") return;
|
|
14
|
+
const timer = window.setTimeout(() => setStatus("idle"), buttonStatusHoldMs);
|
|
15
|
+
return () => window.clearTimeout(timer);
|
|
16
|
+
}, [status]);
|
|
17
|
+
|
|
18
|
+
async function copy() {
|
|
19
|
+
try {
|
|
20
|
+
await navigator.clipboard.writeText(text);
|
|
21
|
+
setStatus("success");
|
|
22
|
+
} catch {
|
|
23
|
+
setStatus("error");
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Button
|
|
29
|
+
role="secondary"
|
|
30
|
+
size="sm"
|
|
31
|
+
icon={<Copy />}
|
|
32
|
+
status={status}
|
|
33
|
+
statusLabels={{ success: "Copied", error: "Couldn't copy" }}
|
|
34
|
+
onClick={copy}
|
|
35
|
+
>
|
|
36
|
+
{label}
|
|
37
|
+
</Button>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — destructive action
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — destructive action (?path=/story/components-button-button--destructive-action)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — external link
|
|
2
|
+
// Storybook: Components/Button/Button → Pattern — external link (?path=/story/components-button-button--external-link)
|
|
3
|
+
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
|
+
|
|
5
|
+
import { Button } from "@thewhatmatters/wmds";
|
|
6
|
+
|
|
7
|
+
export function ShareLinks({ url, title }: { url: string; title: string }) {
|
|
8
|
+
const encodedUrl = encodeURIComponent(url);
|
|
9
|
+
const encodedTitle = encodeURIComponent(title);
|
|
10
|
+
return (
|
|
11
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
12
|
+
<Button
|
|
13
|
+
role="secondary"
|
|
14
|
+
size="sm"
|
|
15
|
+
external
|
|
16
|
+
render={<a href={"https://x.com/intent/post?url=" + encodedUrl + "&text=" + encodedTitle} />}
|
|
17
|
+
>
|
|
18
|
+
Twitter/X
|
|
19
|
+
</Button>
|
|
20
|
+
<Button
|
|
21
|
+
role="secondary"
|
|
22
|
+
size="sm"
|
|
23
|
+
external
|
|
24
|
+
render={<a href={"https://www.linkedin.com/sharing/share-offsite/?url=" + encodedUrl} />}
|
|
25
|
+
>
|
|
26
|
+
LinkedIn
|
|
27
|
+
</Button>
|
|
28
|
+
</div>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — ghost action
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — ghost action (?path=/story/components-button-button--ghost-action)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — inverse action
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — inverse action (?path=/story/components-button-button--inverse-action)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — link
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — link (?path=/story/components-button-button--link-render)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — submit / async
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — submit / async (?path=/story/components-button-button--multi-state-badge)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — outline mono
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — outline mono (?path=/story/components-button-button--outline-mono)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — primary action
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — primary action (?path=/story/components-button-button--primary-action)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — row (hug)
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — row (hug) (?path=/story/components-button-button--row-hug)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — row
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — row (?path=/story/components-button-button--row-layout)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — secondary action
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — secondary action (?path=/story/components-button-button--secondary-action)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — suggestion pills
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — suggestion pills (?path=/story/components-button-button--suggestion-pills)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — with count
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — with count (?path=/story/components-button-button--with-count)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — with icon
|
|
2
2
|
// Storybook: Components/Button/Button → Pattern — with icon (?path=/story/components-button-button--with-icon)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — vertical actions
|
|
2
2
|
// Storybook: Components/Button/FloatingActionButton → Pattern — vertical actions (?path=/story/components-button-floatingactionbutton--vertical-actions)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @thewhatmatters/wmds@0.4.
|
|
1
|
+
// @thewhatmatters/wmds@0.4.1 · Pattern — skip in footer
|
|
2
2
|
// Storybook: Components/CalEmbed → Pattern — skip in footer (?path=/story/components-calembed--pattern-skip-in-footer)
|
|
3
3
|
// Show code — copy verbatim and keep this header; upgrades find pasted patterns by it.
|
|
4
4
|
|