@coinbase/cds-mcp-server 8.28.1 → 8.29.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/CHANGELOG.md +8 -0
- package/mcp-docs/mobile/components/Accordion.txt +3 -1
- package/mcp-docs/mobile/components/Alert.txt +3 -1
- package/mcp-docs/mobile/components/Banner.txt +14 -14
- package/mcp-docs/mobile/components/Button.txt +173 -30
- package/mcp-docs/mobile/components/Carousel.txt +24 -24
- package/mcp-docs/mobile/components/Combobox.txt +187 -0
- package/mcp-docs/mobile/components/ContainedAssetCard.txt +4 -4
- package/mcp-docs/mobile/components/ContentCard.txt +29 -27
- package/mcp-docs/mobile/components/ContentCardBody.txt +4 -4
- package/mcp-docs/mobile/components/ContentCardHeader.txt +2 -2
- package/mcp-docs/mobile/components/FloatingAssetCard.txt +6 -6
- package/mcp-docs/mobile/components/IconButton.txt +126 -51
- package/mcp-docs/mobile/components/LineChart.txt +3 -2
- package/mcp-docs/mobile/components/MultiContentModule.txt +6 -6
- package/mcp-docs/mobile/components/Numpad.txt +2 -2
- package/mcp-docs/mobile/components/PageHeader.txt +3 -1
- package/mcp-docs/mobile/components/PeriodSelector.txt +4 -4
- package/mcp-docs/mobile/components/Pressable.txt +6 -2
- package/mcp-docs/mobile/components/ProgressBarWithFixedLabels.txt +4 -4
- package/mcp-docs/mobile/components/ProgressBarWithFloatLabel.txt +2 -2
- package/mcp-docs/mobile/components/ProgressCircle.txt +5 -1
- package/mcp-docs/mobile/components/SelectChip.txt +2 -0
- package/mcp-docs/mobile/components/SelectChipAlpha.txt +1 -1
- package/mcp-docs/mobile/components/SlideButton.txt +2 -2
- package/mcp-docs/mobile/components/Sparkline.txt +3 -1
- package/mcp-docs/mobile/components/SparklineGradient.txt +3 -1
- package/mcp-docs/mobile/components/SparklineInteractiveHeader.txt +3 -1
- package/mcp-docs/mobile/components/TabbedChips.txt +3 -1
- package/mcp-docs/mobile/components/Tag.txt +19 -9
- package/mcp-docs/mobile/components/TextInput.txt +9 -3
- package/mcp-docs/mobile/components/Tray.txt +2 -0
- package/mcp-docs/mobile/components/UpsellCard.txt +16 -16
- package/mcp-docs/mobile/hooks/useDimensions.txt +4 -4
- package/mcp-docs/mobile/hooks/useMergeRefs.txt +4 -4
- package/mcp-docs/mobile/hooks/usePreviousValue.txt +5 -5
- package/mcp-docs/mobile/hooks/useRefMap.txt +6 -6
- package/mcp-docs/mobile/routes.txt +1 -0
- package/mcp-docs/web/components/Accordion.txt +3 -1
- package/mcp-docs/web/components/Alert.txt +3 -1
- package/mcp-docs/web/components/Banner.txt +14 -14
- package/mcp-docs/web/components/Button.txt +188 -34
- package/mcp-docs/web/components/Carousel.txt +71 -65
- package/mcp-docs/web/components/Combobox.txt +176 -0
- package/mcp-docs/web/components/ContainedAssetCard.txt +4 -4
- package/mcp-docs/web/components/ContentCard.txt +29 -27
- package/mcp-docs/web/components/ContentCardBody.txt +4 -4
- package/mcp-docs/web/components/ContentCardHeader.txt +2 -2
- package/mcp-docs/web/components/FloatingAssetCard.txt +6 -6
- package/mcp-docs/web/components/FullscreenModal.txt +12 -4
- package/mcp-docs/web/components/GridColumn.txt +12 -4
- package/mcp-docs/web/components/IconButton.txt +164 -189
- package/mcp-docs/web/components/LineChart.txt +3 -2
- package/mcp-docs/web/components/MultiContentModule.txt +6 -6
- package/mcp-docs/web/components/PageHeader.txt +11 -9
- package/mcp-docs/web/components/ProgressBarWithFixedLabels.txt +4 -4
- package/mcp-docs/web/components/ProgressBarWithFloatLabel.txt +2 -2
- package/mcp-docs/web/components/ProgressCircle.txt +5 -1
- package/mcp-docs/web/components/SelectChipAlpha.txt +1 -1
- package/mcp-docs/web/components/Sidebar.txt +2 -2
- package/mcp-docs/web/components/Sparkline.txt +3 -1
- package/mcp-docs/web/components/SparklineGradient.txt +3 -1
- package/mcp-docs/web/components/SparklineInteractiveHeader.txt +3 -1
- package/mcp-docs/web/components/TabbedChips.txt +3 -1
- package/mcp-docs/web/components/TableBody.txt +2 -2
- package/mcp-docs/web/components/TableCaption.txt +2 -2
- package/mcp-docs/web/components/TableCell.txt +6 -6
- package/mcp-docs/web/components/Tag.txt +19 -9
- package/mcp-docs/web/components/TextInput.txt +9 -3
- package/mcp-docs/web/components/Tray.txt +2 -1
- package/mcp-docs/web/components/UpsellCard.txt +16 -16
- package/mcp-docs/web/hooks/useDimensions.txt +4 -4
- package/mcp-docs/web/hooks/useHasMounted.txt +7 -3
- package/mcp-docs/web/hooks/useIsoEffect.txt +1 -1
- package/mcp-docs/web/hooks/useMergeRefs.txt +4 -4
- package/mcp-docs/web/hooks/useOverlayContentContext.txt +8 -8
- package/mcp-docs/web/hooks/usePreviousValue.txt +5 -5
- package/mcp-docs/web/hooks/useRefMap.txt +6 -6
- package/mcp-docs/web/hooks/useScrollBlocker.txt +1 -1
- package/mcp-docs/web/hooks/useTheme.txt +3 -3
- package/mcp-docs/web/routes.txt +1 -0
- package/package.json +1 -1
|
@@ -32,9 +32,9 @@ function MyCarousel() {
|
|
|
32
32
|
return (
|
|
33
33
|
<ContainedAssetCard
|
|
34
34
|
description={
|
|
35
|
-
<
|
|
35
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
36
36
|
↗6.37%
|
|
37
|
-
</
|
|
37
|
+
</Text>
|
|
38
38
|
}
|
|
39
39
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
40
40
|
subtitle={name}
|
|
@@ -113,7 +113,9 @@ function DynamicSizingCarousel() {
|
|
|
113
113
|
return (
|
|
114
114
|
<VStack gap={2}>
|
|
115
115
|
<HStack justifyContent="flex-end" gap={2} alignItems="center">
|
|
116
|
-
<
|
|
116
|
+
<Text as="h3" font="headline">
|
|
117
|
+
Items per page
|
|
118
|
+
</Text>
|
|
117
119
|
<SegmentedTabs
|
|
118
120
|
activeTab={selectedItemsPerPage}
|
|
119
121
|
onChange={setSelectedItemsPerPage}
|
|
@@ -146,9 +148,9 @@ function DynamicSizingCarousel() {
|
|
|
146
148
|
}
|
|
147
149
|
minWidth="0"
|
|
148
150
|
title={
|
|
149
|
-
<
|
|
151
|
+
<Text as="h3" font="headline" id="recurring-buy-label">
|
|
150
152
|
Recurring Buy
|
|
151
|
-
</
|
|
153
|
+
</Text>
|
|
152
154
|
}
|
|
153
155
|
width="100%"
|
|
154
156
|
/>
|
|
@@ -164,9 +166,9 @@ function DynamicSizingCarousel() {
|
|
|
164
166
|
action={<ActionButton isVisible={isVisible}>Start earning</ActionButton>}
|
|
165
167
|
dangerouslySetBackground="rgb(var(--purple70))"
|
|
166
168
|
description={
|
|
167
|
-
<
|
|
169
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
168
170
|
Earn staking rewards on ETH by holding it on Coinbase
|
|
169
|
-
</
|
|
171
|
+
</Text>
|
|
170
172
|
}
|
|
171
173
|
media={
|
|
172
174
|
<Box left={16} position="relative" top={12}>
|
|
@@ -175,9 +177,9 @@ function DynamicSizingCarousel() {
|
|
|
175
177
|
}
|
|
176
178
|
minWidth="0"
|
|
177
179
|
title={
|
|
178
|
-
<
|
|
180
|
+
<Text id="eths-apr-label" color="fgInverse" as="h3">
|
|
179
181
|
Up to 3.29% APR on ETHs
|
|
180
|
-
</
|
|
182
|
+
</Text>
|
|
181
183
|
}
|
|
182
184
|
width="100%"
|
|
183
185
|
/>
|
|
@@ -193,9 +195,9 @@ function DynamicSizingCarousel() {
|
|
|
193
195
|
action={<ActionButton isVisible={isVisible}>Start chatting</ActionButton>}
|
|
194
196
|
dangerouslySetBackground="rgb(var(--teal70))"
|
|
195
197
|
description={
|
|
196
|
-
<
|
|
198
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
197
199
|
Chat with other devs in our Discord community
|
|
198
|
-
</
|
|
200
|
+
</Text>
|
|
199
201
|
}
|
|
200
202
|
media={
|
|
201
203
|
<Box left={16} position="relative" top={4}>
|
|
@@ -204,9 +206,9 @@ function DynamicSizingCarousel() {
|
|
|
204
206
|
}
|
|
205
207
|
minWidth="0"
|
|
206
208
|
title={
|
|
207
|
-
<
|
|
209
|
+
<Text id="join-the-community-label" color="fgInverse" as="h3">
|
|
208
210
|
Join the community
|
|
209
|
-
</
|
|
211
|
+
</Text>
|
|
210
212
|
}
|
|
211
213
|
width="100%"
|
|
212
214
|
/>
|
|
@@ -222,9 +224,9 @@ function DynamicSizingCarousel() {
|
|
|
222
224
|
action={<ActionButton isVisible={isVisible}>Get 60 days free</ActionButton>}
|
|
223
225
|
dangerouslySetBackground="rgb(var(--blue80))"
|
|
224
226
|
description={
|
|
225
|
-
<
|
|
227
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
226
228
|
Use code NOV60 when you sign up for Coinbase One
|
|
227
|
-
</
|
|
229
|
+
</Text>
|
|
228
230
|
}
|
|
229
231
|
media={
|
|
230
232
|
<Box left={16} position="relative" top={0}>
|
|
@@ -233,9 +235,9 @@ function DynamicSizingCarousel() {
|
|
|
233
235
|
}
|
|
234
236
|
minWidth="0"
|
|
235
237
|
title={
|
|
236
|
-
<
|
|
238
|
+
<Text id="coinbase-one-offer-label" color="fgInverse" as="h3">
|
|
237
239
|
Coinbase One offer
|
|
238
|
-
</
|
|
240
|
+
</Text>
|
|
239
241
|
}
|
|
240
242
|
width="100%"
|
|
241
243
|
/>
|
|
@@ -251,9 +253,9 @@ function DynamicSizingCarousel() {
|
|
|
251
253
|
action={<ActionButton isVisible={isVisible}>Get started</ActionButton>}
|
|
252
254
|
dangerouslySetBackground="rgb(var(--gray100))"
|
|
253
255
|
description={
|
|
254
|
-
<
|
|
256
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
255
257
|
Spend USDC to get rewards with our Visa® debit card
|
|
256
|
-
</
|
|
258
|
+
</Text>
|
|
257
259
|
}
|
|
258
260
|
media={
|
|
259
261
|
<Box left={16} position="relative" top={0}>
|
|
@@ -262,9 +264,9 @@ function DynamicSizingCarousel() {
|
|
|
262
264
|
}
|
|
263
265
|
minWidth="0"
|
|
264
266
|
title={
|
|
265
|
-
<
|
|
267
|
+
<Text id="coinbase-card-label" color="fgInverse" as="h3">
|
|
266
268
|
Coinbase Card
|
|
267
|
-
</
|
|
269
|
+
</Text>
|
|
268
270
|
}
|
|
269
271
|
width="100%"
|
|
270
272
|
/>
|
|
@@ -367,9 +369,9 @@ function VariedSizingCarousel() {
|
|
|
367
369
|
return (
|
|
368
370
|
<ContainedAssetCard
|
|
369
371
|
description={
|
|
370
|
-
<
|
|
372
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
371
373
|
↗6.37%
|
|
372
|
-
</
|
|
374
|
+
</Text>
|
|
373
375
|
}
|
|
374
376
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
375
377
|
subtitle={name}
|
|
@@ -475,9 +477,9 @@ function DragCarousel() {
|
|
|
475
477
|
return (
|
|
476
478
|
<ContainedAssetCard
|
|
477
479
|
description={
|
|
478
|
-
<
|
|
480
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
479
481
|
↗6.37%
|
|
480
|
-
</
|
|
482
|
+
</Text>
|
|
481
483
|
}
|
|
482
484
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
483
485
|
subtitle={name}
|
|
@@ -488,7 +490,9 @@ function DragCarousel() {
|
|
|
488
490
|
return (
|
|
489
491
|
<VStack gap={2}>
|
|
490
492
|
<HStack justifyContent="flex-end" gap={2} alignItems="center">
|
|
491
|
-
<
|
|
493
|
+
<Text as="h3" font="headline">
|
|
494
|
+
Drag
|
|
495
|
+
</Text>
|
|
492
496
|
<SegmentedTabs activeTab={drag} onChange={setDrag} tabs={dragOptions} />
|
|
493
497
|
</HStack>
|
|
494
498
|
<Box style={{ marginInline: 'calc(-1 * var(--space-3))' }}>
|
|
@@ -532,9 +536,9 @@ function SnapModeCarousel() {
|
|
|
532
536
|
return (
|
|
533
537
|
<ContainedAssetCard
|
|
534
538
|
description={
|
|
535
|
-
<
|
|
539
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
536
540
|
↗6.37%
|
|
537
|
-
</
|
|
541
|
+
</Text>
|
|
538
542
|
}
|
|
539
543
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
540
544
|
subtitle={name}
|
|
@@ -545,7 +549,9 @@ function SnapModeCarousel() {
|
|
|
545
549
|
return (
|
|
546
550
|
<VStack gap={2}>
|
|
547
551
|
<HStack justifyContent="flex-end" gap={2} alignItems="center">
|
|
548
|
-
<
|
|
552
|
+
<Text as="h3" font="headline">
|
|
553
|
+
Snap mode
|
|
554
|
+
</Text>
|
|
549
555
|
<SegmentedTabs activeTab={snapMode} onChange={setSnapMode} tabs={snapModeOptions} />
|
|
550
556
|
</HStack>
|
|
551
557
|
<Box style={{ marginInline: 'calc(-1 * var(--space-3))' }}>
|
|
@@ -591,9 +597,9 @@ function OverflowCarousel() {
|
|
|
591
597
|
return (
|
|
592
598
|
<ContainedAssetCard
|
|
593
599
|
description={
|
|
594
|
-
<
|
|
600
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
595
601
|
↗6.37%
|
|
596
|
-
</
|
|
602
|
+
</Text>
|
|
597
603
|
}
|
|
598
604
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
599
605
|
onClick={isVisible ? () => console.log('clicked') : undefined}
|
|
@@ -665,9 +671,9 @@ If you have elements that are focusable, you can use `isVisible` render prop to
|
|
|
665
671
|
}
|
|
666
672
|
minWidth="0"
|
|
667
673
|
title={
|
|
668
|
-
<
|
|
674
|
+
<Text as="h3" font="headline" id="recurring-buy-label">
|
|
669
675
|
Recurring Buy
|
|
670
|
-
</
|
|
676
|
+
</Text>
|
|
671
677
|
}
|
|
672
678
|
width="100%"
|
|
673
679
|
/>
|
|
@@ -686,11 +692,11 @@ You can customize the navigation and pagination components of the carousel using
|
|
|
686
692
|
function CustomComponentsCarousel() {
|
|
687
693
|
function SeeAllComponent({ style }) {
|
|
688
694
|
return (
|
|
689
|
-
<
|
|
695
|
+
<Text style={style}>
|
|
690
696
|
<Link openInNewWindow href="https://coinbase.com/">
|
|
691
697
|
See all
|
|
692
698
|
</Link>
|
|
693
|
-
</
|
|
699
|
+
</Text>
|
|
694
700
|
);
|
|
695
701
|
}
|
|
696
702
|
function PaginationComponent({ totalPages, activePageIndex, onClickPage, style }) {
|
|
@@ -773,9 +779,9 @@ function CustomComponentsCarousel() {
|
|
|
773
779
|
carousel: { gap: 'var(--space-1)' },
|
|
774
780
|
}}
|
|
775
781
|
title={
|
|
776
|
-
<
|
|
782
|
+
<Text as="h3" font="headline">
|
|
777
783
|
Learn more
|
|
778
|
-
</
|
|
784
|
+
</Text>
|
|
779
785
|
}
|
|
780
786
|
>
|
|
781
787
|
<CarouselItem id="recurring-buy" width={itemWidth}>
|
|
@@ -800,9 +806,9 @@ function CustomComponentsCarousel() {
|
|
|
800
806
|
action={<ActionButton isVisible={isVisible}>Start earning</ActionButton>}
|
|
801
807
|
dangerouslySetBackground="rgb(var(--purple70))"
|
|
802
808
|
description={
|
|
803
|
-
<
|
|
809
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
804
810
|
Earn staking rewards on ETH by holding it on Coinbase
|
|
805
|
-
</
|
|
811
|
+
</Text>
|
|
806
812
|
}
|
|
807
813
|
media={
|
|
808
814
|
<Box left={16} position="relative" top={12}>
|
|
@@ -811,9 +817,9 @@ function CustomComponentsCarousel() {
|
|
|
811
817
|
}
|
|
812
818
|
minWidth="0"
|
|
813
819
|
title={
|
|
814
|
-
<
|
|
820
|
+
<Text color="fgInverse" as="h3" font="headline">
|
|
815
821
|
Up to 3.29% APR on ETHs
|
|
816
|
-
</
|
|
822
|
+
</Text>
|
|
817
823
|
}
|
|
818
824
|
width="100%"
|
|
819
825
|
/>
|
|
@@ -825,9 +831,9 @@ function CustomComponentsCarousel() {
|
|
|
825
831
|
action={<ActionButton isVisible={isVisible}>Start chatting</ActionButton>}
|
|
826
832
|
dangerouslySetBackground="rgb(var(--teal70))"
|
|
827
833
|
description={
|
|
828
|
-
<
|
|
834
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
829
835
|
Chat with other devs in our Discord community
|
|
830
|
-
</
|
|
836
|
+
</Text>
|
|
831
837
|
}
|
|
832
838
|
media={
|
|
833
839
|
<Box left={16} position="relative" top={4}>
|
|
@@ -836,9 +842,9 @@ function CustomComponentsCarousel() {
|
|
|
836
842
|
}
|
|
837
843
|
minWidth="0"
|
|
838
844
|
title={
|
|
839
|
-
<
|
|
845
|
+
<Text color="fgInverse" as="h3" font="headline">
|
|
840
846
|
Join the community
|
|
841
|
-
</
|
|
847
|
+
</Text>
|
|
842
848
|
}
|
|
843
849
|
width="100%"
|
|
844
850
|
/>
|
|
@@ -850,9 +856,9 @@ function CustomComponentsCarousel() {
|
|
|
850
856
|
action={<ActionButton isVisible={isVisible}>Get 60 days free</ActionButton>}
|
|
851
857
|
dangerouslySetBackground="rgb(var(--blue80))"
|
|
852
858
|
description={
|
|
853
|
-
<
|
|
859
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
854
860
|
Use code NOV60 when you sign up for Coinbase One
|
|
855
|
-
</
|
|
861
|
+
</Text>
|
|
856
862
|
}
|
|
857
863
|
media={
|
|
858
864
|
<Box left={16} position="relative" top={0}>
|
|
@@ -861,9 +867,9 @@ function CustomComponentsCarousel() {
|
|
|
861
867
|
}
|
|
862
868
|
minWidth="0"
|
|
863
869
|
title={
|
|
864
|
-
<
|
|
870
|
+
<Text color="fgInverse" as="h3" font="headline">
|
|
865
871
|
Coinbase One offer
|
|
866
|
-
</
|
|
872
|
+
</Text>
|
|
867
873
|
}
|
|
868
874
|
width="100%"
|
|
869
875
|
/>
|
|
@@ -875,9 +881,9 @@ function CustomComponentsCarousel() {
|
|
|
875
881
|
action={<ActionButton isVisible={isVisible}>Get started</ActionButton>}
|
|
876
882
|
dangerouslySetBackground="rgb(var(--gray100))"
|
|
877
883
|
description={
|
|
878
|
-
<
|
|
884
|
+
<Text as="p" font="label2" numberOfLines={3} color="fgInverse">
|
|
879
885
|
Spend USDC to get rewards with our Visa® debit card
|
|
880
|
-
</
|
|
886
|
+
</Text>
|
|
881
887
|
}
|
|
882
888
|
media={
|
|
883
889
|
<Box left={16} position="relative" top={0}>
|
|
@@ -886,9 +892,9 @@ function CustomComponentsCarousel() {
|
|
|
886
892
|
}
|
|
887
893
|
minWidth="0"
|
|
888
894
|
title={
|
|
889
|
-
<
|
|
895
|
+
<Text color="fgInverse" as="h3" font="headline">
|
|
890
896
|
Coinbase Card
|
|
891
|
-
</
|
|
897
|
+
</Text>
|
|
892
898
|
}
|
|
893
899
|
width="100%"
|
|
894
900
|
/>
|
|
@@ -1002,9 +1008,9 @@ function DynamicContentCarousel() {
|
|
|
1002
1008
|
return (
|
|
1003
1009
|
<ContainedAssetCard
|
|
1004
1010
|
description={
|
|
1005
|
-
<
|
|
1011
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1006
1012
|
↗6.37%
|
|
1007
|
-
</
|
|
1013
|
+
</Text>
|
|
1008
1014
|
}
|
|
1009
1015
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1010
1016
|
subtitle={name}
|
|
@@ -1069,9 +1075,9 @@ function AnimatedCarousel() {
|
|
|
1069
1075
|
>
|
|
1070
1076
|
<ContainedAssetCard
|
|
1071
1077
|
description={
|
|
1072
|
-
<
|
|
1078
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1073
1079
|
↗6.37%
|
|
1074
|
-
</
|
|
1080
|
+
</Text>
|
|
1075
1081
|
}
|
|
1076
1082
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1077
1083
|
subtitle={name}
|
|
@@ -1146,9 +1152,9 @@ function AnimatedSelectionCarousel() {
|
|
|
1146
1152
|
>
|
|
1147
1153
|
<ContainedAssetCard
|
|
1148
1154
|
description={
|
|
1149
|
-
<
|
|
1155
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1150
1156
|
↗6.37%
|
|
1151
|
-
</
|
|
1157
|
+
</Text>
|
|
1152
1158
|
}
|
|
1153
1159
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1154
1160
|
subtitle={name}
|
|
@@ -1205,9 +1211,9 @@ function HideNavigationAndPaginationCarousel() {
|
|
|
1205
1211
|
return (
|
|
1206
1212
|
<ContainedAssetCard
|
|
1207
1213
|
description={
|
|
1208
|
-
<
|
|
1214
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1209
1215
|
↗6.37%
|
|
1210
|
-
</
|
|
1216
|
+
</Text>
|
|
1211
1217
|
}
|
|
1212
1218
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1213
1219
|
subtitle={name}
|
|
@@ -1282,9 +1288,9 @@ function AnimatedPaginationCarousel() {
|
|
|
1282
1288
|
return (
|
|
1283
1289
|
<ContainedAssetCard
|
|
1284
1290
|
description={
|
|
1285
|
-
<
|
|
1291
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1286
1292
|
↗6.37%
|
|
1287
|
-
</
|
|
1293
|
+
</Text>
|
|
1288
1294
|
}
|
|
1289
1295
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1290
1296
|
subtitle={name}
|
|
@@ -1359,9 +1365,9 @@ function ImperativeApiCarousel() {
|
|
|
1359
1365
|
return (
|
|
1360
1366
|
<ContainedAssetCard
|
|
1361
1367
|
description={
|
|
1362
|
-
<
|
|
1368
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
1363
1369
|
↗6.37%
|
|
1364
|
-
</
|
|
1370
|
+
</Text>
|
|
1365
1371
|
}
|
|
1366
1372
|
header={<RemoteImage height="32px" source={imageUrl} width="32px" />}
|
|
1367
1373
|
subtitle={name}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Combobox
|
|
2
|
+
|
|
3
|
+
A flexible combobox component for both single and multi-selection, built for web applications with comprehensive accessibility support.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```tsx
|
|
8
|
+
import { Combobox } from '@coinbase/cds-web/alpha/combobox'
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Examples
|
|
12
|
+
|
|
13
|
+
### A note on search logic
|
|
14
|
+
|
|
15
|
+
We use [fuse.js](https://www.fusejs.io/) to power the fuzzy search logic for Combobox. You can override this search logic with your own using the `filterFunction` prop.
|
|
16
|
+
|
|
17
|
+
### Multi-Select
|
|
18
|
+
|
|
19
|
+
Basic multi-selection combobox with search.
|
|
20
|
+
|
|
21
|
+
```jsx live
|
|
22
|
+
function MultiSelect() {
|
|
23
|
+
const fruitOptions: SelectOption[] = [
|
|
24
|
+
{ value: 'apple', label: 'Apple' },
|
|
25
|
+
{ value: 'banana', label: 'Banana' },
|
|
26
|
+
{ value: 'cherry', label: 'Cherry' },
|
|
27
|
+
{ value: 'date', label: 'Date' },
|
|
28
|
+
{ value: 'elderberry', label: 'Elderberry' },
|
|
29
|
+
{ value: 'fig', label: 'Fig' },
|
|
30
|
+
{ value: 'grape', label: 'Grape' },
|
|
31
|
+
{ value: 'honeydew', label: 'Honeydew' },
|
|
32
|
+
{ value: 'kiwi', label: 'Kiwi' },
|
|
33
|
+
{ value: 'lemon', label: 'Lemon' },
|
|
34
|
+
{ value: 'mango', label: 'Mango' },
|
|
35
|
+
{ value: 'orange', label: 'Orange' },
|
|
36
|
+
{ value: 'papaya', label: 'Papaya' },
|
|
37
|
+
{ value: 'raspberry', label: 'Raspberry' },
|
|
38
|
+
{ value: 'strawberry', label: 'Strawberry' },
|
|
39
|
+
];
|
|
40
|
+
|
|
41
|
+
const { value, onChange } = useMultiSelect({ initialValue: ['apple', 'banana'] });
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<Combobox
|
|
45
|
+
label="Select fruits"
|
|
46
|
+
onChange={onChange}
|
|
47
|
+
options={fruitOptions}
|
|
48
|
+
placeholder="Search and select fruits..."
|
|
49
|
+
type="multi"
|
|
50
|
+
value={value}
|
|
51
|
+
/>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Single Select
|
|
57
|
+
|
|
58
|
+
Standard single-selection combobox with an option to clear the current value.
|
|
59
|
+
|
|
60
|
+
```jsx live
|
|
61
|
+
function SingleSelect() {
|
|
62
|
+
const singleSelectOptions = [
|
|
63
|
+
{ value: null, label: 'Remove selection' },
|
|
64
|
+
{ value: 'apple', label: 'Apple' },
|
|
65
|
+
{ value: 'banana', label: 'Banana' },
|
|
66
|
+
{ value: 'cherry', label: 'Cherry' },
|
|
67
|
+
{ value: 'date', label: 'Date' },
|
|
68
|
+
];
|
|
69
|
+
|
|
70
|
+
const [value, setValue] = useState('apple');
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Combobox
|
|
74
|
+
label="Favorite fruit"
|
|
75
|
+
onChange={setValue}
|
|
76
|
+
options={singleSelectOptions}
|
|
77
|
+
placeholder="Search fruits..."
|
|
78
|
+
value={value}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Helper Text
|
|
85
|
+
|
|
86
|
+
Communicate limits or guidance by pairing helper text with multi-select usage.
|
|
87
|
+
|
|
88
|
+
```jsx live
|
|
89
|
+
function HelperText() {
|
|
90
|
+
const fruitOptions: SelectOption[] = [
|
|
91
|
+
{ value: 'apple', label: 'Apple' },
|
|
92
|
+
{ value: 'banana', label: 'Banana' },
|
|
93
|
+
{ value: 'cherry', label: 'Cherry' },
|
|
94
|
+
{ value: 'date', label: 'Date' },
|
|
95
|
+
{ value: 'elderberry', label: 'Elderberry' },
|
|
96
|
+
{ value: 'fig', label: 'Fig' },
|
|
97
|
+
{ value: 'grape', label: 'Grape' },
|
|
98
|
+
{ value: 'honeydew', label: 'Honeydew' },
|
|
99
|
+
{ value: 'kiwi', label: 'Kiwi' },
|
|
100
|
+
{ value: 'lemon', label: 'Lemon' },
|
|
101
|
+
{ value: 'mango', label: 'Mango' },
|
|
102
|
+
{ value: 'orange', label: 'Orange' },
|
|
103
|
+
{ value: 'papaya', label: 'Papaya' },
|
|
104
|
+
{ value: 'raspberry', label: 'Raspberry' },
|
|
105
|
+
{ value: 'strawberry', label: 'Strawberry' },
|
|
106
|
+
];
|
|
107
|
+
|
|
108
|
+
const { value, onChange } = useMultiSelect({ initialValue: ['apple', 'banana'] });
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<Combobox
|
|
112
|
+
helperText="Choose more than one fruit"
|
|
113
|
+
label="Select fruits"
|
|
114
|
+
onChange={onChange}
|
|
115
|
+
options={fruitOptions}
|
|
116
|
+
placeholder="Search and select fruits..."
|
|
117
|
+
type="multi"
|
|
118
|
+
value={value}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Props
|
|
125
|
+
|
|
126
|
+
| Prop | Type | Required | Default | Description |
|
|
127
|
+
| --- | --- | --- | --- | --- |
|
|
128
|
+
| `onChange` | `(value: Type extends multi ? SelectOptionValue \| SelectOptionValue[] \| null : SelectOptionValue \| null) => void` | Yes | `-` | - |
|
|
129
|
+
| `options` | `SelectOptionList<Type, SelectOptionValue>` | Yes | `-` | Array of options to display in the select dropdown. Can be individual options or groups with label and options |
|
|
130
|
+
| `value` | `string \| SelectOptionValue[] \| null` | Yes | `-` | - |
|
|
131
|
+
| `ComboboxControlComponent` | `ComboboxControlComponent` | No | `-` | Custom ComboboxControlComponent to wrap SelectControlComponent. This component must be a stable reference |
|
|
132
|
+
| `SelectAllOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the Select All option |
|
|
133
|
+
| `SelectControlComponent` | `SelectControlComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the select control |
|
|
134
|
+
| `SelectDropdownComponent` | `SelectDropdownComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render the dropdown container |
|
|
135
|
+
| `SelectEmptyDropdownContentsComponent` | `SelectEmptyDropdownContentComponent` | No | `-` | Custom component to render when no options are available |
|
|
136
|
+
| `SelectOptionComponent` | `SelectOptionComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render individual options |
|
|
137
|
+
| `SelectOptionGroupComponent` | `SelectOptionGroupComponent<Type, SelectOptionValue>` | No | `-` | Custom component to render group headers |
|
|
138
|
+
| `accessibilityRoles` | `{ dropdown?: AriaHasPopupType; option?: string \| undefined; } \| undefined` | No | `-` | Accessibility roles for dropdown and option elements |
|
|
139
|
+
| `accessory` | `ReactElement<CellAccessoryProps, string \| JSXElementConstructor<any>>` | No | `-` | Accessory element rendered at the end of the cell (e.g., chevron). |
|
|
140
|
+
| `className` | `string` | No | `-` | CSS class name for the root element |
|
|
141
|
+
| `classNames` | `{ root?: string; control?: string \| undefined; controlStartNode?: string \| undefined; controlInputNode?: string \| undefined; controlValueNode?: string \| undefined; controlLabelNode?: string \| undefined; controlHelperTextNode?: string \| undefined; controlEndNode?: string \| undefined; dropdown?: string \| undefined; option?: string \| undefined; optionCell?: string \| undefined; optionContent?: string \| undefined; optionLabel?: string \| undefined; optionDescription?: string \| undefined; selectAllDivider?: string \| undefined; emptyContentsContainer?: string \| undefined; emptyContentsText?: string \| undefined; optionGroup?: string \| undefined; } \| undefined` | No | `-` | Custom class names for different parts of the select |
|
|
142
|
+
| `clearAllLabel` | `string` | No | `-` | Label for the Clear All option in multi-select mode |
|
|
143
|
+
| `compact` | `boolean` | No | `-` | Whether to use compact styling for the select |
|
|
144
|
+
| `controlAccessibilityLabel` | `string` | No | `-` | Accessibility label for the control |
|
|
145
|
+
| `defaultOpen` | `boolean` | No | `-` | Initial open state when component mounts (uncontrolled mode) |
|
|
146
|
+
| `defaultSearchText` | `string` | No | `-` | Default search text value for uncontrolled mode |
|
|
147
|
+
| `disableClickOutsideClose` | `boolean` | No | `-` | Whether clicking outside the dropdown should close it |
|
|
148
|
+
| `disabled` | `boolean` | No | `false` | Toggles input interactability and opacity |
|
|
149
|
+
| `emptyOptionsLabel` | `string` | No | `-` | Label displayed when there are no options available |
|
|
150
|
+
| `end` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | End-aligned content (e.g., value, status). Replaces the deprecated detail prop. |
|
|
151
|
+
| `endNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Adds content to the end of the inner input. Refer to diagram for location of endNode in InputStack component |
|
|
152
|
+
| `filterFunction` | `((options: SelectOptionList<Type, SelectOptionValue>, searchText: string) => SelectOption<SelectOptionValue>[])` | No | `-` | Custom filter function for searching options |
|
|
153
|
+
| `helperText` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Helper text displayed below the select |
|
|
154
|
+
| `hiddenSelectedOptionsLabel` | `string` | No | `-` | Label to show for showcasing count of hidden selected options |
|
|
155
|
+
| `hideSearchInput` | `boolean` | No | `-` | Hide the search input |
|
|
156
|
+
| `hideSelectAll` | `boolean` | No | `-` | Whether to hide the Select All option in multi-select mode |
|
|
157
|
+
| `label` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Label displayed above the control |
|
|
158
|
+
| `labelVariant` | `inside \| outside` | No | `'outside'` | The variant of the label. Only used when compact is not true. |
|
|
159
|
+
| `maxSelectedOptionsToShow` | `number` | No | `-` | Maximum number of selected options to show before truncating |
|
|
160
|
+
| `media` | `ReactElement` | No | `-` | Media rendered at the start of the cell (icon, avatar, image, etc). |
|
|
161
|
+
| `onSearch` | `((searchText: string) => void)` | No | `-` | Search text change handler |
|
|
162
|
+
| `open` | `boolean` | No | `-` | Controlled open state of the dropdown |
|
|
163
|
+
| `placeholder` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Placeholder text displayed when no option is selected |
|
|
164
|
+
| `ref` | `null \| (instance: SelectRef \| null) => void \| RefObject<SelectRef>` | No | `-` | - |
|
|
165
|
+
| `removeSelectedOptionAccessibilityLabel` | `string` | No | `-` | Accessibility label for each chip in a multi-select |
|
|
166
|
+
| `searchText` | `string` | No | `-` | Controlled search text value |
|
|
167
|
+
| `selectAllLabel` | `string` | No | `-` | Label for the Select All option in multi-select mode |
|
|
168
|
+
| `setOpen` | `((open: boolean \| ((open: boolean) => boolean)) => void)` | No | `-` | Callback to update the open state |
|
|
169
|
+
| `startNode` | `null \| string \| number \| false \| true \| ReactElement<any, string \| JSXElementConstructor<any>> \| Iterable<ReactNode> \| ReactPortal` | No | `-` | Adds content to the start of the inner input. Refer to diagram for location of startNode in InputStack component |
|
|
170
|
+
| `style` | `CSSProperties` | No | `-` | Inline styles for the root element |
|
|
171
|
+
| `styles` | `{ root?: CSSProperties; control?: CSSProperties \| undefined; controlStartNode?: CSSProperties \| undefined; controlInputNode?: CSSProperties \| undefined; controlValueNode?: CSSProperties \| undefined; controlLabelNode?: CSSProperties \| undefined; controlHelperTextNode?: CSSProperties \| undefined; controlEndNode?: CSSProperties \| undefined; controlBlendStyles?: InteractableBlendStyles \| undefined; dropdown?: CSSProperties \| undefined; option?: CSSProperties \| undefined; optionCell?: CSSProperties \| undefined; optionContent?: CSSProperties \| undefined; optionLabel?: CSSProperties \| undefined; optionDescription?: CSSProperties \| undefined; optionBlendStyles?: InteractableBlendStyles \| undefined; selectAllDivider?: CSSProperties \| undefined; emptyContentsContainer?: CSSProperties \| undefined; emptyContentsText?: CSSProperties \| undefined; optionGroup?: CSSProperties \| undefined; } \| undefined` | No | `-` | Custom styles for different parts of the select |
|
|
172
|
+
| `testID` | `string` | No | `-` | Test ID for the root element |
|
|
173
|
+
| `type` | `multi \| single` | No | `-` | Whether the select allows single or multiple selections |
|
|
174
|
+
| `variant` | `primary \| secondary \| positive \| negative \| foregroundMuted \| foreground` | No | `foregroundMuted` | Determines the sentiment of the input. Because we allow startContent and endContent to be custom ReactNode, the content placed inside these slots will not change colors according to the variant. You will have to add that yourself |
|
|
175
|
+
|
|
176
|
+
|
|
@@ -23,9 +23,9 @@ function Example() {
|
|
|
23
23
|
{
|
|
24
24
|
title: '$4.15',
|
|
25
25
|
description: (
|
|
26
|
-
<
|
|
26
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
27
27
|
↗73.37%
|
|
28
|
-
</
|
|
28
|
+
</Text>
|
|
29
29
|
),
|
|
30
30
|
subtitle: 'ETH',
|
|
31
31
|
onClick: NoopFn,
|
|
@@ -55,9 +55,9 @@ function Example() {
|
|
|
55
55
|
{
|
|
56
56
|
title: '$309.43',
|
|
57
57
|
description: (
|
|
58
|
-
<
|
|
58
|
+
<Text as="p" font="label2" color="fgPositive" numberOfLines={2}>
|
|
59
59
|
↗3.37%
|
|
60
|
-
</
|
|
60
|
+
</Text>
|
|
61
61
|
),
|
|
62
62
|
subtitle: 'Bitcoin',
|
|
63
63
|
onClick: NoopFn,
|