@thewhatmatters/wmds 0.4.0 → 0.4.2
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 +82 -0
- package/CONSUMING.md +9 -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/Breadcrumb/Breadcrumb.d.ts +59 -0
- package/dist/components/molecules/Breadcrumb/Breadcrumb.d.ts.map +1 -0
- package/dist/components/molecules/Breadcrumb/Breadcrumb.js +188 -0
- package/dist/components/molecules/Breadcrumb/breadcrumbStyles.d.ts +21 -0
- package/dist/components/molecules/Breadcrumb/breadcrumbStyles.d.ts.map +1 -0
- package/dist/components/molecules/Breadcrumb/breadcrumbStyles.js +11 -0
- 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/Dropdown/DropdownItem.d.ts +7 -2
- package/dist/components/molecules/Dropdown/DropdownItem.d.ts.map +1 -1
- package/dist/components/molecules/Dropdown/DropdownItem.js +40 -24
- 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/SiteNav/SiteNav.js +86 -86
- package/dist/components/organisms/Toast/Toast.js +5 -5
- package/dist/index.d.ts +8 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +124 -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 +17 -12
- package/docs/exports.json +85 -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-breadcrumb--editorial.tsx +9 -0
- package/docs/patterns/components-breadcrumb--long-path.tsx +9 -0
- package/docs/patterns/components-breadcrumb--path.tsx +9 -0
- package/docs/patterns/components-breadcrumb--router-links.tsx +10 -0
- 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 +148 -0
- package/docs/patterns/guides-profile-typography--editorial-profile.tsx +1 -1
- package/docs/patterns/index.json +161 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,88 @@ Every release of `@thewhatmatters/wmds` is listed here, newest first.
|
|
|
7
7
|
- **Pasted patterns:** when a release changes a **Pattern — …** story's Show code, it is named under Consumer actions so apps re-copy it.
|
|
8
8
|
- **How to add an entry** (contributors): add your change to the top entry. If that version is already on npm (`npm view @thewhatmatters/wmds versions`), start a new entry above it and bump `version` in `package.json` to match. `npm run check:changelog` enforces the format.
|
|
9
9
|
|
|
10
|
+
## 0.4.2
|
|
11
|
+
|
|
12
|
+
**Breadcrumb** — the path to the current page, after the shadcn/ui breadcrumb: links from the root, a separator between them, the current page last, and a long path folded into a "…" menu of links. See **ADR-0042**.
|
|
13
|
+
|
|
14
|
+
- **Breadcrumb** (new) — pass `items` (`{ label, href }`; the last item, without `href`, is the current page). Above `maxItems` (default 4) the first item and the last two stay and the middle folds into a "…" control; it opens a menu of the hidden links, with focus on the first, arrow keys between them, and Escape back to the control. Long labels truncate. `separator`: `chevron` (default) or `slash`. `variant`: `sans` (default) or `mono` (eyebrow caps). `renderLink` routes every link through your router (`(item) => <Link href={item.href} />`). New **Pattern — path**, **Pattern — long path**, **Pattern — router links**, and **Pattern — editorial**.
|
|
15
|
+
- **Dropdown.Item** `render` — compose a row onto another element, such as `render={<a href />}` for a menu of links.
|
|
16
|
+
- **Guides/Post page → Pattern — post page** — a mono, slash-separated **Breadcrumb** above the title. `PostPageData` gains `breadcrumb`.
|
|
17
|
+
|
|
18
|
+
### Consumer actions
|
|
19
|
+
|
|
20
|
+
1. **WhatMatters site, post page: re-copy Guides/Post page → Pattern — post page** (`node_modules/@thewhatmatters/wmds/docs/patterns/guides-post-page--post-page.tsx`) and re-apply only your content, data, and handlers. Pass `breadcrumb` in `PostPageData`, ending with the post — for example `[{ label: "Home", href: "/" }, { label: "Blog", href: "/blog" }, { label: post.title }]`, with the post's category between Blog and the title if you link categories. To route crumbs through Next, pass `renderLink={(item) => <Link href={item.href} />}` on the pattern's **Breadcrumb**.
|
|
21
|
+
2. **WhatMatters site, other deep pages** (a resource category, a case study): add `<Breadcrumb items={…} />` above the page title — `variant="mono" separator="slash"` on editorial pages, to match the post page.
|
|
22
|
+
3. Other apps: none. **Breadcrumb** and **Dropdown.Item** `render` are new and optional.
|
|
23
|
+
|
|
24
|
+
## 0.4.1
|
|
25
|
+
|
|
26
|
+
**ChatDock:** follow-ups in the open window, actions and a match score under each reply, a Start a project gate in the composer's place, the visitor's messages on a brand tint, and a new open and close transition.
|
|
27
|
+
|
|
28
|
+
- **`followUps`** — predefined next questions for the latest reply, the same items as `suggestions`. They show under the reply (`followUpsPlacement="inline"`, the default; `"composer"` pins them as pills above the composer), hide while `thinking`, and disappear the moment the visitor sends. Choosing one calls `onSuggestionSelect`, then `onSend` with its `prompt`. A follow-up's `icon` is not shown: inline rows all lead with a corner-down-right arrow, and pills above the composer are text only. **Components/ChatDock → Pattern — chat dock** now keeps the follow-up state: `ask` may resolve with `string | { reply, followUps? }`.
|
|
29
|
+
- **Reply row** — under each finished reply: **Copy** (the message's `copyText`), thumbs up and down (shown when `onMessageFeedback` is passed, on replies that carry `feedback` — `"up" | "down" | null`, `null` until the visitor votes; pressing the active thumb clears it), and a short muted note (`meta: { label, description? }`, for example "Match 99%", with `description` read to screen readers). Each part shows on its own. Where the pointer can hover, the row shows while the reply is hovered or holds focus; on touch screens it is always shown. It keeps its place either way, so the thread never moves, and it stays empty while the latest reply is still arriving (`thinking`). Buttons are 44px on phones. New labels `copy`, `copied`, `helpful`, `notHelpful`; new types `ChatDockFeedback` and `ChatDockMessageMeta`.
|
|
30
|
+
- **`gate`** and **ChatDock.Gate** — a multi-step form in the composer's place, with the conversation above it. Setting `gate` opens the window and moves focus into it; the composer, suggestion rows, follow-ups, and disclaimer step aside, and come back with focus when it is cleared. The two crossfade while the area eases between their heights. The gate hugs each step up to a cap that keeps the last lines of the latest reply in view, then its body scrolls. Escape belongs to the gate (it closes it); the window's close keeps the gate, with its progress, for when the window reopens. **ChatDock.Gate** (`ChatDockGate`) is the shell: the step's title and subtitle with previous, "2 of 4", next, and close; the step in a scrolling body that slides between steps; a footer with a start slot, Cancel, and Next. 44px controls on phones. New **Pattern — start a project gate**.
|
|
31
|
+
- **Phones:** the full-screen window and the composer stay inside the part of the screen a keyboard leaves visible. The conversation takes keyboard focus so it can be scrolled without a mouse.
|
|
32
|
+
- **`useKbdChoiceKeys`** takes a `scope`: digits act only while focus is inside that element. A focused checkbox or radio now takes digits too (only text entry is skipped).
|
|
33
|
+
- **IconButton `pressed`** — the toggle pattern: sets `aria-pressed` and, while on, shows the pressed fill and a filled glyph.
|
|
34
|
+
- **Open and close.** The resting bar and the window are one object: one composer serves both states and stays on screen every frame. From `md` the window is an opaque card that grows up and out of the bar from its bottom edge; the mark moves to the header, the composer keeps its width and rises only by the disclaimer line, and the header, conversation, and rows fade in after it. Closing fades them and folds the window back into the bar, and the hover pills return once it has folded. On phones the window rises from the bottom edge to full screen and falls back. Escape while opening, or a click while closing, reverses from where it is. Reduced motion crossfades the window in place.
|
|
35
|
+
- **PromptBar:** the `start` slot takes its content's width (an **Avatar** `size="md"` is unchanged), so a caller can fold the mark away.
|
|
36
|
+
- The visitor's messages sit on a light navy tint, so they read apart from the replies. New color token `--color-brand-tint` (`bg-brand-tint`): 10% navy in light, a lifted navy in dark.
|
|
37
|
+
- **Fix:** choosing a suggestion row in the open window (by click or Enter) moves focus to the composer. The rows leave once the first message lands, and focus used to fall to the page, so Escape no longer closed the window.
|
|
38
|
+
|
|
39
|
+
**Index pages** — what the whatmatters.so blog index placed by hand. See **ADR-0040**.
|
|
40
|
+
|
|
41
|
+
- **IndexList** (new) — editorial index rows: **IndexList.Item** with `meta` (a `<time>`), a linked `title` (`href`; a quiet **TextLink** in an `h2`, `titleAs` to change it), and an optional `preview` that an **IconButton** at the row's end expands under the title (`defaultOpen`, or `open` / `onOpenChange`). `captions={{ meta, title }}` (sentence case — the "/" marker and rule come with them) sit over the rows on the same tracks. Two tracks (7.5rem meta, then the title, with the page grid's column gap) once the list is 32rem wide — a container query — and one column below, captions hidden. `size`: `lg` (type-display-3, default), `md`, `sm`. `empty` takes the rows' place when there are none. New **Pattern — post index**.
|
|
42
|
+
- **Guides/Filter panel → Pattern — filtered index** (new) — the filtered index page: a "/ Filters" panel of collapsible checkbox groups with counts and Clear all beside an **IndexList**, a live count in the title and a visually hidden status line, and below `md` a Filters button (with the number of filters on) that opens the same groups in a bottom **Sheet** with Clear all and Show N posts.
|
|
43
|
+
- **Checkbox** and **CheckboxGroup.Item** `count` — a muted number at the row's end, styled like **NavList** counts. Screen readers hear it after the label in parentheses: "Guides (2)", or "Guides (2 posts)" with `countLabel`.
|
|
44
|
+
- **`type-eyebrow`** — small uppercase mono caption (`typographyClass("eyebrow")`) for editorial labels such as "/ Filters" and "/ Date". `components.md` → Theme tokens says when to use it.
|
|
45
|
+
- **TextLink `variant`** — `prose` (default, unchanged) or `quiet`: no underline at rest, an underline scaled to the text on hover and focus, the same focus ring, and the size and weight of the heading around it. A wrapped quiet link draws its focus ring on every line. New **Pattern — quiet title link**; new exports `textLinkVariants` and `TextLinkVariant`.
|
|
46
|
+
- **Accordion `flush`** (plain variant) — no horizontal inset, so labels and panels line up with the text around the accordion; the trigger's hover band reaches 8px past each edge. New **Pattern — flush**.
|
|
47
|
+
- **Fix:** a closed **Accordion** panel — any `.motion-collapse` with `data-visible="false"` — turns `visibility: hidden` once its fold ends, so Tab skips its controls and screen readers skip its content. It opens visible at once.
|
|
48
|
+
|
|
49
|
+
**Post pages** — what the whatmatters.so blog post page placed by hand. See **ADR-0041**.
|
|
50
|
+
|
|
51
|
+
- **DescriptionList** (new) — name-and-value rows as `dl` / `dt` / `dd`. **DescriptionList.Item** takes a `name` and a value (text, `<time>`, **Badge** tags, or **Button** actions). `layout`: `inline` (value beside the name, 2 : 3, default) or `stacked` (value under it), per list or per row. `rule`: `solid` (default), `dotted` (the quieter hairline), or `none`. `variant`: `sans` (caption name, body value) or `mono` (eyebrow name, mono caps value, tabular figures). New **Pattern — post metadata** and **Pattern — details**.
|
|
52
|
+
- **SectionCaption** (new) — the "/ Metadata" caption over a page column: `type-eyebrow` on an emphasized rule, the "/" marker hidden from screen readers, `as` (`h2` default, or `p`), and an `end` slot for a **Button** `size="xs"`. New **Pattern — column caption** and **Pattern — caption with an action**. **IndexList** captions and **Guides/Filter panel** use it (their rule is now the emphasized hairline).
|
|
53
|
+
- **Prose** (new) — long-form content from plain HTML elements: headings, paragraphs, lists, quotes, inline code, code blocks, rules, images, figures, and tables, with the spacing between them. `size="lg"` (default) sets `type-reading`; `size="md"` keeps `type-body`. `measure="reading"` (default) caps lines at 40rem. New **Pattern — article body**.
|
|
54
|
+
- **`type-reading`** — long-form text, 17px at a 28px line (`typographyClass("reading")`).
|
|
55
|
+
- **Badge** `emphasis="outline"` (hairline, transparent fill), `mono` (mono caps, as **Button** `mono`), and `render` — `render={<a href />}` makes a tag a link, with a hover underline, the focus ring, and a 44px-tall hit area. New **Pattern — outline tags**.
|
|
56
|
+
- **Button** `status` works with `icon`: the icon morphs into the status glyph, and the result is announced. New export `buttonStatusHoldMs` (2000) for how long a confirmation holds. New **Pattern — copy button**.
|
|
57
|
+
- **Button** `external` (with `render={<a href />}`): opens a new tab with a safe `rel`, adds a visually hidden "(opens in a new tab)", and shows **TextLink**'s trailing icon (`externalIcon={false}` drops it). New **Pattern — external link**.
|
|
58
|
+
- **Button** and **Badge** set their own text case: inside an `uppercase` parent (a mono **DescriptionList**), their labels no longer turn to capitals. `mono` still sets caps.
|
|
59
|
+
- **Guides/Post page → Pattern — post page** (new) — the display title, the metadata panel in 4 of 12 columns (sticky from `lg` under the pinned **SiteNav**), and the article in 8; below `lg` the panel stacks above the article.
|
|
60
|
+
|
|
61
|
+
### Consumer actions
|
|
62
|
+
|
|
63
|
+
1. **WhatMatters site: re-copy Components/ChatDock → Pattern — chat dock** (`node_modules/@thewhatmatters/wmds/docs/patterns/components-chatdock--pattern-chat-dock.tsx`) over `components/ask-whatmatters.tsx`, and re-apply only your content, data, and handlers. The pattern now holds the follow-up state, each reply's vote, and the Start a project gate's open state; `onStartProject` is gone.
|
|
64
|
+
2. **Paste Components/ChatDock → Pattern — start a project gate** (`node_modules/@thewhatmatters/wmds/docs/patterns/components-chatdock--pattern-start-project-gate.tsx`) as `components/start-project-gate.tsx`. Replace the services, budgets, and step copy with yours, and pass your calendar through `renderCalendar` (call `booked` when the visitor confirms a time).
|
|
65
|
+
3. **Wire the gate where you mount `AskWhatMatters`**, and remove the `Dialog` intake:
|
|
66
|
+
- Hold `const [startProject, setStartProject] = useState<StartProjectRequest | null>(null)` and pass `startProject={startProject}` and `onStartProjectChange={setStartProject}`. Site buttons that opened the intake `Dialog` call `setStartProject({})` instead.
|
|
67
|
+
- Pass `renderStartProject={(slot) => <StartProjectGate {...slot} onSubmit={sendIntake} renderCalendar={yourCalendar} />}`, where `sendIntake` posts the intake as the `Dialog` did.
|
|
68
|
+
- Delete the intake `Dialog`, its open state, and its **IntakeConfirmation** step. Keep one **ConfettiProvider** at the app root; the gate fires the burst when it finishes.
|
|
69
|
+
4. **Return follow-ups, the score, the copy text, and Start a project requests from `ask`** for the replies that have them: resolve with `{ reply, followUps?, meta?, copyText?, startProject? }`.
|
|
70
|
+
- `followUps`: one to three items, each `{ id, label, prompt? }`. Leave out `icon`; it is not shown. An item without a `prompt`, such as `{ id: "start", label: "Start a project" }`, opens the gate.
|
|
71
|
+
- `startProject`: `{ services?, budget? }` with what the assistant picked up; the gate opens with them filled in.
|
|
72
|
+
- `meta`: the score, for example `{ label: "Match 99%", description: "How sure the assistant is that it matched your question." }`. Your app computes it; leave it out when there is none.
|
|
73
|
+
- `copyText`: what **Copy** puts on the clipboard. The pattern uses the reply text when you leave it out.
|
|
74
|
+
- Replies with none of these can keep resolving with the reply string.
|
|
75
|
+
5. **Handle `onFeedback`** where you mount `AskWhatMatters`: `onFeedback={(reply, value) => …}`. `value` is `"up"`, `"down"`, or `null` when the visitor clears their vote; store it against `reply.id`. The prop is required, so TypeScript flags the mount until you add it.
|
|
76
|
+
6. **The open and close transition:** nothing to do. It comes with the upgrade.
|
|
77
|
+
7. **WhatMatters site, blog index: replace `components/blog-index.tsx` with Guides/Filter panel → Pattern — filtered index** (`node_modules/@thewhatmatters/wmds/docs/patterns/guides-filter-panel--filtered-index.tsx`). Map each post to `FilteredPost` (`facets: { topic: post.topic }`, `dateLabel` from your date formatter) and your topics to one `FilterGroupDef` (`{ id: "topic", label: "Topic", options }`), then render `<FilteredIndex title={copy["blog-title"]} posts={posts} groups={groups} />`. If the page already sits inside a `<main>`, change the pattern's `main` to a `div`. The pattern replaces these hand-placed parts of `components/blog-index.tsx`:
|
|
78
|
+
- the rows' two-track grid (`grid-cols-[7.5rem_1fr]`, `border-b border-border py-4`) with the date and a **TextLink** title → **IndexList** + **IndexList.Item** (`meta={<time dateTime={post.date}>…</time>}`, `title`, `href`, `preview` for the description);
|
|
79
|
+
- the "/ DATE" and "/ NAME" captions → **IndexList** `captions={{ meta: "Date", title: "Name" }}`;
|
|
80
|
+
- the "/ FILTERS" caption built from `type-code uppercase text-muted` → **SectionCaption** with Clear all in its `end`;
|
|
81
|
+
- the always-open Topic **CheckboxGroup** with the count written into each label ("Guides (2)") → an **Accordion** `variant="plain"` `flush` group of **CheckboxGroup.Item** with `count` and `countLabel`;
|
|
82
|
+
- and it adds Clear all, the empty state, the announced post count, and the phone **Sheet**.
|
|
83
|
+
8. **If you keep your own blog index instead**, make the same swaps by hand: the row grid → **IndexList**; `type-code uppercase text-muted` captions → **SectionCaption**; `label="Guides (2)"` → `label="Guides" count={2} countLabel="2 posts"`; a large linked title → `<TextLink variant="quiet">` inside its heading. The Topic group can now collapse: closed panels leave the tab order.
|
|
84
|
+
9. **WhatMatters site, blog post page: paste Guides/Post page → Pattern — post page** (`node_modules/@thewhatmatters/wmds/docs/patterns/guides-post-page--post-page.tsx`) and render it from `app/blog/[slug]/page.tsx` as `<PostPage post={post}>{body}</PostPage>`, where `body` is the rendered markdown. Fill `PostPageData`: `markdown` is the post file's source, `markdownHref` your plain-markdown route, `url` the post's address. If the page already sits inside a `<main>`, change the pattern's `main` to a `div`. Then:
|
|
85
|
+
- **`components/post-meta.tsx` — delete it.** Its hand-built `<dl>` (two-track `grid-cols-[2fr_3fr]` rows with `border-b border-border py-3`, `type-code text-muted uppercase` names, `type-code text-fg uppercase tabular-nums` values) is **DescriptionList** `variant="mono"` `rule="dotted"`; the author and category `Badge size="sm" emphasis="muted"` are **Badge** `emphasis="outline"` `mono`, with `render={<a href />}` on each category; the share buttons' hand-written `target`, `rel`, and visually hidden "(opens in a new tab)" are **Button** `external`.
|
|
86
|
+
- **`components/copy-text-button.tsx` — delete it.** Its Copy → Check icon swap, "Copied" label, two-second timer, and `role="status"` text are **Button** `icon={<Copy />}` with `status` and `statusLabels`, held for `buttonStatusHoldMs` — the pattern's `CopyButton` (also **Components/Button/Button → Pattern — copy button**).
|
|
87
|
+
- **`components/section-caption.tsx` — delete it** and import **SectionCaption** where it was used. Pass the caption in sentence case ("Metadata", not "/ METADATA"); the marker and the `border-border-emphasized` rule come with it.
|
|
88
|
+
- **`components/markdown.tsx` — keep `compiler(…)`, drop the class map.** Keep the `h1` → `h2` and `a` → `MarkdownLink` (**TextLink** `external`) overrides; delete `blocksClasses`, the other class constants and overrides, and `MarkdownTable`, and return the compiled output without a wrapper `div`. The post page puts it in **Prose**; for a resource category's notes wrap it in `<Prose size="md">` (add `measure="none"` to fill the column). Long-form text moves from 14px (`type-body`) to 17px (`type-reading`).
|
|
89
|
+
10. **If you keep your own post page instead**, make the same swaps by hand: the `<dl>` → **DescriptionList**; muted badges → **Badge** `emphasis="outline"` `mono`; the copy swap → **Button** `icon` + `status`; hand-written new-tab links → **Button** `external`; the caption → **SectionCaption**; the markdown class map → **Prose**.
|
|
90
|
+
11. Other apps: none. The tint comes with the upgrade; **IconButton**'s `pressed`, **ChatDock**'s `gate`, **useKbdChoiceKeys**' `scope`, **Checkbox** `count`, **TextLink** `variant`, **Accordion** `flush`, **Badge** `emphasis="outline"` / `mono` / `render`, and **Button** `external` are optional. A **Button** or **Badge** inside an `uppercase` parent used to inherit the capitals and no longer does — set `mono` where caps were intended. If you show thumbs with `onMessageFeedback`, give each reply `feedback: null` until the visitor votes — replies without `feedback` take no vote. A test that finds content inside a closed **Accordion** panel (or any `.motion-collapse`) by role must open the panel first — closed, it is hidden.
|
|
91
|
+
|
|
10
92
|
## 0.4.0
|
|
11
93
|
|
|
12
94
|
**ChatDock** is the site assistant: a pinned composer that shows suggested questions on hover and opens into a chat window, instead of a separate ask page. **PromptBar** gains `start` and `end` slots. **Components/PromptBar → Pattern — marketing composer** is removed. See **ADR-0039**.
|
package/CONSUMING.md
CHANGED
|
@@ -259,17 +259,22 @@ import {
|
|
|
259
259
|
|
|
260
260
|
| Component | Key props | Storybook |
|
|
261
261
|
|-----------|-----------|-----------|
|
|
262
|
-
| `Button` | `role` (`primary` \| `secondary` \| `ghost` \| `destructive` \| `inverse` \| `outline`), `layout` (`pill` \| `row` \| `nav`), `size`, `status
|
|
262
|
+
| `Button` | `role` (`primary` \| `secondary` \| `ghost` \| `destructive` \| `inverse` \| `outline`), `layout` (`pill` \| `row` \| `nav`), `size`, `status` (with `icon` — **Pattern — copy button**), `icon`, `endIcon`, `mono`, `count`, `render`, `external` (with `render={<a href />}`) | Components/Button/Button — copy a **Pattern** story (`row` for flat detail lines; **Pattern — secondary action** for the gallery intro — `role="secondary"`, label Start a project, no className) |
|
|
263
263
|
| `IconButton` | `icon`, `aria-label`, `role`, `size`, `fab`, `loading`, `title` | Components/Button/IconButton — copy a **Pattern** story |
|
|
264
264
|
| `Chip` | `size`, `value`, `selected`, `onRemove`, `icon`, `count`, `readOnly` | Components/Chip — use `ChipFilterGroup` for multi-select filters |
|
|
265
265
|
| `Input` | `label`, `description`, `status`, `message`, `loading`, `endBadge`, `icon`, `size` | Components/Input — pill shell; Required via `endBadge={<Badge>…</Badge>}` |
|
|
266
266
|
| `Search` | `size`, `placeholder`, `onSubmit` | Components/Search — inline input + button row |
|
|
267
267
|
| `PromptBar` | `value`, `onValueChange`, `onSend`, `placeholder` (default Ask anything…), `start`, `end` | Components/PromptBar — **Pattern — prompt bar**. Wide pill, inline field (one line empty, up to 3 lines, then scroll), inset **IconButton** send. Muted until there is text, then `--color-brand` (`#011272`). Enter sends. `start` takes the brand mark; `end` takes extra inset controls. Voice and attachments are not part of this version. |
|
|
268
|
-
| `ChatDock` | `title`, `subtitle`, `mark`, `greeting`, `messages`, `thinking`, `suggestions`, `onSend`, `onSuggestionSelect`, `disclaimer` | Components/ChatDock — **Pattern — chat dock**. The site assistant: a pinned **PromptBar** with suggested-question pills on hover that opens into a non-modal chat window (full screen on phones). The app owns the conversation and the request. Replaces the separate ask page. |
|
|
268
|
+
| `ChatDock` | `title`, `subtitle`, `mark`, `greeting`, `messages` (replies may carry `copyText`, `meta`, `feedback`), `thinking`, `suggestions`, `followUps`, `followUpsPlacement`, `onSend`, `onSuggestionSelect`, `onMessageFeedback`, `gate` (**ChatDock.Gate**), `disclaimer` | Components/ChatDock — **Pattern — chat dock**. The site assistant: a pinned **PromptBar** with suggested-question pills on hover that opens into a non-modal chat window (full screen on phones). The app owns the conversation and the request, and passes `followUps` for the latest reply when it has them (shown under the reply by default). Finished replies get Copy, thumbs, and a score row from `copyText`, `onMessageFeedback` with `feedback`, and `meta`. Start a project runs as a `gate` in the composer's place — **Pattern — start a project gate**. Replaces the separate ask page. |
|
|
269
269
|
| `Card` | `variant`, `shape`, `padding` | Components/Card/Card — `Card.Header` (`start` | `end`), **`Card.Body` slot** (no default fill), `Card.Footer` |
|
|
270
|
-
| `Accordion` | `variant`, `Accordion.Item` `leading` / `label` / `trailing` / `open` | Components/Accordion — FAQ, settings sections |
|
|
270
|
+
| `Accordion` | `variant`, `flush` (plain), `Accordion.Item` `leading` / `label` / `trailing` / `open` | Components/Accordion — FAQ, settings sections; **Pattern — flush** for filter groups. Closed panels leave the tab order |
|
|
271
|
+
| `Breadcrumb` | `items` (`{ label, href }`, current page last), `maxItems`, `separator` (`chevron` \| `slash`), `variant` (`sans` \| `mono`), `renderLink`, `labels` | Components/Breadcrumb — **Pattern — path**, **long path**, **router links**, **editorial** |
|
|
272
|
+
| `DescriptionList` | `layout` (`inline` \| `stacked`), `rule` (`solid` \| `dotted` \| `none`), `variant` (`sans` \| `mono`), `DescriptionList.Item` `name` / `layout` | Components/DescriptionList — **Pattern — post metadata**, **Pattern — details** |
|
|
273
|
+
| `SectionCaption` | `children`, `as`, `id`, `end`, `marker`, `rule` | Components/SectionCaption — **Pattern — column caption**, **Pattern — caption with an action** |
|
|
274
|
+
| `Prose` | `size` (`lg` \| `md`), `measure` (`reading` \| `none`), `as` | Components/Prose — **Pattern — article body**. Full page: **Guides/Post page → Pattern — post page** |
|
|
275
|
+
| `IndexList` | `captions`, `size`, `titleAs`, `empty`, `IndexList.Item` `meta` / `title` / `href` / `preview` | Components/IndexList — **Pattern — post index**. With filters: **Guides/Filter panel → Pattern — filtered index** |
|
|
271
276
|
| `TaskRows` | `variant`, `status`, `meta`, `detailsLayout`, `TaskRows.Detail` | Components/TaskRows — **Pattern — status rows**, **capsules**, **action details** (`Detail variant="button"`), **tag chips** (`Chip readOnly size="sm"`), detail lines (`Detail` + `onPress` → `Button layout="row"`) |
|
|
272
|
-
| `Badge` | `variant`, `size`, `emphasis`, `count`, `icon`, `avatar`, `iconOnly` | Components/Badge — copy a **Pattern** story. `avatar={{ src, alt }}` is a leading round **Avatar** sized to the badge (`badgeAvatarSize`: sm → 20px, md → 24px) and is mutually exclusive with `icon`. Pass `alt=""` when the label already speaks the word. |
|
|
277
|
+
| `Badge` | `variant`, `size`, `emphasis` (`solid` \| `muted` \| `outline`), `mono`, `render` (tag links), `count`, `icon`, `avatar`, `iconOnly` | Components/Badge — copy a **Pattern** story. `avatar={{ src, alt }}` is a leading round **Avatar** sized to the badge (`badgeAvatarSize`: sm → 20px, md → 24px) and is mutually exclusive with `icon`. Pass `alt=""` when the label already speaks the word. |
|
|
273
278
|
| `Status` | `variant`, `tone`, `label`, `besideLabel`, `pulsing`, `active`, `step` | Components/Status — `variant="ring"` or `variant="dot"` |
|
|
274
279
|
| `FooterReveal` | `FooterReveal.Content`, `FooterReveal.Footer`, `FooterReveal.Brand` (`headline`, `ctaLabel`, `onCtaClick`, optional `ctaHref`, `wordmark`, `socialLinks`), `footerRevealFieldClasses` | Components/FooterReveal — **Pattern — marketing page** and **Pattern — marketing hero**. Cover sits on the page background; the brand field sticks underneath and sharpens from 12px of blur. Field is `bg-brand` / `text-on-brand` (`#011272`). The wordmark is `--color-brand-soft`, spans the footer width, and is cropped at the bottom edge. CTA is **Button** `role="inverse"` `type="button"` (`onCtaClick` opens the project modal). Pass `ctaHref` only to render a link. Reduced motion stays sharp, including the server render (the SSR snapshot is sharp, so a Next page does not hydrate a leftover blur). The root does not clip, so **GridOverlay** guides still cover the hero. The marketing hero's guide `grid-page` uses `!py-0` so the expanded gallery tile meets the footer with no page-background strip. |
|
|
275
280
|
| `HeroIntro` | `lead`, `children`, `step` (`large` default \| `display`), `className` (layout only) | Components/HeroIntro — **Pattern — two-line intro**. Also composed by **Components/HeroTileStack → Pattern — marketing hero**. `lead` is the first sentence. Children always start on the next line. Both steps are `type-display-2` at normal weight (`!font-normal`) and `text-balance`, the same font-size as **ScrollHorizontal.Intro**. Keep “Austin, Texas” together with a non-breaking space. `lead` wraps, including from `md`. `large` (default) is columns 4–9 from `lg`. `display` is full width of the page grid — **Pattern — marketing hero text sequence** and **FooterReveal → Pattern — marketing hero with sequenced gallery**. The shell is `grid-page` with the page block pad removed. Do not insert a line break in the copy. |
|
package/dist/collapse.css
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
/** Shared height-collapse motion — List panels, Table filter rows. */
|
|
2
2
|
.motion-collapse {
|
|
3
3
|
display: grid;
|
|
4
|
+
/*
|
|
5
|
+
* visibility interpolates as "visible" for the whole transition, so a closing panel stays drawn
|
|
6
|
+
* while it folds and turns hidden once the fold ends; an opening panel is visible at once. Hidden,
|
|
7
|
+
* its controls leave the tab order and the accessibility tree.
|
|
8
|
+
*/
|
|
4
9
|
transition:
|
|
5
10
|
grid-template-rows var(--duration-medium) var(--ease-standard),
|
|
6
|
-
opacity var(--duration-medium) var(--ease-standard)
|
|
11
|
+
opacity var(--duration-medium) var(--ease-standard),
|
|
12
|
+
visibility var(--duration-medium) var(--ease-standard);
|
|
7
13
|
}
|
|
8
14
|
|
|
9
15
|
.motion-collapse[data-visible="true"] {
|
|
10
16
|
grid-template-rows: 1fr;
|
|
11
17
|
opacity: 1;
|
|
18
|
+
visibility: visible;
|
|
12
19
|
}
|
|
13
20
|
|
|
14
21
|
.motion-collapse[data-visible="false"] {
|
|
15
22
|
grid-template-rows: 0fr;
|
|
16
23
|
opacity: 0;
|
|
17
24
|
pointer-events: none;
|
|
25
|
+
visibility: hidden;
|
|
18
26
|
}
|
|
19
27
|
|
|
20
28
|
@media (prefers-reduced-motion: reduce) {
|
package/dist/colors.css
CHANGED
|
@@ -96,6 +96,11 @@
|
|
|
96
96
|
--color-on-brand: #ffffff;
|
|
97
97
|
--color-brand-outline: var(--color-brand);
|
|
98
98
|
--color-brand-soft: color-mix(in srgb, var(--color-on-brand) 40%, var(--color-brand));
|
|
99
|
+
/*
|
|
100
|
+
* Brand tint — the visitor's turns in ChatDock. 10% navy over the surface (about #e3e5ee):
|
|
101
|
+
* reads as brand, not as a neutral well, and dark text keeps full contrast (about 14:1).
|
|
102
|
+
*/
|
|
103
|
+
--color-brand-tint: color-mix(in srgb, var(--color-brand) 10%, transparent);
|
|
99
104
|
|
|
100
105
|
/* Derived from --color-primary — 62% clears WCAG 3:1 on white and #f8f8f8 */
|
|
101
106
|
--color-focus-ring: color-mix(in srgb, var(--color-primary) 62%, transparent);
|
|
@@ -205,6 +210,8 @@
|
|
|
205
210
|
--color-on-brand: #ffffff;
|
|
206
211
|
--color-brand-outline: color-mix(in srgb, var(--color-brand) 45%, white);
|
|
207
212
|
--color-brand-soft: color-mix(in srgb, var(--color-on-brand) 40%, var(--color-brand));
|
|
213
|
+
/* The navy disappears on dark surfaces, so the tint lifts it: 28% of the outline mix (about #3d3f49 on #1b1b1b). */
|
|
214
|
+
--color-brand-tint: color-mix(in srgb, var(--color-brand-outline) 28%, transparent);
|
|
208
215
|
|
|
209
216
|
/*
|
|
210
217
|
* Derived from --color-primary: lift the brand toward white so the ring stays
|
|
@@ -21,8 +21,19 @@ export interface BadgeProps {
|
|
|
21
21
|
/** Semantic color — solid or muted fills. Default: `neutral`. */
|
|
22
22
|
variant?: BadgeVariant;
|
|
23
23
|
size?: BadgeSize;
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* `solid` (default), `muted` soft fills for trailing status copy, or `outline` — a hairline and a
|
|
26
|
+
* transparent fill, for author and category tags.
|
|
27
|
+
*/
|
|
25
28
|
emphasis?: BadgeEmphasis;
|
|
29
|
+
/** Mono uppercase label — the same face and tracking as **Button** `mono`. Label patterns only. */
|
|
30
|
+
mono?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Compose the badge onto another element (Base UI `render`) — `render={<a href="/blog?topic=guides" />}`
|
|
33
|
+
* makes a tag a link, with a hover underline, the focus ring, and a 44px-tall hit area. Label,
|
|
34
|
+
* icon, and avatar patterns only.
|
|
35
|
+
*/
|
|
36
|
+
render?: ReactElement;
|
|
26
37
|
/** Compact numeric pill — notifications, unread totals. Not combinable with `icon`. */
|
|
27
38
|
count?: number;
|
|
28
39
|
/** Leading Lucide icon — label pattern, or required for `iconOnly`. Not with `avatar`. */
|
|
@@ -40,8 +51,9 @@ export interface BadgeProps {
|
|
|
40
51
|
className?: BadgeLayoutClassName;
|
|
41
52
|
}
|
|
42
53
|
/**
|
|
43
|
-
* Short status, count, or category label — solid semantic fills.
|
|
44
|
-
* Pattern-first: label, count, icon + label, avatar + label, icon-only, muted emphasis
|
|
54
|
+
* Short status, count, or category label — solid, muted, or outline semantic fills.
|
|
55
|
+
* Pattern-first: label, count, icon + label, avatar + label, icon-only, muted and outline emphasis,
|
|
56
|
+
* mono caps, and links (`render`).
|
|
45
57
|
*/
|
|
46
|
-
export declare function Badge({ children, variant, size, emphasis, count, icon, avatar, iconOnly, id, className, }: BadgeProps): import("react").JSX.Element;
|
|
58
|
+
export declare function Badge({ children, variant, size, emphasis, mono, render, count, icon, avatar, iconOnly, id, className, }: BadgeProps): import("react").JSX.Element;
|
|
47
59
|
//# sourceMappingURL=Badge.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Badge/Badge.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Badge.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Badge/Badge.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAE3D,OAAO,EAYL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAE7D,sEAAsE;AACtE,MAAM,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE1C,6GAA6G;AAC7G,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,SAAS,EAAE,UAAU,CAGzD,CAAC;AAEF,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,iEAAiE;IACjE,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,mGAAmG;IACnG,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,uFAAuF;IACvF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0FAA0F;IAC1F,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mGAAmG;IACnG,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6DAA6D;IAC7D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oDAAoD;IACpD,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC;AAiDD;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,OAAmB,EACnB,IAAW,EACX,QAAkB,EAClB,IAAY,EACZ,MAAM,EACN,KAAK,EACL,IAAI,EACJ,MAAM,EACN,QAAgB,EAChB,EAAE,EACF,SAAS,GACV,EAAE,UAAU,+BAiEZ"}
|
|
@@ -1,68 +1,80 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../../../lib/cn.js";
|
|
3
3
|
import { Avatar as t } from "../Avatar/Avatar.js";
|
|
4
|
-
import { badgeAvatarLabelSizeClasses as n, badgeBaseClasses as r, badgeCountSizeClasses as i, badgeEmphases as a, badgeIconGapClasses as o, badgeIconOnlySizeClasses as s,
|
|
5
|
-
import { BadgeIcon as
|
|
6
|
-
import { jsx as
|
|
4
|
+
import { badgeAvatarLabelSizeClasses as n, badgeBaseClasses as r, badgeCountSizeClasses as i, badgeEmphases as a, badgeIconGapClasses as o, badgeIconOnlySizeClasses as s, badgeInteractiveClasses as c, badgeLabelSizeClasses as l, badgeSolidClasses as u, badgeSurfaceClasses as d, badgeVariants as f } from "./badgeStyles.js";
|
|
5
|
+
import { BadgeIcon as p } from "./BadgeIcon.js";
|
|
6
|
+
import { jsx as m, jsxs as h } from "react/jsx-runtime";
|
|
7
|
+
import { useRender as g } from "@base-ui/react/use-render";
|
|
7
8
|
//#region src/components/atoms/Badge/Badge.tsx
|
|
8
|
-
var
|
|
9
|
+
var _ = {
|
|
9
10
|
sm: "xsm",
|
|
10
11
|
md: "sm"
|
|
11
12
|
};
|
|
12
|
-
function
|
|
13
|
-
if (e.avatar && (e.icon || e.iconOnly || e.count != null) && console.warn("[WMDS Badge] `avatar` is mutually exclusive with `icon`, `iconOnly`, and `count`."), e.count != null && e.icon && console.warn("[WMDS Badge] `count` is mutually exclusive with `icon`."), e.iconOnly) {
|
|
13
|
+
function v(e) {
|
|
14
|
+
if ((e.render != null || e.mono) && (e.count != null || e.iconOnly) && console.warn("[WMDS Badge] `render` and `mono` apply to label, icon, and avatar badges — not `count` or `iconOnly`."), e.avatar && (e.icon || e.iconOnly || e.count != null) && console.warn("[WMDS Badge] `avatar` is mutually exclusive with `icon`, `iconOnly`, and `count`."), e.count != null && e.icon && console.warn("[WMDS Badge] `count` is mutually exclusive with `icon`."), e.iconOnly) {
|
|
14
15
|
e.icon || console.warn("[WMDS Badge] `iconOnly` requires `icon`."), (e.count != null || e.children != null) && console.warn("[WMDS Badge] `iconOnly` is mutually exclusive with `children` and `count`.");
|
|
15
16
|
return;
|
|
16
17
|
}
|
|
17
18
|
e.children == null && e.count == null && console.warn("[WMDS Badge] Provide `children`, `count`, or `iconOnly` + `icon`.");
|
|
18
19
|
}
|
|
19
|
-
function
|
|
20
|
-
g({
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
iconOnly: S,
|
|
25
|
-
children: a
|
|
20
|
+
function y({ render: e, ...t }) {
|
|
21
|
+
return g({
|
|
22
|
+
render: e,
|
|
23
|
+
defaultTagName: "span",
|
|
24
|
+
props: t
|
|
26
25
|
});
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
26
|
+
}
|
|
27
|
+
function b({ children: a, variant: f = "neutral", size: g = "sm", emphasis: b = "solid", mono: x = !1, render: S, count: C, icon: w, avatar: T, iconOnly: E = !1, id: D, className: O }) {
|
|
28
|
+
v({
|
|
29
|
+
count: C,
|
|
30
|
+
icon: w,
|
|
31
|
+
avatar: T,
|
|
32
|
+
iconOnly: E,
|
|
33
|
+
children: a,
|
|
34
|
+
render: S,
|
|
35
|
+
mono: x
|
|
36
|
+
});
|
|
37
|
+
let k = d(f, b), A = C != null && T == null, j = E && w != null && !A && T == null, M = T != null && !A && !j, N = w != null && !A && !j && !M;
|
|
38
|
+
return A ? /* @__PURE__ */ m("span", {
|
|
39
|
+
id: D,
|
|
40
|
+
className: e(r, k, i[g], O),
|
|
41
|
+
"data-variant": f,
|
|
42
|
+
"data-size": g,
|
|
43
|
+
"data-emphasis": b,
|
|
34
44
|
"data-pattern": "count",
|
|
35
|
-
children:
|
|
36
|
-
}) :
|
|
37
|
-
id:
|
|
38
|
-
className: e(r,
|
|
39
|
-
"data-variant":
|
|
45
|
+
children: C
|
|
46
|
+
}) : j ? /* @__PURE__ */ m("span", {
|
|
47
|
+
id: D,
|
|
48
|
+
className: e(r, u[f], s, O),
|
|
49
|
+
"data-variant": f,
|
|
40
50
|
"data-pattern": "icon-only",
|
|
41
51
|
"aria-hidden": !0,
|
|
42
|
-
children: /* @__PURE__ */ p
|
|
52
|
+
children: /* @__PURE__ */ m(p, {
|
|
43
53
|
size: "sm",
|
|
44
|
-
children:
|
|
54
|
+
children: w
|
|
45
55
|
})
|
|
46
|
-
}) : /* @__PURE__ */
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
"
|
|
50
|
-
"data-
|
|
51
|
-
"data-
|
|
52
|
-
"data-
|
|
56
|
+
}) : /* @__PURE__ */ h(y, {
|
|
57
|
+
render: S,
|
|
58
|
+
id: D,
|
|
59
|
+
className: e(r, k, M ? n[g] : l[g], N && o[g], x && "!font-mono !text-[length:var(--font-size-sm)] !font-normal !uppercase !tracking-[0.14em]", S != null && c, S != null && b === "outline" && "hover:border-fg", O),
|
|
60
|
+
"data-variant": f,
|
|
61
|
+
"data-size": g,
|
|
62
|
+
"data-emphasis": b,
|
|
63
|
+
"data-pattern": M ? "avatar" : N ? "icon" : "label",
|
|
64
|
+
"data-mono": x ? "" : void 0,
|
|
53
65
|
children: [
|
|
54
|
-
|
|
55
|
-
name:
|
|
56
|
-
src:
|
|
57
|
-
size:
|
|
66
|
+
M && T != null ? /* @__PURE__ */ m(t, {
|
|
67
|
+
name: T.alt,
|
|
68
|
+
src: T.src,
|
|
69
|
+
size: _[g]
|
|
58
70
|
}) : null,
|
|
59
|
-
|
|
60
|
-
size:
|
|
61
|
-
children:
|
|
71
|
+
N ? /* @__PURE__ */ m(p, {
|
|
72
|
+
size: g,
|
|
73
|
+
children: w
|
|
62
74
|
}) : null,
|
|
63
75
|
a
|
|
64
76
|
]
|
|
65
77
|
});
|
|
66
78
|
}
|
|
67
79
|
//#endregion
|
|
68
|
-
export {
|
|
80
|
+
export { b as Badge, _ as badgeAvatarSize, a as badgeEmphases, f as badgeVariants };
|
|
@@ -2,10 +2,10 @@ import type { SemanticVariant } from "../../../lib/semanticVariants";
|
|
|
2
2
|
export declare const badgeVariants: readonly ["neutral", "info", "success", "warning", "destructive"];
|
|
3
3
|
export type BadgeVariant = (typeof badgeVariants)[number];
|
|
4
4
|
export type BadgeSize = "sm" | "md";
|
|
5
|
-
export declare const badgeEmphases: readonly ["solid", "muted"];
|
|
5
|
+
export declare const badgeEmphases: readonly ["solid", "muted", "outline"];
|
|
6
6
|
export type BadgeEmphasis = (typeof badgeEmphases)[number];
|
|
7
7
|
/** Shared shell — Astryx-style compact pill labels. */
|
|
8
|
-
export declare const badgeBaseClasses = "inline-flex shrink-0 items-center justify-center font-sans font-medium tracking-normal";
|
|
8
|
+
export declare const badgeBaseClasses = "inline-flex shrink-0 items-center justify-center font-sans font-medium normal-case tracking-normal";
|
|
9
9
|
/**
|
|
10
10
|
* Solid semantic fills — matches [Astryx Badge](https://astryx.atmeta.com/components/Badge) status row.
|
|
11
11
|
* Neutral stays subtle (category / draft tags).
|
|
@@ -13,7 +13,17 @@ export declare const badgeBaseClasses = "inline-flex shrink-0 items-center justi
|
|
|
13
13
|
export declare const badgeSolidClasses: Record<BadgeVariant, string>;
|
|
14
14
|
/** Soft semantic fills — task row trailing pills, subtle status copy. */
|
|
15
15
|
export declare const badgeMutedClasses: Record<BadgeVariant, string>;
|
|
16
|
+
/** Hairline outline, transparent fill — author and category tags. */
|
|
17
|
+
export declare const badgeOutlineClasses: Record<BadgeVariant, string>;
|
|
16
18
|
export declare function badgeSurfaceClasses(variant: BadgeVariant, emphasis: BadgeEmphasis): string;
|
|
19
|
+
/** Mono uppercase label — the same face, size, and tracking as **Button** `mono`. `!` beats the sans medium shell. */
|
|
20
|
+
export declare const badgeMonoClasses = "!font-mono !text-[length:var(--font-size-sm)] !font-normal !uppercase !tracking-[0.14em]";
|
|
21
|
+
/**
|
|
22
|
+
* A badge composed onto a link (`render`): an underline on hover, the hairline darkens on an
|
|
23
|
+
* outline badge, the focus ring, and a 44px-tall hit area around the 20–24px pill.
|
|
24
|
+
*/
|
|
25
|
+
export declare const badgeInteractiveClasses: string;
|
|
26
|
+
export declare const badgeInteractiveOutlineClasses = "hover:border-fg";
|
|
17
27
|
/** Label sizing — text-only and icon patterns share the same padding shell. */
|
|
18
28
|
export declare const badgeLabelSizeClasses: Record<BadgeSize, string>;
|
|
19
29
|
/** Gap between leading icon and label — only when `icon` is set. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badgeStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Badge/badgeStyles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"badgeStyles.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Badge/badgeStyles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAIrE,eAAO,MAAM,aAAa,mEAAoE,CAAC;AAE/F,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE1D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;AAEpC,eAAO,MAAM,aAAa,wCAAyC,CAAC;AAEpE,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC;AAE3D,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,uGACyE,CAAC;AAEvG;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM1D,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM1D,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,YAAY,EAAE,MAAM,CAM5D,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,GAAG,MAAM,CAG1F;AAED,sHAAsH;AACtH,eAAO,MAAM,gBAAgB,6FAC+D,CAAC;AAE7F;;;GAGG;AACH,eAAO,MAAM,uBAAuB,QAMnC,CAAC;AAEF,eAAO,MAAM,8BAA8B,oBAAoB,CAAC;AAEhE,+EAA+E;AAC/E,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAG3D,CAAC;AAEF,oEAAoE;AACpE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAGzD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAGjE,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAG1D,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAG3D,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,wBAAwB,qCAAqC,CAAC;AAE3E,8DAA8D;AAC9D,eAAO,MAAM,yBAAyB,+DACwB,CAAC;AAE/D,kFAAkF;AAClF,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,CAKhE;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,YAAY,CAEnE;AAED,YAAY,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -1,46 +1,57 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn as e } from "../../../lib/cn.js";
|
|
3
|
+
import { motionTransition as t } from "../../../lib/motion.js";
|
|
3
4
|
//#region src/components/atoms/Badge/badgeStyles.ts
|
|
4
|
-
var
|
|
5
|
+
var n = [
|
|
5
6
|
"neutral",
|
|
6
7
|
"info",
|
|
7
8
|
"success",
|
|
8
9
|
"warning",
|
|
9
10
|
"destructive"
|
|
10
|
-
],
|
|
11
|
+
], r = [
|
|
12
|
+
"solid",
|
|
13
|
+
"muted",
|
|
14
|
+
"outline"
|
|
15
|
+
], i = "inline-flex shrink-0 items-center justify-center font-sans font-medium normal-case tracking-normal", a = {
|
|
11
16
|
neutral: "border border-border bg-secondary text-secondary-foreground shadow-raised",
|
|
12
17
|
info: "bg-info text-on-info",
|
|
13
18
|
success: "bg-success text-on-success",
|
|
14
19
|
warning: "bg-warning text-on-warning",
|
|
15
20
|
destructive: "bg-error text-on-error"
|
|
16
|
-
},
|
|
21
|
+
}, o = {
|
|
17
22
|
neutral: "border border-border bg-secondary text-secondary-foreground",
|
|
18
23
|
info: "bg-info-muted text-info",
|
|
19
24
|
success: "bg-success-muted text-success",
|
|
20
25
|
warning: "bg-warning-muted text-warning",
|
|
21
26
|
destructive: "bg-error-muted text-error"
|
|
27
|
+
}, s = {
|
|
28
|
+
neutral: "border border-border-emphasized bg-transparent text-fg",
|
|
29
|
+
info: "border border-info bg-transparent text-info",
|
|
30
|
+
success: "border border-success bg-transparent text-success",
|
|
31
|
+
warning: "border border-warning bg-transparent text-warning",
|
|
32
|
+
destructive: "border border-error bg-transparent text-error"
|
|
22
33
|
};
|
|
23
|
-
function
|
|
24
|
-
return t === "muted" ?
|
|
34
|
+
function c(e, t) {
|
|
35
|
+
return t === "outline" ? s[e] : t === "muted" ? o[e] : a[e];
|
|
25
36
|
}
|
|
26
|
-
var
|
|
37
|
+
var l = "!font-mono !text-[length:var(--font-size-sm)] !font-normal !uppercase !tracking-[0.14em]", u = e("relative cursor-pointer decoration-1 underline-offset-2 hover:underline", "after:absolute after:inset-x-0 after:top-1/2 after:h-11 after:-translate-y-1/2 after:content-['']", "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-focus-ring focus-visible:ring-offset-2 focus-visible:ring-offset-body", "transition-[border-color,text-decoration-color]", t("fast")), d = "hover:border-fg", f = {
|
|
27
38
|
sm: "h-5 rounded-full px-2 text-xs leading-none",
|
|
28
39
|
md: "h-6 rounded-full px-2.5 text-sm leading-none"
|
|
29
|
-
},
|
|
40
|
+
}, p = {
|
|
30
41
|
sm: "gap-1",
|
|
31
42
|
md: "gap-1.5"
|
|
32
|
-
},
|
|
43
|
+
}, m = {
|
|
33
44
|
sm: "h-5 gap-1 rounded-full py-0 pl-0 pr-2 text-xs leading-none",
|
|
34
45
|
md: "h-6 gap-1.5 rounded-full py-0 pl-0 pr-2.5 text-sm leading-none"
|
|
35
|
-
},
|
|
46
|
+
}, h = {
|
|
36
47
|
sm: "size-3 shrink-0 stroke-current",
|
|
37
48
|
md: "size-3.5 shrink-0 stroke-current"
|
|
38
|
-
},
|
|
49
|
+
}, g = {
|
|
39
50
|
sm: "min-h-[1.125rem] min-w-[1.125rem] rounded-full px-1 text-xs leading-none tabular-nums",
|
|
40
51
|
md: "min-h-[1.25rem] min-w-[1.25rem] rounded-full px-1 text-sm leading-none tabular-nums"
|
|
41
|
-
},
|
|
42
|
-
function
|
|
52
|
+
}, _ = "size-[1.375rem] rounded-full p-0", v = "border border-transparent bg-surface text-fg shadow-raised";
|
|
53
|
+
function y(t) {
|
|
43
54
|
return e("rounded px-[length:var(--spacing-1)] text-[10.5px] leading-none tabular-nums text-muted", t && "bg-secondary");
|
|
44
55
|
}
|
|
45
56
|
//#endregion
|
|
46
|
-
export {
|
|
57
|
+
export { m as badgeAvatarLabelSizeClasses, i as badgeBaseClasses, g as badgeCountSizeClasses, r as badgeEmphases, p as badgeIconGapClasses, _ as badgeIconOnlySizeClasses, h as badgeIconSizeClasses, u as badgeInteractiveClasses, d as badgeInteractiveOutlineClasses, f as badgeLabelSizeClasses, l as badgeMonoClasses, o as badgeMutedClasses, v as badgeOnButtonCountClasses, s as badgeOutlineClasses, y as badgeSegmentCountClasses, a as badgeSolidClasses, c as badgeSurfaceClasses, n as badgeVariants };
|
|
@@ -4,7 +4,7 @@ import { type ButtonAlign, type ButtonEmphasis, type ButtonLayout, type ButtonRo
|
|
|
4
4
|
export type { ButtonAlign, ButtonEmphasis, ButtonLayout, ButtonRole, ButtonSize, ButtonWidth } from "./buttonStyles";
|
|
5
5
|
export { buttonAligns, buttonEmphases, buttonLayouts, buttonRoles, buttonWidths } from "./buttonStyles";
|
|
6
6
|
export type { ButtonStatus } from "./buttonStatusStyles";
|
|
7
|
-
export { defaultStatusLabels, getNextButtonStatus } from "./buttonStatusStyles";
|
|
7
|
+
export { buttonStatusHoldMs, defaultStatusLabels, getNextButtonStatus } from "./buttonStatusStyles";
|
|
8
8
|
/** Layout-only — not for colors, borders, or typography overrides. */
|
|
9
9
|
export type ButtonLayoutClassName = string;
|
|
10
10
|
export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "className" | "role" | "size"> {
|
|
@@ -35,13 +35,14 @@ export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement
|
|
|
35
35
|
/**
|
|
36
36
|
* Async / submit morph — whole pill animates idle → loading → success → error.
|
|
37
37
|
* [Motion multi-state badge](https://motion.dev/examples/react-multi-state-badge).
|
|
38
|
-
*
|
|
38
|
+
* With `icon`, the status glyphs morph out of the icon (a copy button's Copy glyph turns into the
|
|
39
|
+
* check). Mutually exclusive with `count`, `endIcon`, `mono`, and `render`.
|
|
39
40
|
*/
|
|
40
41
|
status?: ButtonStatus;
|
|
41
42
|
statusLabels?: Partial<Record<ButtonStatus, string>>;
|
|
42
43
|
/** When true, error state is non-interactive. Default: clickable for retry. */
|
|
43
44
|
disableOnError?: boolean;
|
|
44
|
-
/** Leading Lucide icon — `import { … } from "lucide-react"`.
|
|
45
|
+
/** Leading Lucide icon — `import { … } from "lucide-react"`. With `status`, it morphs into the status glyph. */
|
|
45
46
|
icon?: ReactElement;
|
|
46
47
|
/** Trailing numeric count (inbox / notifications). Not combinable with `status`. */
|
|
47
48
|
count?: number;
|
|
@@ -63,6 +64,13 @@ export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement
|
|
|
63
64
|
* `disabled` maps to `aria-disabled` on non-button elements.
|
|
64
65
|
*/
|
|
65
66
|
render?: ReactElement;
|
|
67
|
+
/**
|
|
68
|
+
* With `render={<a href />}` to another site: opens it in a new tab (`target="_blank"`, a safe
|
|
69
|
+
* `rel`), tells screen readers so, and shows the trailing external icon **TextLink** uses.
|
|
70
|
+
*/
|
|
71
|
+
external?: boolean;
|
|
72
|
+
/** `external` only — `false` drops the trailing icon; the spoken "opens in a new tab" stays. */
|
|
73
|
+
externalIcon?: boolean;
|
|
66
74
|
/** Layout-only: width, margin, flex placement. */
|
|
67
75
|
className?: ButtonLayoutClassName;
|
|
68
76
|
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Button/Button.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../../src/components/atoms/Button/Button.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAeL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,WAAW,EACjB,MAAM,gBAAgB,CAAC;AAExB,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrH,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACxG,YAAY,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEpG,sEAAsE;AACtE,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC;AAE3C,MAAM,WAAW,WACf,SAAQ,IAAI,CACV,oBAAoB,CAAC,iBAAiB,CAAC,EACvC,UAAU,GAAG,WAAW,GAAG,MAAM,GAAG,MAAM,CAC3C;IACD,oBAAoB;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,kIAAkI;IAClI,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,oFAAoF;IACpF,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAC;IACrC;;;;;OAKG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,YAAY,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,+EAA+E;IAC/E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,gHAAgH;IAChH,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gGAAgG;IAChG,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kDAAkD;IAClD,SAAS,CAAC,EAAE,qBAAqB,CAAC;IAClC,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC;IACrD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAwFD,eAAO,MAAM,MAAM,2GAyKjB,CAAC"}
|