diff --git a/src/@next/Menu/Menu.tsx b/src/@next/Menu/Menu.tsx index 2b0fe7663..5862d7734 100644 --- a/src/@next/Menu/Menu.tsx +++ b/src/@next/Menu/Menu.tsx @@ -11,6 +11,7 @@ export interface Option { disabled?: boolean; id?: string; label: string | React.ReactNode; + sublabel?: React.ReactNode; value: string; } @@ -55,7 +56,7 @@ export const Menu = ({ return ( {options?.map((option: Option) => { - const { value, label, disabled, id } = option; + const { value, label, sublabel, disabled, id } = option; const randomId = nextId('glints-menu-option'); const menuOptionId = id ? id : randomId; const isSelected = selectedValues?.includes(value); @@ -69,7 +70,7 @@ export const Menu = ({ onClick={onClick} allowMultiple={allowMultiple} > - + ); })} diff --git a/src/@next/Menu/components/MenuOptionLabel.tsx b/src/@next/Menu/components/MenuOptionLabel.tsx index fee4faa1f..5de52829b 100644 --- a/src/@next/Menu/components/MenuOptionLabel.tsx +++ b/src/@next/Menu/components/MenuOptionLabel.tsx @@ -1,11 +1,30 @@ import React from 'react'; import { Typography } from '../../Typography'; import { Neutral } from '../../utilities/colors'; +import { MenuOptionLabelContainer } from './MenuOptionLabelStyle'; + +interface MenuOptionLabelProps { + label: React.ReactNode; + sublabel?: React.ReactNode; +} + +export const MenuOptionLabel = ({ label, sublabel }: MenuOptionLabelProps) => { + if (!sublabel) { + return ( + + {label} + + ); + } -export const MenuOptionLabel = ({ label }: { label: React.ReactNode }) => { return ( - - {label} - + + + {label} + + + {sublabel} + + ); }; diff --git a/src/@next/Menu/components/MenuOptionLabelStyle.ts b/src/@next/Menu/components/MenuOptionLabelStyle.ts new file mode 100644 index 000000000..801f0e6fb --- /dev/null +++ b/src/@next/Menu/components/MenuOptionLabelStyle.ts @@ -0,0 +1,10 @@ +import styled from 'styled-components'; + +export const MenuOptionLabelContainer = styled.div<{ + sublabel?: React.ReactNode; +}>` + display: flex; + flex-direction: column; + align-items: center; + padding: 4px 0; +`; diff --git a/src/@next/Select/Select.stories.tsx b/src/@next/Select/Select.stories.tsx index 48c485898..2c0b573d9 100644 --- a/src/@next/Select/Select.stories.tsx +++ b/src/@next/Select/Select.stories.tsx @@ -35,6 +35,13 @@ const countries = [ { label: 'Vietnam', value: 'VIETNAM' }, ]; +const skills = [ + { label: 'Fishing', sublabel: 'Memancing', value: 'fishing' }, + { label: 'Cooking', sublabel: 'Memasak', value: 'cooking' }, + { label: 'Swimming', sublabel: 'Renang', value: 'swimming' }, + { label: 'Flying', sublabel: 'Terbang', value: 'flying' }, +]; + const options = [ { active: false, @@ -1425,3 +1432,106 @@ WithCustomPrefix.parameters = { }, }, }; + +const OptionsWithSublabelTemplate: Story = args => { + return ; +}; + +export const OptionsWithSublabel = OptionsWithSublabelTemplate.bind({}); + +OptionsWithSublabel.args = {}; + +OptionsWithSublabel.parameters = { + docs: { + source: { + code: ` + const skills = [ + { label: 'Fishing', sublabel: 'Memancing', value: 'fishing' }, + { label: 'Cooking', sublabel: 'Memasak', value: 'cooking' }, + { label: 'Swimming', sublabel: 'Renang', value: 'swimming' }, + { label: 'Flying', sublabel: 'Terbang', value: 'flying' }, + ]; + + const [inputValue, setInputValue] = useState(''); + const [selectedOptions, setSelectedOptions] = useState([]); + const [isSearchEmpty, setIsSearchEmpty] = useState(false); + + const [options, setOptions] = useState(countries); + + const handleInputChange = (value: string) => { + setInputValue(value); + + if (value === '') { + setOptions(countries); + return; + } + + const filterRegex = new RegExp(value, 'i'); + const filterOptions = options.filter((option: Option) => + (option.label as string).match(filterRegex) + ); + setOptions(filterOptions); + }; + + const handleSelect = ({ value }: { value: string }) => { + if (selectedOptions.includes(value)) { + setSelectedOptions(selectedOptions.filter(option => option !== value)); + } else { + setSelectedOptions([...selectedOptions, value]); + } + }; + + const removeTag = useCallback( + tag => () => { + const options = [...selectedOptions]; + options.splice(options.indexOf(tag), 1); + setSelectedOptions(options); + }, + [selectedOptions] + ); + + const tagsMarkup = selectedOptions.map(option => ( + + {option} + + )); + + useEffect(() => { + if (options.length === 0) { + setIsSearchEmpty(true); + } + + if (options.length > 0 && isSearchEmpty === true) { + setIsSearchEmpty(false); + } + }, [isSearchEmpty, options]); + + + return ( +
+