diff --git a/.changeset/spotty-papers-call.md b/.changeset/spotty-papers-call.md new file mode 100644 index 0000000000..3e39e8e1f8 --- /dev/null +++ b/.changeset/spotty-papers-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': minor +--- + +The icon prop in TextField now accept a ReactNode instead of an icon name. We also updated the icon sizes for each input sizes. diff --git a/canon-docs/src/app/(docs)/components/text-field/page.mdx b/canon-docs/src/app/(docs)/components/text-field/page.mdx index bd5fa31025..ed857def4e 100644 --- a/canon-docs/src/app/(docs)/components/text-field/page.mdx +++ b/canon-docs/src/app/(docs)/components/text-field/page.mdx @@ -33,9 +33,16 @@ A text field component for your forms. We recommend starting with our [global tokens](/theme/theming) to customize the library and align it with your brand. For additional flexibility, you can use the provided class names for each element listed below. - `} - /> + - `canon-TextField` + - `canon-TextFieldLabel` + - `canon-TextFieldRequired` + - `canon-TextFieldInputWrapper` + - `canon-TextFieldIcon` + - `canon-TextFieldInput` + - `canon-TextFieldClearButton` + - `canon-TextFieldClearButtonIcon` + - `canon-TextFieldDescription` + - `canon-TextFieldError` @@ -55,8 +62,8 @@ We support two different sizes: `small`, `medium`. open preview={} code={` - - + } /> + } /> `} /> diff --git a/canon-docs/src/app/(docs)/components/text-field/props.ts b/canon-docs/src/app/(docs)/components/text-field/props.ts index cafed21189..74dec9d5e6 100644 --- a/canon-docs/src/app/(docs)/components/text-field/props.ts +++ b/canon-docs/src/app/(docs)/components/text-field/props.ts @@ -5,12 +5,16 @@ export const inputPropDefs: Record = { size: { type: 'enum', values: ['small', 'medium'], - default: 'medium', - responsive: false, + default: 'small', + responsive: true, }, label: { type: 'string', }, + icon: { + type: 'enum', + values: ['ReactNode'], + }, description: { type: 'string', }, diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 6aae715633..d479444df9 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -576,13 +576,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 5fb6a934cb..6c53aaa198 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9800,13 +9800,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/css/textfield.css b/packages/canon/css/textfield.css index a2980d6beb..c3c1a88ad6 100644 --- a/packages/canon/css/textfield.css +++ b/packages/canon/css/textfield.css @@ -43,13 +43,20 @@ display: flex; } -.canon-TextFieldInputIcon { - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; - display: block; +} + +.canon-TextFieldIcon[data-size="small"], .canon-TextFieldIcon[data-size="small"] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size="medium"], .canon-TextFieldIcon[data-size="medium"] svg { + width: 1.25rem; + height: 1.25rem; } .canon-TextFieldInput { diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index da1b5015b4..cbbdd4db33 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -15,6 +15,7 @@ import { ForwardRefExoticComponent } from 'react'; import { HTMLAttributes } from 'react'; import { JSX as JSX_2 } from 'react/jsx-runtime'; import { Menu as Menu_2 } from '@base-ui-components/react/menu'; +import type { MouseEventHandler } from 'react'; import { ReactElement } from 'react'; import { ReactNode } from 'react'; import { RefAttributes } from 'react'; @@ -1220,10 +1221,10 @@ export interface TextFieldProps className?: string; description?: string; error?: string | null; - icon?: IconNames; + icon?: ReactNode; label?: string; name: string; - onClear?: React.MouseEventHandler; + onClear?: MouseEventHandler; size?: 'small' | 'medium' | Partial>; } diff --git a/packages/canon/src/components/TextField/TextField.stories.tsx b/packages/canon/src/components/TextField/TextField.stories.tsx index 0615a157a1..7e625dad24 100644 --- a/packages/canon/src/components/TextField/TextField.stories.tsx +++ b/packages/canon/src/components/TextField/TextField.stories.tsx @@ -17,6 +17,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { TextField } from './TextField'; import { Flex } from '../Flex'; +import { Icon } from '../Icon'; const meta = { title: 'Components/TextField', @@ -79,8 +80,8 @@ export const Sizes: Story = { }, render: args => ( - - + } /> + } /> ), }; @@ -114,7 +115,7 @@ export const WithIcon: Story = { args: { ...WithLabel.args, placeholder: 'Search...', - icon: 'search', + icon: , }, }; diff --git a/packages/canon/src/components/TextField/TextField.styles.css b/packages/canon/src/components/TextField/TextField.styles.css index ad3ccc931b..be7ec3379c 100644 --- a/packages/canon/src/components/TextField/TextField.styles.css +++ b/packages/canon/src/components/TextField/TextField.styles.css @@ -59,15 +59,24 @@ background-color: var(--canon-bg-surface-1); } -.canon-TextFieldInputIcon { - display: block; - padding-right: var(--canon-space-1); - width: 1.5rem; - height: 1.5rem; +.canon-TextFieldIcon { + margin-right: var(--canon-space-1); color: var(--canon-fg-primary); flex-shrink: 0; } +.canon-TextFieldIcon[data-size='small'], +.canon-TextFieldIcon[data-size='small'] svg { + width: 1rem; + height: 1rem; +} + +.canon-TextFieldIcon[data-size='medium'], +.canon-TextFieldIcon[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; +} + .canon-TextFieldInput { border: none; background: none; diff --git a/packages/canon/src/components/TextField/TextField.tsx b/packages/canon/src/components/TextField/TextField.tsx index bb32033da4..e4cf43a711 100644 --- a/packages/canon/src/components/TextField/TextField.tsx +++ b/packages/canon/src/components/TextField/TextField.tsx @@ -27,7 +27,7 @@ export const TextField = forwardRef( (props: TextFieldProps, ref) => { const { className, - size = 'medium', + size = 'small', label, description, error, @@ -61,7 +61,15 @@ export const TextField = forwardRef( )}
- {icon && } + {icon && ( + + )} , 'size'> { @@ -54,10 +53,10 @@ export interface TextFieldProps /** * An icon to render before the input */ - icon?: IconNames; + icon?: ReactNode; /** * Handler to call when the clear button is pressed */ - onClear?: React.MouseEventHandler; + onClear?: MouseEventHandler; }