diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index 40a45b34cc..5d2e3e7d50 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -697,21 +697,21 @@ width: 100%; } -.canon-SelectFieldRoot { +.canon-Select { font-family: var(--canon-font-regular); flex-direction: column; width: 100%; display: flex; } -.canon-SelectFieldLabel { +.canon-Select--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-SelectFieldDescription { +.canon-Select--description { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); color: var(--canon-fg-secondary); @@ -719,7 +719,7 @@ margin: 0; } -.canon-SelectFieldError { +.canon-Select--error { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); color: var(--canon-fg-danger); @@ -727,7 +727,7 @@ margin: 0; } -.canon-SelectTrigger { +.canon-Select--trigger { box-sizing: border-box; border-radius: var(--canon-radius-3); border: 1px solid var(--canon-border); @@ -745,38 +745,38 @@ display: flex; } -.canon-SelectTrigger::placeholder { +.canon-Select--trigger::placeholder { color: var(--canon-fg-secondary); } -.canon-SelectTrigger:hover { +.canon-Select--trigger:hover { border-color: var(--canon-border-hover); } -.canon-SelectTrigger:focus-visible { +.canon-Select--trigger:focus-visible { border-color: var(--canon-border-pressed); outline: 0; } -.canon-SelectTrigger[data-invalid] { +.canon-Select--trigger[data-invalid] { border-color: var(--canon-fg-danger); } -.canon-SelectTrigger[data-invalid]:hover, .canon-SelectTrigger[data-invalid]:focus-visible { +.canon-Select--trigger[data-invalid]:hover, .canon-Select--trigger[data-invalid]:focus-visible { border-width: 2px; } -.canon-SelectTrigger[data-disabled] { +.canon-Select--trigger[data-disabled] { cursor: not-allowed; border-color: var(--canon-border-disabled); color: var(--canon-fg-disabled); } -.canon-SelectTrigger--size-small, .canon-SelectItem--size-small { +.canon-Select--trigger-size-small { height: 2rem; } -.canon-SelectTrigger--size-medium, .canon-SelectItem--size-medium { +.canon-Select--trigger-size-medium { height: 3rem; } @@ -785,11 +785,11 @@ transition: transform .2s; } -.canon-SelectTrigger[data-popup-open] .canon-SelectIcon { +.canon-Select--trigger[data-popup-open] .canon-SelectIcon { transform: rotate(180deg); } -.canon-SelectPopup { +.canon-Select--popup { box-sizing: border-box; max-height: var(--available-height); background-color: var(--canon-bg-surface-1); @@ -804,12 +804,12 @@ box-shadow: 0 4px 12px #0003; } -.canon-SelectPopup[data-starting-style], .canon-SelectPopup[data-ending-style] { +.canon-Select--popup[data-starting-style], .canon-Select--popup[data-ending-style] { opacity: 0; transform: scale(.9); } -.canon-SelectItem { +.canon-Select--item { width: var(--anchor-width); padding-block: var(--canon-space-2); padding-inline: var(--canon-space-4); @@ -827,13 +827,13 @@ position: relative; } -.canon-SelectItem[data-highlighted] { +.canon-Select--item[data-highlighted] { z-index: 0; color: var(--canon-fg-primary); position: relative; } -.canon-SelectItem[data-highlighted]:before { +.canon-Select--item[data-highlighted]:before { content: ""; z-index: -1; background-color: var(--canon-bg-tint-hover); @@ -843,19 +843,26 @@ inset-inline: .25rem; } -.canon-SelectItem[data-disabled] { +.canon-Select--item[data-disabled] { cursor: not-allowed; color: var(--canon-fg-disabled); } -.canon-SelectItemIndicator { +.canon-Select--item-indicator { grid-area: icon; justify-content: center; align-items: center; display: flex; } -.canon-SelectItemText { +.canon-Select--item-text { flex: 1; grid-area: text; } + +.canon-Select--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); +} diff --git a/packages/canon/css/select.css b/packages/canon/css/select.css index 77a88eaa00..6c64c39245 100644 --- a/packages/canon/css/select.css +++ b/packages/canon/css/select.css @@ -1,18 +1,18 @@ -.canon-SelectFieldRoot { +.canon-Select { font-family: var(--canon-font-regular); flex-direction: column; width: 100%; display: flex; } -.canon-SelectFieldLabel { +.canon-Select--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-SelectFieldDescription { +.canon-Select--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-SelectFieldError { +.canon-Select--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-SelectTrigger { +.canon-Select--trigger { box-sizing: border-box; border-radius: var(--canon-radius-3); border: 1px solid var(--canon-border); @@ -46,38 +46,38 @@ display: flex; } -.canon-SelectTrigger::placeholder { +.canon-Select--trigger::placeholder { color: var(--canon-fg-secondary); } -.canon-SelectTrigger:hover { +.canon-Select--trigger:hover { border-color: var(--canon-border-hover); } -.canon-SelectTrigger:focus-visible { +.canon-Select--trigger:focus-visible { border-color: var(--canon-border-pressed); outline: 0; } -.canon-SelectTrigger[data-invalid] { +.canon-Select--trigger[data-invalid] { border-color: var(--canon-fg-danger); } -.canon-SelectTrigger[data-invalid]:hover, .canon-SelectTrigger[data-invalid]:focus-visible { +.canon-Select--trigger[data-invalid]:hover, .canon-Select--trigger[data-invalid]:focus-visible { border-width: 2px; } -.canon-SelectTrigger[data-disabled] { +.canon-Select--trigger[data-disabled] { cursor: not-allowed; border-color: var(--canon-border-disabled); color: var(--canon-fg-disabled); } -.canon-SelectTrigger--size-small, .canon-SelectItem--size-small { +.canon-Select--trigger-size-small { height: 2rem; } -.canon-SelectTrigger--size-medium, .canon-SelectItem--size-medium { +.canon-Select--trigger-size-medium { height: 3rem; } @@ -86,11 +86,11 @@ transition: transform .2s; } -.canon-SelectTrigger[data-popup-open] .canon-SelectIcon { +.canon-Select--trigger[data-popup-open] .canon-SelectIcon { transform: rotate(180deg); } -.canon-SelectPopup { +.canon-Select--popup { box-sizing: border-box; max-height: var(--available-height); background-color: var(--canon-bg-surface-1); @@ -105,12 +105,12 @@ box-shadow: 0 4px 12px #0003; } -.canon-SelectPopup[data-starting-style], .canon-SelectPopup[data-ending-style] { +.canon-Select--popup[data-starting-style], .canon-Select--popup[data-ending-style] { opacity: 0; transform: scale(.9); } -.canon-SelectItem { +.canon-Select--item { width: var(--anchor-width); padding-block: var(--canon-space-2); padding-inline: var(--canon-space-4); @@ -128,13 +128,13 @@ position: relative; } -.canon-SelectItem[data-highlighted] { +.canon-Select--item[data-highlighted] { z-index: 0; color: var(--canon-fg-primary); position: relative; } -.canon-SelectItem[data-highlighted]:before { +.canon-Select--item[data-highlighted]:before { content: ""; z-index: -1; background-color: var(--canon-bg-tint-hover); @@ -144,19 +144,26 @@ inset-inline: .25rem; } -.canon-SelectItem[data-disabled] { +.canon-Select--item[data-disabled] { cursor: not-allowed; color: var(--canon-fg-disabled); } -.canon-SelectItemIndicator { +.canon-Select--item-indicator { grid-area: icon; justify-content: center; align-items: center; display: flex; } -.canon-SelectItemText { +.canon-Select--item-text { flex: 1; grid-area: text; } + +.canon-Select--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); +} diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index 66795e1a59..74bbc3d3e2 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9903,21 +9903,21 @@ width: 100%; } -.canon-SelectFieldRoot { +.canon-Select { font-family: var(--canon-font-regular); flex-direction: column; width: 100%; display: flex; } -.canon-SelectFieldLabel { +.canon-Select--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-SelectFieldDescription { +.canon-Select--description { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); color: var(--canon-fg-secondary); @@ -9925,7 +9925,7 @@ margin: 0; } -.canon-SelectFieldError { +.canon-Select--error { font-size: var(--canon-font-size-2); font-weight: var(--canon-font-weight-regular); color: var(--canon-fg-danger); @@ -9933,7 +9933,7 @@ margin: 0; } -.canon-SelectTrigger { +.canon-Select--trigger { box-sizing: border-box; border-radius: var(--canon-radius-3); border: 1px solid var(--canon-border); @@ -9951,38 +9951,38 @@ display: flex; } -.canon-SelectTrigger::placeholder { +.canon-Select--trigger::placeholder { color: var(--canon-fg-secondary); } -.canon-SelectTrigger:hover { +.canon-Select--trigger:hover { border-color: var(--canon-border-hover); } -.canon-SelectTrigger:focus-visible { +.canon-Select--trigger:focus-visible { border-color: var(--canon-border-pressed); outline: 0; } -.canon-SelectTrigger[data-invalid] { +.canon-Select--trigger[data-invalid] { border-color: var(--canon-fg-danger); } -.canon-SelectTrigger[data-invalid]:hover, .canon-SelectTrigger[data-invalid]:focus-visible { +.canon-Select--trigger[data-invalid]:hover, .canon-Select--trigger[data-invalid]:focus-visible { border-width: 2px; } -.canon-SelectTrigger[data-disabled] { +.canon-Select--trigger[data-disabled] { cursor: not-allowed; border-color: var(--canon-border-disabled); color: var(--canon-fg-disabled); } -.canon-SelectTrigger--size-small, .canon-SelectItem--size-small { +.canon-Select--trigger-size-small { height: 2rem; } -.canon-SelectTrigger--size-medium, .canon-SelectItem--size-medium { +.canon-Select--trigger-size-medium { height: 3rem; } @@ -9991,11 +9991,11 @@ transition: transform .2s; } -.canon-SelectTrigger[data-popup-open] .canon-SelectIcon { +.canon-Select--trigger[data-popup-open] .canon-SelectIcon { transform: rotate(180deg); } -.canon-SelectPopup { +.canon-Select--popup { box-sizing: border-box; max-height: var(--available-height); background-color: var(--canon-bg-surface-1); @@ -10010,12 +10010,12 @@ box-shadow: 0 4px 12px #0003; } -.canon-SelectPopup[data-starting-style], .canon-SelectPopup[data-ending-style] { +.canon-Select--popup[data-starting-style], .canon-Select--popup[data-ending-style] { opacity: 0; transform: scale(.9); } -.canon-SelectItem { +.canon-Select--item { width: var(--anchor-width); padding-block: var(--canon-space-2); padding-inline: var(--canon-space-4); @@ -10033,13 +10033,13 @@ position: relative; } -.canon-SelectItem[data-highlighted] { +.canon-Select--item[data-highlighted] { z-index: 0; color: var(--canon-fg-primary); position: relative; } -.canon-SelectItem[data-highlighted]:before { +.canon-Select--item[data-highlighted]:before { content: ""; z-index: -1; background-color: var(--canon-bg-tint-hover); @@ -10049,19 +10049,26 @@ inset-inline: .25rem; } -.canon-SelectItem[data-disabled] { +.canon-Select--item[data-disabled] { cursor: not-allowed; color: var(--canon-fg-disabled); } -.canon-SelectItemIndicator { +.canon-Select--item-indicator { grid-area: icon; justify-content: center; align-items: center; display: flex; } -.canon-SelectItemText { +.canon-Select--item-text { flex: 1; grid-area: text; } + +.canon-Select--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); +} diff --git a/packages/canon/report.api.md b/packages/canon/report.api.md index c4cfbefcc2..56223efb51 100644 --- a/packages/canon/report.api.md +++ b/packages/canon/report.api.md @@ -4,8 +4,10 @@ ```ts import { Breakpoint as Breakpoint_2 } from '@backstage/canon'; +import { ChangeEvent } from 'react'; import { Context } from 'react'; import type { CSSProperties } from 'react'; +import { FocusEvent as FocusEvent_2 } from 'react'; import { ForwardRefExoticComponent } from 'react'; import { Menu as Menu_2 } from '@base-ui-components/react/menu'; import { default as React_2 } from 'react'; @@ -915,7 +917,7 @@ export const ScrollArea: { // @public (undocumented) export const Select: React_2.ForwardRefExoticComponent< - SelectProps & React_2.RefAttributes + SelectProps & React_2.RefAttributes >; // @public (undocumented) @@ -924,8 +926,11 @@ export interface SelectProps { defaultValue?: string; description?: string; disabled?: boolean; + error?: string; label?: string; name: string; + onBlur?: (event: FocusEvent_2) => void; + onChange?: (event: ChangeEvent) => void; onOpenChange?: (open: boolean) => void; onValueChange?: (value: string) => void; options?: Array<{ diff --git a/packages/canon/src/components/Select/Select.stories.tsx b/packages/canon/src/components/Select/Select.stories.tsx index d04570ace7..96bfb31f9f 100644 --- a/packages/canon/src/components/Select/Select.stories.tsx +++ b/packages/canon/src/components/Select/Select.stories.tsx @@ -13,11 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import React, { useState } from 'react'; +import React from 'react'; import type { Meta, StoryObj } from '@storybook/react'; import { Select } from './Select'; -import { Form } from '@base-ui-components/react/form'; -import { Button } from '../Button'; import { Flex } from '../Flex'; const meta = { diff --git a/packages/canon/src/stories/Form.stories.tsx b/packages/canon/src/stories/Form.stories.tsx index d9f1acd5e8..b28cc273eb 100644 --- a/packages/canon/src/stories/Form.stories.tsx +++ b/packages/canon/src/stories/Form.stories.tsx @@ -34,7 +34,7 @@ type Inputs = { city: string; }; -export const Default: Story = { +export const Uncontrolled: Story = { render: () => { const { register, @@ -96,3 +96,101 @@ export const Default: Story = { ); }, }; + +export const Controlled: Story = { + render: () => { + const { + register, + handleSubmit, + control, + formState: { errors }, + } = useForm(); + + const [firstname, setFirstname] = React.useState('John'); + const [lastname, setLastname] = React.useState('Doe'); + const [city, setCity] = React.useState('london'); + + const onSubmit: SubmitHandler = data => { + console.log('data', data); + setFirstname(data.firstname); + setLastname(data.lastname); + setCity(data.city); + }; + + return ( +
+ { + return ( + { + field.onChange(e); + setFirstname(e.target.value); + }} + error={errors.firstname?.message} + /> + ); + }} + /> + { + return ( + { + field.onChange(e); + setLastname(e.target.value); + }} + error={errors.lastname?.message} + /> + ); + }} + /> + { + return ( +