New view picker (#4610)

* Implement new view picker

* Complete feature

* Fixes according to review
This commit is contained in:
Charles Bochet
2024-03-22 15:04:17 +01:00
committed by GitHub
parent d876b40056
commit 4a493b6ecf
61 changed files with 1216 additions and 422 deletions

View File

@ -20,6 +20,7 @@ export type ButtonProps = {
position?: ButtonPosition;
accent?: ButtonAccent;
soon?: boolean;
justify?: 'center' | 'flex-start' | 'flex-end';
disabled?: boolean;
focus?: boolean;
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
@ -28,7 +29,13 @@ export type ButtonProps = {
const StyledButton = styled.button<
Pick<
ButtonProps,
'fullWidth' | 'variant' | 'size' | 'position' | 'accent' | 'focus'
| 'fullWidth'
| 'variant'
| 'size'
| 'position'
| 'accent'
| 'focus'
| 'justify'
>
>`
align-items: center;
@ -177,9 +184,7 @@ const StyledButton = styled.button<
`;
case 'danger':
return css`
background: ${!disabled
? theme.background.transparent.primary
: 'transparent'};
background: transparent;
border-color: ${variant === 'secondary'
? focus
? theme.color.red
@ -236,6 +241,7 @@ const StyledButton = styled.button<
font-weight: 500;
gap: ${({ theme }) => theme.spacing(1)};
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
justify-content: ${({ justify }) => justify};
padding: ${({ theme }) => {
return `0 ${theme.spacing(2)}`;
}};
@ -266,6 +272,7 @@ export const Button = ({
position = 'standalone',
soon = false,
disabled = false,
justify = 'flex-start',
focus = false,
onClick,
}: ButtonProps) => {
@ -279,6 +286,7 @@ export const Button = ({
position={position}
disabled={soon || disabled}
focus={focus}
justify={justify}
accent={accent}
className={className}
onClick={onClick}

View File

@ -31,6 +31,7 @@ export const LightIconButtonGroup = ({
<LightIconButton
key={`light-icon-button-${index}`}
Icon={Icon}
disabled={!onClick}
onClick={onClick}
size={size}
/>

View File

@ -30,6 +30,7 @@ type IconPickerProps = {
onOpen?: () => void;
variant?: IconButtonVariant;
className?: string;
disableBlur?: boolean;
};
const StyledMenuIconItemsContainer = styled.div`
@ -86,6 +87,7 @@ export const IconPicker = ({
onClose,
onOpen,
variant = 'secondary',
disableBlur = false,
className,
}: IconPickerProps) => {
const [searchString, setSearchString] = useState('');
@ -148,6 +150,7 @@ export const IconPicker = ({
/>
}
dropdownMenuWidth={176}
disableBlur={disableBlur}
dropdownComponents={
<SelectableList
selectableListId="icon-list"

View File

@ -22,6 +22,7 @@ export type SelectOption<Value extends string | number | null> = {
export type SelectProps<Value extends string | number | null> = {
className?: string;
disabled?: boolean;
disableBlur?: boolean;
dropdownId: string;
dropdownWidth?: `${string}px` | 'auto' | number;
emptyOption?: SelectOption<Value>;
@ -75,6 +76,7 @@ const StyledIconChevronDown = styled(IconChevronDown)<{ disabled?: boolean }>`
export const Select = <Value extends string | number | null>({
className,
disabled: disabledFromProps,
disableBlur = false,
dropdownId,
dropdownWidth = 176,
emptyOption,
@ -141,6 +143,7 @@ export const Select = <Value extends string | number | null>({
dropdownMenuWidth={dropdownWidth}
dropdownPlacement="bottom-start"
clickableComponent={selectControl}
disableBlur={disableBlur}
dropdownComponents={
<>
{!!withSearchInput && (

View File

@ -35,6 +35,7 @@ type DropdownProps = {
dropdownPlacement?: Placement;
dropdownMenuWidth?: `${string}px` | `${number}%` | 'auto' | number;
dropdownOffset?: { x?: number; y?: number };
disableBlur?: boolean;
onClickOutside?: () => void;
onClose?: () => void;
onOpen?: () => void;
@ -50,6 +51,7 @@ export const Dropdown = ({
dropdownHotkeyScope,
dropdownPlacement = 'bottom-end',
dropdownOffset = { x: 0, y: 0 },
disableBlur = false,
onClickOutside,
onClose,
onOpen,
@ -109,7 +111,10 @@ export const Dropdown = ({
{clickableComponent && (
<div
ref={refs.setReference}
onClick={toggleDropdown}
onClick={() => {
toggleDropdown();
onClickOutside?.();
}}
className={className}
>
{clickableComponent}
@ -123,6 +128,7 @@ export const Dropdown = ({
)}
{isDropdownOpen && (
<DropdownMenu
disableBlur={disableBlur}
width={dropdownMenuWidth ?? dropdownWidth}
data-select-disable
ref={refs.setFloating}

View File

@ -9,7 +9,10 @@ const StyledDropdownMenu = styled.div<{
? 'none'
: 'blur(12px) saturate(200%) contrast(50%) brightness(130%)'};
background: ${({ theme }) => theme.background.transparent.forBackdropFilter};
background: ${({ theme, disableBlur }) =>
disableBlur
? theme.background.primary
: theme.background.transparent.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};

View File

@ -11,14 +11,11 @@ const StyledHeader = styled.li`
display: flex;
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
border-radius: ${({ theme }) => theme.border.radius.sm};
padding: ${({ theme }) => theme.spacing(1)};
user-select: none;
&:hover {
background: ${({ theme }) => theme.background.transparent.light};
}
`;
const StyledChildrenWrapper = styled.span`
@ -46,9 +43,10 @@ export const DropdownMenuHeader = ({
testId,
}: DropdownMenuHeaderProps) => {
return (
<StyledHeader data-testid={testId} onClick={onClick}>
<StyledHeader data-testid={testId}>
{StartIcon && (
<LightIconButton
onClick={onClick}
testId="dropdown-menu-header-end-icon"
Icon={StartIcon}
accent="tertiary"
@ -58,6 +56,7 @@ export const DropdownMenuHeader = ({
<StyledChildrenWrapper>{children}</StyledChildrenWrapper>
{EndIcon && (
<StyledLightIconButton
onClick={onClick}
testId="dropdown-menu-header-end-icon"
Icon={EndIcon}
accent="tertiary"

View File

@ -30,12 +30,12 @@ const StyledInputContainer = styled.div`
export const DropdownMenuInput = forwardRef<
HTMLInputElement,
InputHTMLAttributes<HTMLInputElement>
>(({ autoFocus, defaultValue, placeholder, onChange }, ref) => {
>(({ autoFocus, value, placeholder, onChange }, ref) => {
return (
<StyledInputContainer>
<StyledInput
autoFocus={autoFocus}
defaultValue={defaultValue}
value={value}
placeholder={placeholder}
onChange={onChange}
ref={ref}

View File

@ -274,7 +274,7 @@ export const WithInput: Story = {
args: {
dropdownComponents: (
<>
<DropdownMenuInput defaultValue="Lorem ipsum" autoFocus />
<DropdownMenuInput value="Lorem ipsum" autoFocus />
<DropdownMenuSeparator />
<DropdownMenuItemsContainer hasMaxHeight>
{optionsMock.map(({ name }) => (

View File

@ -8,7 +8,7 @@ const meta: Meta<typeof DropdownMenuInput> = {
title: 'UI/Layout/Dropdown/DropdownMenuInput',
component: DropdownMenuInput,
decorators: [ComponentDecorator],
args: { defaultValue: 'Lorem ipsum' },
args: { value: 'Lorem ipsum' },
};
export default meta;