@lar-works/design-system 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/actions/Button.d.ts +39 -1
- package/dist/actions/Button.js +39 -9
- package/dist/actions/Button.js.map +1 -1
- package/dist/actions/ButtonLink.d.ts +5 -1
- package/dist/actions/ButtonLink.js +28 -2
- package/dist/actions/ButtonLink.js.map +1 -1
- package/dist/actions/ButtonRecipes.js +7 -0
- package/dist/actions/ButtonRecipes.js.map +1 -0
- package/dist/actions/IconButton.d.ts +2 -2
- package/dist/actions/IconButton.js +1 -1
- package/dist/actions/IconButton.js.map +1 -1
- package/dist/actions/ThemeSwitch.js +1 -1
- package/dist/board/ActivityLine.d.ts +36 -0
- package/dist/board/ActivityLine.js +144 -0
- package/dist/board/ActivityLine.js.map +1 -0
- package/dist/board/ActivityTrack.d.ts +11 -0
- package/dist/board/ActivityTrack.js +25 -0
- package/dist/board/ActivityTrack.js.map +1 -0
- package/dist/board/AddItem.d.ts +82 -0
- package/dist/board/AddItem.js +185 -0
- package/dist/board/AddItem.js.map +1 -0
- package/dist/board/Archive.d.ts +21 -0
- package/dist/board/Archive.js +63 -0
- package/dist/board/Archive.js.map +1 -0
- package/dist/board/Attention.d.ts +66 -0
- package/dist/board/Attention.js +122 -0
- package/dist/board/Attention.js.map +1 -0
- package/dist/board/BoardShell.d.ts +16 -0
- package/dist/board/BoardShell.js +35 -0
- package/dist/board/BoardShell.js.map +1 -0
- package/dist/board/BoardTitleBar.d.ts +50 -0
- package/dist/board/BoardTitleBar.js +125 -0
- package/dist/board/BoardTitleBar.js.map +1 -0
- package/dist/board/ButtonKinds.d.ts +24 -0
- package/dist/board/ButtonKinds.js +19 -0
- package/dist/board/ButtonKinds.js.map +1 -0
- package/dist/board/Cleanup.d.ts +8 -0
- package/dist/board/Cleanup.js +15 -0
- package/dist/board/Cleanup.js.map +1 -0
- package/dist/board/Counters.d.ts +101 -0
- package/dist/board/Counters.js +202 -0
- package/dist/board/Counters.js.map +1 -0
- package/dist/board/DataAttributes.d.ts +6 -0
- package/dist/board/Dependencies.d.ts +17 -0
- package/dist/board/Dependencies.js +44 -0
- package/dist/board/Dependencies.js.map +1 -0
- package/dist/board/Desk.d.ts +52 -0
- package/dist/board/Desk.js +130 -0
- package/dist/board/Desk.js.map +1 -0
- package/dist/board/Dossier.d.ts +100 -0
- package/dist/board/Dossier.js +194 -0
- package/dist/board/Dossier.js.map +1 -0
- package/dist/board/Filters.d.ts +33 -0
- package/dist/board/Filters.js +64 -0
- package/dist/board/Filters.js.map +1 -0
- package/dist/board/ItemDetails.d.ts +167 -0
- package/dist/board/ItemDetails.js +339 -0
- package/dist/board/ItemDetails.js.map +1 -0
- package/dist/board/ItemDialog.d.ts +73 -0
- package/dist/board/ItemDialog.js +140 -0
- package/dist/board/ItemDialog.js.map +1 -0
- package/dist/board/ItemParts.d.ts +42 -0
- package/dist/board/ItemParts.js +82 -0
- package/dist/board/ItemParts.js.map +1 -0
- package/dist/board/ItemProgress.d.ts +56 -0
- package/dist/board/ItemProgress.js +138 -0
- package/dist/board/ItemProgress.js.map +1 -0
- package/dist/board/List.d.ts +65 -0
- package/dist/board/List.js +118 -0
- package/dist/board/List.js.map +1 -0
- package/dist/board/LoadingScreen.d.ts +38 -0
- package/dist/board/LoadingScreen.js +74 -0
- package/dist/board/LoadingScreen.js.map +1 -0
- package/dist/board/NeedsYou.d.ts +13 -0
- package/dist/board/NeedsYou.js +31 -0
- package/dist/board/NeedsYou.js.map +1 -0
- package/dist/board/Onboarding.d.ts +53 -0
- package/dist/board/Onboarding.js +122 -0
- package/dist/board/Onboarding.js.map +1 -0
- package/dist/board/PartsList.d.ts +60 -0
- package/dist/board/PartsList.js +115 -0
- package/dist/board/PartsList.js.map +1 -0
- package/dist/board/ProjectIcon.d.ts +51 -0
- package/dist/board/ProjectIcon.js +120 -0
- package/dist/board/ProjectIcon.js.map +1 -0
- package/dist/board/PullRequests.d.ts +43 -0
- package/dist/board/PullRequests.js +83 -0
- package/dist/board/PullRequests.js.map +1 -0
- package/dist/board/RowStyles.js +14 -0
- package/dist/board/RowStyles.js.map +1 -0
- package/dist/board/Settings.d.ts +54 -0
- package/dist/board/Settings.js +112 -0
- package/dist/board/Settings.js.map +1 -0
- package/dist/board/Slices.d.ts +32 -0
- package/dist/board/Slices.js +88 -0
- package/dist/board/Slices.js.map +1 -0
- package/dist/board/SourceIcon.d.ts +12 -0
- package/dist/board/SourceIcon.js +24 -0
- package/dist/board/SourceIcon.js.map +1 -0
- package/dist/board/StagePane.d.ts +43 -0
- package/dist/board/StagePane.js +97 -0
- package/dist/board/StagePane.js.map +1 -0
- package/dist/board/StageRow.d.ts +141 -0
- package/dist/board/StageRow.js +287 -0
- package/dist/board/StageRow.js.map +1 -0
- package/dist/board/StageTrack.d.ts +18 -0
- package/dist/board/StageTrack.js +38 -0
- package/dist/board/StageTrack.js.map +1 -0
- package/dist/board/StartControls.d.ts +30 -0
- package/dist/board/StartControls.js +51 -0
- package/dist/board/StartControls.js.map +1 -0
- package/dist/board/StatusColors.d.ts +5 -0
- package/dist/board/StatusColors.js +17 -0
- package/dist/board/StatusColors.js.map +1 -0
- package/dist/board/StatusGlyph.d.ts +18 -0
- package/dist/board/StatusGlyph.js +51 -0
- package/dist/board/StatusGlyph.js.map +1 -0
- package/dist/board/Threads.d.ts +13 -0
- package/dist/board/Threads.js +35 -0
- package/dist/board/Threads.js.map +1 -0
- package/dist/board/TrackerLabels.d.ts +27 -0
- package/dist/board/TrackerLabels.js +56 -0
- package/dist/board/TrackerLabels.js.map +1 -0
- package/dist/board/UpdatePill.d.ts +52 -0
- package/dist/board/UpdatePill.js +188 -0
- package/dist/board/UpdatePill.js.map +1 -0
- package/dist/board/Vocabulary.d.ts +56 -0
- package/dist/board/Vocabulary.js +104 -0
- package/dist/board/Vocabulary.js.map +1 -0
- package/dist/board/Warnings.d.ts +35 -0
- package/dist/board/Warnings.js +85 -0
- package/dist/board/Warnings.js.map +1 -0
- package/dist/board/WorkMap.d.ts +136 -0
- package/dist/board/WorkMap.js +274 -0
- package/dist/board/WorkMap.js.map +1 -0
- package/dist/board/index.d.ts +42 -0
- package/dist/collections/CollectionState.d.ts +10 -1
- package/dist/collections/CollectionState.js +12 -5
- package/dist/collections/CollectionState.js.map +1 -1
- package/dist/collections/ResultList.js +1 -1
- package/dist/collections/ScrollRow.js +1 -1
- package/dist/collections/VirtualList.js +1 -1
- package/dist/display/Avatar.d.ts +5 -2
- package/dist/display/Avatar.js +2 -2
- package/dist/display/Avatar.js.map +1 -1
- package/dist/display/Badge.d.ts +6 -1
- package/dist/display/Badge.js +9 -4
- package/dist/display/Badge.js.map +1 -1
- package/dist/display/CheckList.js +1 -1
- package/dist/display/Comment.d.ts +12 -0
- package/dist/display/Comment.js +39 -0
- package/dist/display/Comment.js.map +1 -0
- package/dist/display/CopyButton.d.ts +10 -2
- package/dist/display/CopyButton.js +29 -16
- package/dist/display/CopyButton.js.map +1 -1
- package/dist/display/Diagram.d.ts +17 -0
- package/dist/display/Diagram.js +49 -0
- package/dist/display/Diagram.js.map +1 -0
- package/dist/display/ImagePicker.js +1 -1
- package/dist/display/InfoBox.js +2 -2
- package/dist/display/InsetPanel.d.ts +3 -1
- package/dist/display/InsetPanel.js +7 -4
- package/dist/display/InsetPanel.js.map +1 -1
- package/dist/display/ItemAction.js +2 -2
- package/dist/display/LabelChip.d.ts +26 -0
- package/dist/display/LabelChip.js +41 -0
- package/dist/display/LabelChip.js.map +1 -0
- package/dist/display/LabelTint.js +60 -0
- package/dist/display/LabelTint.js.map +1 -0
- package/dist/display/Person.d.ts +5 -0
- package/dist/display/Person.js +19 -0
- package/dist/display/Person.js.map +1 -0
- package/dist/display/PropertySheet.js +1 -1
- package/dist/display/RadioChoice.d.ts +9 -2
- package/dist/display/RadioChoice.js +5 -1
- package/dist/display/RadioChoice.js.map +1 -1
- package/dist/display/RatingLink.js +1 -1
- package/dist/display/RichText.d.ts +12 -0
- package/dist/display/RichText.js +94 -0
- package/dist/display/RichText.js.map +1 -0
- package/dist/display/RowList.js +1 -1
- package/dist/display/index.d.ts +6 -1
- package/dist/feedback/Alert.js +1 -1
- package/dist/feedback/AsyncState.js +1 -1
- package/dist/feedback/DismissButton.d.ts +12 -0
- package/dist/feedback/DismissButton.js +20 -0
- package/dist/feedback/DismissButton.js.map +1 -0
- package/dist/feedback/ErrorNotification.js +2 -0
- package/dist/feedback/ErrorNotification.js.map +1 -1
- package/dist/feedback/FormResult.d.ts +16 -0
- package/dist/feedback/FormResult.js +30 -0
- package/dist/feedback/FormResult.js.map +1 -0
- package/dist/feedback/LiveRegion.d.ts +7 -0
- package/dist/feedback/LiveRegion.js +15 -0
- package/dist/feedback/LiveRegion.js.map +1 -0
- package/dist/feedback/Loading.d.ts +19 -0
- package/dist/feedback/Loading.js +63 -0
- package/dist/feedback/Loading.js.map +1 -0
- package/dist/feedback/Notifications.d.ts +35 -1
- package/dist/feedback/Notifications.js +196 -4
- package/dist/feedback/Notifications.js.map +1 -1
- package/dist/feedback/Progress.d.ts +15 -0
- package/dist/feedback/Progress.js +38 -0
- package/dist/feedback/Progress.js.map +1 -0
- package/dist/feedback/ProgressStatusRow.js +1 -1
- package/dist/feedback/StatusIndicator.d.ts +6 -1
- package/dist/feedback/StatusIndicator.js +19 -5
- package/dist/feedback/StatusIndicator.js.map +1 -1
- package/dist/feedback/index.d.ts +8 -4
- package/dist/forms/Checkbox.js +1 -1
- package/dist/forms/ColorSwatches.d.ts +21 -0
- package/dist/forms/ColorSwatches.js +26 -0
- package/dist/forms/ColorSwatches.js.map +1 -0
- package/dist/forms/FormSection.d.ts +68 -6
- package/dist/forms/FormSection.js +139 -8
- package/dist/forms/FormSection.js.map +1 -1
- package/dist/forms/HiddenField.d.ts +6 -0
- package/dist/forms/HiddenField.js +13 -0
- package/dist/forms/HiddenField.js.map +1 -0
- package/dist/forms/Input.d.ts +12 -2
- package/dist/forms/Input.js +10 -3
- package/dist/forms/Input.js.map +1 -1
- package/dist/forms/LabelPicker.d.ts +43 -0
- package/dist/forms/LabelPicker.js +107 -0
- package/dist/forms/LabelPicker.js.map +1 -0
- package/dist/forms/MarkdownEditor.d.ts +21 -0
- package/dist/forms/MarkdownEditor.js +175 -0
- package/dist/forms/MarkdownEditor.js.map +1 -0
- package/dist/forms/MarkdownToolbar.js +204 -0
- package/dist/forms/MarkdownToolbar.js.map +1 -0
- package/dist/forms/OptionSelect.d.ts +30 -9
- package/dist/forms/OptionSelect.js +53 -13
- package/dist/forms/OptionSelect.js.map +1 -1
- package/dist/forms/Select.d.ts +4 -1
- package/dist/forms/Select.js +3 -1
- package/dist/forms/Select.js.map +1 -1
- package/dist/forms/Switch.d.ts +4 -1
- package/dist/forms/Switch.js +5 -2
- package/dist/forms/Switch.js.map +1 -1
- package/dist/forms/TagInput.js +1 -1
- package/dist/forms/index.d.ts +7 -3
- package/dist/foundations/AmbientMotion.d.ts +2 -0
- package/dist/foundations/AmbientMotion.js +39 -0
- package/dist/foundations/AmbientMotion.js.map +1 -0
- package/dist/foundations/DesignSystemProvider.d.ts +34 -0
- package/dist/foundations/DesignSystemProvider.js +26 -1
- package/dist/foundations/DesignSystemProvider.js.map +1 -1
- package/dist/foundations/index.d.ts +2 -1
- package/dist/icons/BrandIcons.d.ts +8 -2
- package/dist/icons/BrandIcons.js +14 -3
- package/dist/icons/BrandIcons.js.map +1 -1
- package/dist/icons/dynamic.d.ts +2 -0
- package/dist/icons/dynamic.js +1 -0
- package/dist/icons/index.d.ts +2 -2
- package/dist/icons/index.js +1 -1
- package/dist/icons.d.ts +2 -2
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +71 -10
- package/dist/index.js +78 -21
- package/dist/layout/Site.js +1 -1
- package/dist/layout/TitleBar.js +1 -1
- package/dist/layout/index.d.ts +2 -2
- package/dist/layout/index.js +3 -3
- package/dist/layout/toolbar/CommandPaletteTrigger.d.ts +17 -2
- package/dist/layout/toolbar/CommandPaletteTrigger.js +89 -6
- package/dist/layout/toolbar/CommandPaletteTrigger.js.map +1 -1
- package/dist/layout/toolbar/TriggerFit.js +56 -0
- package/dist/layout/toolbar/TriggerFit.js.map +1 -0
- package/dist/navigation/CollectionBrowseSelector.js +1 -1
- package/dist/navigation/CollectionViewToggle.d.ts +26 -0
- package/dist/navigation/CollectionViewToggle.js +54 -23
- package/dist/navigation/CollectionViewToggle.js.map +1 -1
- package/dist/navigation/DrilldownBrowseSelector.js +1 -1
- package/dist/navigation/FolderSelector.js +2 -2
- package/dist/navigation/SortMenu.d.ts +10 -0
- package/dist/navigation/SortMenu.js +33 -0
- package/dist/navigation/SortMenu.js.map +1 -0
- package/dist/navigation/index.d.ts +3 -2
- package/dist/overlays/CommandPalette.d.ts +38 -4
- package/dist/overlays/CommandPalette.js +140 -54
- package/dist/overlays/CommandPalette.js.map +1 -1
- package/dist/overlays/Drawer.js +1 -1
- package/dist/overlays/DropdownMenu.d.ts +7 -1
- package/dist/overlays/DropdownMenu.js +13 -2
- package/dist/overlays/DropdownMenu.js.map +1 -1
- package/dist/overlays/HelpTip.d.ts +8 -0
- package/dist/overlays/HelpTip.js +29 -0
- package/dist/overlays/HelpTip.js.map +1 -0
- package/dist/overlays/ImageViewer.js +2 -2
- package/dist/overlays/Modal.d.ts +5 -0
- package/dist/overlays/Modal.js +17 -2
- package/dist/overlays/Modal.js.map +1 -1
- package/dist/overlays/ModalExpandButton.d.ts +18 -0
- package/dist/overlays/ModalExpandButton.js +43 -0
- package/dist/overlays/ModalExpandButton.js.map +1 -0
- package/dist/overlays/Popover.d.ts +2 -1
- package/dist/overlays/Popover.js +1 -0
- package/dist/overlays/Popover.js.map +1 -1
- package/dist/overlays/index.d.ts +4 -2
- package/dist/showcase/Cards.js +1 -1
- package/dist/showcase/FeatureRow.js +1 -1
- package/dist/showcase/PhotoSearchConcept.js +1 -1
- package/dist/showcase/ProductBand.js +1 -1
- package/dist/showcase/Status.js +1 -1
- package/dist/typography/Code.d.ts +18 -0
- package/dist/typography/Code.js +24 -0
- package/dist/typography/Code.js.map +1 -0
- package/dist/typography/Link.d.ts +7 -2
- package/dist/typography/Link.js +15 -5
- package/dist/typography/Link.js.map +1 -1
- package/dist/typography/Typography.d.ts +19 -1
- package/dist/typography/Typography.js +11 -3
- package/dist/typography/Typography.js.map +1 -1
- package/dist/typography/index.d.ts +3 -3
- package/package.json +26 -3
- package/src/actions/Button.tsx +78 -11
- package/src/actions/ButtonLink.tsx +34 -0
- package/src/actions/ButtonRecipes.ts +10 -0
- package/src/actions/IconButton.tsx +7 -4
- package/src/board/ActivityLine.tsx +176 -0
- package/src/board/ActivityTrack.tsx +23 -0
- package/src/board/AddItem.tsx +259 -0
- package/src/board/Archive.tsx +75 -0
- package/src/board/Attention.tsx +135 -0
- package/src/board/BoardShell.tsx +30 -0
- package/src/board/BoardTitleBar.tsx +167 -0
- package/src/board/ButtonKinds.ts +32 -0
- package/src/board/Cleanup.tsx +19 -0
- package/src/board/Counters.tsx +224 -0
- package/src/board/DataAttributes.ts +3 -0
- package/src/board/Dependencies.tsx +49 -0
- package/src/board/Desk.tsx +155 -0
- package/src/board/Dossier.tsx +262 -0
- package/src/board/Filters.tsx +85 -0
- package/src/board/ItemDetails.tsx +435 -0
- package/src/board/ItemDialog.tsx +179 -0
- package/src/board/ItemParts.tsx +128 -0
- package/src/board/ItemProgress.tsx +164 -0
- package/src/board/List.tsx +154 -0
- package/src/board/LoadingScreen.tsx +78 -0
- package/src/board/NeedsYou.tsx +30 -0
- package/src/board/Onboarding.tsx +124 -0
- package/src/board/PartsList.tsx +160 -0
- package/src/board/ProjectIcon.tsx +172 -0
- package/src/board/PullRequests.tsx +106 -0
- package/src/board/RowStyles.ts +17 -0
- package/src/board/Settings.tsx +124 -0
- package/src/board/Slices.tsx +103 -0
- package/src/board/SourceIcon.tsx +33 -0
- package/src/board/StagePane.tsx +128 -0
- package/src/board/StageRow.tsx +320 -0
- package/src/board/StageTrack.tsx +61 -0
- package/src/board/StartControls.tsx +77 -0
- package/src/board/StatusColors.ts +28 -0
- package/src/board/StatusGlyph.tsx +70 -0
- package/src/board/Threads.tsx +38 -0
- package/src/board/TrackerLabels.tsx +75 -0
- package/src/board/UpdatePill.tsx +222 -0
- package/src/board/Vocabulary.tsx +155 -0
- package/src/board/Warnings.tsx +83 -0
- package/src/board/WorkMap.tsx +436 -0
- package/src/board/base.css +121 -0
- package/src/board/button-kinds.css +8 -0
- package/src/board/index.ts +224 -0
- package/src/board/items.css +75 -0
- package/src/board/loading-screen.css +171 -0
- package/src/board/rows.css +180 -0
- package/src/board/title-bar.css +56 -0
- package/src/board/tokens.css +52 -0
- package/src/board.css +19 -0
- package/src/collections/CollectionState.tsx +20 -7
- package/src/display/Avatar.tsx +6 -3
- package/src/display/Badge.tsx +25 -3
- package/src/display/Comment.tsx +26 -0
- package/src/display/CopyButton.tsx +48 -18
- package/src/display/Diagram.tsx +59 -0
- package/src/display/InsetPanel.tsx +4 -1
- package/src/display/LabelChip.tsx +73 -0
- package/src/display/LabelTint.ts +72 -0
- package/src/display/Person.tsx +11 -0
- package/src/display/RadioChoice.tsx +11 -2
- package/src/display/RichText.tsx +114 -0
- package/src/display/index.ts +5 -0
- package/src/feedback/DismissButton.tsx +28 -0
- package/src/feedback/ErrorNotification.ts +3 -0
- package/src/feedback/FormResult.tsx +50 -0
- package/src/feedback/LiveRegion.tsx +10 -0
- package/src/feedback/Loading.tsx +75 -0
- package/src/feedback/Notifications.tsx +267 -2
- package/src/feedback/Progress.tsx +44 -0
- package/src/feedback/StatusIndicator.tsx +34 -3
- package/src/feedback/index.ts +12 -2
- package/src/forms/ColorSwatches.tsx +50 -0
- package/src/forms/FormSection.tsx +245 -10
- package/src/forms/HiddenField.tsx +4 -0
- package/src/forms/Input.tsx +26 -4
- package/src/forms/LabelPicker.tsx +140 -0
- package/src/forms/MarkdownEditor.tsx +283 -0
- package/src/forms/MarkdownToolbar.tsx +267 -0
- package/src/forms/OptionSelect.tsx +110 -25
- package/src/forms/Select.tsx +20 -13
- package/src/forms/Switch.tsx +16 -2
- package/src/forms/index.ts +16 -2
- package/src/foundations/AmbientMotion.ts +51 -0
- package/src/foundations/DesignSystemProvider.tsx +19 -0
- package/src/foundations/index.ts +1 -0
- package/src/foundations/theme.css +64 -0
- package/src/icons/BrandIcons.tsx +12 -3
- package/src/icons/dynamic.ts +4 -0
- package/src/icons/index.ts +1 -1
- package/src/index.ts +2 -1
- package/src/layout/index.ts +1 -1
- package/src/layout/toolbar/CommandPaletteTrigger.tsx +187 -31
- package/src/layout/toolbar/TriggerFit.ts +84 -0
- package/src/navigation/CollectionViewToggle.tsx +94 -24
- package/src/navigation/SortMenu.tsx +41 -0
- package/src/navigation/index.ts +2 -1
- package/src/overlays/CommandPalette.tsx +190 -60
- package/src/overlays/DropdownMenu.tsx +12 -1
- package/src/overlays/HelpTip.tsx +29 -0
- package/src/overlays/Modal.tsx +23 -0
- package/src/overlays/ModalExpandButton.tsx +48 -0
- package/src/overlays/Popover.tsx +3 -1
- package/src/overlays/index.ts +9 -1
- package/src/showcase.css +6 -0
- package/src/styles.css +9 -1
- package/src/typography/Code.tsx +24 -0
- package/src/typography/Link.tsx +19 -10
- package/src/typography/Typography.tsx +25 -2
- package/src/typography/index.ts +1 -1
- package/dist/feedback/index.js +0 -11
- package/dist/typography/index.js +0 -4
|
@@ -10,6 +10,9 @@ declare const textStyles: {
|
|
|
10
10
|
readonly lead: 'text-[17px] leading-[1.6] tracking-[-0.011em] sm:text-lg sm:leading-[1.6] text-pretty';
|
|
11
11
|
/** Running copy on marketing pages. */
|
|
12
12
|
readonly prose: 'text-[15px] leading-[1.65] tracking-[-0.006em] text-pretty';
|
|
13
|
+
/** The surrounding text's size and, unless a `tone` is given, its colour: a message inside a note or a form that
|
|
14
|
+
* sets its own type. */
|
|
15
|
+
readonly inherit: '';
|
|
13
16
|
};
|
|
14
17
|
/** T3's headings: semibold with tightening tracking as they grow; the hero takes t3.codes' display setting. */
|
|
15
18
|
declare const headingStyles: {
|
|
@@ -42,8 +45,23 @@ interface TypographyProps extends HTMLAttributes<HTMLElement> {
|
|
|
42
45
|
export interface TextProps extends TypographyProps {
|
|
43
46
|
as?: 'p' | 'span' | 'div';
|
|
44
47
|
variant?: keyof typeof textStyles;
|
|
48
|
+
/** Keeps the text on one line, such as a date that shouldn't break. */
|
|
49
|
+
nowrap?: boolean;
|
|
50
|
+
/** Lines its figures up as a table's. */
|
|
51
|
+
numeric?: boolean;
|
|
52
|
+
/** Lets a long word, such as a path, break anywhere. */
|
|
53
|
+
breaks?: boolean;
|
|
54
|
+
/** Takes a line of its own in a wrapping row. */
|
|
55
|
+
ownLine?: boolean;
|
|
56
|
+
/** Shows it only in a container under 40rem (`narrow`) or, on one line, in one 40rem or wider (`wide`), where the
|
|
57
|
+
* same words show elsewhere in the other. */
|
|
58
|
+
only?: keyof typeof containers | undefined;
|
|
45
59
|
}
|
|
46
|
-
|
|
60
|
+
declare const containers: {
|
|
61
|
+
readonly narrow: '@min-[40rem]:hidden';
|
|
62
|
+
readonly wide: 'whitespace-nowrap @max-[40rem]:hidden';
|
|
63
|
+
};
|
|
64
|
+
export declare function Text({ as: Tag, variant, tone, truncate, nowrap, numeric, breaks, ownLine, only, loading, className, children, ...props }: TextProps): import("react").JSX.Element;
|
|
47
65
|
export interface HeadingProps extends TypographyProps {
|
|
48
66
|
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
49
67
|
variant?: keyof typeof headingStyles;
|
|
@@ -11,7 +11,10 @@ const textStyles = {
|
|
|
11
11
|
/** The paragraph under a hero or section title. */
|
|
12
12
|
lead: "text-[17px] leading-[1.6] tracking-[-0.011em] sm:text-lg sm:leading-[1.6] text-pretty",
|
|
13
13
|
/** Running copy on marketing pages. */
|
|
14
|
-
prose: "text-[15px] leading-[1.65] tracking-[-0.006em] text-pretty"
|
|
14
|
+
prose: "text-[15px] leading-[1.65] tracking-[-0.006em] text-pretty",
|
|
15
|
+
/** The surrounding text's size and, unless a `tone` is given, its colour: a message inside a note or a form that
|
|
16
|
+
* sets its own type. */
|
|
17
|
+
inherit: ""
|
|
15
18
|
};
|
|
16
19
|
/** T3's headings: semibold with tightening tracking as they grow; the hero takes t3.codes' display setting. */
|
|
17
20
|
const headingStyles = {
|
|
@@ -36,10 +39,15 @@ const tones = {
|
|
|
36
39
|
warning: "text-warning",
|
|
37
40
|
success: "text-success"
|
|
38
41
|
};
|
|
39
|
-
|
|
42
|
+
const containers = {
|
|
43
|
+
narrow: "@min-[40rem]:hidden",
|
|
44
|
+
wide: "whitespace-nowrap @max-[40rem]:hidden"
|
|
45
|
+
};
|
|
46
|
+
function Text({ as: Tag = "p", variant = "body", tone = variant === "inherit" ? void 0 : "default", truncate, nowrap = false, numeric = false, breaks = false, ownLine = false, only, loading, className = "", children, ...props }) {
|
|
47
|
+
const layout = `${numeric ? " tabular-nums" : ""}${breaks ? " wrap-anywhere" : ""}${ownLine ? " w-full" : ""}${only ? ` ${containers[only]}` : ""}`;
|
|
40
48
|
return /* @__PURE__ */ jsx(Tag, {
|
|
41
49
|
...props,
|
|
42
|
-
className: `${textStyles[variant]} ${tones[tone]} ${tone === "muted" && (variant === "lead" || variant === "prose") ? "dark:text-[#a3a3aa]" : ""} ${truncate ? "truncate" : ""} ${loading ? `relative ${Tag === "span" ? "inline-block w-full" : ""}` : ""} ${className}`,
|
|
50
|
+
className: `${textStyles[variant]} ${tone ? tones[tone] : ""} ${tone === "muted" && (variant === "lead" || variant === "prose") ? "dark:text-[#a3a3aa]" : ""} ${truncate ? "truncate" : ""} ${nowrap ? "whitespace-nowrap" : ""} ${loading ? `relative ${Tag === "span" ? "inline-block w-full" : ""}` : ""} ${className}${layout}`,
|
|
43
51
|
children: loading ? /* @__PURE__ */ jsx(LoadingText, {}) : children
|
|
44
52
|
});
|
|
45
53
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Typography.js","names":[],"sources":["../../src/typography/Typography.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\n\nimport { SkeletonLoader } from '../feedback/SkeletonLoader';\n\nconst textStyles = {\n body: 'text-sm leading-5',\n description: 'text-[15px] leading-6',\n caption: 'text-xs leading-4',\n label: 'text-sm font-medium leading-5',\n overline: 'text-[11px] font-semibold uppercase leading-4 tracking-[0.08em]',\n metric: 'text-2xl font-semibold leading-8 tracking-[-0.02em] tabular-nums',\n /** The paragraph under a hero or section title. */\n lead: 'text-[17px] leading-[1.6] tracking-[-0.011em] sm:text-lg sm:leading-[1.6] text-pretty',\n /** Running copy on marketing pages. */\n prose: 'text-[15px] leading-[1.65] tracking-[-0.006em] text-pretty',\n} as const;\n\n/** T3's headings: semibold with tightening tracking as they grow; the hero takes t3.codes' display setting. */\nconst headingStyles = {\n page: 'text-[1.375rem] font-semibold leading-7 tracking-[-0.02em]',\n section: 'text-base font-semibold leading-6 tracking-[-0.01em]',\n subsection: 'text-[15px] font-semibold leading-6 tracking-[-0.005em]',\n title: 'text-sm font-semibold leading-5',\n label: 'text-sm font-semibold leading-5',\n hero: 'text-3xl font-semibold leading-[1.05] tracking-[-0.035em] [text-box:trim-both_cap_alphabetic] sm:text-4xl lg:text-[2.875rem]',\n /** A page's one big statement. */\n display:\n 'text-[2.625rem] font-semibold leading-[1.04] tracking-[-0.036em] text-balance sm:text-6xl lg:text-[4.5rem] xl:text-[5rem]',\n /** A marketing section's title. */\n headline:\n 'text-[1.875rem] font-semibold leading-[1.08] tracking-[-0.035em] text-balance sm:text-[2.5rem] lg:text-[3rem]',\n /** A feature's title inside a section. */\n feature: 'text-xl font-semibold leading-7 tracking-[-0.02em] text-balance sm:text-2xl sm:leading-8',\n} as const;\n\nconst tones = {\n default: 'text-base-content',\n muted: 'text-base-700',\n soft: 'text-base-800',\n danger: 'text-danger',\n warning: 'text-warning',\n success: 'text-success',\n} as const;\n\ninterface TypographyProps extends HTMLAttributes<HTMLElement> {\n loading?: boolean;\n tone?: keyof typeof tones;\n truncate?: boolean;\n}\n\nexport interface TextProps extends TypographyProps {\n as?: 'p' | 'span' | 'div';\n variant?: keyof typeof textStyles;\n}\n\nexport function Text({\n as: Tag = 'p',\n variant = 'body',\n tone = 'default',\n truncate,\n loading,\n className = '',\n children,\n ...props\n}: TextProps) {\n return (\n <Tag\n {...props}\n className={`${textStyles[variant]} ${tones[tone]} ${tone === 'muted' && (variant === 'lead' || variant === 'prose') ? 'dark:text-[#a3a3aa]' : ''} ${truncate ? 'truncate' : ''} ${loading ? `relative ${Tag === 'span' ? 'inline-block w-full' : ''}` : ''} ${className}`}\n >\n {loading ? <LoadingText /> : children}\n </Tag>\n );\n}\n\nexport interface HeadingProps extends TypographyProps {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n variant?: keyof typeof headingStyles;\n}\n\nexport function Heading({\n as: Tag = 'h2',\n variant = 'section',\n tone = 'default',\n truncate,\n loading,\n className = '',\n children,\n ...props\n}: HeadingProps) {\n return (\n <Tag\n {...props}\n className={`${headingStyles[variant]} ${tones[tone]} ${truncate ? 'truncate' : ''} ${loading ? 'relative' : ''} ${className}`}\n >\n {loading ? <LoadingText heading={variant === 'hero'} /> : children}\n </Tag>\n );\n}\n\n/** An invisible glyph retains the font's line box, including cap-height trimming. */\nfunction LoadingText({ heading = false }: { heading?: boolean }) {\n return (\n <>\n <span aria-hidden=\"true\" className=\"invisible\">\n \n </span>\n <span aria-hidden=\"true\" className=\"absolute inset-0 flex items-center\">\n <SkeletonLoader.Shape presentation={heading ? 'heading' : 'line'} />\n </span>\n </>\n );\n}\n"],"mappings":";;;AAIA,MAAM,aAAa;CACf,MAAM;CACN,aAAa;CACb,SAAS;CACT,OAAO;CACP,UAAU;CACV,QAAQ;;CAER,MAAM;;CAEN,OAAO;
|
|
1
|
+
{"version":3,"file":"Typography.js","names":[],"sources":["../../src/typography/Typography.tsx"],"sourcesContent":["import type { HTMLAttributes } from 'react';\n\nimport { SkeletonLoader } from '../feedback/SkeletonLoader';\n\nconst textStyles = {\n body: 'text-sm leading-5',\n description: 'text-[15px] leading-6',\n caption: 'text-xs leading-4',\n label: 'text-sm font-medium leading-5',\n overline: 'text-[11px] font-semibold uppercase leading-4 tracking-[0.08em]',\n metric: 'text-2xl font-semibold leading-8 tracking-[-0.02em] tabular-nums',\n /** The paragraph under a hero or section title. */\n lead: 'text-[17px] leading-[1.6] tracking-[-0.011em] sm:text-lg sm:leading-[1.6] text-pretty',\n /** Running copy on marketing pages. */\n prose: 'text-[15px] leading-[1.65] tracking-[-0.006em] text-pretty',\n /** The surrounding text's size and, unless a `tone` is given, its colour: a message inside a note or a form that\n * sets its own type. */\n inherit: '',\n} as const;\n\n/** T3's headings: semibold with tightening tracking as they grow; the hero takes t3.codes' display setting. */\nconst headingStyles = {\n page: 'text-[1.375rem] font-semibold leading-7 tracking-[-0.02em]',\n section: 'text-base font-semibold leading-6 tracking-[-0.01em]',\n subsection: 'text-[15px] font-semibold leading-6 tracking-[-0.005em]',\n title: 'text-sm font-semibold leading-5',\n label: 'text-sm font-semibold leading-5',\n hero: 'text-3xl font-semibold leading-[1.05] tracking-[-0.035em] [text-box:trim-both_cap_alphabetic] sm:text-4xl lg:text-[2.875rem]',\n /** A page's one big statement. */\n display:\n 'text-[2.625rem] font-semibold leading-[1.04] tracking-[-0.036em] text-balance sm:text-6xl lg:text-[4.5rem] xl:text-[5rem]',\n /** A marketing section's title. */\n headline:\n 'text-[1.875rem] font-semibold leading-[1.08] tracking-[-0.035em] text-balance sm:text-[2.5rem] lg:text-[3rem]',\n /** A feature's title inside a section. */\n feature: 'text-xl font-semibold leading-7 tracking-[-0.02em] text-balance sm:text-2xl sm:leading-8',\n} as const;\n\nconst tones = {\n default: 'text-base-content',\n muted: 'text-base-700',\n soft: 'text-base-800',\n danger: 'text-danger',\n warning: 'text-warning',\n success: 'text-success',\n} as const;\n\ninterface TypographyProps extends HTMLAttributes<HTMLElement> {\n loading?: boolean;\n tone?: keyof typeof tones;\n truncate?: boolean;\n}\n\nexport interface TextProps extends TypographyProps {\n as?: 'p' | 'span' | 'div';\n variant?: keyof typeof textStyles;\n /** Keeps the text on one line, such as a date that shouldn't break. */\n nowrap?: boolean;\n /** Lines its figures up as a table's. */\n numeric?: boolean;\n /** Lets a long word, such as a path, break anywhere. */\n breaks?: boolean;\n /** Takes a line of its own in a wrapping row. */\n ownLine?: boolean;\n /** Shows it only in a container under 40rem (`narrow`) or, on one line, in one 40rem or wider (`wide`), where the\n * same words show elsewhere in the other. */\n only?: keyof typeof containers | undefined;\n}\n\nconst containers = { narrow: '@min-[40rem]:hidden', wide: 'whitespace-nowrap @max-[40rem]:hidden' } as const;\n\nexport function Text({\n as: Tag = 'p',\n variant = 'body',\n tone = variant === 'inherit' ? undefined : 'default',\n truncate,\n nowrap = false,\n numeric = false,\n breaks = false,\n ownLine = false,\n only,\n loading,\n className = '',\n children,\n ...props\n}: TextProps) {\n const layout = `${numeric ? ' tabular-nums' : ''}${breaks ? ' wrap-anywhere' : ''}${ownLine ? ' w-full' : ''}${only ? ` ${containers[only]}` : ''}`;\n\n return (\n <Tag\n {...props}\n className={`${textStyles[variant]} ${tone ? tones[tone] : ''} ${tone === 'muted' && (variant === 'lead' || variant === 'prose') ? 'dark:text-[#a3a3aa]' : ''} ${truncate ? 'truncate' : ''} ${nowrap ? 'whitespace-nowrap' : ''} ${loading ? `relative ${Tag === 'span' ? 'inline-block w-full' : ''}` : ''} ${className}${layout}`}\n >\n {loading ? <LoadingText /> : children}\n </Tag>\n );\n}\n\nexport interface HeadingProps extends TypographyProps {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n variant?: keyof typeof headingStyles;\n}\n\nexport function Heading({\n as: Tag = 'h2',\n variant = 'section',\n tone = 'default',\n truncate,\n loading,\n className = '',\n children,\n ...props\n}: HeadingProps) {\n return (\n <Tag\n {...props}\n className={`${headingStyles[variant]} ${tones[tone]} ${truncate ? 'truncate' : ''} ${loading ? 'relative' : ''} ${className}`}\n >\n {loading ? <LoadingText heading={variant === 'hero'} /> : children}\n </Tag>\n );\n}\n\n/** An invisible glyph retains the font's line box, including cap-height trimming. */\nfunction LoadingText({ heading = false }: { heading?: boolean }) {\n return (\n <>\n <span aria-hidden=\"true\" className=\"invisible\">\n \n </span>\n <span aria-hidden=\"true\" className=\"absolute inset-0 flex items-center\">\n <SkeletonLoader.Shape presentation={heading ? 'heading' : 'line'} />\n </span>\n </>\n );\n}\n"],"mappings":";;;AAIA,MAAM,aAAa;CACf,MAAM;CACN,aAAa;CACb,SAAS;CACT,OAAO;CACP,UAAU;CACV,QAAQ;;CAER,MAAM;;CAEN,OAAO;;;CAGP,SAAS;AACb;;AAGA,MAAM,gBAAgB;CAClB,MAAM;CACN,SAAS;CACT,YAAY;CACZ,OAAO;CACP,OAAO;CACP,MAAM;;CAEN,SACI;;CAEJ,UACI;;CAEJ,SAAS;AACb;AAEA,MAAM,QAAQ;CACV,SAAS;CACT,OAAO;CACP,MAAM;CACN,QAAQ;CACR,SAAS;CACT,SAAS;AACb;AAwBA,MAAM,aAAa;CAAE,QAAQ;CAAuB,MAAM;AAAwC;AAElG,SAAgB,KAAK,EACjB,IAAI,MAAM,KACV,UAAU,QACV,OAAO,YAAY,YAAY,KAAA,IAAY,WAC3C,UACA,SAAS,OACT,UAAU,OACV,SAAS,OACT,UAAU,OACV,MACA,SACA,YAAY,IACZ,UACA,GAAG,SACO;CACV,MAAM,SAAS,GAAG,UAAU,kBAAkB,KAAK,SAAS,mBAAmB,KAAK,UAAU,YAAY,KAAK,OAAO,IAAI,WAAW,UAAU;CAE/I,OACI,oBAAC,KAAD;EACI,GAAI;EACJ,WAAW,GAAG,WAAW,SAAS,GAAG,OAAO,MAAM,QAAQ,GAAG,GAAG,SAAS,YAAY,YAAY,UAAU,YAAY,WAAW,wBAAwB,GAAG,GAAG,WAAW,aAAa,GAAG,GAAG,SAAS,sBAAsB,GAAG,GAAG,UAAU,YAAY,QAAQ,SAAS,wBAAwB,OAAO,GAAG,GAAG,YAAY;EAE1T,UAAA,UAAU,oBAAC,aAAD,CAAc,CAAA,IAAI;CAC5B,CAAA;AAEb;AAOA,SAAgB,QAAQ,EACpB,IAAI,MAAM,MACV,UAAU,WACV,OAAO,WACP,UACA,SACA,YAAY,IACZ,UACA,GAAG,SACU;CACb,OACI,oBAAC,KAAD;EACI,GAAI;EACJ,WAAW,GAAG,cAAc,SAAS,GAAG,MAAM,MAAM,GAAG,WAAW,aAAa,GAAG,GAAG,UAAU,aAAa,GAAG,GAAG;EAEjH,UAAA,UAAU,oBAAC,aAAD,EAAa,SAAS,YAAY,OAAS,CAAA,IAAI;CACzD,CAAA;AAEb;;AAGA,SAAS,YAAY,EAAE,UAAU,SAAgC;CAC7D,OACI,qBAAA,UAAA,EAAA,UAAA,CACI,oBAAC,QAAD;EAAM,eAAY;EAAO,WAAU;EAAY,UAAA;CAEzC,CAAA,GACN,oBAAC,QAAD;EAAM,eAAY;EAAO,WAAU;EAC/B,UAAA,oBAAC,eAAe,OAAhB,EAAsB,cAAc,UAAU,YAAY,OAAS,CAAA;CACjE,CAAA,CACR,EAAA,CAAA;AAEV"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Code, CodeProps } from "./Code.js";
|
|
2
|
+
import { InlineLink, Link, LinkBox, LinkOverlay, LinkOverlayProps, LinkProps } from "./Link.js";
|
|
2
3
|
import { Heading, HeadingProps, Text, TextProps } from "./Typography.js";
|
|
3
|
-
|
|
4
|
-
export { Code$1 as Code, Heading, type HeadingProps, InlineLink, Link$1 as Link, LinkBox$1 as LinkBox, LinkOverlay$1 as LinkOverlay, type LinkOverlayProps$1 as LinkOverlayProps, type LinkProps$1 as LinkProps, Text, type TextProps };
|
|
4
|
+
export { Code, type CodeProps, Heading, type HeadingProps, InlineLink, Link, LinkBox, LinkOverlay, type LinkOverlayProps, type LinkProps, Text, type TextProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lar-works/design-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Lar's design system: tokens, base styles and every visual component the Lar web apps use.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -21,20 +21,34 @@
|
|
|
21
21
|
"types": "./dist/icons.d.ts",
|
|
22
22
|
"default": "./dist/icons.js"
|
|
23
23
|
},
|
|
24
|
+
"./icons/dynamic": {
|
|
25
|
+
"types": "./dist/icons/dynamic.d.ts",
|
|
26
|
+
"default": "./dist/icons/dynamic.js"
|
|
27
|
+
},
|
|
24
28
|
"./testing": {
|
|
25
29
|
"types": "./dist/testing.d.ts",
|
|
26
30
|
"default": "./dist/testing.js"
|
|
27
31
|
},
|
|
28
32
|
"./styles.css": "./src/styles.css",
|
|
29
|
-
"./showcase.css": "./src/showcase.css"
|
|
33
|
+
"./showcase.css": "./src/showcase.css",
|
|
34
|
+
"./board.css": "./src/board.css"
|
|
30
35
|
},
|
|
31
36
|
"files": [
|
|
32
37
|
"dist",
|
|
33
38
|
"src",
|
|
39
|
+
"!src/**/*.test.ts",
|
|
34
40
|
"!src/**/*.test.tsx",
|
|
35
41
|
"!src/**/*.stories.tsx"
|
|
36
42
|
],
|
|
37
43
|
"dependencies": {
|
|
44
|
+
"@lexical/code": "0.52.0",
|
|
45
|
+
"@lexical/html": "0.52.0",
|
|
46
|
+
"@lexical/link": "0.52.0",
|
|
47
|
+
"@lexical/list": "0.52.0",
|
|
48
|
+
"@lexical/markdown": "0.52.0",
|
|
49
|
+
"@lexical/react": "0.52.0",
|
|
50
|
+
"@lexical/rich-text": "0.52.0",
|
|
51
|
+
"@lexical/selection": "0.52.0",
|
|
38
52
|
"@ninna-ui/core": "^0.6.0",
|
|
39
53
|
"@ninna-ui/feedback": "^0.6.0",
|
|
40
54
|
"@ninna-ui/forms": "^0.6.0",
|
|
@@ -43,8 +57,16 @@
|
|
|
43
57
|
"@ninna-ui/primitives": "^0.6.0",
|
|
44
58
|
"@ninna-ui/react-internal": "^0.6.0",
|
|
45
59
|
"@tanstack/react-virtual": "^3.14.26",
|
|
60
|
+
"hast-util-to-jsx-runtime": "^2.3.7",
|
|
61
|
+
"lexical": "0.52.0",
|
|
46
62
|
"lucide-react": "^1.70.0",
|
|
47
|
-
"qrcode-generator": "^2.0.4"
|
|
63
|
+
"qrcode-generator": "^2.0.4",
|
|
64
|
+
"react-markdown": "^10.1.0",
|
|
65
|
+
"rehype-parse": "^9.0.1",
|
|
66
|
+
"rehype-raw": "^7.0.0",
|
|
67
|
+
"rehype-sanitize": "^6.0.0",
|
|
68
|
+
"remark-gfm": "^4.0.1",
|
|
69
|
+
"unified": "^11.0.5"
|
|
48
70
|
},
|
|
49
71
|
"peerDependencies": {
|
|
50
72
|
"react": "^19.2.0",
|
|
@@ -61,6 +83,7 @@
|
|
|
61
83
|
"@testing-library/jest-dom": "^7.0.1",
|
|
62
84
|
"@testing-library/react": "^16.3.3",
|
|
63
85
|
"@testing-library/user-event": "^14.6.8",
|
|
86
|
+
"@types/hast": "^3.0.5",
|
|
64
87
|
"@types/node": "^24.19.2",
|
|
65
88
|
"@types/react": "^19.3.0",
|
|
66
89
|
"@types/react-dom": "^19.3.0",
|
package/src/actions/Button.tsx
CHANGED
|
@@ -1,25 +1,33 @@
|
|
|
1
1
|
import { Button as NinnaButton, type ButtonProps as NinnaButtonProps } from '@ninna-ui/primitives';
|
|
2
2
|
import { forwardRef } from 'react';
|
|
3
3
|
|
|
4
|
+
import { SpinnerIcon } from '../feedback/Loading';
|
|
4
5
|
import { tabbable } from '../foundations/KeyboardFocus';
|
|
6
|
+
import { ghostRecipe, outlineRecipe, primaryRecipe } from './ButtonRecipes';
|
|
5
7
|
|
|
6
8
|
/** T3 Code's button (coss ui): an 8px-radius control, 36px on touch and 32px with a pointer, that dips to
|
|
7
9
|
* 97% while pressed. Every recipe sets its own colours, so ninna-ui only supplies behaviour. */
|
|
8
10
|
const base =
|
|
9
|
-
'
|
|
11
|
+
'gap-2 rounded-md border px-[11px] font-medium transition-[background-color,box-shadow,scale,color] duration-150 active:scale-[0.97] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary focus-visible:ring-offset-0 disabled:opacity-64 [&_[data-slot=icon]>svg]:size-4';
|
|
12
|
+
/** The default 36px (32px with a pointer) control, and the compact 28px one with 12px text that dense tools use. */
|
|
13
|
+
const sizes = { default: 'h-9 text-sm sm:h-8', compact: 'h-7 text-xs sm:h-7' } as const;
|
|
14
|
+
/** A label that would clip on a narrow surface wraps instead, growing the button past its height. */
|
|
15
|
+
const wrapping = {
|
|
16
|
+
nowrap: 'whitespace-nowrap',
|
|
17
|
+
wrap: 'h-auto min-h-7 max-w-full min-w-0 py-1 whitespace-normal wrap-anywhere sm:h-auto',
|
|
18
|
+
} as const;
|
|
10
19
|
|
|
11
|
-
const outline =
|
|
12
|
-
|
|
13
|
-
const ghost =
|
|
14
|
-
'border-transparent text-base-content hover:bg-base-200 data-[state=open]:bg-base-200 [&_[data-slot=icon]]:text-base-700';
|
|
20
|
+
const outline = outlineRecipe;
|
|
21
|
+
const ghost = ghostRecipe;
|
|
15
22
|
|
|
16
23
|
const recipes = {
|
|
17
|
-
primary:
|
|
18
|
-
'border-primary bg-primary text-primary-content shadow-xs shadow-primary/24 inset-shadow-[0_1px_rgb(255_255_255/16%)] hover:bg-primary/90 active:shadow-none active:inset-shadow-[0_1px_rgb(0_0_0/8%)]',
|
|
24
|
+
primary: primaryRecipe,
|
|
19
25
|
secondary: outline,
|
|
20
26
|
quiet: ghost,
|
|
21
27
|
row: `${ghost} h-auto min-h-8 min-w-0 max-w-full justify-start whitespace-normal px-0 py-1 text-left text-xs font-normal text-base-700 hover:bg-transparent hover:text-base-content sm:h-auto active:scale-100`,
|
|
22
28
|
subtle: 'border-transparent bg-base-200 text-base-content hover:bg-base-300/70 dark:bg-base-300 dark:hover:bg-base-400',
|
|
29
|
+
/** The primary colour tinted on the card, with no border or shadow, deeper on hover and while its popup is open. */
|
|
30
|
+
tinted: 'border-transparent bg-[color-mix(in_srgb,var(--color-primary)_10%,var(--color-base-100))] text-primary shadow-none not-disabled:not-aria-disabled:hover:bg-[color-mix(in_srgb,var(--color-primary)_18%,var(--color-base-100))] data-[state=open]:bg-[color-mix(in_srgb,var(--color-primary)_18%,var(--color-base-100))] [&_[data-slot=icon]]:text-current',
|
|
23
31
|
destructive:
|
|
24
32
|
'border-danger bg-danger text-white shadow-xs shadow-danger/24 inset-shadow-[0_1px_rgb(255_255_255/16%)] hover:bg-danger/90 active:shadow-none',
|
|
25
33
|
'destructive-quiet':
|
|
@@ -31,16 +39,57 @@ const recipes = {
|
|
|
31
39
|
status: 'h-4 min-w-0 max-w-full justify-start gap-1.5 rounded-sm border-transparent px-0 text-xs font-normal text-base-700 hover:bg-transparent hover:text-base-content sm:h-4 active:scale-100 [&>svg]:size-3 [&>svg]:shrink-0',
|
|
32
40
|
} as const;
|
|
33
41
|
|
|
42
|
+
/** An icon-only button is as wide as it is tall, with no padding. */
|
|
43
|
+
const square = { default: 'size-9 px-0 sm:size-8', compact: 'w-7 px-0' } as const;
|
|
44
|
+
const pending = 'aria-disabled:cursor-progress aria-disabled:opacity-70';
|
|
45
|
+
const heldDisabled = 'aria-disabled:opacity-64';
|
|
46
|
+
|
|
34
47
|
const selectedChoice =
|
|
35
48
|
'border-primary/60 bg-primary/8 text-base-content ring-1 ring-inset ring-primary/40 hover:bg-primary/12 dark:border-primary/60 dark:bg-primary/16 dark:hover:bg-primary/20';
|
|
36
49
|
|
|
37
50
|
export type ButtonProps = Omit<NinnaButtonProps, 'color' | 'radius' | 'size' | 'variant'> & {
|
|
38
51
|
variant?: keyof typeof recipes;
|
|
39
52
|
selected?: boolean;
|
|
53
|
+
/** The dense 28px control with 12px text, as Lar Factory's board draws every button. */
|
|
54
|
+
compact?: boolean;
|
|
55
|
+
/** Lets a long label wrap, anywhere in a long word if it must, growing the button, which never grows past its
|
|
56
|
+
* container, where it would otherwise clip. */
|
|
57
|
+
wrap?: boolean;
|
|
58
|
+
/** A square button showing its `leftIcon` alone, named by its `aria-label`. */
|
|
59
|
+
iconOnly?: boolean;
|
|
60
|
+
/** Lets the button shrink in a crowded row: its label truncates, while its `mark` (a trailing character, such as ▾
|
|
61
|
+
* or ✓) stays. */
|
|
62
|
+
shrinks?: boolean;
|
|
63
|
+
mark?: string;
|
|
64
|
+
/** Its action is in flight: a spinner, turning even under reduced motion, takes its left icon's place, and it reads
|
|
65
|
+
* as busy. `false` leaves out the busy state altogether. */
|
|
66
|
+
busy?: boolean;
|
|
67
|
+
/** Draws the button as waiting, with the progress cursor at 70%, while `aria-disabled` holds it for an action in
|
|
68
|
+
* flight; `'disabled'` draws it as a disabled button instead, while it keeps its focus (a save with nothing to
|
|
69
|
+
* save, say). */
|
|
70
|
+
pendingLook?: boolean | 'disabled';
|
|
40
71
|
};
|
|
41
72
|
|
|
42
73
|
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
43
|
-
(
|
|
74
|
+
(
|
|
75
|
+
{
|
|
76
|
+
variant = 'primary',
|
|
77
|
+
selected,
|
|
78
|
+
compact = false,
|
|
79
|
+
wrap = false,
|
|
80
|
+
iconOnly = false,
|
|
81
|
+
shrinks = false,
|
|
82
|
+
mark,
|
|
83
|
+
busy,
|
|
84
|
+
pendingLook = false,
|
|
85
|
+
className = '',
|
|
86
|
+
children,
|
|
87
|
+
leftIcon,
|
|
88
|
+
rightIcon,
|
|
89
|
+
...props
|
|
90
|
+
},
|
|
91
|
+
ref,
|
|
92
|
+
) => {
|
|
44
93
|
const context = variant === 'context';
|
|
45
94
|
|
|
46
95
|
return (
|
|
@@ -53,13 +102,31 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
53
102
|
variant="ghost"
|
|
54
103
|
color="neutral"
|
|
55
104
|
aria-pressed={selected ?? props['aria-pressed']}
|
|
56
|
-
|
|
105
|
+
{...(busy === undefined ? {} : { 'aria-busy': busy || undefined })}
|
|
106
|
+
data-wrap={wrap || undefined}
|
|
107
|
+
{...(iconOnly ? { 'data-icon-only': '' } : {})}
|
|
108
|
+
className={`${base} ${sizes[compact ? 'compact' : 'default']} ${wrapping[wrap ? 'wrap' : 'nowrap']} ${variant === 'choice' && selected ? selectedChoice : recipes[variant]} ${selected && variant !== 'choice' ? 'bg-base-200' : ''} ${iconOnly ? square[compact ? 'compact' : 'default'] : ''} ${shrinks ? 'max-w-full min-w-0 shrink' : ''} ${pendingLook === 'disabled' ? heldDisabled : pendingLook ? pending : ''} ${className}`}
|
|
57
109
|
leftIcon={
|
|
58
|
-
|
|
110
|
+
busy ? (
|
|
111
|
+
<SpinnerIcon motion="always" className="size-4" />
|
|
112
|
+
) : context ? (
|
|
113
|
+
<span className="text-(--color-header-icon) [&>svg]:size-4">{leftIcon}</span>
|
|
114
|
+
) : (
|
|
115
|
+
leftIcon
|
|
116
|
+
)
|
|
59
117
|
}
|
|
60
118
|
rightIcon={context ? <span className="text-base-700 [&>svg]:size-3.5">{rightIcon}</span> : rightIcon}
|
|
61
119
|
>
|
|
62
|
-
{context ?
|
|
120
|
+
{context ? (
|
|
121
|
+
<span className="truncate">{children}</span>
|
|
122
|
+
) : shrinks ? (
|
|
123
|
+
<>
|
|
124
|
+
<span className="truncate">{children}</span>
|
|
125
|
+
{mark !== undefined && <> {mark}</>}
|
|
126
|
+
</>
|
|
127
|
+
) : (
|
|
128
|
+
children
|
|
129
|
+
)}
|
|
63
130
|
</NinnaButton>
|
|
64
131
|
);
|
|
65
132
|
},
|
|
@@ -2,6 +2,7 @@ import { ArrowRightIcon } from 'lucide-react';
|
|
|
2
2
|
import type { AnchorHTMLAttributes, ReactNode } from 'react';
|
|
3
3
|
|
|
4
4
|
import { tabbable } from '../foundations/KeyboardFocus';
|
|
5
|
+
import { ghostRecipe, outlineRecipe, primaryRecipe } from './ButtonRecipes';
|
|
5
6
|
|
|
6
7
|
/** The marketing pages' calls to action: the Button recipes at a roomier 44px, as links. */
|
|
7
8
|
const recipes = {
|
|
@@ -14,6 +15,17 @@ const recipes = {
|
|
|
14
15
|
quiet: 'border-transparent text-base-content hover:text-primary dark:hover:text-[color-mix(in_srgb,var(--color-primary)_45%,white)]',
|
|
15
16
|
} as const;
|
|
16
17
|
|
|
18
|
+
/** A compact link is the app Button's compact 28px control with 12px text, in the Button's own recipes, for an action
|
|
19
|
+
* that opens a page from a dense tool (such as Lar Factory's board). */
|
|
20
|
+
const compactBase =
|
|
21
|
+
'relative isolate inline-flex h-7 items-center justify-center gap-2 rounded-md border px-[11px] text-xs font-medium whitespace-nowrap transition-[background-color,box-shadow,scale,color] duration-150 active:scale-[0.97] focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary focus-visible:outline-none [&_[data-slot=icon]>svg]:size-4';
|
|
22
|
+
const compactRecipes = {
|
|
23
|
+
primary: primaryRecipe,
|
|
24
|
+
secondary: outlineRecipe,
|
|
25
|
+
inverse: recipes.inverse,
|
|
26
|
+
quiet: ghostRecipe,
|
|
27
|
+
} as const;
|
|
28
|
+
|
|
17
29
|
export interface ButtonLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className' | 'style'> {
|
|
18
30
|
href: string;
|
|
19
31
|
variant?: keyof typeof recipes;
|
|
@@ -23,6 +35,10 @@ export interface ButtonLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorEle
|
|
|
23
35
|
arrow?: boolean;
|
|
24
36
|
external?: boolean;
|
|
25
37
|
onNavigate?: (href: string) => void;
|
|
38
|
+
/** The app Button's compact 28px look in place of the marketing one, its `icon` leading it. */
|
|
39
|
+
compact?: boolean;
|
|
40
|
+
/** With `compact`, a square link showing its icon alone, named by its `aria-label`. */
|
|
41
|
+
iconOnly?: boolean;
|
|
26
42
|
}
|
|
27
43
|
|
|
28
44
|
export function ButtonLink({
|
|
@@ -33,10 +49,28 @@ export function ButtonLink({
|
|
|
33
49
|
external,
|
|
34
50
|
onNavigate,
|
|
35
51
|
onClick,
|
|
52
|
+
compact = false,
|
|
53
|
+
iconOnly = false,
|
|
36
54
|
children,
|
|
37
55
|
href,
|
|
38
56
|
...props
|
|
39
57
|
}: ButtonLinkProps) {
|
|
58
|
+
if (compact)
|
|
59
|
+
return (
|
|
60
|
+
<a
|
|
61
|
+
{...props}
|
|
62
|
+
href={href}
|
|
63
|
+
{...(external ? { target: '_blank', rel: 'noreferrer' } : {})}
|
|
64
|
+
onClick={onClick}
|
|
65
|
+
data-slot="button"
|
|
66
|
+
{...(iconOnly ? { 'data-icon-only': '' } : {})}
|
|
67
|
+
className={`${compactBase} ${compactRecipes[variant]} ${iconOnly ? 'w-7 px-0' : ''}`}
|
|
68
|
+
>
|
|
69
|
+
{icon && <span data-slot="icon">{icon}</span>}
|
|
70
|
+
{children}
|
|
71
|
+
</a>
|
|
72
|
+
);
|
|
73
|
+
|
|
40
74
|
return (
|
|
41
75
|
<a
|
|
42
76
|
{...tabbable}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// The app Button's filled and outlined recipes, which ButtonLink's compact links draw too.
|
|
2
|
+
|
|
3
|
+
export const primaryRecipe =
|
|
4
|
+
'border-primary bg-primary text-primary-content shadow-xs shadow-primary/24 inset-shadow-[0_1px_rgb(255_255_255/16%)] hover:bg-primary/90 active:shadow-none active:inset-shadow-[0_1px_rgb(0_0_0/8%)]';
|
|
5
|
+
|
|
6
|
+
export const outlineRecipe =
|
|
7
|
+
'border-base-400/90 bg-base-100 text-base-content shadow-xs/5 hover:bg-base-200/70 dark:border-base-400 dark:bg-base-400/30 dark:hover:bg-base-400/60 [&_[data-slot=icon]]:text-base-700';
|
|
8
|
+
|
|
9
|
+
export const ghostRecipe =
|
|
10
|
+
'border-transparent text-base-content hover:bg-base-200 data-[state=open]:bg-base-200 [&_[data-slot=icon]]:text-base-700';
|
|
@@ -5,7 +5,7 @@ import { StatusIndicator, type StatusTone } from '../feedback/StatusIndicator';
|
|
|
5
5
|
import { tabbable } from '../foundations/KeyboardFocus';
|
|
6
6
|
|
|
7
7
|
export type IconButtonProps = Omit<NinnaIconButtonProps, 'color' | 'radius' | 'size' | 'variant'> & {
|
|
8
|
-
variant?: 'header' | 'quiet' | 'title-bar';
|
|
8
|
+
variant?: 'header' | 'quiet' | 'title-bar' | 'inline';
|
|
9
9
|
tone?: StatusTone | 'accent';
|
|
10
10
|
notification?: string;
|
|
11
11
|
};
|
|
@@ -42,9 +42,12 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
|
|
|
42
42
|
: variant === 'title-bar'
|
|
43
43
|
? // The title bar's 28px row of controls, with 16px icons.
|
|
44
44
|
'text-base-700 hover:bg-base-200 hover:text-base-content data-[state=open]:bg-base-200 data-[state=open]:text-base-content size-7 rounded-md p-0 before:-inset-1.5 **:data-[slot=icon]:size-4 '
|
|
45
|
-
:
|
|
46
|
-
?
|
|
47
|
-
|
|
45
|
+
: variant === 'inline'
|
|
46
|
+
? // A 20px control inside a line of text, such as the pencil beside a list of labels, with a 12px icon.
|
|
47
|
+
'text-base-700 hover:bg-base-200 grid size-5 place-items-center rounded p-0 disabled:opacity-50 disabled:hover:bg-transparent **:data-[slot=icon]:size-3 '
|
|
48
|
+
: tone === 'neutral'
|
|
49
|
+
? 'text-base-700 hover:bg-base-200 hover:text-base-content data-[state=open]:bg-base-200 rounded-md '
|
|
50
|
+
: 'rounded-md ') +
|
|
48
51
|
'transition-[background-color,color,scale] active:scale-[0.94] [&_svg]:size-full ' +
|
|
49
52
|
className
|
|
50
53
|
}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// What a row says its T3 thread is doing, in its second line's text slot: a status mark, then the newest action, its
|
|
2
|
+
// age and the agents at work; and the list of agents at work, in its tooltip and the item dialog.
|
|
3
|
+
|
|
4
|
+
import type { ReactNode } from 'react';
|
|
5
|
+
|
|
6
|
+
import { Badge } from '../display/Badge';
|
|
7
|
+
import { Tooltip, TooltipPopup, TooltipTrigger } from '../overlays/Tooltip';
|
|
8
|
+
|
|
9
|
+
/** What a thread's activity line says it is doing. */
|
|
10
|
+
export type ActivityState = 'working' | 'quiet' | 'waiting' | 'stopped' | 'unavailable';
|
|
11
|
+
|
|
12
|
+
/** Quiet is hollow and stopped is square, so each reads apart from working without its colour. */
|
|
13
|
+
const MARK: Record<ActivityState, string> = {
|
|
14
|
+
working: 'rounded-full bg-(--st-now)',
|
|
15
|
+
quiet: 'rounded-full border-[1.5px] border-(--warning-foreground)',
|
|
16
|
+
waiting: 'rounded-full bg-(--st-amber)',
|
|
17
|
+
stopped: 'rounded-[1px] bg-(--st-idle)',
|
|
18
|
+
unavailable: 'rounded-full border-[1.5px] border-(--st-idle)',
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** The line's words for its state, which `data-action` marks. */
|
|
22
|
+
function Words({ state, children }: { state: ActivityState; children: ReactNode }) {
|
|
23
|
+
switch (state) {
|
|
24
|
+
case 'working':
|
|
25
|
+
return (
|
|
26
|
+
<span data-action className="min-w-0 truncate text-(--foreground)">
|
|
27
|
+
{children}
|
|
28
|
+
</span>
|
|
29
|
+
);
|
|
30
|
+
case 'quiet':
|
|
31
|
+
return (
|
|
32
|
+
<span data-action className="min-w-0 truncate font-medium text-(--warning-foreground) tabular-nums">
|
|
33
|
+
{children}
|
|
34
|
+
</span>
|
|
35
|
+
);
|
|
36
|
+
case 'waiting':
|
|
37
|
+
return (
|
|
38
|
+
<Badge data-action data-activity-badge tone="warning" className="shrink-0">
|
|
39
|
+
{children}
|
|
40
|
+
</Badge>
|
|
41
|
+
);
|
|
42
|
+
case 'stopped':
|
|
43
|
+
return (
|
|
44
|
+
<Badge data-action data-activity-badge className="shrink-0">
|
|
45
|
+
{children}
|
|
46
|
+
</Badge>
|
|
47
|
+
);
|
|
48
|
+
case 'unavailable':
|
|
49
|
+
return (
|
|
50
|
+
<span data-action className="min-w-0 truncate">
|
|
51
|
+
{children}
|
|
52
|
+
</span>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* A thread's activity: its state's mark, its `action`, then its `age` and how many `agents` work, each after a dot. With
|
|
59
|
+
* `agentList`, the line takes focus and its tooltip lists the agents at work.
|
|
60
|
+
*/
|
|
61
|
+
export function ActivityLine({
|
|
62
|
+
state,
|
|
63
|
+
action,
|
|
64
|
+
age,
|
|
65
|
+
agents,
|
|
66
|
+
agentList,
|
|
67
|
+
}: {
|
|
68
|
+
state: ActivityState;
|
|
69
|
+
action: ReactNode;
|
|
70
|
+
age?: string | undefined;
|
|
71
|
+
agents?: string | undefined;
|
|
72
|
+
agentList?: ReactNode;
|
|
73
|
+
}) {
|
|
74
|
+
const shown = (
|
|
75
|
+
<span
|
|
76
|
+
data-activity={state}
|
|
77
|
+
tabIndex={agentList ? 0 : undefined}
|
|
78
|
+
className="flex min-w-0 items-center gap-1.5 rounded focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--primary)"
|
|
79
|
+
>
|
|
80
|
+
<span data-mark className={`inline-block size-2 shrink-0 ${MARK[state]}`} />
|
|
81
|
+
<Words state={state}>{action}</Words>
|
|
82
|
+
{age !== undefined && (
|
|
83
|
+
<span data-age className="shrink-0 tabular-nums">
|
|
84
|
+
· {age}
|
|
85
|
+
</span>
|
|
86
|
+
)}
|
|
87
|
+
{agents && (
|
|
88
|
+
<span data-agents className="shrink-0 tabular-nums">
|
|
89
|
+
· {agents}
|
|
90
|
+
</span>
|
|
91
|
+
)}
|
|
92
|
+
</span>
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
if (!agentList) return shown;
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<Tooltip>
|
|
99
|
+
<TooltipTrigger asChild>{shown}</TooltipTrigger>
|
|
100
|
+
<TooltipPopup side="bottom" align="start" className="max-w-md">
|
|
101
|
+
{agentList}
|
|
102
|
+
</TooltipPopup>
|
|
103
|
+
</Tooltip>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** The agents at work, one AgentRow each. */
|
|
108
|
+
export function AgentList({ children }: { children: ReactNode }) {
|
|
109
|
+
return (
|
|
110
|
+
<ul data-agent-list className="m-0 grid min-w-0 list-none gap-1 p-0 text-left">
|
|
111
|
+
{children}
|
|
112
|
+
</ul>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** An agent at work: its title, any `model` after it, its action's `age` at the right, and its `action` under it. */
|
|
117
|
+
export function AgentRow({
|
|
118
|
+
title,
|
|
119
|
+
model,
|
|
120
|
+
age,
|
|
121
|
+
action,
|
|
122
|
+
}: {
|
|
123
|
+
title: string;
|
|
124
|
+
model?: string | undefined;
|
|
125
|
+
age?: ReactNode;
|
|
126
|
+
action?: string | undefined;
|
|
127
|
+
}) {
|
|
128
|
+
return (
|
|
129
|
+
<li className="grid grid-cols-[auto_minmax(0,1fr)_auto] items-baseline gap-x-1.5">
|
|
130
|
+
<span className={`inline-block size-2 self-center ${MARK.working}`} />
|
|
131
|
+
<span className="flex min-w-0 gap-1.5">
|
|
132
|
+
<span className="min-w-0 truncate font-medium">{title}</span>
|
|
133
|
+
{model && <span className="shrink-0 opacity-70">· {model}</span>}
|
|
134
|
+
</span>
|
|
135
|
+
{age || <span />}
|
|
136
|
+
{action && (
|
|
137
|
+
<span title={action} className="col-span-2 col-start-2 truncate opacity-70">
|
|
138
|
+
{action}
|
|
139
|
+
</span>
|
|
140
|
+
)}
|
|
141
|
+
</li>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** An agent's action's age, in AgentRow. */
|
|
146
|
+
export function AgentAge({ children }: { children: ReactNode }) {
|
|
147
|
+
return (
|
|
148
|
+
<span data-agent-age className="shrink-0 tabular-nums opacity-70">
|
|
149
|
+
{children}
|
|
150
|
+
</span>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/** The agents at work in the item dialog, under `heading`; or, with `unavailable`, why they can't be listed. */
|
|
155
|
+
export function WorkingAgents({
|
|
156
|
+
heading,
|
|
157
|
+
unavailable,
|
|
158
|
+
children,
|
|
159
|
+
}: {
|
|
160
|
+
heading: string;
|
|
161
|
+
unavailable?: string | undefined;
|
|
162
|
+
children?: ReactNode;
|
|
163
|
+
}) {
|
|
164
|
+
return (
|
|
165
|
+
<section data-working-agents className="grid min-w-0 grid-cols-[minmax(0,1fr)] gap-2 text-xs">
|
|
166
|
+
{unavailable ? (
|
|
167
|
+
<p className="m-0 text-(--muted-foreground)">{unavailable}</p>
|
|
168
|
+
) : (
|
|
169
|
+
<>
|
|
170
|
+
<p className="m-0 font-medium">{heading}</p>
|
|
171
|
+
{children}
|
|
172
|
+
</>
|
|
173
|
+
)}
|
|
174
|
+
</section>
|
|
175
|
+
);
|
|
176
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// A piece of work's activity as the board reads it from T3: the track that sweeps while it runs, and its label.
|
|
2
|
+
|
|
3
|
+
import type { ReactNode } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ambientMotion } from '../foundations/AmbientMotion';
|
|
6
|
+
|
|
7
|
+
/** A thin track named by `label`, swept by a bar while `running`. */
|
|
8
|
+
export function ActivityTrack({ label, running }: { label: string; running: boolean }) {
|
|
9
|
+
return (
|
|
10
|
+
<div role="img" aria-label={label} className="activity-track h-1.5 overflow-hidden rounded-full bg-(--soft)">
|
|
11
|
+
{running && (
|
|
12
|
+
<span ref={ambientMotion} className="activity-sweep block h-1.5 w-1/3 rounded-full bg-(--st-now)" />
|
|
13
|
+
)}
|
|
14
|
+
</div>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** The activity's words alone, in one small muted line. */
|
|
19
|
+
export function ActivityLabel({ children }: { children: ReactNode }) {
|
|
20
|
+
return (
|
|
21
|
+
<span className="block h-4 text-[11px] leading-4 whitespace-nowrap text-(--muted-foreground)">{children}</span>
|
|
22
|
+
);
|
|
23
|
+
}
|