New view picker (#4610)
* Implement new view picker * Complete feature * Fixes according to review
This commit is contained in:
@ -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}
|
||||
|
||||
@ -31,6 +31,7 @@ export const LightIconButtonGroup = ({
|
||||
<LightIconButton
|
||||
key={`light-icon-button-${index}`}
|
||||
Icon={Icon}
|
||||
disabled={!onClick}
|
||||
onClick={onClick}
|
||||
size={size}
|
||||
/>
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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 && (
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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};
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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 }) => (
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user