From d2818d437bcd27ea4935c53003ac943f0266a9a8 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 15 May 2025 18:49:16 +0100 Subject: [PATCH 1/6] Improve TextField Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/types.ts | 5 ++--- .../TextField/TextField.stories.tsx | 7 ++++--- .../components/TextField/TextField.styles.css | 19 ++++++++++++++----- .../src/components/TextField/TextField.tsx | 12 ++++++++++-- .../canon/src/components/TextField/types.ts | 3 +-- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 4ab62d5683..15feca581c 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -15,7 +15,6 @@ */ import type { ButtonOwnProps } from './Button.props'; -import { ReactElement } from 'react'; /** * Properties for {@link Button} @@ -44,10 +43,10 @@ export interface ButtonProps /** * Optional icon to display at the start of the button */ - iconStart?: ReactElement; + iconStart?: React.ReactNode; /** * Optional icon to display at the end of the button */ - iconEnd?: ReactElement; + iconEnd?: React.ReactNode; } diff --git a/packages/canon/src/components/TextField/TextField.stories.tsx b/packages/canon/src/components/TextField/TextField.stories.tsx index 0615a157a1..86f9034e5c 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 && ( + + )} Date: Thu, 15 May 2025 18:50:34 +0100 Subject: [PATCH 2/6] Update Button.tsx Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/Button.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index ab70f168c8..e9774ad083 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -24,7 +24,7 @@ import type { ButtonProps } from './types'; export const Button = forwardRef( (props: ButtonProps, ref) => { const { - size = 'medium', + size = 'small', variant = 'primary', disabled, iconStart, From 04a65c63ebc8078e6fd9ffda9953d8ba46c4e3f5 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Thu, 15 May 2025 18:54:38 +0100 Subject: [PATCH 3/6] Add API report + styles + changeset Signed-off-by: Charles de Dreuille --- .changeset/spotty-papers-call.md | 5 +++++ packages/canon/css/components.css | 17 ++++++++++++----- packages/canon/css/styles.css | 17 ++++++++++++----- packages/canon/css/textfield.css | 17 ++++++++++++----- packages/canon/report.api.md | 6 +++--- packages/canon/src/components/Button/Button.tsx | 2 +- 6 files changed, 45 insertions(+), 19 deletions(-) create mode 100644 .changeset/spotty-papers-call.md 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/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..dec30129e3 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -174,8 +174,8 @@ export const buttonPropDefs: { export interface ButtonProps extends Omit, 'children'> { children: React.ReactNode; - iconEnd?: ReactElement; - iconStart?: ReactElement; + iconEnd?: React.ReactNode; + iconStart?: React.ReactNode; size?: ButtonOwnProps['size']; variant?: ButtonOwnProps['variant']; } @@ -1220,7 +1220,7 @@ export interface TextFieldProps className?: string; description?: string; error?: string | null; - icon?: IconNames; + icon?: React.ReactNode; label?: string; name: string; onClear?: React.MouseEventHandler; diff --git a/packages/canon/src/components/Button/Button.tsx b/packages/canon/src/components/Button/Button.tsx index e9774ad083..ab70f168c8 100644 --- a/packages/canon/src/components/Button/Button.tsx +++ b/packages/canon/src/components/Button/Button.tsx @@ -24,7 +24,7 @@ import type { ButtonProps } from './types'; export const Button = forwardRef( (props: ButtonProps, ref) => { const { - size = 'small', + size = 'medium', variant = 'primary', disabled, iconStart, From 3fd94f8f5fd3bba158f2a5ac49e597d8b309d244 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 08:20:18 +0100 Subject: [PATCH 4/6] Docs improvements Signed-off-by: Charles de Dreuille --- .../app/(docs)/components/text-field/page.mdx | 17 ++++++++++++----- .../app/(docs)/components/text-field/props.ts | 8 ++++++-- packages/canon/report.api.md | 5 +++-- .../components/TextField/TextField.stories.tsx | 4 ++-- .../canon/src/components/TextField/types.ts | 6 +++--- 5 files changed, 26 insertions(+), 14 deletions(-) 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/report.api.md b/packages/canon/report.api.md index dec30129e3..ebec81fcae 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?: React.ReactNode; + 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 86f9034e5c..7e625dad24 100644 --- a/packages/canon/src/components/TextField/TextField.stories.tsx +++ b/packages/canon/src/components/TextField/TextField.stories.tsx @@ -80,8 +80,8 @@ export const Sizes: Story = { }, render: args => ( - } /> - } /> + } /> + } /> ), }; diff --git a/packages/canon/src/components/TextField/types.ts b/packages/canon/src/components/TextField/types.ts index a01061cbfd..8a37a23efe 100644 --- a/packages/canon/src/components/TextField/types.ts +++ b/packages/canon/src/components/TextField/types.ts @@ -15,7 +15,7 @@ */ import type { Breakpoint } from '../../types'; - +import type { ReactNode, MouseEventHandler } from 'react'; /** @public */ export interface TextFieldProps extends Omit, 'size'> { @@ -53,10 +53,10 @@ export interface TextFieldProps /** * An icon to render before the input */ - icon?: React.ReactNode; + icon?: ReactNode; /** * Handler to call when the clear button is pressed */ - onClear?: React.MouseEventHandler; + onClear?: MouseEventHandler; } From 42c36f2a7f04ee6bd8fce1ef623ef1a7424b3c7a Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 08:24:53 +0100 Subject: [PATCH 5/6] Update types.ts Signed-off-by: Charles de Dreuille --- packages/canon/src/components/Button/types.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/canon/src/components/Button/types.ts b/packages/canon/src/components/Button/types.ts index 15feca581c..4ab62d5683 100644 --- a/packages/canon/src/components/Button/types.ts +++ b/packages/canon/src/components/Button/types.ts @@ -15,6 +15,7 @@ */ import type { ButtonOwnProps } from './Button.props'; +import { ReactElement } from 'react'; /** * Properties for {@link Button} @@ -43,10 +44,10 @@ export interface ButtonProps /** * Optional icon to display at the start of the button */ - iconStart?: React.ReactNode; + iconStart?: ReactElement; /** * Optional icon to display at the end of the button */ - iconEnd?: React.ReactNode; + iconEnd?: ReactElement; } From 6ea31e22a3abddf1c4b00f15fa8a96046087f476 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Fri, 16 May 2025 09:26:19 +0100 Subject: [PATCH 6/6] Update report.api.md Signed-off-by: Charles de Dreuille --- packages/canon/report.api.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index ebec81fcae..cbbdd4db33 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -175,8 +175,8 @@ export const buttonPropDefs: { export interface ButtonProps extends Omit, 'children'> { children: React.ReactNode; - iconEnd?: React.ReactNode; - iconStart?: React.ReactNode; + iconEnd?: ReactElement; + iconStart?: ReactElement; size?: ButtonOwnProps['size']; variant?: ButtonOwnProps['variant']; }