@adres/mgda-ui 0.0.0-stage → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/brand-knowledge.json +451 -0
- package/knowledge/accordion.md +135 -0
- package/knowledge/activity-rings.md +123 -0
- package/knowledge/alert.md +184 -0
- package/knowledge/answer-actions.md +217 -0
- package/knowledge/aspect-ratio.md +82 -0
- package/knowledge/avatar.md +158 -0
- package/knowledge/badge.md +172 -0
- package/knowledge/bar-graph.md +167 -0
- package/knowledge/bento-grid.md +115 -0
- package/knowledge/blockquote.md +153 -0
- package/knowledge/box-list.md +177 -0
- package/knowledge/bullet-list.md +128 -0
- package/knowledge/button-group.md +179 -0
- package/knowledge/button.md +231 -0
- package/knowledge/calendar.md +168 -0
- package/knowledge/card.md +321 -0
- package/knowledge/cards-nav.md +170 -0
- package/knowledge/chain-of-thought.md +164 -0
- package/knowledge/chat-container.md +135 -0
- package/knowledge/chat-message.md +224 -0
- package/knowledge/checkbox-card.md +172 -0
- package/knowledge/checkbox.md +111 -0
- package/knowledge/citations.md +241 -0
- package/knowledge/combobox.md +265 -0
- package/knowledge/countdown-pill.md +153 -0
- package/knowledge/cta.md +118 -0
- package/knowledge/data-list.md +173 -0
- package/knowledge/data-table.md +220 -0
- package/knowledge/dialog.md +249 -0
- package/knowledge/drawer.md +236 -0
- package/knowledge/dropdown-menu.md +238 -0
- package/knowledge/dropzone.md +153 -0
- package/knowledge/email-chips-input.md +161 -0
- package/knowledge/empty-state.md +106 -0
- package/knowledge/entity-header.md +166 -0
- package/knowledge/feature-grid.md +120 -0
- package/knowledge/feedback-bar.md +127 -0
- package/knowledge/footer.md +116 -0
- package/knowledge/heading.md +189 -0
- package/knowledge/hero.md +361 -0
- package/knowledge/input-button.md +187 -0
- package/knowledge/input-group.md +185 -0
- package/knowledge/input.md +256 -0
- package/knowledge/inset.md +177 -0
- package/knowledge/kpi-card.md +206 -0
- package/knowledge/list-nav.md +181 -0
- package/knowledge/logo-cloud.md +102 -0
- package/knowledge/media-gallery.md +158 -0
- package/knowledge/message-actions.md +175 -0
- package/knowledge/nav-sidebar.md +225 -0
- package/knowledge/number-stepper.md +159 -0
- package/knowledge/page-header.md +109 -0
- package/knowledge/pagination.md +225 -0
- package/knowledge/popover.md +159 -0
- package/knowledge/pricing.md +132 -0
- package/knowledge/progress.md +156 -0
- package/knowledge/prompt-input.md +337 -0
- package/knowledge/prompt-suggestions.md +168 -0
- package/knowledge/quota-bar.md +160 -0
- package/knowledge/quote.md +116 -0
- package/knowledge/radio-card.md +172 -0
- package/knowledge/radio-group.md +135 -0
- package/knowledge/reasoning.md +142 -0
- package/knowledge/search.md +131 -0
- package/knowledge/section-nav.md +162 -0
- package/knowledge/segmented-control.md +181 -0
- package/knowledge/select-button.md +205 -0
- package/knowledge/select.md +210 -0
- package/knowledge/separator.md +75 -0
- package/knowledge/shimmer-text.md +140 -0
- package/knowledge/sidebar.md +227 -0
- package/knowledge/skeleton.md +142 -0
- package/knowledge/slider.md +133 -0
- package/knowledge/slideshow.md +159 -0
- package/knowledge/source.md +156 -0
- package/knowledge/spinner.md +120 -0
- package/knowledge/stat-strip.md +128 -0
- package/knowledge/stats.md +117 -0
- package/knowledge/step-indicator.md +157 -0
- package/knowledge/switch.md +88 -0
- package/knowledge/table.md +190 -0
- package/knowledge/tabs.md +169 -0
- package/knowledge/testimonials.md +115 -0
- package/knowledge/text-link.md +192 -0
- package/knowledge/text.md +194 -0
- package/knowledge/thinking-bar.md +115 -0
- package/knowledge/thinking-steps.md +140 -0
- package/knowledge/toaster.md +127 -0
- package/knowledge/toggle.md +113 -0
- package/knowledge/tool-call-card.md +241 -0
- package/knowledge/tooltip.md +120 -0
- package/knowledge/top-nav.md +138 -0
- package/knowledge.json +19854 -0
- package/package.json +94 -4
- package/src/components/accordion.stories.tsx +46 -0
- package/src/components/accordion.tsx +74 -0
- package/src/components/activity-rings.stories.tsx +73 -0
- package/src/components/activity-rings.tsx +121 -0
- package/src/components/alert.stories.tsx +43 -0
- package/src/components/alert.tsx +132 -0
- package/src/components/answer-actions.stories.tsx +54 -0
- package/src/components/answer-actions.test.tsx +37 -0
- package/src/components/answer-actions.tsx +313 -0
- package/src/components/aspect-ratio.stories.tsx +32 -0
- package/src/components/aspect-ratio.tsx +5 -0
- package/src/components/avatar.stories.tsx +40 -0
- package/src/components/avatar.tsx +154 -0
- package/src/components/badge.stories.tsx +27 -0
- package/src/components/badge.tsx +63 -0
- package/src/components/bar-graph.stories.tsx +28 -0
- package/src/components/bar-graph.tsx +204 -0
- package/src/components/bento-grid.stories.tsx +23 -0
- package/src/components/bento-grid.tsx +67 -0
- package/src/components/blockquote.stories.tsx +28 -0
- package/src/components/blockquote.tsx +88 -0
- package/src/components/box-list.stories.tsx +25 -0
- package/src/components/box-list.tsx +108 -0
- package/src/components/bullet-list.stories.tsx +22 -0
- package/src/components/bullet-list.tsx +101 -0
- package/src/components/button-group.stories.tsx +31 -0
- package/src/components/button-group.tsx +156 -0
- package/src/components/button.stories.tsx +66 -0
- package/src/components/button.test.ts +17 -0
- package/src/components/button.tsx +139 -0
- package/src/components/calendar.stories.tsx +25 -0
- package/src/components/calendar.tsx +367 -0
- package/src/components/card.stories.tsx +44 -0
- package/src/components/card.tsx +392 -0
- package/src/components/cards-nav.stories.tsx +35 -0
- package/src/components/cards-nav.tsx +115 -0
- package/src/components/chain-of-thought.stories.tsx +67 -0
- package/src/components/chain-of-thought.test.tsx +50 -0
- package/src/components/chain-of-thought.tsx +170 -0
- package/src/components/chat-container.stories.tsx +47 -0
- package/src/components/chat-container.test.tsx +49 -0
- package/src/components/chat-container.tsx +222 -0
- package/src/components/chat-message.stories.tsx +52 -0
- package/src/components/chat-message.test.tsx +36 -0
- package/src/components/chat-message.tsx +163 -0
- package/src/components/checkbox-card.stories.tsx +27 -0
- package/src/components/checkbox-card.tsx +200 -0
- package/src/components/checkbox.stories.tsx +26 -0
- package/src/components/checkbox.tsx +61 -0
- package/src/components/citations.stories.tsx +64 -0
- package/src/components/citations.test.tsx +61 -0
- package/src/components/citations.tsx +220 -0
- package/src/components/combobox.stories.tsx +184 -0
- package/src/components/combobox.test.tsx +82 -0
- package/src/components/combobox.tsx +407 -0
- package/src/components/countdown-pill.stories.tsx +24 -0
- package/src/components/countdown-pill.tsx +129 -0
- package/src/components/cta.stories.tsx +29 -0
- package/src/components/cta.tsx +52 -0
- package/src/components/data-list.stories.tsx +50 -0
- package/src/components/data-list.test.tsx +35 -0
- package/src/components/data-list.tsx +181 -0
- package/src/components/data-table.stories.tsx +29 -0
- package/src/components/data-table.tsx +200 -0
- package/src/components/dialog.stories.tsx +42 -0
- package/src/components/dialog.tsx +200 -0
- package/src/components/drawer.stories.tsx +48 -0
- package/src/components/drawer.tsx +385 -0
- package/src/components/dropdown-menu.stories.tsx +41 -0
- package/src/components/dropdown-menu.tsx +252 -0
- package/src/components/dropzone.stories.tsx +19 -0
- package/src/components/dropzone.tsx +250 -0
- package/src/components/email-chips-input.stories.tsx +135 -0
- package/src/components/email-chips-input.tsx +210 -0
- package/src/components/empty-state.stories.tsx +22 -0
- package/src/components/empty-state.tsx +35 -0
- package/src/components/entity-header.stories.tsx +43 -0
- package/src/components/entity-header.test.tsx +35 -0
- package/src/components/entity-header.tsx +92 -0
- package/src/components/feature-grid.stories.tsx +25 -0
- package/src/components/feature-grid.tsx +87 -0
- package/src/components/feedback-bar.stories.tsx +25 -0
- package/src/components/feedback-bar.test.tsx +24 -0
- package/src/components/feedback-bar.tsx +62 -0
- package/src/components/footer.stories.tsx +23 -0
- package/src/components/footer.tsx +78 -0
- package/src/components/heading.stories.tsx +45 -0
- package/src/components/heading.test.tsx +22 -0
- package/src/components/heading.tsx +77 -0
- package/src/components/hero.stories.tsx +38 -0
- package/src/components/hero.tsx +498 -0
- package/src/components/input-button.stories.tsx +19 -0
- package/src/components/input-button.tsx +112 -0
- package/src/components/input-group.stories.tsx +38 -0
- package/src/components/input-group.tsx +157 -0
- package/src/components/input.stories.tsx +31 -0
- package/src/components/input.tsx +284 -0
- package/src/components/inset.stories.tsx +29 -0
- package/src/components/inset.tsx +70 -0
- package/src/components/kpi-card.stories.tsx +29 -0
- package/src/components/kpi-card.tsx +284 -0
- package/src/components/list-nav.stories.tsx +22 -0
- package/src/components/list-nav.tsx +145 -0
- package/src/components/logo-cloud.stories.tsx +23 -0
- package/src/components/logo-cloud.tsx +42 -0
- package/src/components/media-gallery.stories.tsx +25 -0
- package/src/components/media-gallery.tsx +347 -0
- package/src/components/message-actions.stories.tsx +45 -0
- package/src/components/message-actions.test.tsx +32 -0
- package/src/components/message-actions.tsx +119 -0
- package/src/components/nav-sidebar.stories.tsx +58 -0
- package/src/components/nav-sidebar.test.tsx +54 -0
- package/src/components/nav-sidebar.tsx +462 -0
- package/src/components/number-stepper.stories.tsx +19 -0
- package/src/components/number-stepper.tsx +158 -0
- package/src/components/page-header.stories.tsx +25 -0
- package/src/components/page-header.tsx +64 -0
- package/src/components/pagination.stories.tsx +110 -0
- package/src/components/pagination.test.tsx +46 -0
- package/src/components/pagination.tsx +144 -0
- package/src/components/popover.stories.tsx +26 -0
- package/src/components/popover.tsx +62 -0
- package/src/components/pricing.stories.tsx +42 -0
- package/src/components/pricing.tsx +130 -0
- package/src/components/progress.stories.tsx +22 -0
- package/src/components/progress.tsx +189 -0
- package/src/components/prompt-input.stories.tsx +62 -0
- package/src/components/prompt-input.test.tsx +106 -0
- package/src/components/prompt-input.tsx +343 -0
- package/src/components/prompt-suggestions.stories.tsx +53 -0
- package/src/components/prompt-suggestions.test.tsx +37 -0
- package/src/components/prompt-suggestions.tsx +122 -0
- package/src/components/quota-bar.stories.tsx +19 -0
- package/src/components/quota-bar.tsx +191 -0
- package/src/components/quote.stories.tsx +18 -0
- package/src/components/quote.tsx +43 -0
- package/src/components/radio-card.stories.tsx +27 -0
- package/src/components/radio-card.tsx +225 -0
- package/src/components/radio-group.stories.tsx +32 -0
- package/src/components/radio-group.tsx +68 -0
- package/src/components/reasoning.stories.tsx +50 -0
- package/src/components/reasoning.test.tsx +48 -0
- package/src/components/reasoning.tsx +143 -0
- package/src/components/search.stories.tsx +18 -0
- package/src/components/search.tsx +133 -0
- package/src/components/section-nav.stories.tsx +59 -0
- package/src/components/section-nav.test.tsx +36 -0
- package/src/components/section-nav.tsx +146 -0
- package/src/components/segmented-control.stories.tsx +22 -0
- package/src/components/segmented-control.tsx +301 -0
- package/src/components/select-button.stories.tsx +27 -0
- package/src/components/select-button.tsx +174 -0
- package/src/components/select.stories.tsx +27 -0
- package/src/components/select.tsx +198 -0
- package/src/components/separator.stories.tsx +22 -0
- package/src/components/separator.tsx +23 -0
- package/src/components/shimmer-text.stories.tsx +23 -0
- package/src/components/shimmer-text.test.tsx +35 -0
- package/src/components/shimmer-text.tsx +43 -0
- package/src/components/sidebar.stories.tsx +25 -0
- package/src/components/sidebar.tsx +234 -0
- package/src/components/skeleton.stories.tsx +22 -0
- package/src/components/skeleton.tsx +96 -0
- package/src/components/slider.stories.tsx +20 -0
- package/src/components/slider.tsx +176 -0
- package/src/components/slideshow.stories.tsx +30 -0
- package/src/components/slideshow.tsx +291 -0
- package/src/components/source.stories.tsx +32 -0
- package/src/components/source.test.tsx +40 -0
- package/src/components/source.tsx +161 -0
- package/src/components/spinner.stories.tsx +19 -0
- package/src/components/spinner.tsx +76 -0
- package/src/components/stat-strip.stories.tsx +36 -0
- package/src/components/stat-strip.test.tsx +25 -0
- package/src/components/stat-strip.tsx +85 -0
- package/src/components/stats.stories.tsx +24 -0
- package/src/components/stats.tsx +83 -0
- package/src/components/step-indicator.stories.tsx +18 -0
- package/src/components/step-indicator.test.tsx +18 -0
- package/src/components/step-indicator.tsx +286 -0
- package/src/components/switch.stories.tsx +26 -0
- package/src/components/switch.tsx +32 -0
- package/src/components/table.stories.tsx +38 -0
- package/src/components/table.tsx +220 -0
- package/src/components/tabs.stories.tsx +25 -0
- package/src/components/tabs.tsx +276 -0
- package/src/components/testimonials.stories.tsx +22 -0
- package/src/components/testimonials.tsx +109 -0
- package/src/components/text-link.stories.tsx +47 -0
- package/src/components/text-link.test.tsx +18 -0
- package/src/components/text-link.tsx +88 -0
- package/src/components/text.stories.tsx +49 -0
- package/src/components/text.tsx +105 -0
- package/src/components/thinking-bar.stories.tsx +19 -0
- package/src/components/thinking-bar.test.tsx +27 -0
- package/src/components/thinking-bar.tsx +64 -0
- package/src/components/thinking-steps.stories.tsx +44 -0
- package/src/components/thinking-steps.test.tsx +42 -0
- package/src/components/thinking-steps.tsx +92 -0
- package/src/components/toaster.stories.tsx +80 -0
- package/src/components/toaster.tsx +36 -0
- package/src/components/toggle.stories.tsx +21 -0
- package/src/components/toggle.tsx +103 -0
- package/src/components/tool-call-card.stories.tsx +97 -0
- package/src/components/tool-call-card.test.tsx +88 -0
- package/src/components/tool-call-card.tsx +231 -0
- package/src/components/tooltip.stories.tsx +25 -0
- package/src/components/tooltip.tsx +43 -0
- package/src/components/top-nav.stories.tsx +20 -0
- package/src/components/top-nav.tsx +76 -0
- package/src/docs/Colors.stories.tsx +192 -0
- package/src/docs/GettingStarted.mdx +72 -0
- package/src/docs/Mcp.mdx +52 -0
- package/src/docs/Typography.stories.tsx +114 -0
- package/src/hooks/use-in-view.ts +32 -0
- package/src/hooks/use-reduced-motion.ts +26 -0
- package/src/index.ts +343 -0
- package/src/lib/cn.test.ts +67 -0
- package/src/lib/cn.ts +81 -0
- package/src/lib/motion.ts +109 -0
- package/src/lib/prefix-utilities.test.ts +56 -0
- package/src/lib/prefix-utilities.ts +50 -0
- package/src/styles/base.css +489 -0
- package/src/styles/motion.css +69 -0
- package/src/styles/overrides.css +44 -0
- package/src/styles/typography.css +173 -0
- package/src/theme/theme.css +391 -0
- package/src/theme/tokens.ts +29 -0
- package/src/theme/types.ts +26 -0
- package/README.md +0 -3
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: citations
|
|
6
|
+
sourceFile: packages/design-system/src/components/citations.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-ai
|
|
9
|
+
categoryFromBarrel: web-app-ai
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: CitationMarker
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "({ source, onShow }: CitationMarkerProps) => Element"
|
|
16
|
+
- name: CitationMarkerProps
|
|
17
|
+
kind: type
|
|
18
|
+
- name: CitationSource
|
|
19
|
+
kind: type
|
|
20
|
+
- name: CitationSourceKind
|
|
21
|
+
kind: type
|
|
22
|
+
- name: formatSourceDate
|
|
23
|
+
kind: function
|
|
24
|
+
typeText: "(iso: string) => string"
|
|
25
|
+
- name: isStale
|
|
26
|
+
kind: function
|
|
27
|
+
typeText: "(date: string, asOf: string, days?: number) => boolean"
|
|
28
|
+
- name: SourceAvatar
|
|
29
|
+
kind: component
|
|
30
|
+
typeText: "({ kind, size }: SourceAvatarProps) => Element"
|
|
31
|
+
- name: SourceAvatarProps
|
|
32
|
+
kind: type
|
|
33
|
+
- name: SourceCard
|
|
34
|
+
kind: component
|
|
35
|
+
typeText: "ForwardRefExoticComponent<SourceCardProps & RefAttributes<HTMLDivElement>>"
|
|
36
|
+
- name: SourceCardProps
|
|
37
|
+
kind: type
|
|
38
|
+
- name: SourceList
|
|
39
|
+
kind: component
|
|
40
|
+
typeText: "ForwardRefExoticComponent<SourceListProps & RefAttributes<HTMLDivElement>>"
|
|
41
|
+
- name: SourceListProps
|
|
42
|
+
kind: type
|
|
43
|
+
- name: UnsupportedClaim
|
|
44
|
+
kind: component
|
|
45
|
+
typeText: "({ children, note }: UnsupportedClaimProps) => Element"
|
|
46
|
+
- name: UnsupportedClaimProps
|
|
47
|
+
kind: type
|
|
48
|
+
primaryExport: CitationMarker
|
|
49
|
+
subcomponents:
|
|
50
|
+
- SourceAvatar
|
|
51
|
+
- SourceCard
|
|
52
|
+
- SourceList
|
|
53
|
+
- UnsupportedClaim
|
|
54
|
+
props:
|
|
55
|
+
CitationMarker:
|
|
56
|
+
- name: onShow
|
|
57
|
+
type: "((id: number) => void)"
|
|
58
|
+
required: false
|
|
59
|
+
declaredIn: self
|
|
60
|
+
doc: "Adds \"Show in sources\" to the preview, e.g. to scroll to and highlight the source in a list."
|
|
61
|
+
- name: source
|
|
62
|
+
type: CitationSource
|
|
63
|
+
required: true
|
|
64
|
+
declaredIn: self
|
|
65
|
+
SourceAvatar:
|
|
66
|
+
- name: kind
|
|
67
|
+
type: CitationSourceKind
|
|
68
|
+
required: false
|
|
69
|
+
declaredIn: self
|
|
70
|
+
- name: size
|
|
71
|
+
type: "\"sm\" | \"xs\""
|
|
72
|
+
required: false
|
|
73
|
+
declaredIn: self
|
|
74
|
+
SourceCard:
|
|
75
|
+
- name: asOf
|
|
76
|
+
type: string
|
|
77
|
+
required: false
|
|
78
|
+
declaredIn: self
|
|
79
|
+
doc: "ISO \"today\" for the age check. Without it, no stale badge. Pass a fixed date to render the same on server and client."
|
|
80
|
+
- name: highlighted
|
|
81
|
+
type: boolean
|
|
82
|
+
required: false
|
|
83
|
+
declaredIn: self
|
|
84
|
+
doc: "Rings the card, e.g. after \"Show in sources\"."
|
|
85
|
+
- name: source
|
|
86
|
+
type: CitationSource
|
|
87
|
+
required: true
|
|
88
|
+
declaredIn: self
|
|
89
|
+
- name: staleAfterDays
|
|
90
|
+
type: number
|
|
91
|
+
required: false
|
|
92
|
+
declaredIn: self
|
|
93
|
+
doc: "Days after which the source is marked old."
|
|
94
|
+
- name: staleLabel
|
|
95
|
+
type: string
|
|
96
|
+
required: false
|
|
97
|
+
declaredIn: self
|
|
98
|
+
SourceList:
|
|
99
|
+
- name: asOf
|
|
100
|
+
type: string
|
|
101
|
+
required: false
|
|
102
|
+
declaredIn: self
|
|
103
|
+
- name: getSourceId
|
|
104
|
+
type: "((id: number) => string)"
|
|
105
|
+
required: false
|
|
106
|
+
declaredIn: self
|
|
107
|
+
doc: "DOM id for each card, so a marker's \"Show in sources\" can scroll to and focus it."
|
|
108
|
+
- name: highlighted
|
|
109
|
+
type: number
|
|
110
|
+
required: false
|
|
111
|
+
declaredIn: self
|
|
112
|
+
doc: "The source id to ring."
|
|
113
|
+
- name: initial
|
|
114
|
+
type: number
|
|
115
|
+
required: false
|
|
116
|
+
declaredIn: self
|
|
117
|
+
doc: "How many show before \"Show N more\". Defaults to all."
|
|
118
|
+
- name: onExpand
|
|
119
|
+
type: "(() => void)"
|
|
120
|
+
required: false
|
|
121
|
+
declaredIn: self
|
|
122
|
+
- name: sources
|
|
123
|
+
type: "CitationSource[]"
|
|
124
|
+
required: true
|
|
125
|
+
declaredIn: self
|
|
126
|
+
UnsupportedClaim:
|
|
127
|
+
- name: children
|
|
128
|
+
type: ReactNode
|
|
129
|
+
required: true
|
|
130
|
+
declaredIn: self
|
|
131
|
+
- name: note
|
|
132
|
+
type: string
|
|
133
|
+
required: false
|
|
134
|
+
declaredIn: self
|
|
135
|
+
doc: "Tooltip explaining the mark."
|
|
136
|
+
extendsProps: []
|
|
137
|
+
variants:
|
|
138
|
+
size:
|
|
139
|
+
kind: enum
|
|
140
|
+
options:
|
|
141
|
+
- sm
|
|
142
|
+
- xs
|
|
143
|
+
default: sm
|
|
144
|
+
on: SourceAvatar
|
|
145
|
+
variantSource: prop-union
|
|
146
|
+
compoundVariants: []
|
|
147
|
+
sizeMaps: []
|
|
148
|
+
dataSlots:
|
|
149
|
+
- source-card
|
|
150
|
+
- source-list
|
|
151
|
+
dependsOn:
|
|
152
|
+
internal:
|
|
153
|
+
- avatar
|
|
154
|
+
- badge
|
|
155
|
+
- button
|
|
156
|
+
- popover
|
|
157
|
+
- text
|
|
158
|
+
- text-link
|
|
159
|
+
- tooltip
|
|
160
|
+
lib:
|
|
161
|
+
- cn
|
|
162
|
+
hooks: []
|
|
163
|
+
external:
|
|
164
|
+
- lucide-react
|
|
165
|
+
- react
|
|
166
|
+
contexts: []
|
|
167
|
+
stories:
|
|
168
|
+
- exportName: Sources
|
|
169
|
+
id: components-citations--sources
|
|
170
|
+
- exportName: Collapsed
|
|
171
|
+
id: components-citations--collapsed
|
|
172
|
+
- exportName: Highlighted
|
|
173
|
+
id: components-citations--highlighted
|
|
174
|
+
- exportName: CitedAnswer
|
|
175
|
+
id: components-citations--cited-answer
|
|
176
|
+
storybookTitle: Components/Citations
|
|
177
|
+
docsId: components-citations--documentation
|
|
178
|
+
argTypeOptions: {}
|
|
179
|
+
resolvedCleanly: true
|
|
180
|
+
contractHash: "0c4ab9435b20"
|
|
181
|
+
factsHash: "2578f26d8544"
|
|
182
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
183
|
+
status: beta
|
|
184
|
+
summary: "Source citations for AI answers: numbered markers in the text that preview the passage used, a mark for claims no source backs, and a numbered source list with age warnings."
|
|
185
|
+
useWhen:
|
|
186
|
+
- "an assistant answer states facts that people should be able to check"
|
|
187
|
+
- "a claim in an answer has no source and should be marked as an estimate"
|
|
188
|
+
- "an answer lists its sources with the exact passage used and how old each is"
|
|
189
|
+
useInstead:
|
|
190
|
+
- id: blockquote
|
|
191
|
+
when: "quoting a passage on its own, not citing it from an answer"
|
|
192
|
+
- id: text-link
|
|
193
|
+
when: "a plain inline link with no preview or numbering"
|
|
194
|
+
related:
|
|
195
|
+
- chat-message
|
|
196
|
+
- popover
|
|
197
|
+
- blockquote
|
|
198
|
+
a11y:
|
|
199
|
+
notes:
|
|
200
|
+
- "Each marker is a button named \"Source N: title\" that opens the preview popover."
|
|
201
|
+
- "The unsupported-claim icon is a real button named \"Not backed by a source\" so keyboard users reach the tooltip."
|
|
202
|
+
- "SourceList is an ordered list labelled \"Sources\"; cards take focus (tabIndex -1) so \"Show in sources\" can move focus to them."
|
|
203
|
+
radixHandles: true
|
|
204
|
+
pitfalls:
|
|
205
|
+
- "Pass a fixed asOf date to SourceCard and SourceList; reading today's date on the server and client renders different badges."
|
|
206
|
+
- "Give getSourceId and focus the card yourself in onShow; the marker only calls back with the id."
|
|
207
|
+
- "Markers and the unsupported mark use tooltips and popovers, so mount a TooltipProvider above them."
|
|
208
|
+
canonicalSnippet: |
|
|
209
|
+
import { CitationMarker, SourceList } from "@adres/mgda-ui"
|
|
210
|
+
|
|
211
|
+
<p>
|
|
212
|
+
Listed at about AED 2,400 per sqft
|
|
213
|
+
<CitationMarker source={sources[0]} onShow={scrollToSource} />.
|
|
214
|
+
</p>
|
|
215
|
+
<SourceList sources={sources} asOf="2026-10-06" getSourceId={(id) => `source-${id}`} />
|
|
216
|
+
reviewedAt: 2026-10-06
|
|
217
|
+
reviewedAgainstContractHash: "0c4ab9435b20"
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Usage
|
|
221
|
+
|
|
222
|
+
Put a `CitationMarker` after each cited fact in the answer. It is a small
|
|
223
|
+
muted pill with the source kind's icon and number; opening it previews the publisher, date, title and the passage
|
|
224
|
+
used, with "Open" and, when `onShow` is set, "Show in sources". Wrap a claim
|
|
225
|
+
no source backs in `UnsupportedClaim` so it reads as the assistant's
|
|
226
|
+
estimate.
|
|
227
|
+
|
|
228
|
+
Under the answer, `SourceList` numbers the sources as `SourceCard`s with the
|
|
229
|
+
linked title, publisher, kind and date, an "Older than 6 months" badge past
|
|
230
|
+
`staleAfterDays`, and the passage. `initial` and `onExpand` fold long lists
|
|
231
|
+
behind "Show N more". Each source can carry a `kind` (`{ label, icon }`);
|
|
232
|
+
`SourceAvatar` shows that icon, for example stacked in a sources button.
|
|
233
|
+
`isStale` and `formatSourceDate` are exported.
|
|
234
|
+
|
|
235
|
+
## Anatomy
|
|
236
|
+
|
|
237
|
+
- `CitationMarker` - numbered inline marker with a source preview.
|
|
238
|
+
- `UnsupportedClaim` - dashed warning underline plus an explained warning icon.
|
|
239
|
+
- `SourceCard` - one numbered source with its passage.
|
|
240
|
+
- `SourceList` - ordered list of source cards with "Show N more".
|
|
241
|
+
- `SourceAvatar` - the source kind's icon in a small avatar.
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: combobox
|
|
6
|
+
sourceFile: packages/design-system/src/components/combobox.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-core-primitives
|
|
9
|
+
categoryFromBarrel: web-app-core-primitives
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: Combobox
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "({ items, value, onValueChange, onSelect, query: queryProp, onQueryChange, filter, startContent, emptyMessage, loading, loadingMessage, maxPerGroup, highlightMatches, placeholder, \"aria-label\": ariaLabel, id, name, size,...[truncated]"
|
|
16
|
+
- name: ComboboxItem
|
|
17
|
+
kind: type
|
|
18
|
+
- name: ComboboxProps
|
|
19
|
+
kind: type
|
|
20
|
+
- name: ComboboxSize
|
|
21
|
+
kind: type
|
|
22
|
+
- name: defaultComboboxFilter
|
|
23
|
+
kind: function
|
|
24
|
+
typeText: "(item: ComboboxItem, query: string) => boolean"
|
|
25
|
+
- name: groupComboboxItems
|
|
26
|
+
kind: function
|
|
27
|
+
typeText: "(items: ComboboxItem[], maxPerGroup?: number) => { name: string | undefined; items: ComboboxItem[]; }[]"
|
|
28
|
+
- name: nextEnabledIndex
|
|
29
|
+
kind: function
|
|
30
|
+
typeText: "(items: ComboboxItem[], from: number, direction: 1 | -1) => number"
|
|
31
|
+
- name: splitComboboxMatch
|
|
32
|
+
kind: function
|
|
33
|
+
typeText: "(text: string, query: string) => { before: string; match: string; after: string; }"
|
|
34
|
+
primaryExport: Combobox
|
|
35
|
+
subcomponents: []
|
|
36
|
+
props:
|
|
37
|
+
Combobox:
|
|
38
|
+
- name: aria-label
|
|
39
|
+
type: string
|
|
40
|
+
required: false
|
|
41
|
+
declaredIn: self
|
|
42
|
+
doc: "Accessible name. Required unless a <Label htmlFor={id}> names the input."
|
|
43
|
+
- name: className
|
|
44
|
+
type: string
|
|
45
|
+
required: false
|
|
46
|
+
declaredIn: self
|
|
47
|
+
- name: disabled
|
|
48
|
+
type: boolean
|
|
49
|
+
required: false
|
|
50
|
+
declaredIn: self
|
|
51
|
+
- name: emptyMessage
|
|
52
|
+
type: "((query: string) => ReactNode) | ReactNode"
|
|
53
|
+
required: false
|
|
54
|
+
declaredIn: self
|
|
55
|
+
doc: "Shown when the query matches nothing. Receives the trimmed query."
|
|
56
|
+
- name: filter
|
|
57
|
+
type: "((item: ComboboxItem, query: string) => boolean)"
|
|
58
|
+
required: false
|
|
59
|
+
declaredIn: self
|
|
60
|
+
doc: "Return true to keep an item. Default: case-insensitive match on label, description and keywords."
|
|
61
|
+
- name: highlightMatches
|
|
62
|
+
type: boolean
|
|
63
|
+
required: false
|
|
64
|
+
declaredIn: self
|
|
65
|
+
doc: "Bold the matched part of each label. Default true."
|
|
66
|
+
- name: id
|
|
67
|
+
type: string
|
|
68
|
+
required: false
|
|
69
|
+
declaredIn: self
|
|
70
|
+
- name: invalid
|
|
71
|
+
type: boolean
|
|
72
|
+
required: false
|
|
73
|
+
declaredIn: self
|
|
74
|
+
- name: items
|
|
75
|
+
type: "ComboboxItem[]"
|
|
76
|
+
required: true
|
|
77
|
+
declaredIn: self
|
|
78
|
+
- name: loading
|
|
79
|
+
type: boolean
|
|
80
|
+
required: false
|
|
81
|
+
declaredIn: self
|
|
82
|
+
doc: "Show a pending row instead of results, e.g. while fetching remote items."
|
|
83
|
+
- name: loadingMessage
|
|
84
|
+
type: ReactNode
|
|
85
|
+
required: false
|
|
86
|
+
declaredIn: self
|
|
87
|
+
- name: maxPerGroup
|
|
88
|
+
type: number
|
|
89
|
+
required: false
|
|
90
|
+
declaredIn: self
|
|
91
|
+
doc: "Cap the rows shown per group (or overall when ungrouped)."
|
|
92
|
+
- name: name
|
|
93
|
+
type: string
|
|
94
|
+
required: false
|
|
95
|
+
declaredIn: self
|
|
96
|
+
- name: onQueryChange
|
|
97
|
+
type: "((query: string) => void)"
|
|
98
|
+
required: false
|
|
99
|
+
declaredIn: self
|
|
100
|
+
- name: onSelect
|
|
101
|
+
type: "((item: ComboboxItem) => void)"
|
|
102
|
+
required: false
|
|
103
|
+
declaredIn: self
|
|
104
|
+
doc: "Called on every pick. Without `value`, the input clears after a pick (search launcher)."
|
|
105
|
+
- name: onValueChange
|
|
106
|
+
type: "((value: string | null) => void)"
|
|
107
|
+
required: false
|
|
108
|
+
declaredIn: self
|
|
109
|
+
- name: placeholder
|
|
110
|
+
type: string
|
|
111
|
+
required: false
|
|
112
|
+
declaredIn: self
|
|
113
|
+
- name: query
|
|
114
|
+
type: string
|
|
115
|
+
required: false
|
|
116
|
+
declaredIn: self
|
|
117
|
+
doc: "Controlled query. Leave unset to let the combobox own it."
|
|
118
|
+
- name: size
|
|
119
|
+
type: InputSize
|
|
120
|
+
required: false
|
|
121
|
+
declaredIn: self
|
|
122
|
+
- name: startContent
|
|
123
|
+
type: ReactNode
|
|
124
|
+
required: false
|
|
125
|
+
declaredIn: self
|
|
126
|
+
doc: "Shown instead of the item list while the query is empty, e.g. recent searches."
|
|
127
|
+
- name: value
|
|
128
|
+
type: string
|
|
129
|
+
required: false
|
|
130
|
+
declaredIn: self
|
|
131
|
+
doc: "Selected item's value. Set it (with onValueChange) for a picker that shows the choice in the input."
|
|
132
|
+
extendsProps: []
|
|
133
|
+
variants:
|
|
134
|
+
size:
|
|
135
|
+
kind: enum
|
|
136
|
+
options:
|
|
137
|
+
- sm
|
|
138
|
+
- md
|
|
139
|
+
- lg
|
|
140
|
+
default: md
|
|
141
|
+
on: Combobox
|
|
142
|
+
variantSource: prop-union
|
|
143
|
+
compoundVariants: []
|
|
144
|
+
sizeMaps:
|
|
145
|
+
- SIZE_TEXT
|
|
146
|
+
dataSlots:
|
|
147
|
+
- combobox
|
|
148
|
+
dependsOn:
|
|
149
|
+
internal:
|
|
150
|
+
- input
|
|
151
|
+
- spinner
|
|
152
|
+
lib:
|
|
153
|
+
- cn
|
|
154
|
+
hooks: []
|
|
155
|
+
external:
|
|
156
|
+
- "@radix-ui/react-popover"
|
|
157
|
+
- lucide-react
|
|
158
|
+
- react
|
|
159
|
+
contexts: []
|
|
160
|
+
stories:
|
|
161
|
+
- exportName: Default
|
|
162
|
+
id: components-combobox--default
|
|
163
|
+
- exportName: WithLabel
|
|
164
|
+
id: components-combobox--with-label
|
|
165
|
+
- exportName: SearchLauncher
|
|
166
|
+
id: components-combobox--search-launcher
|
|
167
|
+
- exportName: Loading
|
|
168
|
+
id: components-combobox--loading
|
|
169
|
+
- exportName: Invalid
|
|
170
|
+
id: components-combobox--invalid
|
|
171
|
+
- exportName: KeyboardSelection
|
|
172
|
+
id: components-combobox--keyboard-selection
|
|
173
|
+
- exportName: SearchSelection
|
|
174
|
+
id: components-combobox--search-selection
|
|
175
|
+
- exportName: RemoteResults
|
|
176
|
+
id: components-combobox--remote-results
|
|
177
|
+
storybookTitle: Components/Combobox
|
|
178
|
+
docsId: components-combobox--documentation
|
|
179
|
+
argTypeOptions: {}
|
|
180
|
+
resolvedCleanly: true
|
|
181
|
+
contractHash: b8d3d12095c6
|
|
182
|
+
factsHash: ec2144723e3f
|
|
183
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
184
|
+
status: beta
|
|
185
|
+
summary: "Text input with a filtered, keyboard-navigable list of options: a picker that keeps the chosen value, or a search launcher that clears after each pick."
|
|
186
|
+
useWhen:
|
|
187
|
+
- "a single choice from a list too long to scan in a Select, e.g. communities, projects or agents"
|
|
188
|
+
- "an app-wide search box that suggests grouped results while typing"
|
|
189
|
+
- "options load from a server as the user types, using query, onQueryChange and loading"
|
|
190
|
+
useInstead:
|
|
191
|
+
- id: select
|
|
192
|
+
when: "there are only a handful of options and typing to filter adds nothing"
|
|
193
|
+
- id: search
|
|
194
|
+
when: "the field filters a list already on the page and needs no suggestions"
|
|
195
|
+
- id: dropdown-menu
|
|
196
|
+
when: "the options are actions to run, not values to choose"
|
|
197
|
+
related:
|
|
198
|
+
- search
|
|
199
|
+
- select
|
|
200
|
+
- popover
|
|
201
|
+
a11y:
|
|
202
|
+
notes:
|
|
203
|
+
- "Implements the WAI-ARIA combobox pattern: role=combobox on the input, aria-expanded, aria-controls on the open listbox, and aria-activedescendant for the highlighted option. Focus never leaves the input."
|
|
204
|
+
- "Give it a name with aria-label, or with a <Label htmlFor={id}> and the id prop. Without either the input is announced only as 'combobox'."
|
|
205
|
+
- "The result count is announced through a polite live region while typing."
|
|
206
|
+
- "The trailing clear button is labelled 'Clear selection' in picker mode and 'Clear search' otherwise, and returns focus to the input."
|
|
207
|
+
- "Mark decorative item icons aria-hidden; the label is the option's accessible name."
|
|
208
|
+
keyboard:
|
|
209
|
+
- "ArrowDown / ArrowUp open the list and move through enabled options, wrapping at the ends; disabled options are skipped."
|
|
210
|
+
- "Home / End jump to the first or last enabled option while the list is open."
|
|
211
|
+
- "Enter picks the highlighted option. Typing highlights the first match, so Enter picks it straight away."
|
|
212
|
+
- "Escape closes the list and keeps the typed text; Tab closes it and moves on."
|
|
213
|
+
radixHandles: false
|
|
214
|
+
pitfalls:
|
|
215
|
+
- "Passing value turns on picker mode: the input shows the selected label and clearing it calls onValueChange(null). Leave value unset (undefined, not null) for a search launcher that clears after each pick."
|
|
216
|
+
- "startContent replaces the item list while the query is empty. Without it, an empty query lists every item, which suits a picker but not a large search index."
|
|
217
|
+
- "The default filter is a substring match on label, description and keywords. Pass filter for fuzzy or server-side matching, and set loading while results are fetched."
|
|
218
|
+
- "The list renders in a portal, so it is not clipped by overflow-hidden parents, but it also does not inherit their styles."
|
|
219
|
+
canonicalSnippet: |
|
|
220
|
+
import { Combobox } from "@adres/mgda-ui"
|
|
221
|
+
|
|
222
|
+
<Combobox
|
|
223
|
+
items={communities}
|
|
224
|
+
value={community}
|
|
225
|
+
onValueChange={setCommunity}
|
|
226
|
+
placeholder="Choose a community"
|
|
227
|
+
aria-label="Community"
|
|
228
|
+
/>
|
|
229
|
+
reviewedAt: 2026-10-05
|
|
230
|
+
reviewedAgainstContractHash: b8d3d12095c6
|
|
231
|
+
---
|
|
232
|
+
|
|
233
|
+
## Usage
|
|
234
|
+
|
|
235
|
+
`Combobox` is the DS answer whenever typing should narrow a list of options.
|
|
236
|
+
It has two modes, chosen by whether you pass `value`:
|
|
237
|
+
|
|
238
|
+
- **Picker** (`value` + `onValueChange`): the chosen option's label stays in
|
|
239
|
+
the input, the selected option is marked in the list, and clearing the input
|
|
240
|
+
clears the value. Use it in forms in place of a `Select` with many options.
|
|
241
|
+
- **Search launcher** (`onSelect` only): each pick fires `onSelect` and the
|
|
242
|
+
input clears for the next search. Pair it with `startContent` for recent
|
|
243
|
+
searches and `group` on items for sections such as Properties and Agents.
|
|
244
|
+
|
|
245
|
+
Items are plain data. `group` sections them in first-seen order (capped by
|
|
246
|
+
`maxPerGroup`), `description` adds trailing detail such as a price, `icon`
|
|
247
|
+
adds a leading visual, and `keywords` adds hidden match text, for example a
|
|
248
|
+
property's community.
|
|
249
|
+
|
|
250
|
+
### Remote results
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
<Combobox
|
|
254
|
+
items={results}
|
|
255
|
+
query={query}
|
|
256
|
+
onQueryChange={setQuery}
|
|
257
|
+
filter={() => true}
|
|
258
|
+
loading={isFetching}
|
|
259
|
+
onSelect={openResult}
|
|
260
|
+
aria-label="Search listings"
|
|
261
|
+
/>
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
Own the `query`, fetch on change, and pass `filter={() => true}` because the
|
|
265
|
+
server has already filtered.
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: countdown-pill
|
|
6
|
+
sourceFile: packages/design-system/src/components/countdown-pill.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-patterns
|
|
9
|
+
categoryFromBarrel: web-app-patterns
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: CountdownPill
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<CountdownPillProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: CountdownPillProps
|
|
17
|
+
kind: type
|
|
18
|
+
- name: CountdownSize
|
|
19
|
+
kind: type
|
|
20
|
+
- name: CountdownTone
|
|
21
|
+
kind: type
|
|
22
|
+
- name: getCountdownLabel
|
|
23
|
+
kind: function
|
|
24
|
+
typeText: "(dateIso: string, ongoingLabel: string, now?: number) => string"
|
|
25
|
+
primaryExport: CountdownPill
|
|
26
|
+
subcomponents: []
|
|
27
|
+
props:
|
|
28
|
+
CountdownPill:
|
|
29
|
+
- name: icon
|
|
30
|
+
type: ReactNode
|
|
31
|
+
required: false
|
|
32
|
+
declaredIn: self
|
|
33
|
+
doc: "Optional icon override. Defaults to a Clock glyph. Pass `null` to omit."
|
|
34
|
+
- name: label
|
|
35
|
+
type: string
|
|
36
|
+
required: false
|
|
37
|
+
declaredIn: self
|
|
38
|
+
doc: "Optional context label rendered before the value. e.g. `\"Starts in\"`, `\"Bidding ends in\"`."
|
|
39
|
+
- name: size
|
|
40
|
+
type: CountdownSize
|
|
41
|
+
required: false
|
|
42
|
+
declaredIn: self
|
|
43
|
+
doc: "Visual density."
|
|
44
|
+
- name: tone
|
|
45
|
+
type: CountdownTone
|
|
46
|
+
required: false
|
|
47
|
+
declaredIn: self
|
|
48
|
+
doc: "Visual urgency tier. Drives the value (and icon) color so the consumer can dial attention up or down without changing markup."
|
|
49
|
+
- name: value
|
|
50
|
+
type: string
|
|
51
|
+
required: true
|
|
52
|
+
declaredIn: self
|
|
53
|
+
doc: "The countdown text itself - the bit that gets emphasized. e.g. `\"2h 15m\"`, `\"3 days\"`, `\"Live now\"`."
|
|
54
|
+
extendsProps:
|
|
55
|
+
- "React.HTMLAttributes<HTMLDivElement>"
|
|
56
|
+
variants:
|
|
57
|
+
tone:
|
|
58
|
+
kind: enum
|
|
59
|
+
options:
|
|
60
|
+
- info
|
|
61
|
+
- success
|
|
62
|
+
- warning
|
|
63
|
+
- neutral
|
|
64
|
+
- critical
|
|
65
|
+
default: neutral
|
|
66
|
+
on: CountdownPill
|
|
67
|
+
size:
|
|
68
|
+
kind: enum
|
|
69
|
+
options:
|
|
70
|
+
- sm
|
|
71
|
+
- md
|
|
72
|
+
- lg
|
|
73
|
+
default: md
|
|
74
|
+
on: CountdownPill
|
|
75
|
+
variantSource: prop-union
|
|
76
|
+
compoundVariants: []
|
|
77
|
+
sizeMaps:
|
|
78
|
+
- GAP_CLASS
|
|
79
|
+
- ICON_CLASS
|
|
80
|
+
- LABEL_CLASS
|
|
81
|
+
- TONE_ICON
|
|
82
|
+
- TONE_VALUE
|
|
83
|
+
- VALUE_CLASS
|
|
84
|
+
dataSlots: []
|
|
85
|
+
dependsOn:
|
|
86
|
+
internal: []
|
|
87
|
+
lib:
|
|
88
|
+
- cn
|
|
89
|
+
hooks: []
|
|
90
|
+
external:
|
|
91
|
+
- lucide-react
|
|
92
|
+
- react
|
|
93
|
+
contexts: []
|
|
94
|
+
stories:
|
|
95
|
+
- exportName: Default
|
|
96
|
+
id: components-countdownpill--default
|
|
97
|
+
- exportName: Critical
|
|
98
|
+
id: components-countdownpill--critical
|
|
99
|
+
storybookTitle: Components/CountdownPill
|
|
100
|
+
docsId: components-countdownpill--documentation
|
|
101
|
+
argTypeOptions: {}
|
|
102
|
+
resolvedCleanly: true
|
|
103
|
+
contractHash: "8ad71d408603"
|
|
104
|
+
factsHash: "372ace40c571"
|
|
105
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
106
|
+
status: stable
|
|
107
|
+
summary: "An inline countdown display for time-to-event copy - a muted context label plus a large, tone-colored value, with a matching getCountdownLabel formatter."
|
|
108
|
+
useWhen:
|
|
109
|
+
- "showing time remaining until, or since, an event inline - session starts, deadlines, auction end times"
|
|
110
|
+
- "urgency should visually escalate as the deadline approaches, via tone"
|
|
111
|
+
useInstead:
|
|
112
|
+
- id: step-indicator
|
|
113
|
+
when: "the content is discrete steps in a process, not a countdown to a single point in time"
|
|
114
|
+
related:
|
|
115
|
+
- step-indicator
|
|
116
|
+
tokens:
|
|
117
|
+
- "--foreground"
|
|
118
|
+
- "--muted-foreground"
|
|
119
|
+
- "--primary"
|
|
120
|
+
- "--success-foreground"
|
|
121
|
+
- "--warning-foreground"
|
|
122
|
+
- "--destructive-foreground"
|
|
123
|
+
a11y:
|
|
124
|
+
notes:
|
|
125
|
+
- "Purely presentational text - no live region or ARIA is added, so a countdown that updates in place (e.g. on an interval) does not announce its own changes to screen readers. Wrap it in your own aria-live region if the live update itself needs to be announced, not just visible."
|
|
126
|
+
radixHandles: false
|
|
127
|
+
pitfalls:
|
|
128
|
+
- "CountdownPill is display-only - it does not tick down on its own or manage any timer. value is a static string recomputed and re-rendered by the caller, typically alongside getCountdownLabel on an interval."
|
|
129
|
+
- "tone is never inferred from the value or from time remaining - the component has no concept of how urgent a given duration is. Pick the tone in the consumer based on your own thresholds, and update it alongside value."
|
|
130
|
+
- "getCountdownLabel deliberately does not return a tone - it only formats the string (\"2h 15m\", \"3 days\", or your ongoingLabel). It will not also tell you how urgent that duration is."
|
|
131
|
+
canonicalSnippet: |
|
|
132
|
+
import { CountdownPill } from "@adres/mgda-ui"
|
|
133
|
+
|
|
134
|
+
<CountdownPill label="Starts in" value="2h 15m" tone="warning" />
|
|
135
|
+
reviewedAt: 2026-09-01
|
|
136
|
+
reviewedAgainstContractHash: "8ad71d408603"
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Usage
|
|
140
|
+
|
|
141
|
+
`CountdownPill` is for inline time-to-event copy - a session starting soon,
|
|
142
|
+
a bidding deadline, a limited-time offer. It pairs a muted context `label`
|
|
143
|
+
("Starts in") with a large, `tone`-colored `value` ("2h 15m") that raises
|
|
144
|
+
attention as urgency increases. Reach for `StepIndicator` instead when the
|
|
145
|
+
content is discrete steps in a process, not a countdown to one point in
|
|
146
|
+
time.
|
|
147
|
+
|
|
148
|
+
The component is presentational only - it has no timer of its own. Compute
|
|
149
|
+
`value` yourself - the paired `getCountdownLabel(dateIso, ongoingLabel)`
|
|
150
|
+
helper formats an ISO timestamp into `"2h 15m"`/`"3 days"`/your ongoing
|
|
151
|
+
label - and re-render on whatever interval you choose. `tone` is likewise
|
|
152
|
+
never inferred; pick it from your own urgency thresholds and update it
|
|
153
|
+
alongside `value`.
|