⚡️ feat: add hideValues
prop to hide the values when on multiple
This commit is contained in:
parent
410def0750
commit
54c2e8ec0b
@ -34,7 +34,7 @@ export const selectTheme = tv({
|
||||
],
|
||||
icon: ['text-elements-mid-em'],
|
||||
helperIcon: [],
|
||||
helperText: ['flex', 'gap-2', 'items-center', 'text-elements-danger'],
|
||||
helperText: ['flex', 'gap-2', 'items-center', 'text-elements-low-em'],
|
||||
popover: [
|
||||
'z-20',
|
||||
'absolute',
|
||||
@ -70,12 +70,8 @@ export const selectTheme = tv({
|
||||
container: [],
|
||||
},
|
||||
},
|
||||
state: {
|
||||
default: {
|
||||
inputWrapper: '',
|
||||
helperText: ['text-elements-low-em'],
|
||||
},
|
||||
error: {
|
||||
true: {
|
||||
inputWrapper: [
|
||||
'outline',
|
||||
'outline-offset-0',
|
||||
@ -121,6 +117,11 @@ export const selectTheme = tv({
|
||||
input: ['cursor-pointer'],
|
||||
},
|
||||
},
|
||||
hideValues: {
|
||||
true: {
|
||||
input: ['placeholder:text-elements-mid-em'],
|
||||
},
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
@ -143,6 +144,7 @@ export const selectTheme = tv({
|
||||
variant: 'default',
|
||||
size: 'md',
|
||||
state: 'default',
|
||||
error: false,
|
||||
isOpen: false,
|
||||
hasValue: false,
|
||||
},
|
||||
|
@ -91,6 +91,10 @@ interface SelectProps
|
||||
* The helper text of the select
|
||||
*/
|
||||
helperText?: string;
|
||||
/**
|
||||
* Show the values of the select if it's multiple
|
||||
*/
|
||||
hideValues?: boolean;
|
||||
}
|
||||
|
||||
export const Select = ({
|
||||
@ -99,7 +103,7 @@ export const Select = ({
|
||||
searchable = false,
|
||||
clearable,
|
||||
size,
|
||||
state,
|
||||
error,
|
||||
orientation = 'horizontal',
|
||||
variant,
|
||||
label,
|
||||
@ -107,9 +111,10 @@ export const Select = ({
|
||||
leftIcon,
|
||||
rightIcon,
|
||||
helperText,
|
||||
hideValues = false,
|
||||
placeholder: placeholderProp = 'Select an option',
|
||||
}: SelectProps) => {
|
||||
const theme = selectTheme({ size, state, variant, orientation });
|
||||
const theme = selectTheme({ size, error, variant, orientation });
|
||||
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const [selectedItem, setSelectedItem] = useState<SelectOption | null>(null);
|
||||
@ -273,20 +278,28 @@ export const Select = ({
|
||||
const renderHelperText = useMemo(
|
||||
() => (
|
||||
<div className={theme.helperText()}>
|
||||
{state === 'error' &&
|
||||
{error &&
|
||||
cloneIcon(<WarningIcon className={theme.helperIcon()} />, {
|
||||
'aria-hidden': true,
|
||||
})}
|
||||
<p>{helperText}</p>
|
||||
</div>
|
||||
),
|
||||
[cloneIcon, state, theme, helperText],
|
||||
[cloneIcon, error, theme, helperText],
|
||||
);
|
||||
|
||||
const isMultipleHasValue = multiple && selectedItems.length > 0;
|
||||
const isMultipleHasValueButNotSearchable =
|
||||
multiple && !searchable && selectedItems.length > 0;
|
||||
const placeholder = isMultipleHasValueButNotSearchable ? '' : placeholderProp;
|
||||
const displayPlaceholder = useMemo(() => {
|
||||
if (hideValues && isMultipleHasValue) {
|
||||
return `${selectedItems.length} selected`;
|
||||
}
|
||||
if (isMultipleHasValueButNotSearchable) {
|
||||
return '';
|
||||
}
|
||||
return placeholderProp;
|
||||
}, [hideValues, multiple, selectedItems.length, placeholderProp]);
|
||||
|
||||
return (
|
||||
<div className={theme.container()}>
|
||||
@ -297,7 +310,7 @@ export const Select = ({
|
||||
<div
|
||||
ref={inputWrapperRef}
|
||||
className={theme.inputWrapper({
|
||||
hasValue: isMultipleHasValue,
|
||||
hasValue: isMultipleHasValue && !hideValues,
|
||||
})}
|
||||
onClick={() => !dropdownOpen && openMenu()}
|
||||
>
|
||||
@ -306,6 +319,7 @@ export const Select = ({
|
||||
|
||||
{/* Multiple input values */}
|
||||
{isMultipleHasValue &&
|
||||
!hideValues &&
|
||||
selectedItems.map((item, index) => (
|
||||
<SelectValue
|
||||
key={`selected-item-${index}`}
|
||||
@ -319,15 +333,21 @@ export const Select = ({
|
||||
{/* Single input value or searchable area */}
|
||||
<input
|
||||
{...getInputProps(getDropdownProps())}
|
||||
placeholder={placeholder}
|
||||
placeholder={displayPlaceholder}
|
||||
// Control readOnly based on searchable
|
||||
readOnly={!searchable}
|
||||
className={cn(theme.input({ searchable }), {
|
||||
readOnly={!searchable || hideValues}
|
||||
className={cn(
|
||||
theme.input({
|
||||
searchable,
|
||||
hideValues: hideValues && selectedItems.length > 0,
|
||||
}),
|
||||
{
|
||||
// Make the input width smaller because we don't need it (not searchable)
|
||||
'w-6': isMultipleHasValueButNotSearchable,
|
||||
'w-6': isMultipleHasValueButNotSearchable && !hideValues,
|
||||
// Add margin to the X icon
|
||||
'ml-6': isMultipleHasValueButNotSearchable && clearable,
|
||||
})}
|
||||
},
|
||||
)}
|
||||
/>
|
||||
|
||||
{/* Right icon */}
|
||||
@ -339,12 +359,12 @@ export const Select = ({
|
||||
|
||||
{/* Popover */}
|
||||
<ul
|
||||
{...getMenuProps()}
|
||||
{...getMenuProps({ ref: popoverRef }, { suppressRefError: true })}
|
||||
id="popover"
|
||||
ref={popoverRef}
|
||||
className={cn(theme.popover({ isOpen }), {
|
||||
// Position the popover based on the dropdown position
|
||||
'top-[12.5%]': dropdownPosition === 'bottom' && !label,
|
||||
'top-[27.5%]': dropdownPosition === 'bottom' && !label,
|
||||
'top-[35%]': dropdownPosition === 'bottom' && label,
|
||||
'top-[42.5%]': dropdownPosition === 'bottom' && label && description,
|
||||
'bottom-[92.5%]': dropdownPosition === 'top' && !label,
|
||||
|
@ -31,6 +31,7 @@ import {
|
||||
import { renderDefaultTag, renderMinimalTag } from './renders/tag';
|
||||
import { renderToast, renderToastsWithCta } from './renders/toast';
|
||||
import { renderTooltips } from './renders/tooltip';
|
||||
import { renderDropdowns } from './renders/dropdown';
|
||||
|
||||
type ValuePiece = Date | null;
|
||||
type Value = ValuePiece | [ValuePiece, ValuePiece];
|
||||
@ -270,6 +271,14 @@ const Page: React.FC = () => {
|
||||
|
||||
<div className="w-full h border border-gray-200 px-20 my-10" />
|
||||
|
||||
{/* Dropdown */}
|
||||
<div className="flex flex-col gap-10 items-center justify-between">
|
||||
<h1 className="text-2xl font-bold">Dropdown / Select</h1>
|
||||
{renderDropdowns()}
|
||||
</div>
|
||||
|
||||
<div className="w-full h border border-gray-200 px-20 my-10" />
|
||||
|
||||
{/* Inline notification */}
|
||||
<div className="flex flex-col gap-10 items-center justify-between">
|
||||
<h1 className="text-2xl font-bold">Inline Notification</h1>
|
||||
|
240
packages/frontend/src/pages/components/renders/dropdown.tsx
Normal file
240
packages/frontend/src/pages/components/renders/dropdown.tsx
Normal file
@ -0,0 +1,240 @@
|
||||
import React from 'react';
|
||||
import { PencilIcon } from 'components/shared/CustomIcon';
|
||||
import { SelectOption, Select } from 'components/shared/Select';
|
||||
|
||||
export const DROPDOWN_ITEMS: SelectOption[] = [
|
||||
{
|
||||
value: 'apple',
|
||||
label: 'Apple',
|
||||
description: 'Apple is fruit',
|
||||
leftIcon: <PencilIcon />,
|
||||
},
|
||||
{
|
||||
value: 'banana',
|
||||
label: 'Banana',
|
||||
description: 'Banana is fruit',
|
||||
leftIcon: <PencilIcon />,
|
||||
},
|
||||
{
|
||||
value: 'orange',
|
||||
label: 'Orange',
|
||||
description: 'Orange is fruit',
|
||||
leftIcon: <PencilIcon />,
|
||||
},
|
||||
{
|
||||
value: 'watermelon',
|
||||
label: 'Watermelon',
|
||||
description: 'Watermelon is fruit',
|
||||
disabled: true,
|
||||
leftIcon: <PencilIcon />,
|
||||
},
|
||||
];
|
||||
|
||||
export const renderDropdowns = () => (
|
||||
<>
|
||||
<p className="text-sm text-center text-gray-500 -mb-8">Single – Small</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select size="sm" placeholder="Default" options={DROPDOWN_ITEMS} />
|
||||
<Select
|
||||
size="sm"
|
||||
placeholder="Clearable"
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
size="sm"
|
||||
searchable
|
||||
placeholder="Searchable"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
size="sm"
|
||||
placeholder="Vertical"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-8">Single – Medium</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select placeholder="Default" options={DROPDOWN_ITEMS} />
|
||||
<Select placeholder="Clearable" clearable options={DROPDOWN_ITEMS} />
|
||||
<Select searchable placeholder="Searchable" options={DROPDOWN_ITEMS} />
|
||||
<Select
|
||||
placeholder="Vertical"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-8">Multiple – Small</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select
|
||||
multiple
|
||||
size="sm"
|
||||
placeholder="Default"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
multiple
|
||||
size="sm"
|
||||
placeholder="Clearable"
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
searchable
|
||||
multiple
|
||||
size="sm"
|
||||
placeholder="Searchable"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
multiple
|
||||
size="sm"
|
||||
placeholder="Vertical"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
multiple
|
||||
hideValues
|
||||
size="sm"
|
||||
orientation="vertical"
|
||||
placeholder="Hide values"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-8">Multiple – Medium</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select multiple placeholder="Default" options={DROPDOWN_ITEMS} />
|
||||
<Select
|
||||
multiple
|
||||
placeholder="Clearable"
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
searchable
|
||||
multiple
|
||||
placeholder="Searchable"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
multiple
|
||||
placeholder="Vertical"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
multiple
|
||||
hideValues
|
||||
orientation="vertical"
|
||||
placeholder="Hide values"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-4">
|
||||
Single – With label, description, and helper text
|
||||
</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select
|
||||
label="Default"
|
||||
description="Single select component"
|
||||
helperText="This is a helper text"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
label="Clearable"
|
||||
description="Single select component"
|
||||
helperText="This is a helper text"
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
searchable
|
||||
label="Searchable"
|
||||
description="Single select component"
|
||||
helperText="This is a helper text"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
label="Vertical"
|
||||
description="Single select component"
|
||||
helperText="This is a helper text"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-4">
|
||||
Multiple – With label, description, and helper text
|
||||
</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select
|
||||
label="Default"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
multiple
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
label="Clearable"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
multiple
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
searchable
|
||||
label="Searchable"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
multiple
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
label="Vertical"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
multiple
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
<p className="text-sm text-center text-gray-500 -mb-4">
|
||||
Error – With label, description, and helper text
|
||||
</p>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<Select
|
||||
error
|
||||
label="Default"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
error
|
||||
label="Clearable"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
clearable
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
error
|
||||
searchable
|
||||
label="Searchable"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
<Select
|
||||
error
|
||||
label="Vertical"
|
||||
description="Multiple select component"
|
||||
helperText="This is a helper text"
|
||||
orientation="vertical"
|
||||
options={DROPDOWN_ITEMS}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
Loading…
Reference in New Issue
Block a user