ui: add more props to Select

pull/305/head
Yangshun Tay 2 years ago
parent 0a3fb2503d
commit 4fcf80ae2a

@ -7,6 +7,9 @@ const SelectDisplays: ReadonlyArray<SelectDisplay> = ['inline', 'block'];
export default {
argTypes: {
disabled: {
control: 'boolean',
},
display: {
control: { type: 'select' },
options: SelectDisplays,
@ -71,9 +74,87 @@ Basic.args = {
export function Display() {
const [value, setValue] = useState('apple');
return (
<div className="space-y-4">
<Select
label="Select a fruit"
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
onChange={setValue}
/>
<Select
display="block"
label="Select a fruit"
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
onChange={setValue}
/>
</div>
);
}
export function HiddenLabel() {
const [value, setValue] = useState('apple');
return (
<div className="space-x-4">
<Select
isLabelHidden={true}
label="Select a fruit"
options={[
{
label: 'Apple',
value: 'apple',
},
{
label: 'Banana',
value: 'banana',
},
{
label: 'Orange',
value: 'orange',
},
]}
value={value}
onChange={setValue}
/>
</div>
);
}
export function Disabled() {
const [value, setValue] = useState('apple');
return (
<div className="space-x-4">
<Select
disabled={true}
label="Select a fruit"
options={[
{

@ -1,6 +1,13 @@
import clsx from 'clsx';
import type { ForwardedRef, SelectHTMLAttributes } from 'react';
import { forwardRef } from 'react';
import { useId } from 'react';
type Attributes = Pick<
SelectHTMLAttributes<HTMLSelectElement>,
'disabled' | 'name' | 'onBlur' | 'onFocus' | 'required'
>;
export type SelectItem<T> = Readonly<{
label: string;
value: T;
@ -16,17 +23,22 @@ type Props<T> = Readonly<{
onChange: (value: string) => void;
options: ReadonlyArray<SelectItem<T>>;
value: T;
}>;
}> &
Readonly<Attributes>;
export default function Select<T>({
display,
label,
isLabelHidden,
name,
options,
value,
onChange,
}: Props<T>) {
function Select<T>(
{
display,
disabled,
label,
isLabelHidden,
options,
value,
onChange,
...props
}: Props<T>,
ref: ForwardedRef<HTMLSelectElement>,
) {
const id = useId();
return (
@ -40,17 +52,20 @@ export default function Select<T>({
{label}
</label>
<select
ref={ref}
aria-label={isLabelHidden ? label : undefined}
className={clsx(
display === 'block' && 'block w-full',
'focus:border-primary-500 focus:ring-primary-500 rounded-md border-slate-300 py-2 pl-3 pr-10 text-base focus:outline-none sm:text-sm',
disabled && 'bg-slate-100',
)}
disabled={disabled}
id={id}
name={name ?? undefined}
value={String(value)}
onChange={(event) => {
onChange(event.target.value);
}}>
}}
{...props}>
{options.map(({ label: optionLabel, value: optionValue }) => (
<option key={String(optionValue)} value={String(optionValue)}>
{optionLabel}
@ -60,3 +75,5 @@ export default function Select<T>({
</div>
);
}
export default forwardRef(Select);

@ -7,7 +7,7 @@ import type {
} from 'react';
import React, { forwardRef, useId } from 'react';
type TextInputInputAttributes = Pick<
type Attributes = Pick<
InputHTMLAttributes<HTMLInputElement>,
| 'autoComplete'
| 'disabled'
@ -16,17 +16,14 @@ type TextInputInputAttributes = Pick<
| 'min'
| 'minLength'
| 'name'
| 'onBlur'
| 'onFocus'
| 'pattern'
| 'placeholder'
| 'required'
| 'type'
>;
type TextInputDOMAttributes = Pick<
InputHTMLAttributes<HTMLInputElement>,
'onBlur' | 'onFocus'
>;
type Props = Readonly<{
defaultValue?: string;
endIcon?: React.ComponentType<React.ComponentProps<'svg'>>;
@ -39,8 +36,7 @@ type Props = Readonly<{
startIcon?: React.ComponentType<React.ComponentProps<'svg'>>;
value?: string;
}> &
Readonly<TextInputDOMAttributes> &
Readonly<TextInputInputAttributes>;
Readonly<Attributes>;
type State = 'error' | 'normal';

Loading…
Cancel
Save