Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/common/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.

<!-- template-start -->

## 8.58.0 ((3/25/2026, 11:42 AM PST))

This is an artificial version bump with no new change.

## 8.57.1 ((3/24/2026, 01:14 PM PST))

This is an artificial version bump with no new change.
Expand Down
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-common",
"version": "8.57.1",
"version": "8.58.0",
"description": "Coinbase Design System - Common",
"repository": {
"type": "git",
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ All notable changes to this project will be documented in this file.

<!-- template-start -->

## 8.58.0 ((3/25/2026, 11:42 AM PST))

This is an artificial version bump with no new change.

## 8.57.1 ((3/24/2026, 01:14 PM PST))

This is an artificial version bump with no new change.
Expand Down
2 changes: 1 addition & 1 deletion packages/mcp-server/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-mcp-server",
"version": "8.57.1",
"version": "8.58.0",
"description": "Coinbase Design System - MCP Server",
"repository": {
"type": "git",
Expand Down
7 changes: 7 additions & 0 deletions packages/mobile/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ All notable changes to this project will be documented in this file.

<!-- template-start -->

## 8.58.0 (3/25/2026 PST)

#### 🚀 Updates

- Feat: support inputFont on inputs. [[#545](https://github.com/coinbase/cds/pull/545)]
- Feat: support borderRadius on SearchInput. [[#545](https://github.com/coinbase/cds/pull/545)]

## 8.57.1 ((3/24/2026, 01:14 PM PST))

This is an artificial version bump with no new change.
Expand Down
2 changes: 1 addition & 1 deletion packages/mobile/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@coinbase/cds-mobile",
"version": "8.57.1",
"version": "8.58.0",
"description": "Coinbase Design System - Mobile",
"repository": {
"type": "git",
Expand Down
6 changes: 4 additions & 2 deletions packages/mobile/src/alpha/combobox/Combobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export type ComboboxControlProps<
Type extends SelectType = 'single',
SelectOptionValue extends string = string,
> = SelectControlProps<Type, SelectOptionValue> &
Pick<ComboboxBaseProps<Type, SelectOptionValue>, 'hideSearchInput'> & {
Pick<ComboboxBaseProps<Type, SelectOptionValue>, 'hideSearchInput' | 'inputFont'> & {
/** Search text value */
searchText: string;
/** Search text change handler */
Expand Down Expand Up @@ -191,6 +191,7 @@ const ComboboxBase = memo(
ComboboxControlComponent = DefaultComboboxControl,
SelectDropdownComponent = DefaultSelectDropdown,
hideSearchInput,
inputFont,
...props
}: ComboboxProps<Type, SelectOptionValue>,
ref: React.Ref<ComboboxRef>,
Expand Down Expand Up @@ -261,11 +262,12 @@ const ComboboxBase = memo(
ComboboxControlComponent={ComboboxControlComponent}
SelectControlComponent={SelectControlComponent}
controlRef={controlRef}
inputFont={inputFont}
searchInputRef={searchInputRef}
/>
);
},
[ComboboxControlComponent, SelectControlComponent, searchInputRef],
[ComboboxControlComponent, SelectControlComponent, inputFont, searchInputRef],
);

const ComboboxDropdown = useCallback(
Expand Down
7 changes: 5 additions & 2 deletions packages/mobile/src/alpha/combobox/DefaultComboboxControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const DefaultComboboxControl = <
options,
searchText,
onSearch,
inputFont = 'body',
searchInputRef,
hideSearchInput,
accessibilityLabel,
Expand Down Expand Up @@ -56,6 +57,7 @@ export const DefaultComboboxControl = <
accessibilityLabel={computedAccessibilityLabel}
align={align}
disabled={disabled}
inputFont={inputFont}
open={open}
options={options}
setOpen={setOpen}
Expand All @@ -67,6 +69,7 @@ export const DefaultComboboxControl = <
<NativeInput
ref={searchInputRef}
disabled={disabled || !open}
inputFont={inputFont}
onChangeText={onSearch}
onPress={() => !disabled && setOpen(true)}
placeholder={typeof placeholder === 'string' ? placeholder : undefined}
Expand All @@ -76,7 +79,7 @@ export const DefaultComboboxControl = <
flexShrink: 1,
minWidth: 0,
padding: 0,
height: hasValue ? 24 : 48,
height: hasValue ? theme.lineHeight[inputFont] : 48,
marginTop: hasValue ? 0 : -24,
marginBottom: hasValue ? -12 : -24,
paddingTop: hasValue ? 8 : 0,
Expand All @@ -91,7 +94,7 @@ export const DefaultComboboxControl = <
) : (
<>
{hasValue ? null : (
<Text color="fgMuted" font="body" paddingY={0} textAlign={valueAlignment}>
<Text color="fgMuted" font={inputFont} paddingY={0} textAlign={valueAlignment}>
{typeof placeholder === 'string' ? placeholder : ''}
</Text>
)}
Expand Down
22 changes: 22 additions & 0 deletions packages/mobile/src/alpha/combobox/__tests__/Combobox.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { createRef } from 'react';
import { StyleSheet } from 'react-native';
import { fireEvent, render, screen } from '@testing-library/react-native';

import { defaultTheme } from '../../../themes/defaultTheme';
import { DefaultThemeProvider } from '../../../utils/testHelpers';
import type { SelectOption } from '../../select/Select';
import { Combobox, type ComboboxProps, type ComboboxRef } from '../Combobox';
Expand Down Expand Up @@ -129,6 +131,26 @@ describe('Combobox', () => {
expect(input).toBeTruthy();
});

it('passes inputFont to the search input', () => {
render(
<DefaultThemeProvider>
<Combobox {...defaultProps} defaultOpen inputFont="label1" />
</DefaultThemeProvider>,
);

const inputs = screen.getAllByPlaceholderText('Search and select...');
expect(
inputs.some((input) => {
const flattenedStyle = StyleSheet.flatten(input.props.style);
return (
flattenedStyle?.fontSize === defaultTheme.fontSize.label1 &&
flattenedStyle?.lineHeight === defaultTheme.lineHeight.label1 &&
flattenedStyle?.fontWeight === defaultTheme.fontWeight.label1
);
}),
).toBe(true);
});

it('throws error when searchText is provided without onSearch', () => {
const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

Expand Down
4 changes: 3 additions & 1 deletion packages/mobile/src/alpha/select/DefaultSelectControl.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const DefaultSelectControlComponent = memo(
endNode: customEndNode,
compact,
align = 'start',
inputFont = 'body',
bordered = true,
borderWidth = bordered ? 100 : 0,
focusedBorderWidth = bordered ? undefined : 200,
Expand Down Expand Up @@ -264,7 +265,7 @@ export const DefaultSelectControlComponent = memo(
}

return typeof singleValueContent === 'string' ? (
<Text align={align} color={hasValue ? 'fg' : 'fgMuted'} ellipsize="tail" font="body">
<Text align={align} color={hasValue ? 'fg' : 'fgMuted'} ellipsize="tail" font={inputFont}>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels slightly funky to use inputFont here but this matches visually with the same spot on TextInput and Combobox.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah def funky naming for Select specifically - makes sense in the context of combobox

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could call it controlFont for Select and then map the property for combobox's NativeInput, any thoughts there?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hcopp what about just font for Select? Could that work for Combobox too and we just document that it maps to both the values and text input elements? If they needed to break from that convention (seems uncommon) they could provide a custom component

{singleValueContent}
</Text>
) : (
Expand All @@ -274,6 +275,7 @@ export const DefaultSelectControlComponent = memo(
hasValue,
isMultiSelect,
singleValueContent,
inputFont,
align,
value,
maxSelectedOptionsToShow,
Expand Down
2 changes: 2 additions & 0 deletions packages/mobile/src/alpha/select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ const SelectBase = memo(
media,
end,
align,
inputFont,
bordered = true,
SelectOptionComponent = DefaultSelectOption,
SelectAllOptionComponent = DefaultSelectAllOption,
Expand Down Expand Up @@ -180,6 +181,7 @@ const SelectBase = memo(
endNode={endNode}
helperText={helperText}
hiddenSelectedOptionsLabel={hiddenSelectedOptionsLabel}
inputFont={inputFont}
label={label}
labelVariant={labelVariant}
maxSelectedOptionsToShow={maxSelectedOptionsToShow}
Expand Down
7 changes: 7 additions & 0 deletions packages/mobile/src/alpha/select/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type React from 'react';
import type { AccessibilityRole, StyleProp, TouchableOpacity, View, ViewStyle } from 'react-native';
import type { ThemeVars } from '@coinbase/cds-common/core/theme';
import type { SharedAccessibilityProps } from '@coinbase/cds-common/types';

import type { CellBaseProps } from '../../cells/Cell';
Expand Down Expand Up @@ -250,6 +251,11 @@ export type SelectControlProps<
* @default 'start'
*/
align?: 'start' | 'center' | 'end';
/**
* Typography font token used for typed search input text in select controls that render inputs.
* @default body
*/
inputFont?: ThemeVars.Font;
/**
* Determines if the control should have a default border.
* @note focusedBorderWidth on the control still shows a border when focused by default.
Expand Down Expand Up @@ -414,6 +420,7 @@ export type SelectBaseProps<
| 'labelVariant'
| 'endNode'
| 'align'
| 'inputFont'
| 'bordered'
> &
Pick<SelectOptionProps<Type, SelectOptionValue>, 'accessory' | 'media' | 'end'> &
Expand Down
30 changes: 23 additions & 7 deletions packages/mobile/src/controls/NativeInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { forwardRef, memo, useMemo } from 'react';
import { TextInput } from 'react-native';
import type { TextInputProps, ViewStyle } from 'react-native';
import type { StyleProp, TextInputProps, TextStyle, ViewStyle } from 'react-native';
import type { ThemeVars } from '@coinbase/cds-common/core/theme';
import type { SharedProps } from '@coinbase/cds-common/types';
import type { SharedAccessibilityProps } from '@coinbase/cds-common/types/SharedAccessibilityProps';

Expand Down Expand Up @@ -29,6 +30,11 @@ export type NativeInputProps = {
* @warning Setting this to unset will break alignment for RTL languages.
*/
textAlign?: TextInputProps['textAlign'] | 'unset';
/**
* Typography font token used for typed input text.
* @default body
*/
inputFont?: ThemeVars.Font;
} & SharedProps &
Pick<TextInputBaseProps, 'compact'> &
Pick<
Expand All @@ -46,6 +52,7 @@ export const NativeInput = memo(
align = 'start',
disabled,
textAlign,
inputFont = 'body',
accessibilityLabel,
compact,
style,
Expand All @@ -56,16 +63,25 @@ export const NativeInput = memo(
const theme = useTheme();
const textAlignInputTransformed = useTextAlign(align).textAlign;

const inputTextStyle = useMemo(
const inputTextStyle: TextStyle = useMemo(
() => ({
fontSize: theme.fontSize.body,
fontFamily: theme.fontFamily.body,
minHeight: theme.lineHeight.body,
fontSize: theme.fontSize[inputFont],
fontFamily: theme.fontFamily[inputFont],
lineHeight: theme.lineHeight[inputFont],
minHeight: theme.lineHeight[inputFont],
fontWeight: theme.fontWeight[inputFont] as TextStyle['fontWeight'],
padding: 0,
margin: 0,
color: theme.color.fg,
}),
[theme.fontSize, theme.fontFamily, theme.lineHeight, theme.color.fg],
[
theme.fontSize,
theme.fontFamily,
theme.lineHeight,
theme.fontWeight,
theme.color.fg,
inputFont,
],
);

const containerStyle: ViewStyle = useMemo(() => {
Expand All @@ -87,7 +103,7 @@ export const NativeInput = memo(
disabled,
]);

const inputRootStyles = useMemo(() => {
const inputRootStyles: StyleProp<TextStyle> = useMemo(() => {
return [
inputTextStyle,
containerStyle,
Expand Down
5 changes: 4 additions & 1 deletion packages/mobile/src/controls/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ export type SearchInputBaseProps = Pick<
| 'accessibilityLabel'
| 'accessibilityLabelledBy'
| 'bordered'
| 'borderRadius'
| 'compact'
| 'disabled'
| 'enableColorSurge'
| 'focusedBorderWidth'
| 'helperTextErrorIconAccessibilityLabel'
| 'inputFont'
| 'placeholder'
| 'testID'
| 'testIDMap'
Expand Down Expand Up @@ -107,6 +109,7 @@ export const SearchInput = memo(
end,
startIconAccessibilityLabel = 'Back',
clearIconAccessibilityLabel = 'Clear text',
borderRadius = 1000,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also unlocking custom border radius for search input

...props
}: SearchInputProps,
ref: ForwardedRef<RNTextInput>,
Expand Down Expand Up @@ -174,7 +177,7 @@ export const SearchInput = memo(
<TextInput
ref={refs}
accessibilityRole="search"
borderRadius={1000}
borderRadius={borderRadius}
disabled={disabled}
end={
end ??
Expand Down
7 changes: 7 additions & 0 deletions packages/mobile/src/controls/TextInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ export type TextInputBaseProps = SharedProps &
* @default start
*/
align?: TextAlignProps['align'];
/**
* Typography font token used for typed input text.
* @default body
*/
inputFont?: ThemeVars.Font;
/**
* Adds suffix text to the end of input
*/
Expand Down Expand Up @@ -141,6 +146,7 @@ export const TextInput = memo(
width = '100%',
disabled = false,
align = 'start',
inputFont = 'body',
compact,
suffix = '',
accessibilityLabel,
Expand Down Expand Up @@ -297,6 +303,7 @@ export const TextInput = memo(
compact={compact}
containerSpacing={containerSpacing}
disabled={disabled}
inputFont={inputFont}
testID={testID}
{...editableInputAddonProps}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const BorderlessVariants = () => {
return (
<VStack gap={2}>
<SearchInput
borderRadius={200}
bordered={false}
editable={__DEV__}
onChangeText={setDefaultBorderlessText}
Expand Down
Loading
Loading