feat(form): add select size variants
This commit is contained in:
parent
56f642aadd
commit
934a612df3
5 changed files with 59 additions and 4 deletions
|
|
@ -73,6 +73,7 @@
|
||||||
.select {
|
.select {
|
||||||
width: auto;
|
width: auto;
|
||||||
min-width: 130px;
|
min-width: 130px;
|
||||||
|
box-sizing: border-box;
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background:
|
background:
|
||||||
|
|
@ -95,7 +96,6 @@
|
||||||
font: inherit;
|
font: inherit;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
padding: 8px 32px 8px 12px;
|
|
||||||
transition:
|
transition:
|
||||||
border-color 0.18s ease,
|
border-color 0.18s ease,
|
||||||
background 0.18s ease,
|
background 0.18s ease,
|
||||||
|
|
@ -107,6 +107,24 @@
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.selectSizeSm {
|
||||||
|
min-height: 32px;
|
||||||
|
padding: 6px 30px 6px 10px;
|
||||||
|
background-position:
|
||||||
|
0 0,
|
||||||
|
0 0,
|
||||||
|
right 10px center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectSizeMd {
|
||||||
|
min-height: 36px;
|
||||||
|
padding: 8px 32px 8px 12px;
|
||||||
|
background-position:
|
||||||
|
0 0,
|
||||||
|
0 0,
|
||||||
|
right 12px center;
|
||||||
|
}
|
||||||
|
|
||||||
.select:hover {
|
.select:hover {
|
||||||
border-color: rgba(255, 255, 255, 0.16);
|
border-color: rgba(255, 255, 255, 0.16);
|
||||||
background:
|
background:
|
||||||
|
|
|
||||||
|
|
@ -138,6 +138,7 @@ describe('form primitives', () => {
|
||||||
expect(screen.getByText('Short summary')).toBeInTheDocument();
|
expect(screen.getByText('Short summary')).toBeInTheDocument();
|
||||||
expect(screen.getByRole('alert')).toHaveTextContent('Validation failed');
|
expect(screen.getByRole('alert')).toHaveTextContent('Validation failed');
|
||||||
expect(screen.getByLabelText('Status')).toHaveValue('open');
|
expect(screen.getByLabelText('Status')).toHaveValue('open');
|
||||||
|
expect(screen.getByLabelText('Status')).toHaveAttribute('data-size', 'md');
|
||||||
fireEvent.change(screen.getByLabelText('Status'), { target: { value: 'resolved' } });
|
fireEvent.change(screen.getByLabelText('Status'), { target: { value: 'resolved' } });
|
||||||
expect(screen.getByLabelText('Status')).toHaveValue('resolved');
|
expect(screen.getByLabelText('Status')).toHaveValue('resolved');
|
||||||
|
|
||||||
|
|
@ -176,4 +177,15 @@ describe('form primitives', () => {
|
||||||
'primary',
|
'primary',
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('supports compact select sizing', () => {
|
||||||
|
render(
|
||||||
|
<Select aria-label="Compact" defaultValue="one" size="sm">
|
||||||
|
<option value="one">One</option>
|
||||||
|
<option value="two">Two</option>
|
||||||
|
</Select>,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(screen.getByLabelText('Compact')).toHaveAttribute('data-size', 'sm');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -77,13 +77,32 @@ export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(function
|
||||||
return <textarea ref={ref} className={clsx(styles.textArea, className)} {...props} />;
|
return <textarea ref={ref} className={clsx(styles.textArea, className)} {...props} />;
|
||||||
});
|
});
|
||||||
|
|
||||||
export type SelectProps = SelectHTMLAttributes<HTMLSelectElement>;
|
export type SelectSize = 'sm' | 'md';
|
||||||
|
|
||||||
|
export type SelectProps = Omit<SelectHTMLAttributes<HTMLSelectElement>, 'className' | 'size'> & {
|
||||||
|
className?: string;
|
||||||
|
size?: SelectSize;
|
||||||
|
};
|
||||||
|
|
||||||
export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(
|
export const Select = forwardRef<HTMLSelectElement, SelectProps>(function Select(
|
||||||
{ className, ...props },
|
{ className, size = 'md', ...props },
|
||||||
ref,
|
ref,
|
||||||
) {
|
) {
|
||||||
return <select ref={ref} className={clsx(styles.select, className)} {...props} />;
|
return (
|
||||||
|
<select
|
||||||
|
ref={ref}
|
||||||
|
className={clsx(
|
||||||
|
styles.select,
|
||||||
|
{
|
||||||
|
[styles.selectSizeSm]: size === 'sm',
|
||||||
|
[styles.selectSizeMd]: size === 'md',
|
||||||
|
},
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
data-size={size}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
type BaseCheckboxProps = ComponentPropsWithoutRef<typeof BaseCheckbox.Root>;
|
type BaseCheckboxProps = ComponentPropsWithoutRef<typeof BaseCheckbox.Root>;
|
||||||
|
|
|
||||||
|
|
@ -303,6 +303,11 @@ describe('import route', () => {
|
||||||
|
|
||||||
expect(await screen.findByRole('button', { name: /^Needs Review\s*1$/ })).toBeInTheDocument();
|
expect(await screen.findByRole('button', { name: /^Needs Review\s*1$/ })).toBeInTheDocument();
|
||||||
expect(screen.getAllByText('Album A').length).toBeGreaterThan(0);
|
expect(screen.getAllByText('Album A').length).toBeGreaterThan(0);
|
||||||
|
const intervalSelect = document.getElementById('auto-import-interval');
|
||||||
|
if (!(intervalSelect instanceof HTMLElement)) {
|
||||||
|
throw new Error('auto-import interval select missing');
|
||||||
|
}
|
||||||
|
expect(intervalSelect).toHaveAttribute('data-size', 'sm');
|
||||||
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/groups'))).toBe(false);
|
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/groups'))).toBe(false);
|
||||||
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/suggestions'))).toBe(
|
expect(getFetchUrls().some((url) => url.includes('/api/import/staging/suggestions'))).toBe(
|
||||||
false,
|
false,
|
||||||
|
|
|
||||||
|
|
@ -214,6 +214,7 @@ export function AutoImportPanel({
|
||||||
<span>Interval:</span>
|
<span>Interval:</span>
|
||||||
<Select
|
<Select
|
||||||
id="auto-import-interval"
|
id="auto-import-interval"
|
||||||
|
size="sm"
|
||||||
value={interval}
|
value={interval}
|
||||||
onChange={(event) => setInterval(Number(event.target.value))}
|
onChange={(event) => setInterval(Number(event.target.value))}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue