Skip to content

Commit

Permalink
feat(select): removed dual placeholder logic from select
Browse files Browse the repository at this point in the history
Select.Value placeholder prop has been removed

BREAKING CHANGE: prop removal - placeholder of Select.Value
  • Loading branch information
Powerplex committed Aug 1, 2024
1 parent 101cda5 commit 9629c9c
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 57 deletions.
2 changes: 1 addition & 1 deletion packages/components/dropdown/src/DropdownValue.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { useDropdownContext } from './DropdownContext'
export interface ValueProps {
children?: ReactNode
className?: string
placeholder: string
placeholder?: string
}

export const Value = forwardRef(
Expand Down
12 changes: 12 additions & 0 deletions packages/components/select/src/Select.doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ import { Select } from '@spark-ui/select'
of: Select.Items,
description: 'The wrapper which contains all the options.',
},
'Select.Placeholder': {
of: Select.Placeholder,
description: 'Option selected when no value is set',
},
'Select.Item': { of: Select.Item, description: 'Each option of the element field' },
'Select.Group': {
of: Select.Group,
Expand Down Expand Up @@ -97,6 +101,14 @@ It is important to use `Select.Label` inside each `Select.Group` to give it an a

<Canvas of={stories.Grouped} />

### Placeholder

Using a placeholder is optional, but you must know that an HTML `select` is always in a selected state. It means if you don't provide any placeholder, the first item will be selected by default.

When using `Select.Placeholder`, you can apply `disabled` on it if the user should not be able to go to unselected state again.

<Canvas of={stories.Placeholder} />

### Read only

Use `readOnly` prop to indicate the Select is only readable.
Expand Down
89 changes: 67 additions & 22 deletions packages/components/select/src/Select.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable max-lines */
import { StoryLabel } from '@docs/helpers/StoryLabel'
import { FormField } from '@spark-ui/form-field'
import { BookmarkFill } from '@spark-ui/icons/dist/icons/BookmarkFill'
import { VisuallyHidden } from '@spark-ui/visually-hidden'
Expand All @@ -22,11 +23,11 @@ export const Default: StoryFn = _args => {
<Select.LeadingIcon>
<BookmarkFill />
</Select.LeadingIcon>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
Expand All @@ -46,11 +47,11 @@ export const Controlled: StoryFn = () => {
<div>
<Select name="book" value={value} onValueChange={setValue}>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
Expand All @@ -68,11 +69,11 @@ export const Disabled: StoryFn = _args => {
<div>
<Select name="book" disabled>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
Expand All @@ -85,16 +86,60 @@ export const Disabled: StoryFn = _args => {
)
}

export const Placeholder: StoryFn = _args => {
return (
<div className="flex flex-col gap-lg">
<div>
<StoryLabel>default placeholder</StoryLabel>
<Select name="book">
<Select.Trigger aria-label="Book">
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
<Select.Item value="book-4">A Picture of Dorian Gray</Select.Item>
<Select.Item value="book-5">1984</Select.Item>
<Select.Item value="book-6">Pride and Prejudice</Select.Item>
</Select.Items>
</Select>
</div>

<div>
<StoryLabel>disabled placeholder</StoryLabel>
<Select name="book">
<Select.Trigger aria-label="Book">
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder disabled>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
<Select.Item value="book-4">A Picture of Dorian Gray</Select.Item>
<Select.Item value="book-5">1984</Select.Item>
<Select.Item value="book-6">Pride and Prejudice</Select.Item>
</Select.Items>
</Select>
</div>
</div>
)
}

export const ReadOnly: StoryFn = _args => {
return (
<div>
<Select name="book" readOnly>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
Expand All @@ -112,11 +157,11 @@ export const DisabledItem: StoryFn = _args => {
<div>
<Select name="book">
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3" disabled>
Expand All @@ -136,11 +181,11 @@ export const Grouped: StoryFn = _args => {
<div>
<Select name="book">
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Group>
<Select.Label>Best-sellers</Select.Label>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
Expand Down Expand Up @@ -168,11 +213,11 @@ export const LeadingIcon: StoryFn = _args => {
<Select.LeadingIcon>
<BookmarkFill />
</Select.LeadingIcon>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
<Select.Placeholder>--Pick a book--</Select.Placeholder>
<Select.Placeholder>Pick a book</Select.Placeholder>
<Select.Item value="book-1">To Kill a Mockingbird</Select.Item>
<Select.Item value="book-2">War and Peace</Select.Item>
<Select.Item value="book-3">The Idiot</Select.Item>
Expand All @@ -194,9 +239,9 @@ export const Statuses: StoryFn = () => {
<div className="flex flex-col gap-lg">
{statuses.map(status => {
return (
<Select name={'book-' + status} state={status}>
<Select key={status} name={'book-' + status} state={status}>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -221,7 +266,7 @@ export const FormFieldLabel: StoryFn = _args => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -247,7 +292,7 @@ export const FormFieldHiddenLabel: StoryFn = _args => {
</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -271,7 +316,7 @@ export const FormFieldReadOnly: StoryFn = _args => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -295,7 +340,7 @@ export const FormFieldDisabled: StoryFn = _args => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -319,7 +364,7 @@ export const FormFieldRequired: StoryFn = _args => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -348,7 +393,7 @@ export const FormFieldValidation: StoryFn = () => {
}}
>
<Select.Trigger>
<Select.Value placeholder="Pick an state" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down
20 changes: 10 additions & 10 deletions packages/components/select/src/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ describe('Select', () => {
<Select.LeadingIcon>
<BookmarkFill />
</Select.LeadingIcon>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -56,7 +56,7 @@ describe('Select', () => {
render(
<Select>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -89,7 +89,7 @@ describe('Select', () => {
render(
<Select>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book">You have selected a book</Select.Value>
<Select.Value>You have selected a book</Select.Value>
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -132,7 +132,7 @@ describe('Select', () => {

<Select value={value} onValueChange={setValue}>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -165,7 +165,7 @@ describe('Select', () => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -194,7 +194,7 @@ describe('Select', () => {
<FormField.Label>Book</FormField.Label>
<Select>
<Select.Trigger>
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -219,7 +219,7 @@ describe('Select', () => {
render(
<Select>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -251,7 +251,7 @@ describe('Select', () => {
render(
<Select defaultValue="book-2">
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand All @@ -277,7 +277,7 @@ describe('Select', () => {
return (
<Select value={value} onValueChange={setValue}>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down Expand Up @@ -321,7 +321,7 @@ describe('Select', () => {
}}
>
<Select.Trigger aria-label="Book">
<Select.Value placeholder="Pick a book" />
<Select.Value />
</Select.Trigger>

<Select.Items>
Expand Down
15 changes: 10 additions & 5 deletions packages/components/select/src/SelectItem.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import { forwardRef, type Ref } from 'react'
import { ComponentPropsWithoutRef, forwardRef, type Ref } from 'react'

export interface ItemProps {
disabled?: boolean
export interface ItemProps extends ComponentPropsWithoutRef<'option'> {
value: string
children: string
hidden?: boolean
disabled?: boolean
}

export const Item = forwardRef(
({ disabled = false, value, children }: ItemProps, forwardedRef: Ref<HTMLOptionElement>) => {
(
{ disabled = false, hidden = false, value, children, ...props }: ItemProps,
forwardedRef: Ref<HTMLOptionElement>
) => {
return (
<option
data-spark-component="select-item"
ref={forwardedRef}
key={value}
value={value}
disabled={disabled}
// label
hidden={hidden}
{...props}
>
{children}
</option>
Expand Down
2 changes: 1 addition & 1 deletion packages/components/select/src/SelectItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const Items = forwardRef(
aria-labelledby={fieldLabelId}
{...(ariaLabel && { 'aria-label': ariaLabel })}
className={styles({ className, state, disabled, readOnly })}
value={selectedItem?.value}
value={selectedItem?.value || ''}
onChange={handleChange}
id={fieldId}
{...rest}
Expand Down
Loading

0 comments on commit 9629c9c

Please sign in to comment.