@adres/mgda-ui 0.0.0-stage → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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,177 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: inset
|
|
6
|
+
sourceFile: packages/design-system/src/components/inset.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: Inset
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<InsetProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: InsetClip
|
|
17
|
+
kind: type
|
|
18
|
+
- name: InsetProps
|
|
19
|
+
kind: type
|
|
20
|
+
- name: InsetSide
|
|
21
|
+
kind: type
|
|
22
|
+
primaryExport: Inset
|
|
23
|
+
subcomponents: []
|
|
24
|
+
props:
|
|
25
|
+
Inset:
|
|
26
|
+
- name: clip
|
|
27
|
+
type: InsetClip
|
|
28
|
+
required: false
|
|
29
|
+
declaredIn: self
|
|
30
|
+
doc: "Whether the content clips at the border or allows overflow. Default \"border-box\"."
|
|
31
|
+
- name: pb
|
|
32
|
+
type: "\"current\" | \"none\""
|
|
33
|
+
required: false
|
|
34
|
+
declaredIn: self
|
|
35
|
+
doc: "Add padding equal to the container's inset padding BELOW the element. Use with side=\"top\" to gap the inset away from siblings below it."
|
|
36
|
+
- name: pl
|
|
37
|
+
type: "\"current\" | \"none\""
|
|
38
|
+
required: false
|
|
39
|
+
declaredIn: self
|
|
40
|
+
doc: "Add padding equal to the container's inset padding LEFT of the element. Use with side=\"right\" to gap the inset away from siblings to its left."
|
|
41
|
+
- name: pr
|
|
42
|
+
type: "\"current\" | \"none\""
|
|
43
|
+
required: false
|
|
44
|
+
declaredIn: self
|
|
45
|
+
doc: "Add padding equal to the container's inset padding RIGHT of the element. Use with side=\"left\" to gap the inset away from siblings to its right."
|
|
46
|
+
- name: pt
|
|
47
|
+
type: "\"current\" | \"none\""
|
|
48
|
+
required: false
|
|
49
|
+
declaredIn: self
|
|
50
|
+
doc: "Add padding equal to the container's inset padding ABOVE the element. Use with side=\"bottom\" to gap the inset away from siblings above it."
|
|
51
|
+
- name: side
|
|
52
|
+
type: InsetSide
|
|
53
|
+
required: false
|
|
54
|
+
declaredIn: self
|
|
55
|
+
doc: "Which edges the content bleeds to. Named by the face of the container: \"top\" → bleeds to top, left, and right edges. \"left\" → bleeds to left, top, and bottom edges."
|
|
56
|
+
extendsProps:
|
|
57
|
+
- "React.HTMLAttributes<HTMLDivElement>"
|
|
58
|
+
variants:
|
|
59
|
+
side:
|
|
60
|
+
kind: enum
|
|
61
|
+
options:
|
|
62
|
+
- left
|
|
63
|
+
- right
|
|
64
|
+
- bottom
|
|
65
|
+
- top
|
|
66
|
+
- all
|
|
67
|
+
- x
|
|
68
|
+
- y
|
|
69
|
+
default: all
|
|
70
|
+
on: Inset
|
|
71
|
+
clip:
|
|
72
|
+
kind: enum
|
|
73
|
+
options:
|
|
74
|
+
- border-box
|
|
75
|
+
- padding-box
|
|
76
|
+
default: border-box
|
|
77
|
+
on: Inset
|
|
78
|
+
pt:
|
|
79
|
+
kind: enum
|
|
80
|
+
options:
|
|
81
|
+
- none
|
|
82
|
+
- current
|
|
83
|
+
default: none
|
|
84
|
+
on: Inset
|
|
85
|
+
pb:
|
|
86
|
+
kind: enum
|
|
87
|
+
options:
|
|
88
|
+
- none
|
|
89
|
+
- current
|
|
90
|
+
default: none
|
|
91
|
+
on: Inset
|
|
92
|
+
pl:
|
|
93
|
+
kind: enum
|
|
94
|
+
options:
|
|
95
|
+
- none
|
|
96
|
+
- current
|
|
97
|
+
default: none
|
|
98
|
+
on: Inset
|
|
99
|
+
pr:
|
|
100
|
+
kind: enum
|
|
101
|
+
options:
|
|
102
|
+
- none
|
|
103
|
+
- current
|
|
104
|
+
default: none
|
|
105
|
+
on: Inset
|
|
106
|
+
variantSource: prop-union
|
|
107
|
+
compoundVariants: []
|
|
108
|
+
sizeMaps: []
|
|
109
|
+
dataSlots: []
|
|
110
|
+
dependsOn:
|
|
111
|
+
internal: []
|
|
112
|
+
lib:
|
|
113
|
+
- cn
|
|
114
|
+
hooks: []
|
|
115
|
+
external:
|
|
116
|
+
- react
|
|
117
|
+
contexts: []
|
|
118
|
+
stories:
|
|
119
|
+
- exportName: Default
|
|
120
|
+
id: components-inset--default
|
|
121
|
+
storybookTitle: Components/Inset
|
|
122
|
+
docsId: components-inset--documentation
|
|
123
|
+
argTypeOptions: {}
|
|
124
|
+
resolvedCleanly: true
|
|
125
|
+
contractHash: "9ebe09dabae3"
|
|
126
|
+
factsHash: "2326dc7f0878"
|
|
127
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
128
|
+
status: stable
|
|
129
|
+
summary: "A layout helper that lets a child bleed past its Card's padding via negative margin, for full-bleed media or dividers inside a padded Card."
|
|
130
|
+
useWhen:
|
|
131
|
+
- "an image, banner, or divider inside a Card needs to visually touch the card's edges despite the card's own padding"
|
|
132
|
+
useInstead:
|
|
133
|
+
- id: card
|
|
134
|
+
when: "you need the actual bordered or elevated surface, not just the bleed helper used inside one"
|
|
135
|
+
related:
|
|
136
|
+
- card
|
|
137
|
+
a11y:
|
|
138
|
+
notes:
|
|
139
|
+
- "Inset only affects layout via negative margins and padding, so it carries no semantic role - the accessibility of its children is unaffected by using it."
|
|
140
|
+
radixHandles: false
|
|
141
|
+
pitfalls:
|
|
142
|
+
- "Inset reads --inset-padding from a Card ancestor's inline style - used outside a Card, or with no ancestor setting that variable, side has no visible effect because the negative margin falls back to var(--inset-padding, 0px), which resolves to 0."
|
|
143
|
+
- "side names the edges being bled TO, not the edge left alone - side=\"top\" bleeds the top, left, and right edges (all but the bottom), which reads backwards from what the name suggests."
|
|
144
|
+
canonicalSnippet: |
|
|
145
|
+
import { Card, CardContent, CardHeader, CardTitle, Inset } from "@adres/mgda-ui"
|
|
146
|
+
|
|
147
|
+
<Card className="ax:max-w-sm">
|
|
148
|
+
<CardHeader>
|
|
149
|
+
<CardTitle>Media card</CardTitle>
|
|
150
|
+
</CardHeader>
|
|
151
|
+
<Inset side="x" clip="padding-box">
|
|
152
|
+
<img src="/banner.jpg" alt="" className="ax:h-32 ax:w-full ax:object-cover" />
|
|
153
|
+
</Inset>
|
|
154
|
+
<CardContent>
|
|
155
|
+
<p>Content below the inset.</p>
|
|
156
|
+
</CardContent>
|
|
157
|
+
</Card>
|
|
158
|
+
reviewedAt: 2026-09-29
|
|
159
|
+
reviewedAgainstContractHash: "9ebe09dabae3"
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Usage
|
|
163
|
+
|
|
164
|
+
`Inset` is a layout helper, not a surface - it only exists to let content
|
|
165
|
+
break out of its container's padding via negative margin. It reads
|
|
166
|
+
`--inset-padding` from the nearest ancestor that sets it, currently only
|
|
167
|
+
`Card` (keyed off `Card`'s own `padding` prop), so it only does anything
|
|
168
|
+
meaningful nested inside a `Card`.
|
|
169
|
+
|
|
170
|
+
Reach for it to make a media block, banner image, or divider touch the edges
|
|
171
|
+
of an otherwise padded `Card`, without overriding the `Card`'s own padding for
|
|
172
|
+
the whole surface. `side` names the edge or edges being bled to, not the edge
|
|
173
|
+
being kept: `side="x"` bleeds left and right, `side="top"` bleeds top, left,
|
|
174
|
+
and right - all edges except the bottom.
|
|
175
|
+
|
|
176
|
+
Use `clip="padding-box"` (the default is `"border-box"`) when the bled content
|
|
177
|
+
should be allowed to overflow rather than clip at the container's edge.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: kpi-card
|
|
6
|
+
sourceFile: packages/design-system/src/components/kpi-card.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: KpiCard
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<KpiCardProps & RefAttributes<HTMLDivElement>>"
|
|
16
|
+
- name: KpiCardGroup
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<KpiCardGroupProps & RefAttributes<HTMLDivElement>>"
|
|
19
|
+
- name: KpiCardGroupProps
|
|
20
|
+
kind: type
|
|
21
|
+
- name: KpiCardProps
|
|
22
|
+
kind: type
|
|
23
|
+
- name: KpiCardSize
|
|
24
|
+
kind: type
|
|
25
|
+
primaryExport: KpiCard
|
|
26
|
+
subcomponents:
|
|
27
|
+
- KpiCardGroup
|
|
28
|
+
props:
|
|
29
|
+
KpiCard:
|
|
30
|
+
- name: change
|
|
31
|
+
type: number
|
|
32
|
+
required: false
|
|
33
|
+
declaredIn: self
|
|
34
|
+
doc: "Optional period-over-period delta as a percentage. Positive → success pill with an up-arrow; negative → destructive pill with a down-arrow. `0` and `undefined` both render no delta - zero isn't a trend."
|
|
35
|
+
- name: description
|
|
36
|
+
type: ReactNode
|
|
37
|
+
required: false
|
|
38
|
+
declaredIn: self
|
|
39
|
+
doc: "Optional context line under the value (e.g. \"vs last 30 days\")."
|
|
40
|
+
- name: icon
|
|
41
|
+
type: ReactNode
|
|
42
|
+
required: false
|
|
43
|
+
declaredIn: self
|
|
44
|
+
doc: "Optional topic icon - rendered muted, top-end of the card."
|
|
45
|
+
- name: loading
|
|
46
|
+
type: boolean
|
|
47
|
+
required: false
|
|
48
|
+
declaredIn: self
|
|
49
|
+
doc: "While true, swaps the title/value/delta for skeleton placeholders."
|
|
50
|
+
- name: size
|
|
51
|
+
type: KpiCardSize
|
|
52
|
+
required: false
|
|
53
|
+
declaredIn: self
|
|
54
|
+
doc: "Visual density. `md` is the default."
|
|
55
|
+
- name: suffix
|
|
56
|
+
type: string
|
|
57
|
+
required: false
|
|
58
|
+
declaredIn: self
|
|
59
|
+
doc: "Optional suffix appended to the value (e.g. \"%\", \"h\"). Rendered in a smaller muted style so it doesn't compete with the number."
|
|
60
|
+
- name: title
|
|
61
|
+
type: string
|
|
62
|
+
required: true
|
|
63
|
+
declaredIn: self
|
|
64
|
+
doc: "Overline label sitting above the value."
|
|
65
|
+
- name: value
|
|
66
|
+
type: "number | string"
|
|
67
|
+
required: true
|
|
68
|
+
declaredIn: self
|
|
69
|
+
doc: "The metric itself. Strings are useful for pre-formatted values (\"76 %\", \"1.2k\"). Numbers get a `0` fallback for the empty state."
|
|
70
|
+
KpiCardGroup:
|
|
71
|
+
- name: columns
|
|
72
|
+
type: "2 | 3 | 4"
|
|
73
|
+
required: false
|
|
74
|
+
declaredIn: self
|
|
75
|
+
doc: "Lay the cards out in a fixed N-column grid instead of a single flex row. With `compact`, the grid renders as a seamless bordered \"table\" - 1px hairline dividers between cells inside a rounded outer frame. Give a card `sm:col-span-*` to make a row span fewer, wider columns (e.g. a 4-column grid whose second row is two `col-span-2` cells)."
|
|
76
|
+
- name: compact
|
|
77
|
+
type: boolean
|
|
78
|
+
required: false
|
|
79
|
+
declaredIn: self
|
|
80
|
+
doc: "Merge children into a borderless single-block layout."
|
|
81
|
+
extendsProps:
|
|
82
|
+
- "React.HTMLAttributes<HTMLDivElement>"
|
|
83
|
+
variants:
|
|
84
|
+
size:
|
|
85
|
+
kind: enum
|
|
86
|
+
options:
|
|
87
|
+
- sm
|
|
88
|
+
- md
|
|
89
|
+
- lg
|
|
90
|
+
- mini
|
|
91
|
+
default: md
|
|
92
|
+
on: KpiCard
|
|
93
|
+
variantSource: prop-union
|
|
94
|
+
compoundVariants: []
|
|
95
|
+
sizeMaps:
|
|
96
|
+
- CARD_PADDING
|
|
97
|
+
- CONTENT_GAP
|
|
98
|
+
- GRID_COLS
|
|
99
|
+
- ICON_CLASS
|
|
100
|
+
- SKELETON_VALUE_HEIGHT
|
|
101
|
+
- SUFFIX_CLASS
|
|
102
|
+
- TREND_CLASS
|
|
103
|
+
- TREND_ICON_CLASS
|
|
104
|
+
- VALUE_CLASS
|
|
105
|
+
dataSlots: []
|
|
106
|
+
dependsOn:
|
|
107
|
+
internal:
|
|
108
|
+
- card
|
|
109
|
+
- skeleton
|
|
110
|
+
lib:
|
|
111
|
+
- cn
|
|
112
|
+
hooks: []
|
|
113
|
+
external:
|
|
114
|
+
- lucide-react
|
|
115
|
+
- react
|
|
116
|
+
contexts:
|
|
117
|
+
- name: KpiCardGroupContext
|
|
118
|
+
type: KpiCardGroupContextValue
|
|
119
|
+
default: null
|
|
120
|
+
stories:
|
|
121
|
+
- exportName: Default
|
|
122
|
+
id: components-kpicard--default
|
|
123
|
+
- exportName: Loading
|
|
124
|
+
id: components-kpicard--loading
|
|
125
|
+
storybookTitle: Components/KpiCard
|
|
126
|
+
docsId: components-kpicard--documentation
|
|
127
|
+
argTypeOptions: {}
|
|
128
|
+
resolvedCleanly: true
|
|
129
|
+
contractHash: f7cb46ea7ce2
|
|
130
|
+
factsHash: "6fcc8d61857b"
|
|
131
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
132
|
+
status: stable
|
|
133
|
+
summary: "A single-metric dashboard card - a big number, label, optional trend delta, icon, and description, with a built-in loading and empty state."
|
|
134
|
+
useWhen:
|
|
135
|
+
- "showing one key metric on a dashboard, prominently, with an optional period-over-period trend"
|
|
136
|
+
- "several metrics need to read as one connected block, via KpiCardGroup, optionally compact and/or gridded"
|
|
137
|
+
useInstead:
|
|
138
|
+
- id: card
|
|
139
|
+
when: "the content is not a single headline metric - use plain Card for general-purpose containers"
|
|
140
|
+
- id: data-list
|
|
141
|
+
when: "showing several label/value pairs together, not one prominent metric per card"
|
|
142
|
+
- id: stats
|
|
143
|
+
when: "presenting metrics in a marketing/landing-page context rather than a dashboard"
|
|
144
|
+
related:
|
|
145
|
+
- card
|
|
146
|
+
- data-list
|
|
147
|
+
- stats
|
|
148
|
+
tokens:
|
|
149
|
+
- "--success-foreground"
|
|
150
|
+
- "--destructive-foreground"
|
|
151
|
+
- "--muted-foreground"
|
|
152
|
+
- "--foreground"
|
|
153
|
+
- "--card"
|
|
154
|
+
- "--border"
|
|
155
|
+
a11y:
|
|
156
|
+
notes:
|
|
157
|
+
- "loading swaps content for Skeleton placeholders (aria-hidden, per Skeleton's own contract) - pair a KpiCard's loading state with a real loading announcement elsewhere, e.g. an aria-live region on the dashboard, if the fetch itself needs to be announced."
|
|
158
|
+
- "Making the card clickable (passing onClick) only changes hover styling and cursor - it does not add button or link semantics or keyboard activation on its own. Wrap it in a real interactive element, or add role/tabIndex/keyboard handling directly, if it should truly be operable."
|
|
159
|
+
radixHandles: false
|
|
160
|
+
pitfalls:
|
|
161
|
+
- "The empty state (\"No data yet\") triggers purely from value coercing to 0 - a metric that is legitimately zero (e.g. \"0 open incidents\", a good result) shows the empty-state message instead of \"0\" unless routed around with a formatted string value that does not coerce to exactly 0."
|
|
162
|
+
- "change of exactly 0 renders no trend at all, the same as change={undefined} - there is no neutral or flat trend indicator; a genuinely flat period-over-period reads identically to no data available for the trend row."
|
|
163
|
+
- "KpiCardGroup's compact and columns interact: compact alone merges cards into one flush row or column; compact plus columns renders a seamless bordered grid table instead, and cards inside drop essentially all their own chrome (border, radius, shadow) since the group draws it. Setting size or padding on an individual card inside a compact group has a smaller visual effect than expected."
|
|
164
|
+
- "The hover-lift interactive behavior is automatically suppressed for compact cards even if onClick is passed - compact cards never lift on hover, regardless of interactivity."
|
|
165
|
+
canonicalSnippet: |
|
|
166
|
+
import { KpiCard, KpiCardGroup } from "@adres/mgda-ui"
|
|
167
|
+
|
|
168
|
+
const metricTitle = "Active users"
|
|
169
|
+
const periodLabel = "vs last 30 days"
|
|
170
|
+
|
|
171
|
+
<KpiCardGroup className="ax:max-w-xs">
|
|
172
|
+
<KpiCard title={metricTitle} value={1284} change={12} description={periodLabel} />
|
|
173
|
+
</KpiCardGroup>
|
|
174
|
+
reviewedAt: 2026-09-01
|
|
175
|
+
reviewedAgainstContractHash: f7cb46ea7ce2
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Usage
|
|
179
|
+
|
|
180
|
+
`KpiCard` is a single-metric dashboard card - a big `value` under a `title`
|
|
181
|
+
label, with an optional trend `change` (a success or destructive pill with
|
|
182
|
+
an up or down arrow), a topic `icon`, and a `description` line. Reach for
|
|
183
|
+
plain `Card` when the content is not one headline metric, `DataList` for
|
|
184
|
+
several label/value pairs together rather than one prominent number per
|
|
185
|
+
card, and `Stats` for a marketing or landing-page metrics context instead of
|
|
186
|
+
a dashboard.
|
|
187
|
+
|
|
188
|
+
Always wrap `KpiCard`s in `KpiCardGroup`, even for a single card - it
|
|
189
|
+
supplies the responsive grid or row layout and the `compact`/`columns`
|
|
190
|
+
context every card reads from. `compact` merges cards into one flush block
|
|
191
|
+
with shared borders instead of separate cards; `compact` plus `columns` goes
|
|
192
|
+
further, rendering a seamless bordered grid table where cards drop their own
|
|
193
|
+
chrome entirely.
|
|
194
|
+
|
|
195
|
+
Set `loading` to swap the title, value, and trend for `Skeleton`
|
|
196
|
+
placeholders while data is in flight. The built-in empty state ("No data
|
|
197
|
+
yet") triggers automatically whenever `value` coerces to exactly `0` and no
|
|
198
|
+
`change` is given - a legitimately-zero metric needs a formatted string
|
|
199
|
+
`value` to avoid reading as "no data."
|
|
200
|
+
|
|
201
|
+
## Anatomy
|
|
202
|
+
|
|
203
|
+
| Part | Role |
|
|
204
|
+
| --- | --- |
|
|
205
|
+
| `KpiCardGroup` | Layout wrapper. Owns `compact` and `columns`, shared with every `KpiCard` inside via context. |
|
|
206
|
+
| `KpiCard` | One metric. Built on `Card` and `Skeleton` internally; owns `title`, `value`, `change`, `suffix`, `icon`, `description`, `size`, `loading`. |
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: list-nav
|
|
6
|
+
sourceFile: packages/design-system/src/components/list-nav.tsx
|
|
7
|
+
client: true
|
|
8
|
+
category: web-app-layout-navigation
|
|
9
|
+
categoryFromBarrel: web-app-layout-navigation
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: ListNav
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "ForwardRefExoticComponent<ListNavProps & RefAttributes<HTMLElement>>"
|
|
16
|
+
- name: ListNavItem
|
|
17
|
+
kind: component
|
|
18
|
+
typeText: "ForwardRefExoticComponent<ListNavItemProps & RefAttributes<HTMLButtonElement>>"
|
|
19
|
+
- name: ListNavItemProps
|
|
20
|
+
kind: type
|
|
21
|
+
- name: ListNavProps
|
|
22
|
+
kind: type
|
|
23
|
+
- name: ListNavSize
|
|
24
|
+
kind: type
|
|
25
|
+
primaryExport: ListNav
|
|
26
|
+
subcomponents:
|
|
27
|
+
- ListNavItem
|
|
28
|
+
props:
|
|
29
|
+
ListNav:
|
|
30
|
+
- name: size
|
|
31
|
+
type: ListNavSize
|
|
32
|
+
required: false
|
|
33
|
+
declaredIn: self
|
|
34
|
+
doc: "Row density. `base` (default) is compact; `lg` adds padding for a larger, touch-friendly tap target. Cascades to all items via context."
|
|
35
|
+
- name: title
|
|
36
|
+
type: ReactNode
|
|
37
|
+
required: false
|
|
38
|
+
declaredIn: self
|
|
39
|
+
doc: "Optional eyebrow-style title rendered above the list (uses `t-overline`)."
|
|
40
|
+
ListNavItem:
|
|
41
|
+
- name: active
|
|
42
|
+
type: boolean
|
|
43
|
+
required: false
|
|
44
|
+
declaredIn: self
|
|
45
|
+
- name: asChild
|
|
46
|
+
type: boolean
|
|
47
|
+
required: false
|
|
48
|
+
declaredIn: self
|
|
49
|
+
doc: "Render as the child element (e.g. a Next.js `<Link>`). The child receives the className, ref, and event props so it behaves as a list-nav row while keeping its own navigation behaviour."
|
|
50
|
+
- name: icon
|
|
51
|
+
type: ReactNode
|
|
52
|
+
required: false
|
|
53
|
+
declaredIn: self
|
|
54
|
+
doc: "Optional leading icon."
|
|
55
|
+
- name: inset
|
|
56
|
+
type: boolean
|
|
57
|
+
required: false
|
|
58
|
+
declaredIn: self
|
|
59
|
+
doc: "Reserves the leading icon column even when no icon is provided. Use when mixing items with and without icons in the same list, so labels stay aligned. Has no effect if `icon` is set."
|
|
60
|
+
- name: size
|
|
61
|
+
type: ListNavSize
|
|
62
|
+
required: false
|
|
63
|
+
declaredIn: self
|
|
64
|
+
doc: "Overrides the row density inherited from `ListNav` for this item."
|
|
65
|
+
- name: trailing
|
|
66
|
+
type: ReactNode
|
|
67
|
+
required: false
|
|
68
|
+
declaredIn: self
|
|
69
|
+
doc: "Trailing slot - typically a Badge, count, or shortcut hint."
|
|
70
|
+
extendsProps:
|
|
71
|
+
- "Omit<React.HTMLAttributes<HTMLElement>, \"title\">"
|
|
72
|
+
variants:
|
|
73
|
+
size:
|
|
74
|
+
kind: enum
|
|
75
|
+
options:
|
|
76
|
+
- base
|
|
77
|
+
- lg
|
|
78
|
+
default: base
|
|
79
|
+
on: ListNav
|
|
80
|
+
variantSource: prop-union
|
|
81
|
+
compoundVariants: []
|
|
82
|
+
sizeMaps:
|
|
83
|
+
- ICON_BOX
|
|
84
|
+
- ITEM_SIZE
|
|
85
|
+
dataSlots: []
|
|
86
|
+
dependsOn:
|
|
87
|
+
internal: []
|
|
88
|
+
lib:
|
|
89
|
+
- cn
|
|
90
|
+
hooks: []
|
|
91
|
+
external:
|
|
92
|
+
- "@radix-ui/react-slot"
|
|
93
|
+
- react
|
|
94
|
+
contexts:
|
|
95
|
+
- name: ListNavContext
|
|
96
|
+
type: ListNavContextValue
|
|
97
|
+
default: null
|
|
98
|
+
stories:
|
|
99
|
+
- exportName: Default
|
|
100
|
+
id: components-listnav--default
|
|
101
|
+
storybookTitle: Components/ListNav
|
|
102
|
+
docsId: components-listnav--documentation
|
|
103
|
+
argTypeOptions: {}
|
|
104
|
+
resolvedCleanly: true
|
|
105
|
+
contractHash: "9439cca1c18c"
|
|
106
|
+
factsHash: "0e2c0b22a60d"
|
|
107
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
108
|
+
status: stable
|
|
109
|
+
summary: "A vertical list of selectable items, for in-page jumpers and dense filter lists without an icon-column app-shell nav."
|
|
110
|
+
useWhen:
|
|
111
|
+
- "an in-page section jumper or table-of-contents style list"
|
|
112
|
+
- "a dense filter or facet list (categories, saved views, settings sections)"
|
|
113
|
+
- "a sidebar-adjacent list of selectable rows that doesn't need brand/collapse/tooltips"
|
|
114
|
+
useInstead:
|
|
115
|
+
- id: sidebar
|
|
116
|
+
when: "you need the full app-shell chrome - brand slot, collapse-to-icon-rail, tooltips on collapse"
|
|
117
|
+
- id: nav-sidebar
|
|
118
|
+
when: "the list is a primary app nav driven by the current route, with nested children"
|
|
119
|
+
- id: cards-nav
|
|
120
|
+
when: "each destination deserves a bigger, card-style target with a description, not a compact row"
|
|
121
|
+
related:
|
|
122
|
+
- sidebar
|
|
123
|
+
- cards-nav
|
|
124
|
+
composesWith:
|
|
125
|
+
- badge
|
|
126
|
+
tokens:
|
|
127
|
+
- "--input-radius"
|
|
128
|
+
- "--primary-muted"
|
|
129
|
+
- "--primary-foreground"
|
|
130
|
+
- "--primary-strong"
|
|
131
|
+
- "--muted"
|
|
132
|
+
- "--muted-foreground"
|
|
133
|
+
- "--ring"
|
|
134
|
+
a11y:
|
|
135
|
+
notes:
|
|
136
|
+
- "ListNavItem renders a real <button type=\"button\"> by default, so it's keyboard-reachable and activatable without any extra wiring."
|
|
137
|
+
- "active sets aria-current=\"page\" - use it for the currently selected/viewed item, not just a visual highlight."
|
|
138
|
+
- "asChild switches the rendered element to the child (e.g. a router Link); type is correctly omitted in that case since type is invalid on a non-button element."
|
|
139
|
+
requiredProps: []
|
|
140
|
+
keyboard:
|
|
141
|
+
- "Native button semantics: Enter and Space activate, Tab order is automatic."
|
|
142
|
+
- "asChild hands semantics to the child - wrapping an anchor makes it a link, and Space no longer activates it."
|
|
143
|
+
radixHandles: false
|
|
144
|
+
pitfalls:
|
|
145
|
+
- "size on ListNav only sets the default for items via context; an item can still override it with its own size prop, so an unexpectedly-sized row is usually an explicit override, not a bug in the list."
|
|
146
|
+
- "inset has no effect once icon is set - it only exists to reserve the icon column's width for rows that intentionally have no icon, so sibling labels stay aligned."
|
|
147
|
+
- "ListNav renders a title inside the same <nav>, not a separate landmark - stacking multiple ListNavs for grouped sections means multiple <nav> elements, which is intentional but worth knowing before adding a wrapping <nav> of your own."
|
|
148
|
+
subcomponentNotes:
|
|
149
|
+
ListNavItem: "A single row. Reads its density from the parent ListNav's size via context unless overridden. trailing is typically a Badge, count, or keyboard shortcut hint."
|
|
150
|
+
rtl: "Uses text-start and gap-based spacing throughout, so rows flip correctly under RTL with no extra work."
|
|
151
|
+
canonicalSnippet: |
|
|
152
|
+
import { ListNav, ListNavItem } from "@adres/mgda-ui"
|
|
153
|
+
import { Home, Settings } from "lucide-react"
|
|
154
|
+
|
|
155
|
+
<ListNav title="Workspace">
|
|
156
|
+
<ListNavItem icon={<Home />} active>Overview</ListNavItem>
|
|
157
|
+
<ListNavItem icon={<Settings />}>Settings</ListNavItem>
|
|
158
|
+
</ListNav>
|
|
159
|
+
reviewedAt: 2026-08-31
|
|
160
|
+
reviewedAgainstContractHash: "9439cca1c18c"
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Usage
|
|
164
|
+
|
|
165
|
+
ListNav is a lighter-weight alternative to `Sidebar`/`NavSidebar`: a vertical
|
|
166
|
+
list of rows with an optional eyebrow title, no brand slot, no collapse
|
|
167
|
+
behavior, no built-in routing. Reach for it when you need selectable rows -
|
|
168
|
+
an in-page jumper, a filter list, a settings sub-nav - without the full
|
|
169
|
+
app-shell machinery.
|
|
170
|
+
|
|
171
|
+
`size` cascades from `ListNav` to every `ListNavItem` via context, so setting
|
|
172
|
+
it once on the list sets the density for the whole group; an individual item
|
|
173
|
+
can still opt out with its own `size`.
|
|
174
|
+
|
|
175
|
+
## Anatomy
|
|
176
|
+
|
|
177
|
+
- **ListNav** - the list wrapper: an optional overline `title`, then the
|
|
178
|
+
items in a flex column.
|
|
179
|
+
- **ListNavItem** - a single row: optional leading icon, label, optional
|
|
180
|
+
trailing slot. `active` renders the tinted/bold selected state and sets
|
|
181
|
+
`aria-current="page"`.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
# >>> DERIVED - regenerated by `npm run knowledge:sync`. Do not edit. <<<
|
|
3
|
+
derived:
|
|
4
|
+
schemaVersion: 1
|
|
5
|
+
id: logo-cloud
|
|
6
|
+
sourceFile: packages/design-system/src/components/logo-cloud.tsx
|
|
7
|
+
client: false
|
|
8
|
+
category: marketing
|
|
9
|
+
categoryFromBarrel: marketing
|
|
10
|
+
barrelExported: true
|
|
11
|
+
importPath: "@adres/mgda-ui"
|
|
12
|
+
exports:
|
|
13
|
+
- name: LogoCloud
|
|
14
|
+
kind: component
|
|
15
|
+
typeText: "({ className, eyebrow, items, ...props }: LogoCloudProps) => Element"
|
|
16
|
+
- name: LogoCloudItem
|
|
17
|
+
kind: type
|
|
18
|
+
- name: LogoCloudProps
|
|
19
|
+
kind: type
|
|
20
|
+
primaryExport: LogoCloud
|
|
21
|
+
subcomponents: []
|
|
22
|
+
props:
|
|
23
|
+
LogoCloud:
|
|
24
|
+
- name: eyebrow
|
|
25
|
+
type: ReactNode
|
|
26
|
+
required: false
|
|
27
|
+
declaredIn: self
|
|
28
|
+
- name: items
|
|
29
|
+
type: "LogoCloudItem[]"
|
|
30
|
+
required: true
|
|
31
|
+
declaredIn: self
|
|
32
|
+
extendsProps:
|
|
33
|
+
- "React.HTMLAttributes<HTMLElement>"
|
|
34
|
+
variants: {}
|
|
35
|
+
variantSource: none
|
|
36
|
+
compoundVariants: []
|
|
37
|
+
sizeMaps: []
|
|
38
|
+
dataSlots: []
|
|
39
|
+
dependsOn:
|
|
40
|
+
internal: []
|
|
41
|
+
lib:
|
|
42
|
+
- cn
|
|
43
|
+
hooks: []
|
|
44
|
+
external:
|
|
45
|
+
- react
|
|
46
|
+
contexts: []
|
|
47
|
+
stories:
|
|
48
|
+
- exportName: Default
|
|
49
|
+
id: components-logocloud--default
|
|
50
|
+
storybookTitle: Components/LogoCloud
|
|
51
|
+
docsId: components-logocloud--documentation
|
|
52
|
+
argTypeOptions: {}
|
|
53
|
+
resolvedCleanly: true
|
|
54
|
+
contractHash: b7598f5dedbe
|
|
55
|
+
factsHash: "783b49aab241"
|
|
56
|
+
# >>> AUTHORED - humans own everything below this line. <<<
|
|
57
|
+
status: stable
|
|
58
|
+
summary: "A trust-signal strip of partner or customer logos in a responsive grid, each dimmed to grayscale until hovered."
|
|
59
|
+
useWhen:
|
|
60
|
+
- "showing a set of partner, customer, or press logos as social proof - typically near a hero or footer"
|
|
61
|
+
useInstead:
|
|
62
|
+
- id: footer
|
|
63
|
+
when: "the section is page navigation and legal content, not a logo trust-signal strip"
|
|
64
|
+
related:
|
|
65
|
+
- footer
|
|
66
|
+
a11y:
|
|
67
|
+
notes:
|
|
68
|
+
- "Each logo cell sets a title attribute on its wrapper div, which surfaces as a native hover tooltip in most browsers but is not read by most screen readers on a non-interactive div - if the logos need to be genuinely accessible rather than decorative, give item.logo itself proper alt text or an aria-label, do not rely on the wrapper's title."
|
|
69
|
+
radixHandles: false
|
|
70
|
+
pitfalls:
|
|
71
|
+
- "Every logo renders at reduced opacity and grayscale until hover, by design - a logo passed as a colored image or SVG still visually reads as muted at rest, which is expected here, not a bug to fix by overriding the item's own styling."
|
|
72
|
+
- "The grid is a fixed responsive column count, 2 at mobile up through 6 at lg - there is no columns prop to override it, unlike FeatureGrid or KpiCardGroup which do expose one."
|
|
73
|
+
- "item.logo is fully caller-supplied content, usually an image or inline SVG - LogoCloud itself sets no width or height constraints on it beyond the grid cell, so an unconstrained logo image can render inconsistently sized next to its neighbors unless each logo is pre-sized similarly."
|
|
74
|
+
canonicalSnippet: |
|
|
75
|
+
import { LogoCloud } from "@adres/mgda-ui"
|
|
76
|
+
|
|
77
|
+
const partners = [
|
|
78
|
+
{ name: "Acme", logo: <img src="/logos/acme.svg" alt="Acme" /> },
|
|
79
|
+
{ name: "Globex", logo: <img src="/logos/globex.svg" alt="Globex" /> },
|
|
80
|
+
]
|
|
81
|
+
const eyebrowText = "Trusted by teams worldwide"
|
|
82
|
+
|
|
83
|
+
<LogoCloud items={partners} eyebrow={eyebrowText} />
|
|
84
|
+
reviewedAt: 2026-09-01
|
|
85
|
+
reviewedAgainstContractHash: b7598f5dedbe
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Usage
|
|
89
|
+
|
|
90
|
+
`LogoCloud` shows a set of partner, customer, or press logos as social
|
|
91
|
+
proof, typically near a hero section or a footer. Reach for `Footer`
|
|
92
|
+
instead when the section is page navigation and legal content rather than a
|
|
93
|
+
logo trust-signal strip.
|
|
94
|
+
|
|
95
|
+
Every logo renders at reduced opacity and grayscale until hover, by design -
|
|
96
|
+
this happens regardless of the logo's own colors, so a colored image will
|
|
97
|
+
still read as muted at rest.
|
|
98
|
+
|
|
99
|
+
The grid's column count is fixed and responsive (2 at mobile up through 6 at
|
|
100
|
+
`lg`) with no override prop, unlike `FeatureGrid`'s `columns`. Pre-size each
|
|
101
|
+
`item.logo` similarly, since the component itself sets no width or height
|
|
102
|
+
constraint on the logo content beyond the grid cell.
|