Skip to content

Commit

Permalink
Select: created floating placeholder and required asterisk
Browse files Browse the repository at this point in the history
  • Loading branch information
Tai-DucTran committed Sep 11, 2024
1 parent 33b8349 commit 0f28229
Show file tree
Hide file tree
Showing 32 changed files with 408 additions and 18 deletions.
193 changes: 193 additions & 0 deletions src/@next/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,92 @@ NonSearchableSingleSelect.parameters = {
},
};

const NonSearchableSingleSelectWithFloatingPlaceholderTemplate: Story<
SelectProps
> = args => {
return (
<SingleSelect
options={options}
isPlaceholderFloating={true}
required={true}
height="52px"
border="2px solid #ACACAD"
borderRadius="none"
{...args}
/>
);
};

export const NonSearchableSingleSelectWithFloatingPlaceholder =
NonSearchableSingleSelectWithFloatingPlaceholderTemplate.bind({});

NonSearchableSingleSelectWithFloatingPlaceholder.args = {};

NonSearchableSingleSelectWithFloatingPlaceholder.parameters = {
docs: {
source: {
code: `
const options = [
{
active: false,
disabled: false,
id: '1',
label: 'All status',
value: 'All status',
},
{
active: false,
disabled: false,
id: '2',
label: 'Completed',
value: 'Completed',
},
{
active: false,
disabled: false,
id: '3',
label: 'Pending',
value: 'Pending',
},
{
active: false,
disabled: false,
id: '4',
label: 'Expired',
value: 'Expired',
},
{
active: false,
disabled: false,
id: '5',
label: 'Cancelled',
value: 'Cancelled',
},
];
const [selected, setSelected] = useState('');
const handleSelect = ({ value }: { value: string }) => {
setSelected(value);
};
return (
<SingleSelect
options={options}
isPlaceholderFloating={true}
required={true}
height="52px"
border='2px solid #ACACAD'
borderRadius="none"
{...args}
/>
);
`,
},
},
};

const NonSearchableMultiSelectTemplate: Story<SelectProps> = args => {
return <NonSearchableMultiSelect options={options} {...args} allowMultiple />;
};
Expand Down Expand Up @@ -243,6 +329,113 @@ NonSearchableMultipleSelect.parameters = {
},
};

const NonSearchableMultipleSelectWithFloatingPlaceholderTemplate: Story<
SelectProps
> = args => {
return (
<NonSearchableMultiSelect
allowMultiple={true}
options={options}
isPlaceholderFloating={true}
required={true}
height="52px"
border="2px solid #ACACAD"
borderRadius="none"
{...args}
/>
);
};

export const NonSearchableMultipleSelectWithFloatingPlaceholder =
NonSearchableMultipleSelectWithFloatingPlaceholderTemplate.bind({});

NonSearchableMultipleSelectWithFloatingPlaceholder.args = {};

NonSearchableMultipleSelectWithFloatingPlaceholder.parameters = {
docs: {
source: {
code: `
const options = [
{
active: false,
disabled: false,
id: '1',
label: 'All status',
value: 'All status',
},
{
active: false,
disabled: false,
id: '2',
label: 'Completed',
value: 'Completed',
},
{
active: false,
disabled: false,
id: '3',
label: 'Pending',
value: 'Pending',
},
{
active: false,
disabled: false,
id: '4',
label: 'Expired',
value: 'Expired',
},
{
active: false,
disabled: false,
id: '5',
label: 'Cancelled',
value: 'Cancelled',
},
];
const [selected, setSelected] = useState([]);
const handleSelect = ({ value }: { value: string }) => {
if (selected.includes(value)) {
setSelected(selected.filter(option => option !== value));
} else {
setSelected([...selected, value]);
}
};
const removeTag = useCallback(
({ option }: { option: string }) =>
(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.stopPropagation();
const options = [...selected];
options.splice(options.indexOf(option), 1);
setSelected(options);
},
[selected]
);
return (
<SingleSelect
allowMultiple
onRemoveTag={removeTag}
options={options}
onSelect={handleSelect}
selectedValues={selected}
width="400px"
isPlaceholderFloating={true}
required={true}
height="52px"
border="2px solid #ACACAD"
borderRadius="none"
{...args}
/>
);
`,
},
},
};

const WithErrorNonSearchableTemplate: Story<SelectProps> = args => {
return <SingleSelect options={options} {...args} />;
};
Expand Down
26 changes: 23 additions & 3 deletions src/@next/Select/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,13 @@ export interface SelectProps {
selectedValues?: string[];
/** sets a width for the Select component*/
width: string;
height?: string;
/** sets z-index override for option list dropdown. z-index default to 400 */
zIndexOverride?: number;
border?: string;
borderRadius?: string;
required?: boolean;
isPlaceholderFloating?: boolean;
}

export const Select = ({
Expand All @@ -80,19 +85,24 @@ export const Select = ({
options = [],
placeholder,
prefix,
searchable = false,
searchable,
searchableProps,
optionsPlaceholderProps,
showPopoverOnFocus = false,
scrollable = false,
sections,
selectedValues,
width,
height,
zIndexOverride,
border,
borderRadius,
required,
isPlaceholderFloating,
}: SelectProps) => {
const [popoverActive, setPopoverActive] = useState(false);
const [optionListHeight, setOptionListHeight] = useState('');
const [menuOptions, setMenuOptions] = useState(options);
const [menuOptions, setMenuOptions] = useState([]);
const { length: optionsLength } = options;
const [inputValue, setInputValue] = useState(
searchableProps?.inputValue || ''
Expand Down Expand Up @@ -187,6 +197,7 @@ export const Select = ({
onChange={searchableProps?.onInputChange}
placeholder={placeholder ?? 'Search'}
width={width}
height={height}
selectedValues={selectedValues}
onBlur={onBlur}
onSelect={onSelect}
Expand All @@ -201,6 +212,10 @@ export const Select = ({
updateMenuOptions={updateMenuOptions}
prefix={prefix}
name={name}
isPlaceholderFloating={isPlaceholderFloating}
required={required}
border={border}
borderRadius={borderRadius}
/>
);
}
Expand All @@ -216,11 +231,16 @@ export const Select = ({
onRemoveTag={onRemoveTag}
onSelectClick={handleSelectClick}
width={width}
height={height}
selectedValues={selectedValues}
options={options}
name={name}
prefix={prefix}
onClick={onSelectClick}
required={required}
border={border}
borderRadius={borderRadius}
isPlaceholderFloating={isPlaceholderFloating}
/>
);
};
Expand All @@ -230,7 +250,7 @@ export const Select = ({
active={popoverActive}
activator={
<ActivatorWrapper width={width}>
{label && <Label>{label}</Label>}
{label && !isPlaceholderFloating && <Label>{label}</Label>}
{activator()}
{helpText && (
<HelpTextContainer>
Expand Down
43 changes: 36 additions & 7 deletions src/@next/Select/components/Activator/ActivatorSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import {
StyledSelect,
StyledSelectTypography,
StyledTag,
SuffixContainer,
TagsContainer,
WithPrefixContainer,
} from './ActivatorStyle';
import { AsteriskIcon, FloatingLabel } from '../../../Input/InputStyle';

export interface ActivatorSelectProps
extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'prefix'> {
Expand All @@ -26,6 +28,12 @@ export interface ActivatorSelectProps
onSelectClick?(): void;
options?: Option[];
width?: string;
height?: string;
required?: boolean;
floatingFontSize?: string;
isPlaceholderFloating?: boolean;
border?: string;
borderRadius?: string;
}
export const ActivatorSelect = ({
customActivatorIcon,
Expand All @@ -40,6 +48,12 @@ export const ActivatorSelect = ({
hasError = false,
options,
prefix,
required,
border,
borderRadius,
height,
floatingFontSize,
isPlaceholderFloating,
...props
}: ActivatorSelectProps) => {
const [filteredValues, setFilteredValues] = useState([]);
Expand All @@ -64,14 +78,15 @@ export const ActivatorSelect = ({
onSelectClick();
onClick?.(e);
};
const selectedPlaceholder = required ? `${placeholder}*` : placeholder;

const placeholderMarkup = (
const placeholderMarkup = isPlaceholderFloating ? undefined : (
<Typography
variant="body1"
as="span"
color={disabled ? Neutral.B85 : Neutral.B68}
>
{placeholder}
{selectedPlaceholder}
</Typography>
);

Expand Down Expand Up @@ -111,6 +126,10 @@ export const ActivatorSelect = ({
onClick={handleClick}
disabled={disabled}
width={width}
height={height}
border={border}
borderRadius={borderRadius}
isPlaceholderFloating={isPlaceholderFloating}
>
<WithPrefixContainer>
{prefix && <StyledPrefixContainer>{prefix}</StyledPrefixContainer>}
Expand All @@ -126,11 +145,21 @@ export const ActivatorSelect = ({
</StyledSelectTypography>
)}
</WithPrefixContainer>
<StyledIcon
height={24}
name={customActivatorIcon || 'ri-arrow-m-down-line'}
fill={disabled ? Neutral.B85 : Neutral.B40}
/>

<SuffixContainer>
<StyledIcon
height={24}
name={customActivatorIcon || 'ri-arrow-m-down-line'}
fill={disabled ? Neutral.B85 : Neutral.B40}
/>
</SuffixContainer>

{isPlaceholderFloating && (
<FloatingLabel data-testid="textarea-label" fontSize={floatingFontSize}>
{placeholder}
{required && <AsteriskIcon>*</AsteriskIcon>}
</FloatingLabel>
)}
</StyledSelect>
);
};
Loading

0 comments on commit 0f28229

Please sign in to comment.