@coinbase/cds-mcp-server 8.52.2 → 8.53.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/mcp-docs/mobile/components/Alert.txt +1 -1
  3. package/mcp-docs/mobile/components/AreaChart.txt +2 -0
  4. package/mcp-docs/mobile/components/BarChart.txt +33 -0
  5. package/mcp-docs/mobile/components/CartesianChart.txt +2 -0
  6. package/mcp-docs/mobile/components/Combobox.txt +380 -83
  7. package/mcp-docs/mobile/components/HeroSquare.txt +1 -1
  8. package/mcp-docs/mobile/components/InputChip.txt +75 -9
  9. package/mcp-docs/mobile/components/LineChart.txt +232 -112
  10. package/mcp-docs/mobile/components/MediaChip.txt +49 -26
  11. package/mcp-docs/mobile/components/NudgeCard.txt +1 -1
  12. package/mcp-docs/mobile/components/Pictogram.txt +1 -1
  13. package/mcp-docs/mobile/components/Scrubber.txt +2 -0
  14. package/mcp-docs/mobile/components/SelectChipAlpha.txt +52 -40
  15. package/mcp-docs/mobile/components/SpotIcon.txt +1 -1
  16. package/mcp-docs/mobile/components/SpotRectangle.txt +1 -1
  17. package/mcp-docs/mobile/components/SpotSquare.txt +1 -1
  18. package/mcp-docs/mobile/routes.txt +1 -1
  19. package/mcp-docs/web/components/Alert.txt +1 -1
  20. package/mcp-docs/web/components/Combobox.txt +422 -83
  21. package/mcp-docs/web/components/FullscreenAlert.txt +1 -1
  22. package/mcp-docs/web/components/HeroSquare.txt +1 -1
  23. package/mcp-docs/web/components/InputChip.txt +75 -9
  24. package/mcp-docs/web/components/Legend.txt +6 -6
  25. package/mcp-docs/web/components/LineChart.txt +16 -16
  26. package/mcp-docs/web/components/MediaChip.txt +49 -26
  27. package/mcp-docs/web/components/NudgeCard.txt +1 -1
  28. package/mcp-docs/web/components/Pictogram.txt +1 -1
  29. package/mcp-docs/web/components/SegmentedControl.txt +174 -0
  30. package/mcp-docs/web/components/SelectChipAlpha.txt +47 -13
  31. package/mcp-docs/web/components/SpotIcon.txt +1 -1
  32. package/mcp-docs/web/components/SpotRectangle.txt +1 -1
  33. package/mcp-docs/web/components/SpotSquare.txt +1 -1
  34. package/mcp-docs/web/components/TileButton.txt +1 -1
  35. package/mcp-docs/web/routes.txt +2 -1
  36. package/package.json +1 -1
@@ -157,7 +157,7 @@ function AlertOnModalExample() {
157
157
  | `onDidClose` | `((() => void) & (() => void))` | No | `-` | Callback fired after the component is closed. |
158
158
  | `onDismissActionPress` | `(() => void)` | No | `-` | Callback function fired when the dismiss action is pressed |
159
159
  | `onPreferredActionPress` | `(() => void)` | No | `-` | Callback function fired when the preferred action is pressed |
160
- | `pictogram` | `key \| done \| loop \| cardSuccess \| warning \| error \| add \| arrowsUpDown \| browser \| calculator \| calendar \| checkmark \| clock \| coinbaseOneLogo \| crystalBallInsight \| derivativesProduct \| email \| gasFees \| identityCard \| instantUnstakingClock \| laptop \| learningRewardsProduct \| lock \| passport \| paypal \| phone \| pieChartData \| pieChartWithArrow \| planet \| robot \| safe \| securityKey \| settings \| shield \| support \| taxes \| tokenSales \| trading \| verifiedPools \| wallet \| 2fa \| accountsNavigation \| accreditedInvestor \| addCard \| addPayment \| addPhone \| addressBook \| addToWatchlist \| addWallet \| advancedTradingDesktop \| advancedTradingNavigation \| advancedTradingRebates \| agent \| alerts \| alertsCoinbaseOne \| analyticsNavigation \| apartOfDropsNft \| applyForHigherLimits \| apyInterest \| assetEncryption \| assetHubNavigation \| assetManagement \| assetManagementNavigation \| assetMeasurements \| assetMovement \| authenticationApp \| authenticator \| authenticatorAlt \| authenticatorProgress \| avatarAa \| avatarAb \| avatarAc \| avatarAd \| avatarAe \| avatarAf \| avatarAg \| avatarAh \| avatarAi \| avatarAj \| avatarBa \| avatarBb \| avatarBc \| avatarBd \| avatarBe \| avatarBf \| avatarBg \| avatarBh \| avatarBi \| avatarBj \| avatarCa \| avatarCb \| avatarCc \| avatarCd \| avatarCe \| avatarCf \| avatarCg \| avatarCh \| avatarCi \| avatarCj \| avatarDa \| avatarDb \| avatarDc \| avatarDd \| avatarDe \| avatarDf \| avatarDg \| avatarDh \| avatarDi \| avatarDj \| avatarEa \| avatarEb \| avatarEc \| avatarEd \| avatarEe \| avatarEf \| avatarEg \| avatarEh \| avatarEi \| avatarEj \| avatarFa \| avatarFb \| avatarFc \| avatarFd \| avatarFe \| avatarFf \| avatarFg \| avatarFh \| avatarFi \| avatarFj \| avatarGa \| avatarGb \| avatarGc \| avatarGd \| avatarGe \| avatarGf \| avatarGg \| avatarGh \| avatarGi \| avatarGj \| avatarHa \| avatarHb \| avatarHc \| avatarHd \| avatarHe \| avatarHf \| avatarHg \| avatarHh \| avatarHi \| avatarHj \| avatarIa \| avatarIb \| avatarIc \| avatarId \| avatarIe \| avatarIf \| avatarIg \| avatarIh \| avatarIi \| avatarIj \| avatarJa \| avatarJb \| avatarJc \| avatarJd \| avatarJe \| avatarJf \| avatarJg \| avatarJh \| avatarJi \| avatarJj \| barChart \| baseAscend \| baseCertificateStar \| baseChartSmall \| baseChatBubbleHeart \| baseCheckSmall \| baseCoinCryptoSmall \| baseCoinNetworkSmall \| baseCoinStack \| baseCoinStar \| baseComet \| baseComputer \| baseConfetti \| baseConnectApps \| baseConnectSmall \| baseCreatorCoin \| baseDecentralizationSmall \| baseDiamondSmall \| baseDiamondTrophy \| baseDoor \| baseEarnedBadge \| baseEmptySmall \| baseErrorButterflySmall \| baseErrorSmall \| baseExchange \| baseFire \| baseGem \| baseGlobe \| baseHandStar \| baseLayout \| baseLightningbolt \| baseLoadingSmall \| baseLocationSmall \| baseLogo \| baseLogoNavigation \| baseMedal \| baseMessaging \| baseMintNftSmall \| baseNetworkSmall \| baseNftSmall \| basePaycoinSmall \| basePeopleSmall \| basePiechartSmall \| basePlant \| basePower \| baseRibbon \| baseRocket \| baseRockon \| baseSaved \| baseSecuritySmall \| baseSendSmall \| baseSignin \| baseSmile \| baseStack \| baseStar \| baseTargetSmall \| baseTile \| bigBtcSend \| bitcoin \| bitcoinPizza \| bitcoinRewards \| bitcoinWhitePaper \| blockchainConnection \| bonusFivePercent \| bonusTwoPercent \| borrowCoins \| borrowingLending \| borrowNavigation \| browserMultiPlatform \| browserTransaction \| btcOneHundred \| bundle \| businessProduct \| calendarCaution \| calendarHighlight \| candleSticksGraph \| cardBlocked \| cardDeclined \| cardNavigation \| cb1BankTransfers \| chart \| chat \| cloudNavigation \| coinbaseLogoAdvancedBrand \| coinbaseLogoNavigation \| coinbaseOneAuthenticator \| coinbaseOneChat \| coinbaseOneEarn \| coinbaseOneEarnCoins \| coinbaseOneEarnCoinsLogo \| coinbaseOneFiat \| coinbaseOneProductIcon \| coinbaseOneProductInvestWeekly \| coinbaseOneRefreshed \| coinbaseOneShield \| coinbaseOneTrade \| coinbaseOneTrusted \| coinbaseOneUnlimitedRewards \| coinbaseUnlockOffers \| coinbaseWalletApp \| coinFocus \| coinShare \| coldStorageCheck \| collectionOfAssets \| commerceCheckout \| commerceInvoice \| commerceNavigation \| commodities \| completeQuiz \| complianceNavigation \| congratulations \| connectNavigation \| contactInfo \| controlWalletStorage \| creative \| creditCard \| crypto101 \| cryptoCard \| cryptoCoins \| cryptoFolder \| custodialJourney \| custodyNavigation \| dataMarketplaceNavigation \| decentralizationEverything \| decentralizedExchange \| decentralizedIdentity \| decentralizedWeb3 \| defiEarnMoment \| delegate \| delegateNavigation \| derivativesNavigation \| developerPlatformNavigation \| developerSDKNavigation \| directDepositNavigation \| dollarShowcase \| driversLicense \| driversLicenseWheel \| earnCoins \| earnGraph \| earnNavigation \| easyToUse \| economyGlobal \| emailAndMessages \| enableVoting \| envelope \| ethereumFocus \| ethRewards \| ethStaking \| ethStakingChart \| ethStakingRewards \| ethToken \| exchangeNavigation \| explore \| fast \| faucetNavigation \| feesRestriction \| fiat \| finance \| findYourSelection \| formDownload \| futures \| futuresCoinbaseOne \| gem \| genericCountryIDCard \| getStarted \| giftbox \| globalConnections \| globalPayments \| globalTransactions \| googleAuthenticator \| governance \| hardwareWallet \| helpCenterNavigation \| higherLimits \| holdingCoin \| idBlock \| idError \| idVerification \| increaseLimits \| institutionalNavigation \| institutions \| internationalExchangeNavigation \| internet \| investGraph \| laptopCharts \| laptopVideo \| layerNetworks \| leadGraph \| learn \| learningRewardsNavigation \| lightbulbLearn \| lightningNetworkSend \| linkYourAccount \| listingFees \| locationUsa \| lowFees \| manageWeb3SignersAcct \| miningCoins \| mintedNft \| mobileCharts \| mobileError \| mobileNotifcation \| mobileSuccess \| mobileWarning \| moneyCrypto \| moneyEarn \| moneySwift \| monitoringPerformance \| moreThanBitcoin \| multiAccountsAndCards \| multiPlatform \| multipleAssets \| musicAndSounds \| myNumberCard \| newUserChecklistBuyCrypto \| newUserChecklistCompleteAccount \| newUserChecklistVerifyId \| nftAvatar \| nftLibrary \| nftNavigation \| noAnnualFee \| noNftFound \| notificationHubAnalysis \| notificationHubNews \| notificationHubPortfolio \| notificationHubSocial \| notifications \| noVisibility \| noWiFi \| orders \| outage \| partialCoins \| participateNavigation \| passwordWalletLocked \| payNavigation \| peerToPeer \| pieChart \| pieChartWithArrowBlue \| pizza \| pluginBrowser \| podium \| positiveReviews \| predictionMarkets \| premiumInvestor \| priceTracking \| primeMobileApp \| primeNavigation \| privateClientNavigation \| proNavigation \| protectionPlan \| queryTransactNavigation \| receipt \| recurringPurchases \| restaking \| reviewAndAdd \| rewardsNavigation \| riskStaking \| rosettaNavigation \| securedAssets \| security \| securityCoinShield \| seedPhrase \| selectAddNft \| selfCustodyWallet \| selfServe \| sellSendAnytime \| sendPaymentToOthers \| settled \| sideChainSide \| signInNavigation \| smsAuthenticate \| sparkleCoinbaseOne \| ssnCard \| stableCoinMetaphor \| stacking \| stakingGraph \| standWithCryptoLogoNavigation \| startToday \| strongInfo \| strongWarning \| successPhone \| supportChat \| takeQuiz \| target \| taxBeta \| taxCenterNavigation \| taxesArrangement \| taxSeason \| timingCheck \| tokenBaskets \| transferSend \| transistor \| trendingAssets \| trusted \| tryAgainLater \| twoBonus \| typeScript \| ubiKey \| usaProduct \| usdcEarn \| usdcInterest \| usdcLoan \| usdcLogo \| usdcRewards \| usdcRewardsRibbon \| usdcToken \| venturesNavigation \| videoCalendar \| videoContent \| waiting \| waitingForConsensus \| walletAsServiceNavigation \| walletDeposit \| walletError \| walletExchange \| walletLinkNavigation \| walletLogoNavigation \| walletNavigation \| walletPassword \| walletSuccess \| walletWarning \| winBTC \| worldwide \| wrapEth` | No | `-` | Illustration pictogram name for alert |
160
+ | `pictogram` | `key \| done \| loop \| cardSuccess \| warning \| error \| add \| arrowsUpDown \| browser \| calculator \| calendar \| checkmark \| clock \| coinbaseOneLogo \| crystalBallInsight \| derivativesProduct \| download \| email \| gasFees \| identityCard \| instantUnstakingClock \| laptop \| learningRewardsProduct \| lock \| passport \| paypal \| phone \| pieChartData \| pieChartWithArrow \| planet \| robot \| safe \| securityKey \| settings \| shield \| support \| taxes \| tokenSales \| trading \| verifiedPools \| wallet \| 2fa \| accountsNavigation \| accreditedInvestor \| addCard \| addPayment \| addPhone \| addressBook \| addToWatchlist \| addWallet \| advancedTradingDesktop \| advancedTradingNavigation \| advancedTradingRebates \| agent \| alerts \| alertsCoinbaseOne \| analyticsNavigation \| apartOfDropsNft \| applyForHigherLimits \| apyInterest \| assetEncryption \| assetHubNavigation \| assetManagement \| assetManagementNavigation \| assetMeasurements \| assetMovement \| authenticationApp \| authenticator \| authenticatorAlt \| authenticatorProgress \| avatarAa \| avatarAb \| avatarAc \| avatarAd \| avatarAe \| avatarAf \| avatarAg \| avatarAh \| avatarAi \| avatarAj \| avatarBa \| avatarBb \| avatarBc \| avatarBd \| avatarBe \| avatarBf \| avatarBg \| avatarBh \| avatarBi \| avatarBj \| avatarCa \| avatarCb \| avatarCc \| avatarCd \| avatarCe \| avatarCf \| avatarCg \| avatarCh \| avatarCi \| avatarCj \| avatarDa \| avatarDb \| avatarDc \| avatarDd \| avatarDe \| avatarDf \| avatarDg \| avatarDh \| avatarDi \| avatarDj \| avatarEa \| avatarEb \| avatarEc \| avatarEd \| avatarEe \| avatarEf \| avatarEg \| avatarEh \| avatarEi \| avatarEj \| avatarFa \| avatarFb \| avatarFc \| avatarFd \| avatarFe \| avatarFf \| avatarFg \| avatarFh \| avatarFi \| avatarFj \| avatarGa \| avatarGb \| avatarGc \| avatarGd \| avatarGe \| avatarGf \| avatarGg \| avatarGh \| avatarGi \| avatarGj \| avatarHa \| avatarHb \| avatarHc \| avatarHd \| avatarHe \| avatarHf \| avatarHg \| avatarHh \| avatarHi \| avatarHj \| avatarIa \| avatarIb \| avatarIc \| avatarId \| avatarIe \| avatarIf \| avatarIg \| avatarIh \| avatarIi \| avatarIj \| avatarJa \| avatarJb \| avatarJc \| avatarJd \| avatarJe \| avatarJf \| avatarJg \| avatarJh \| avatarJi \| avatarJj \| barChart \| baseAscend \| baseCertificateStar \| baseChartSmall \| baseChatBubbleHeart \| baseCheckSmall \| baseCoinCryptoSmall \| baseCoinNetworkSmall \| baseCoinStack \| baseCoinStar \| baseComet \| baseComputer \| baseConfetti \| baseConnectApps \| baseConnectSmall \| baseCreatorCoin \| baseDecentralizationSmall \| baseDiamondSmall \| baseDiamondTrophy \| baseDoor \| baseEarnedBadge \| baseEmptySmall \| baseErrorButterflySmall \| baseErrorSmall \| baseExchange \| baseFire \| baseGem \| baseGlobe \| baseHandStar \| baseLayout \| baseLightningbolt \| baseLoadingSmall \| baseLocationSmall \| baseLogo \| baseLogoNavigation \| baseMedal \| baseMessaging \| baseMintNftSmall \| baseNetworkSmall \| baseNftSmall \| basePaycoinSmall \| basePeopleSmall \| basePiechartSmall \| basePlant \| basePower \| baseRibbon \| baseRocket \| baseRockon \| baseSaved \| baseSecuritySmall \| baseSendSmall \| baseSignin \| baseSmile \| baseStack \| baseStar \| baseTargetSmall \| baseTile \| bigBtcSend \| bitcoin \| bitcoinPizza \| bitcoinRewards \| bitcoinWhitePaper \| blockchainConnection \| bonusFivePercent \| bonusTwoPercent \| borrowCoins \| borrowingLending \| borrowNavigation \| browserMultiPlatform \| browserTransaction \| btcOneHundred \| bundle \| businessProduct \| calendarCaution \| calendarHighlight \| candleSticksGraph \| cardBlocked \| cardDeclined \| cardNavigation \| cb1BankTransfers \| chart \| chat \| cloudNavigation \| coinbaseLogoAdvancedBrand \| coinbaseLogoNavigation \| coinbaseOneAuthenticator \| coinbaseOneChat \| coinbaseOneEarn \| coinbaseOneEarnCoins \| coinbaseOneEarnCoinsLogo \| coinbaseOneFiat \| coinbaseOneProductIcon \| coinbaseOneProductInvestWeekly \| coinbaseOneRefreshed \| coinbaseOneShield \| coinbaseOneTrade \| coinbaseOneTrusted \| coinbaseOneUnlimitedRewards \| coinbaseUnlockOffers \| coinbaseWalletApp \| coinFocus \| coinShare \| coldStorageCheck \| collectionOfAssets \| commerceCheckout \| commerceInvoice \| commerceNavigation \| commodities \| completeQuiz \| complianceNavigation \| congratulations \| connectNavigation \| contactInfo \| controlWalletStorage \| creative \| creditCard \| crypto101 \| cryptoCard \| cryptoCoins \| cryptoFolder \| custodialJourney \| custodyNavigation \| dataMarketplaceNavigation \| decentralizationEverything \| decentralizedExchange \| decentralizedIdentity \| decentralizedWeb3 \| defiEarnMoment \| delegate \| delegateNavigation \| derivativesNavigation \| developerPlatformNavigation \| developerSDKNavigation \| directDepositNavigation \| dollarShowcase \| driversLicense \| driversLicenseWheel \| earnCoins \| earnGraph \| earnNavigation \| easyToUse \| economyGlobal \| emailAndMessages \| enableVoting \| envelope \| ethereumFocus \| ethRewards \| ethStaking \| ethStakingChart \| ethStakingRewards \| ethToken \| exchangeNavigation \| explore \| fast \| faucetNavigation \| feesRestriction \| fiat \| finance \| findYourSelection \| formDownload \| futures \| futuresCoinbaseOne \| gem \| genericCountryIDCard \| getStarted \| giftbox \| globalConnections \| globalPayments \| globalTransactions \| googleAuthenticator \| governance \| hardwareWallet \| helpCenterNavigation \| higherLimits \| holdingCoin \| idBlock \| idError \| idVerification \| increaseLimits \| institutionalNavigation \| institutions \| instoAccount \| instoAddressBook \| instoAdvancedTradingRebates \| instoApyInterest \| instoAuthenticatorProgress \| instoBorrowingLending \| instoCoinbaseOneShield \| instoCrypto101 \| instoDecentralizationEverything \| instoDecentralizedExchange \| instoDecentralizedWeb3 \| instoDelegate \| instoEarnCoins \| instoEarnGraph \| instoEth \| instoEthRewards \| instoEthStakingChart \| instoFiat \| instoGem \| instoKey \| instoNftLibrary \| instoPasswordWalletLocked \| instoprimeMobileApp \| instoRestaking \| instoRiskStaking \| instoSelfCustodyWallet \| instoStakingGraph \| instoTrading \| instoWalletWarning \| internationalExchangeNavigation \| internet \| investGraph \| laptopCharts \| laptopVideo \| layerNetworks \| leadGraph \| learn \| learningRewardsNavigation \| lightbulbLearn \| lightningNetworkSend \| linkYourAccount \| listingFees \| locationUsa \| lowFees \| manageWeb3SignersAcct \| miningCoins \| mintedNft \| mobileCharts \| mobileError \| mobileNotifcation \| mobileSuccess \| mobileWarning \| moneyCrypto \| moneyEarn \| moneySwift \| monitoringPerformance \| moreThanBitcoin \| multiAccountsAndCards \| multiPlatform \| multipleAssets \| musicAndSounds \| myNumberCard \| newUserChecklistBuyCrypto \| newUserChecklistCompleteAccount \| newUserChecklistVerifyId \| nftAvatar \| nftLibrary \| nftNavigation \| noAnnualFee \| noNftFound \| notificationHubAnalysis \| notificationHubNews \| notificationHubPortfolio \| notificationHubSocial \| notifications \| noVisibility \| noWiFi \| orders \| outage \| partialCoins \| participateNavigation \| passwordWalletLocked \| payNavigation \| peerToPeer \| pieChart \| pieChartWithArrowBlue \| pizza \| pluginBrowser \| podium \| positiveReviews \| predictionMarkets \| premiumInvestor \| priceTracking \| primeMobileApp \| primeNavigation \| privateClientNavigation \| proNavigation \| protectionPlan \| queryTransactNavigation \| receipt \| recurringPurchases \| restaking \| reviewAndAdd \| rewardsNavigation \| riskStaking \| rosettaNavigation \| securedAssets \| security \| securityCoinShield \| seedPhrase \| selectAddNft \| selfCustodyWallet \| selfServe \| sellSendAnytime \| sendPaymentToOthers \| settled \| sideChainSide \| signInNavigation \| smsAuthenticate \| sparkleCoinbaseOne \| ssnCard \| stableCoinMetaphor \| stacking \| stakingGraph \| standWithCryptoLogoNavigation \| startToday \| strongInfo \| strongWarning \| successPhone \| supportChat \| takeQuiz \| target \| taxBeta \| taxCenterNavigation \| taxesArrangement \| taxSeason \| timingCheck \| tokenBaskets \| transferSend \| transistor \| trendingAssets \| trusted \| tryAgainLater \| twoBonus \| typeScript \| ubiKey \| usaProduct \| usdcEarn \| usdcInterest \| usdcLoan \| usdcLogo \| usdcRewards \| usdcRewardsRibbon \| usdcToken \| venturesNavigation \| videoCalendar \| videoContent \| waiting \| waitingForConsensus \| walletAsServiceNavigation \| walletDeposit \| walletError \| walletExchange \| walletLinkNavigation \| walletLogoNavigation \| walletNavigation \| walletPassword \| walletSuccess \| walletWarning \| winBTC \| worldwide \| wrapEth` | No | `-` | Illustration pictogram name for alert |
161
161
  | `preferredActionVariant` | `primary \| negative` | No | `primary` | Button variant of the preferred action |
162
162
  | `ref` | `((instance: ModalRefBaseProps \| null) => void) \| RefObject<ModalRefBaseProps> \| null` | No | `-` | - |
163
163
  | `stacked` | `boolean` | No | `-` | Indicating if Alert is stacked on top of Modal |
@@ -10,13 +10,37 @@ import { Combobox } from '@coinbase/cds-web/alpha/combobox'
10
10
 
11
11
  ## Examples
12
12
 
13
- ### A note on search logic
13
+ ### Basics
14
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.
15
+ To start, you can provide a label, an array of options, control state.
16
16
 
17
- ### Multi-Select
17
+ ```tsx live
18
+ function SingleSelect() {
19
+ const singleSelectOptions = [
20
+ { value: null, label: 'Remove selection' },
21
+ { value: 'apple', label: 'Apple' },
22
+ { value: 'banana', label: 'Banana' },
23
+ { value: 'cherry', label: 'Cherry' },
24
+ { value: 'date', label: 'Date' },
25
+ ];
26
+
27
+ const [value, setValue] = useState('apple');
28
+
29
+ return (
30
+ <Combobox
31
+ label="Favorite fruit"
32
+ onChange={setValue}
33
+ options={singleSelectOptions}
34
+ placeholder="Search fruits..."
35
+ value={value}
36
+ />
37
+ );
38
+ }
39
+ ```
18
40
 
19
- Basic multi-selection combobox with search.
41
+ #### Multiple Selections
42
+
43
+ You can also allow users to select multiple options with `type="multi"`.
20
44
 
21
45
  ```tsx live
22
46
  function MultiSelect() {
@@ -38,7 +62,7 @@ function MultiSelect() {
38
62
  { value: 'strawberry', label: 'Strawberry' },
39
63
  ];
40
64
 
41
- const { value, onChange } = useMultiSelect({ initialValue: ['apple', 'banana'] });
65
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
42
66
 
43
67
  return (
44
68
  <Combobox
@@ -53,67 +77,80 @@ function MultiSelect() {
53
77
  }
54
78
  ```
55
79
 
56
- ### Single Select
80
+ ### Search
57
81
 
58
- Standard single-selection combobox with an option to clear the current value.
82
+ We use [fuse.js](https://www.fusejs.io/) for fuzzy search by default. You can override with `filterFunction`.
59
83
 
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' },
84
+ ```tsx live
85
+ function CustomFilter() {
86
+ const cryptoOptions: SelectOption[] = [
87
+ { value: 'btc', label: 'Bitcoin', description: 'BTC • Digital Gold' },
88
+ { value: 'eth', label: 'Ethereum', description: 'ETH • Smart Contracts' },
89
+ { value: 'usdc', label: 'USD Coin', description: 'USDC • Stablecoin' },
90
+ { value: 'sol', label: 'Solana', description: 'SOL • High Performance' },
68
91
  ];
69
92
 
70
- const [value, setValue] = useState('apple');
93
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
94
+
95
+ const filterFunction = useCallback((options: SelectOption[], searchText: string) => {
96
+ const search = searchText.toLowerCase().trim();
97
+ if (!search) return options;
98
+ return options.filter((option) => {
99
+ const label = typeof option.label === 'string' ? option.label.toLowerCase() : '';
100
+ const description =
101
+ typeof option.description === 'string' ? option.description.toLowerCase() : '';
102
+ return label.startsWith(search) || description.startsWith(search);
103
+ });
104
+ }, []);
71
105
 
72
106
  return (
73
107
  <Combobox
74
- label="Favorite fruit"
75
- onChange={setValue}
76
- options={singleSelectOptions}
77
- placeholder="Search fruits..."
108
+ filterFunction={filterFunction}
109
+ label="Custom filter (starts with)"
110
+ onChange={onChange}
111
+ options={cryptoOptions}
112
+ placeholder="Type to filter..."
113
+ type="multi"
78
114
  value={value}
79
115
  />
80
116
  );
81
117
  }
82
118
  ```
83
119
 
84
- ### Helper Text
120
+ ### Grouped
85
121
 
86
- Communicate limits or guidance by pairing helper text with multi-select usage.
122
+ Display options under headers using `label` and `options`. Sort options by the same dimension you group by.
87
123
 
88
124
  ```tsx 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' },
125
+ function GroupedOptions() {
126
+ const groupedOptions = [
127
+ {
128
+ label: 'Fruits',
129
+ options: [
130
+ { value: 'apple', label: 'Apple' },
131
+ { value: 'banana', label: 'Banana' },
132
+ { value: 'cherry', label: 'Cherry' },
133
+ { value: 'date', label: 'Date' },
134
+ ],
135
+ },
136
+ {
137
+ label: 'Vegetables',
138
+ options: [
139
+ { value: 'carrot', label: 'Carrot' },
140
+ { value: 'broccoli', label: 'Broccoli' },
141
+ { value: 'spinach', label: 'Spinach' },
142
+ ],
143
+ },
106
144
  ];
107
145
 
108
- const { value, onChange } = useMultiSelect({ initialValue: ['apple', 'banana'] });
146
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
109
147
 
110
148
  return (
111
149
  <Combobox
112
- helperText="Choose more than one fruit"
113
- label="Select fruits"
150
+ label="Category"
114
151
  onChange={onChange}
115
- options={fruitOptions}
116
- placeholder="Search and select fruits..."
152
+ options={groupedOptions}
153
+ placeholder="Search by category..."
117
154
  type="multi"
118
155
  value={value}
119
156
  />
@@ -121,13 +158,75 @@ function HelperText() {
121
158
  }
122
159
  ```
123
160
 
124
- ### Alignment
161
+ ### Accessibility
162
+
163
+ Use accessibility labels to provide clear control and dropdown context. For multi-select, add remove and hidden-selection labels so screen readers can describe chip actions and +X summaries.
164
+
165
+ ```tsx live
166
+ function AccessibilityProps() {
167
+ const priorityOptions: SelectOption[] = [
168
+ { value: 'high', label: 'High Priority' },
169
+ { value: 'medium', label: 'Medium Priority' },
170
+ { value: 'low', label: 'Low Priority' },
171
+ ];
172
+
173
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
174
+
175
+ return (
176
+ <Combobox
177
+ accessibilityLabel="Priority options list"
178
+ controlAccessibilityLabel="Task priority combobox"
179
+ hiddenSelectedOptionsLabel="priorities"
180
+ label="Task Priority"
181
+ maxSelectedOptionsToShow={1}
182
+ onChange={onChange}
183
+ options={priorityOptions}
184
+ placeholder="Choose priority..."
185
+ removeSelectedOptionAccessibilityLabel="Remove priority"
186
+ type="multi"
187
+ value={value}
188
+ />
189
+ );
190
+ }
191
+ ```
192
+
193
+ ### Styling
194
+
195
+ #### Selection Display Limit
196
+
197
+ Cap visible chips with `maxSelectedOptionsToShow`; the rest show as +X more. Pair with `hiddenSelectedOptionsLabel` for screen readers.
198
+
199
+ ```tsx live
200
+ function LimitDisplayedSelections() {
201
+ const countryOptions: SelectOption[] = [
202
+ { value: 'us', label: 'United States', description: 'North America' },
203
+ { value: 'ca', label: 'Canada', description: 'North America' },
204
+ { value: 'mx', label: 'Mexico', description: 'North America' },
205
+ { value: 'uk', label: 'United Kingdom', description: 'Europe' },
206
+ { value: 'fr', label: 'France', description: 'Europe' },
207
+ { value: 'de', label: 'Germany', description: 'Europe' },
208
+ ];
209
+
210
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
211
+
212
+ return (
213
+ <Combobox
214
+ hiddenSelectedOptionsLabel="countries"
215
+ label="Countries"
216
+ maxSelectedOptionsToShow={2}
217
+ onChange={onChange}
218
+ options={countryOptions}
219
+ placeholder="Select countries..."
220
+ type="multi"
221
+ value={value}
222
+ />
223
+ );
224
+ }
225
+ ```
125
226
 
126
- The alignment of the selected value(s) can be adjusted using the `align` prop.
227
+ #### Alignment
127
228
 
128
- ::::note
129
- Left / right alignment is preferred for styling.
130
- ::::
229
+ Align selected values with the `align` prop.
131
230
 
132
231
  ```tsx live
133
232
  function AlignmentExample() {
@@ -136,82 +235,322 @@ function AlignmentExample() {
136
235
  { value: 'banana', label: 'Banana' },
137
236
  { value: 'cherry', label: 'Cherry' },
138
237
  { value: 'date', label: 'Date' },
139
- { value: 'elderberry', label: 'Elderberry' },
140
- { value: 'fig', label: 'Fig' },
141
238
  ];
142
- const { value: multiValue, onChange: multiOnChange } = useMultiSelect({
143
- initialValue: ['apple', 'banana'],
144
- });
239
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
145
240
 
146
241
  return (
147
- <VStack gap={1}>
242
+ <VStack gap={2}>
148
243
  <Combobox
149
- label="Default align - start"
150
- onChange={multiOnChange}
244
+ align="start"
245
+ label="Align start"
246
+ onChange={onChange}
151
247
  options={fruitOptions}
152
- placeholder="Empty value"
248
+ placeholder="Search..."
153
249
  type="multi"
154
- value={multiValue}
250
+ value={value}
155
251
  />
156
252
  <Combobox
157
253
  align="end"
158
- label="End align"
159
- onChange={multiOnChange}
254
+ label="Align end"
255
+ onChange={onChange}
160
256
  options={fruitOptions}
161
- placeholder="Empty value"
257
+ placeholder="Search..."
162
258
  type="multi"
163
- value={multiValue}
259
+ value={value}
164
260
  />
165
261
  </VStack>
166
262
  );
167
263
  }
168
264
  ```
169
265
 
170
- ### Borderless
266
+ #### Borderless
171
267
 
172
- You can remove the border from the combobox control by setting `bordered` to `false`.
268
+ Remove the border with `bordered={false}`.
173
269
 
174
- ```jsx live
270
+ ```tsx live
175
271
  function BorderlessExample() {
176
- const singleSelectOptions = [
177
- { value: null, label: 'Remove selection' },
272
+ const fruitOptions = [
273
+ { value: 'apple', label: 'Apple' },
274
+ { value: 'banana', label: 'Banana' },
275
+ { value: 'cherry', label: 'Cherry' },
276
+ ];
277
+ const [value, setValue] = useState('apple');
278
+
279
+ return (
280
+ <Combobox
281
+ bordered={false}
282
+ label="Borderless"
283
+ onChange={setValue}
284
+ options={fruitOptions}
285
+ placeholder="Search..."
286
+ value={value}
287
+ />
288
+ );
289
+ }
290
+ ```
291
+
292
+ #### Compact
293
+
294
+ Use smaller sizing with `compact`.
295
+
296
+ ```tsx live
297
+ function CompactExample() {
298
+ const fruitOptions = [
299
+ { value: 'apple', label: 'Apple' },
300
+ { value: 'banana', label: 'Banana' },
301
+ { value: 'cherry', label: 'Cherry' },
302
+ ];
303
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
304
+
305
+ return (
306
+ <Combobox
307
+ compact
308
+ label="Compact"
309
+ onChange={onChange}
310
+ options={fruitOptions}
311
+ placeholder="Compact combobox..."
312
+ type="multi"
313
+ value={value}
314
+ />
315
+ );
316
+ }
317
+ ```
318
+
319
+ #### Helper Text
320
+
321
+ Add guidance with `helperText`.
322
+
323
+ ```tsx live
324
+ function HelperTextExample() {
325
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
326
+ const fruitOptions: SelectOption[] = [
178
327
  { value: 'apple', label: 'Apple' },
179
328
  { value: 'banana', label: 'Banana' },
180
329
  { value: 'cherry', label: 'Cherry' },
181
330
  { value: 'date', label: 'Date' },
182
331
  ];
183
332
 
333
+ return (
334
+ <Combobox
335
+ helperText="Choose more than one fruit"
336
+ label="Select fruits"
337
+ onChange={onChange}
338
+ options={fruitOptions}
339
+ placeholder="Search and select fruits..."
340
+ type="multi"
341
+ value={value}
342
+ />
343
+ );
344
+ }
345
+ ```
346
+
347
+ ### Composed Examples
348
+
349
+ #### Country Selection
350
+
351
+ You can include flag emoji in labels to create a country selector.
352
+
353
+ ```tsx live
354
+ function CountrySelectionExample() {
355
+ const getFlagEmoji = (cc) =>
356
+ cc
357
+ .toUpperCase()
358
+ .split('')
359
+ .map((c) => String.fromCodePoint(0x1f1e6 - 65 + c.charCodeAt(0)))
360
+ .join('');
361
+
362
+ const countryOptions = [
363
+ {
364
+ label: 'North America',
365
+ options: [
366
+ { value: 'us', label: `${getFlagEmoji('us')} United States` },
367
+ { value: 'ca', label: `${getFlagEmoji('ca')} Canada` },
368
+ { value: 'mx', label: `${getFlagEmoji('mx')} Mexico` },
369
+ ],
370
+ },
371
+ {
372
+ label: 'Europe',
373
+ options: [
374
+ { value: 'uk', label: `${getFlagEmoji('gb')} United Kingdom` },
375
+ { value: 'fr', label: `${getFlagEmoji('fr')} France` },
376
+ { value: 'de', label: `${getFlagEmoji('de')} Germany` },
377
+ ],
378
+ },
379
+ {
380
+ label: 'Asia',
381
+ options: [
382
+ { value: 'jp', label: `${getFlagEmoji('jp')} Japan` },
383
+ { value: 'cn', label: `${getFlagEmoji('cn')} China` },
384
+ { value: 'in', label: `${getFlagEmoji('in')} India` },
385
+ ],
386
+ },
387
+ ];
388
+
389
+ const { value, onChange } = useMultiSelect({ initialValue: [] });
390
+
391
+ return (
392
+ <Combobox
393
+ label="Country"
394
+ maxSelectedOptionsToShow={3}
395
+ onChange={onChange}
396
+ options={countryOptions}
397
+ placeholder="Select countries..."
398
+ type="multi"
399
+ value={value}
400
+ />
401
+ );
402
+ }
403
+ ```
404
+
405
+ #### Free Solo
406
+
407
+ You can add a dynamic option to Combobox to enable free solo where users can provide their own value.
408
+
409
+ ```tsx live
410
+ function FreeSoloExample() {
411
+ const CREATE_OPTION_PREFIX = '__create__';
412
+
413
+ const FreeSoloCombobox = useMemo(() => {
414
+ function StableFreeSoloCombobox({
415
+ freeSolo = false,
416
+ options: initialOptions,
417
+ value,
418
+ onChange,
419
+ placeholder = 'Search or type to add...',
420
+ ...comboboxProps
421
+ }) {
422
+ const [searchText, setSearchText] = useState('');
423
+ const [options, setOptions] = useState(initialOptions);
424
+
425
+ useEffect(() => {
426
+ if (!freeSolo) return;
427
+ const initialSet = new Set(initialOptions.map((option) => option.value));
428
+ const valueSet = new Set(Array.isArray(value) ? value : value != null ? [value] : []);
429
+ setOptions((prevOptions) => {
430
+ const addedStillSelected = prevOptions.filter(
431
+ (option) => !initialSet.has(option.value) && valueSet.has(option.value),
432
+ );
433
+ return [...initialOptions, ...addedStillSelected];
434
+ });
435
+ }, [freeSolo, initialOptions, value]);
436
+
437
+ const optionsWithCreate = useMemo(() => {
438
+ if (!freeSolo) return options;
439
+ const trimmedSearch = searchText.trim();
440
+ if (!trimmedSearch) return options;
441
+
442
+ const alreadyExists = options.some(
443
+ (option) =>
444
+ typeof option.label === 'string' &&
445
+ option.label.toLowerCase() === trimmedSearch.toLowerCase(),
446
+ );
447
+ if (alreadyExists) return options;
448
+
449
+ return [
450
+ ...options,
451
+ { value: `${CREATE_OPTION_PREFIX}${trimmedSearch}`, label: `Add "${trimmedSearch}"` },
452
+ ];
453
+ }, [freeSolo, options, searchText]);
454
+
455
+ const handleChange = useCallback(
456
+ (newValue) => {
457
+ if (!freeSolo) {
458
+ onChange(newValue);
459
+ return;
460
+ }
461
+
462
+ const values = Array.isArray(newValue) ? newValue : newValue ? [newValue] : [];
463
+ const createValue = values.find((optionValue) =>
464
+ String(optionValue).startsWith(CREATE_OPTION_PREFIX),
465
+ );
466
+
467
+ if (!createValue) {
468
+ onChange(newValue);
469
+ return;
470
+ }
471
+
472
+ const newLabel = String(createValue).slice(CREATE_OPTION_PREFIX.length);
473
+ const normalizedValue = newLabel.toLowerCase();
474
+ const newOption = { value: normalizedValue, label: newLabel };
475
+
476
+ setOptions((prevOptions) => [...prevOptions, newOption]);
477
+
478
+ const updatedValues = values
479
+ .filter((optionValue) => !String(optionValue).startsWith(CREATE_OPTION_PREFIX))
480
+ .concat(normalizedValue);
481
+
482
+ onChange(comboboxProps.type === 'multi' ? updatedValues : normalizedValue);
483
+ setSearchText('');
484
+ },
485
+ [comboboxProps.type, freeSolo, onChange],
486
+ );
487
+
488
+ return (
489
+ <Combobox
490
+ {...comboboxProps}
491
+ {...(freeSolo ? { searchText, onSearch: setSearchText } : {})}
492
+ onChange={handleChange}
493
+ options={freeSolo ? optionsWithCreate : initialOptions}
494
+ placeholder={placeholder}
495
+ value={value}
496
+ />
497
+ );
498
+ }
499
+
500
+ return StableFreeSoloCombobox;
501
+ }, [CREATE_OPTION_PREFIX]);
502
+
184
503
  const fruitOptions = [
185
504
  { value: 'apple', label: 'Apple' },
186
505
  { value: 'banana', label: 'Banana' },
187
506
  { value: 'cherry', label: 'Cherry' },
188
507
  { value: 'date', label: 'Date' },
189
508
  { value: 'elderberry', label: 'Elderberry' },
509
+ { value: 'fig', label: 'Fig' },
190
510
  ];
191
511
 
192
- const [singleValue, setSingleValue] = useState('apple');
193
- const { value: multiValue, onChange: multiOnChange } = useMultiSelect({
194
- initialValue: ['apple'],
195
- });
512
+ const [standardSingleValue, setStandardSingleValue] = useState(null);
513
+ const [freeSoloSingleValue, setFreeSoloSingleValue] = useState(null);
514
+ const standardMulti = useMultiSelect({ initialValue: [] });
515
+ const freeSoloMulti = useMultiSelect({ initialValue: [] });
196
516
 
197
517
  return (
198
518
  <VStack gap={4}>
199
- <Combobox
200
- bordered={false}
201
- label="Borderless single select"
202
- onChange={setSingleValue}
203
- options={singleSelectOptions}
519
+ <FreeSoloCombobox
520
+ freeSolo={false}
521
+ label="Standard single"
522
+ onChange={setStandardSingleValue}
523
+ options={fruitOptions}
204
524
  placeholder="Search fruits..."
205
- value={singleValue}
525
+ type="single"
526
+ value={standardSingleValue}
206
527
  />
207
- <Combobox
208
- bordered={false}
209
- label="Borderless multi select"
210
- onChange={multiOnChange}
528
+ <FreeSoloCombobox
529
+ freeSolo
530
+ label="FreeSolo single"
531
+ onChange={setFreeSoloSingleValue}
532
+ options={fruitOptions}
533
+ placeholder="Search or type to add..."
534
+ type="single"
535
+ value={freeSoloSingleValue}
536
+ />
537
+ <FreeSoloCombobox
538
+ freeSolo={false}
539
+ label="Standard multi"
540
+ onChange={standardMulti.onChange}
211
541
  options={fruitOptions}
212
542
  placeholder="Search fruits..."
213
543
  type="multi"
214
- value={multiValue}
544
+ value={standardMulti.value}
545
+ />
546
+ <FreeSoloCombobox
547
+ freeSolo
548
+ label="FreeSolo multi"
549
+ onChange={freeSoloMulti.onChange}
550
+ options={fruitOptions}
551
+ placeholder="Search or type to add..."
552
+ type="multi"
553
+ value={freeSoloMulti.value}
215
554
  />
216
555
  </VStack>
217
556
  );