Improved form example

Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
Charles de Dreuille
2025-04-04 14:05:01 +01:00
parent 7b544e19d5
commit 73abef2968
5 changed files with 87 additions and 61 deletions
+19 -12
View File
@@ -404,21 +404,21 @@
height: 1.5rem;
}
.canon-FieldRoot {
.canon-TextField {
font-family: var(--canon-font-regular);
flex-direction: column;
width: 100%;
display: flex;
}
.canon-FieldLabel {
.canon-TextField--label {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-primary);
margin-bottom: var(--canon-space-1_5);
}
.canon-FieldDescription {
.canon-TextField--description {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-secondary);
@@ -426,7 +426,7 @@
margin: 0;
}
.canon-FieldError {
.canon-TextField--error {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-danger);
@@ -434,7 +434,7 @@
margin: 0;
}
.canon-Input {
.canon-TextField--input {
border-radius: var(--canon-radius-3);
border: 1px solid var(--canon-border);
padding: 0 var(--canon-space-4);
@@ -447,38 +447,45 @@
transition: border-color .2s ease-in-out, outline-color .2s ease-in-out;
}
.canon-Input::placeholder {
.canon-TextField--input::placeholder {
color: var(--canon-fg-secondary);
}
.canon-Input:hover {
.canon-TextField--input:hover {
border-color: var(--canon-border-hover);
}
.canon-Input:focus-visible {
.canon-TextField--input:focus-visible {
outline-color: var(--canon-border-pressed);
border-color: var(--canon-border-pressed);
outline-width: 0;
}
.canon-Input[data-invalid] {
.canon-TextField--input[data-invalid] {
border-color: var(--canon-fg-danger);
}
.canon-Input[data-disabled] {
.canon-TextField--input[data-disabled] {
opacity: .5;
cursor: not-allowed;
border: 1px solid var(--canon-border-disabled);
}
.canon-Input--size-small {
.canon-TextField--input-size-small {
height: 2rem;
}
.canon-Input--size-medium {
.canon-TextField--input-size-medium {
height: 2.5rem;
}
.canon-TextField--required {
color: var(--canon-fg-secondary);
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
margin-left: var(--canon-space-1);
}
.canon-MenuPositioner {
outline: 0;
}
+19 -12
View File
@@ -9610,21 +9610,21 @@
height: 1.5rem;
}
.canon-FieldRoot {
.canon-TextField {
font-family: var(--canon-font-regular);
flex-direction: column;
width: 100%;
display: flex;
}
.canon-FieldLabel {
.canon-TextField--label {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-primary);
margin-bottom: var(--canon-space-1_5);
}
.canon-FieldDescription {
.canon-TextField--description {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-secondary);
@@ -9632,7 +9632,7 @@
margin: 0;
}
.canon-FieldError {
.canon-TextField--error {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-danger);
@@ -9640,7 +9640,7 @@
margin: 0;
}
.canon-Input {
.canon-TextField--input {
border-radius: var(--canon-radius-3);
border: 1px solid var(--canon-border);
padding: 0 var(--canon-space-4);
@@ -9653,38 +9653,45 @@
transition: border-color .2s ease-in-out, outline-color .2s ease-in-out;
}
.canon-Input::placeholder {
.canon-TextField--input::placeholder {
color: var(--canon-fg-secondary);
}
.canon-Input:hover {
.canon-TextField--input:hover {
border-color: var(--canon-border-hover);
}
.canon-Input:focus-visible {
.canon-TextField--input:focus-visible {
outline-color: var(--canon-border-pressed);
border-color: var(--canon-border-pressed);
outline-width: 0;
}
.canon-Input[data-invalid] {
.canon-TextField--input[data-invalid] {
border-color: var(--canon-fg-danger);
}
.canon-Input[data-disabled] {
.canon-TextField--input[data-disabled] {
opacity: .5;
cursor: not-allowed;
border: 1px solid var(--canon-border-disabled);
}
.canon-Input--size-small {
.canon-TextField--input-size-small {
height: 2rem;
}
.canon-Input--size-medium {
.canon-TextField--input-size-medium {
height: 2.5rem;
}
.canon-TextField--required {
color: var(--canon-fg-secondary);
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
margin-left: var(--canon-space-1);
}
.canon-MenuPositioner {
outline: 0;
}
+19 -12
View File
@@ -1,18 +1,18 @@
.canon-FieldRoot {
.canon-TextField {
font-family: var(--canon-font-regular);
flex-direction: column;
width: 100%;
display: flex;
}
.canon-FieldLabel {
.canon-TextField--label {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-primary);
margin-bottom: var(--canon-space-1_5);
}
.canon-FieldDescription {
.canon-TextField--description {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-secondary);
@@ -20,7 +20,7 @@
margin: 0;
}
.canon-FieldError {
.canon-TextField--error {
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
color: var(--canon-fg-danger);
@@ -28,7 +28,7 @@
margin: 0;
}
.canon-Input {
.canon-TextField--input {
border-radius: var(--canon-radius-3);
border: 1px solid var(--canon-border);
padding: 0 var(--canon-space-4);
@@ -41,34 +41,41 @@
transition: border-color .2s ease-in-out, outline-color .2s ease-in-out;
}
.canon-Input::placeholder {
.canon-TextField--input::placeholder {
color: var(--canon-fg-secondary);
}
.canon-Input:hover {
.canon-TextField--input:hover {
border-color: var(--canon-border-hover);
}
.canon-Input:focus-visible {
.canon-TextField--input:focus-visible {
outline-color: var(--canon-border-pressed);
border-color: var(--canon-border-pressed);
outline-width: 0;
}
.canon-Input[data-invalid] {
.canon-TextField--input[data-invalid] {
border-color: var(--canon-fg-danger);
}
.canon-Input[data-disabled] {
.canon-TextField--input[data-disabled] {
opacity: .5;
cursor: not-allowed;
border: 1px solid var(--canon-border-disabled);
}
.canon-Input--size-small {
.canon-TextField--input-size-small {
height: 2rem;
}
.canon-Input--size-medium {
.canon-TextField--input-size-medium {
height: 2.5rem;
}
.canon-TextField--required {
color: var(--canon-fg-secondary);
font-size: var(--canon-font-size-2);
font-weight: var(--canon-font-weight-regular);
margin-left: var(--canon-space-1);
}
@@ -29,7 +29,6 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
size = 'medium',
label,
description,
name,
error,
required,
...rest
@@ -57,7 +56,6 @@ export const TextField = forwardRef<HTMLDivElement, TextFieldProps>(
)}
<Input
id={inputId}
type={name}
className={clsx('canon-TextField--input', {
'canon-TextField--input-size-small': responsiveSize === 'small',
'canon-TextField--input-size-medium': responsiveSize === 'medium',
+30 -23
View File
@@ -16,19 +16,20 @@
import React from 'react';
import type { Meta, StoryObj } from '@storybook/react';
import { TextField } from '../components/TextField';
import { useForm, SubmitHandler } from 'react-hook-form';
import { TextField } from '../components/TextField';
import { Button } from '../components/Button';
const meta = {
title: 'Global/Form',
title: 'Examples/Form',
} satisfies Meta;
export default meta;
type Story = StoryObj<typeof meta>;
type Inputs = {
example: string;
exampleRequired: string;
firstname: string;
lastname: string;
};
export const Default: Story = {
@@ -36,32 +37,38 @@ export const Default: Story = {
const {
register,
handleSubmit,
watch,
formState: { errors },
} = useForm<Inputs>();
const onSubmit: SubmitHandler<Inputs> = data => console.log(data);
console.log(watch('example')); // watch input value by passing the name of it
return (
<form onSubmit={handleSubmit(onSubmit)}>
{/* register your input into the hook by invoking the "register" function */}
<input defaultValue="test" {...register('example')} />
{/* include validation with required or other standard HTML validation rules */}
{/* <input {...register('exampleRequired', { required: true })} /> */}
<form
onSubmit={handleSubmit(onSubmit)}
style={{
display: 'flex',
flexDirection: 'column',
gap: '1rem',
alignItems: 'flex-start',
}}
>
<TextField
label="Example Required"
description="This is an example required field"
{...register('exampleRequired', { required: true })}
error={errors.exampleRequired?.message}
label="First Name"
{...register('firstname', {
required: 'First name is required',
maxLength: { value: 80, message: 'Max length is 80 characters' },
})}
error={errors.firstname?.message}
/>
{/* errors will return when field validation fails */}
{errors.exampleRequired && <span>This field is required</span>}
<input type="submit" />
<TextField
label="Last Name"
{...register('lastname', {
required: 'Last name is required',
maxLength: { value: 100, message: 'Max length is 100 characters' },
})}
error={errors.lastname?.message}
/>
<Button type="submit">Submit</Button>
</form>
);
},