From 7eead323ae6a8b810ffcc96688a726b52d68a458 Mon Sep 17 00:00:00 2001 From: Charles de Dreuille Date: Mon, 13 Jan 2025 12:22:39 +0000 Subject: [PATCH] Improve input Signed-off-by: Charles de Dreuille --- canon-docs/public/components.css | 1 + .../src/app/(docs)/components/input/page.mdx | 126 ++++++++++++++++++ .../src/app/(playground)/playground/page.tsx | 4 + canon-docs/src/snippets/input.tsx | 38 ++++++ canon-docs/src/utils/data.ts | 9 +- packages/canon/report.api.md | 8 ++ .../src/components/Input/Input.stories.tsx | 21 ++- packages/canon/src/components/Input/Input.tsx | 18 ++- .../canon/src/components/Input/styles.css | 1 + packages/canon/src/components/Input/types.ts | 6 +- packages/canon/src/index.ts | 1 + 11 files changed, 220 insertions(+), 13 deletions(-) create mode 100644 canon-docs/src/app/(docs)/components/input/page.mdx create mode 100644 canon-docs/src/snippets/input.tsx diff --git a/canon-docs/public/components.css b/canon-docs/public/components.css index 8889d8c978..e1cd4c9fad 100644 --- a/canon-docs/public/components.css +++ b/canon-docs/public/components.css @@ -281,6 +281,7 @@ .canon-input-root { font-family: var(--canon-font-regular); flex-direction: column; + width: 100%; display: flex; } diff --git a/canon-docs/src/app/(docs)/components/input/page.mdx b/canon-docs/src/app/(docs)/components/input/page.mdx new file mode 100644 index 0000000000..49cb7bd08c --- /dev/null +++ b/canon-docs/src/app/(docs)/components/input/page.mdx @@ -0,0 +1,126 @@ +import { PropsTable } from '@/components/PropsTable'; +import { Snippet } from '@/components/Snippet'; +import { Tabs } from '@/components/Tabs'; +import { CodeBlock } from '@/components/CodeBlock'; +import { + InputPreview, + InputLabelAndDescription, + InputError, +} from '@/snippets/input'; +import { BaseUI } from '@/components/HeadlessBanners/BaseUI'; + +# Input + +A input component tfor your forms. + +} + code={``} +/> + + + + Usage + Theming + + + +`} + /> + + + 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. + `} + /> + + + +## API reference + + + + + +## Examples + +### With label and description + +Here's a simple input with a label and description. + +} + code={``} +/> + +### Error + +Here's a simple input with an error message. + +} + code={``} +/> diff --git a/canon-docs/src/app/(playground)/playground/page.tsx b/canon-docs/src/app/(playground)/playground/page.tsx index c36a1d3492..9478160517 100644 --- a/canon-docs/src/app/(playground)/playground/page.tsx +++ b/canon-docs/src/app/(playground)/playground/page.tsx @@ -9,6 +9,7 @@ import { ButtonPlayground } from '@/snippets/button'; import { CheckboxPlayground } from '@/snippets/checkbox'; import { HeadingPlayground } from '@/snippets/heading'; import { TextPlayground } from '@/snippets/text'; +import { InputPlayground } from '@/snippets/input'; import styles from './styles.module.css'; @@ -66,6 +67,9 @@ const Content = () => { {selectedComponents.find(c => c === 'text') && ( } title="Text" /> )} + {selectedComponents.find(c => c === 'input') && ( + } title="Input" /> + )} ); }; diff --git a/canon-docs/src/snippets/input.tsx b/canon-docs/src/snippets/input.tsx new file mode 100644 index 0000000000..85db7cde19 --- /dev/null +++ b/canon-docs/src/snippets/input.tsx @@ -0,0 +1,38 @@ +import { Input } from '@backstage/canon'; + +export const InputPreview = () => { + return ( +
+ +
+ ); +}; + +export const InputLabelAndDescription = () => { + return ( +
+ +
+ ); +}; + +export const InputError = () => { + return ( +
+ +
+ ); +}; + +export const InputPlayground = () => { + return ( +
+ +
+ ); +}; diff --git a/canon-docs/src/utils/data.ts b/canon-docs/src/utils/data.ts index f99ef2dbe8..41ae4c0536 100644 --- a/canon-docs/src/utils/data.ts +++ b/canon-docs/src/utils/data.ts @@ -70,12 +70,12 @@ export const components: Page[] = [ { title: 'Button', slug: 'button', - status: 'inProgress', + status: 'alpha', }, { title: 'Checkbox', slug: 'checkbox', - status: 'inProgress', + status: 'alpha', }, { title: 'Heading', @@ -87,6 +87,11 @@ export const components: Page[] = [ slug: 'icon', status: 'alpha', }, + { + title: 'Input', + slug: 'input', + status: 'alpha', + }, { title: 'Table', slug: 'table', diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index fc1f773b4b..5086c16ce0 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -6,6 +6,7 @@ /// import type { CSSProperties } from 'react'; +import { Field } from '@base-ui-components/react/field'; import { ForwardRefExoticComponent } from 'react'; import { default as React_2 } from 'react'; import * as React_3 from 'react'; @@ -323,6 +324,13 @@ export interface InlineProps extends SpaceProps { style?: React.CSSProperties; } +// Warning: (ae-forgotten-export) The symbol "InputProps" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export const Input: React_2.ForwardRefExoticComponent< + InputProps & React_2.RefAttributes +>; + // @public (undocumented) export type JustifyContent = | 'stretch' diff --git a/packages/canon/src/components/Input/Input.stories.tsx b/packages/canon/src/components/Input/Input.stories.tsx index 140696e0f5..a3f2f59581 100644 --- a/packages/canon/src/components/Input/Input.stories.tsx +++ b/packages/canon/src/components/Input/Input.stories.tsx @@ -89,13 +89,26 @@ export const Sizes: Story = { ), }; -export const WithError: Story = { +export const WithErrorValidation: Story = { args: { - invalid: true, - validate: value => (value ? null : 'Please enter your name'), + validate: value => + value !== 'Charles' ? 'Please enter a different name' : null, required: true, label: 'Name', description: 'Visible on your profile', - error: 'Please enter your name', + validationMode: 'onChange', + errorMatch: 'customError', + }, +}; + +export const WithInvalidProp: Story = { + args: { + invalid: true, + required: true, + label: 'Name', + description: 'Visible on your profile', + validationMode: 'onChange', + errorForceShow: true, + validate: () => 'Stuff', }, }; diff --git a/packages/canon/src/components/Input/Input.tsx b/packages/canon/src/components/Input/Input.tsx index e62301c5cf..688ecc5c2d 100644 --- a/packages/canon/src/components/Input/Input.tsx +++ b/packages/canon/src/components/Input/Input.tsx @@ -14,6 +14,8 @@ * limitations under the License. */ +'use client'; + import React, { forwardRef } from 'react'; import clsx from 'clsx'; import { Field } from '@base-ui-components/react/field'; @@ -25,12 +27,14 @@ const Input = forwardRef((props, ref) => { className, label, description, - match = 'valueMissing', + errorMatch = 'customError', + errorForceShow = false, + errorMessage = 'An error occurred', validationMode = 'onChange', size = 'md', placeholder, - error = 'Please enter your a value', required = false, + style, ...rest } = props; @@ -38,6 +42,7 @@ const Input = forwardRef((props, ref) => { @@ -54,9 +59,12 @@ const Input = forwardRef((props, ref) => { })} /> - - {error} - + {description && ( diff --git a/packages/canon/src/components/Input/styles.css b/packages/canon/src/components/Input/styles.css index f8baae4ff4..ef4cfa2a07 100644 --- a/packages/canon/src/components/Input/styles.css +++ b/packages/canon/src/components/Input/styles.css @@ -18,6 +18,7 @@ display: flex; flex-direction: column; font-family: var(--canon-font-regular); + width: 100%; } .canon-input-label { diff --git a/packages/canon/src/components/Input/types.ts b/packages/canon/src/components/Input/types.ts index c4ebff83b5..f268273632 100644 --- a/packages/canon/src/components/Input/types.ts +++ b/packages/canon/src/components/Input/types.ts @@ -16,13 +16,15 @@ import { Field } from '@base-ui-components/react/field'; +/** @public */ export interface InputProps extends React.ComponentPropsWithoutRef { label?: string; description?: string; size?: 'sm' | 'md'; placeholder?: string; - match?: Field.Error.Props['match']; - error?: string; + errorMatch?: Field.Error.Props['match']; + errorForceShow?: boolean; + errorMessage?: string; required?: boolean; } diff --git a/packages/canon/src/index.ts b/packages/canon/src/index.ts index f6cca4bed6..04f29c4b77 100644 --- a/packages/canon/src/index.ts +++ b/packages/canon/src/index.ts @@ -37,6 +37,7 @@ export * from './components/Button'; export * from './components/Icon'; export * from './components/Checkbox'; export * from './components/Table'; +export * from './components/Input'; // Types export * from './types';