feat: add dropdown button (#2407)

This commit is contained in:
Whitewater
2023-05-17 01:32:37 -07:00
committed by Himself65
parent 823bcbb6fb
commit 0444dd9264
3 changed files with 121 additions and 1 deletions

View File

@@ -2,8 +2,11 @@
import type { Meta, StoryFn } from '@storybook/react';
import { useState } from 'react';
import { Button } from '..';
import { Button } from '../ui/button/button';
import { DropdownButton } from '../ui/button/dropdown';
import type { ButtonProps } from '../ui/button/interface';
import { Menu } from '../ui/menu/menu';
import { toast } from '../ui/toast/toast';
export default {
title: 'AFFiNE/Button',
@@ -20,30 +23,72 @@ export const Primary = Template.bind(undefined);
Primary.args = {
type: 'primary',
children: 'This is a primary button',
onClick: () => toast('Click button'),
};
export const Default = Template.bind(undefined);
Default.args = {
type: 'default',
children: 'This is a default button',
onClick: () => toast('Click button'),
};
export const Light = Template.bind(undefined);
Light.args = {
type: 'light',
children: 'This is a light button',
onClick: () => toast('Click button'),
};
export const Warning = Template.bind(undefined);
Warning.args = {
type: 'warning',
children: 'This is a warning button',
onClick: () => toast('Click button'),
};
export const Danger = Template.bind(undefined);
Danger.args = {
type: 'danger',
children: 'This is a danger button',
onClick: () => toast('Click button'),
};
export const Dropdown: StoryFn = ({ onClickDropDown, ...props }) => {
const [open, setOpen] = useState(false);
return (
<>
<DropdownButton onClickDropDown={onClickDropDown} {...props}>
Dropdown Button
</DropdownButton>
<Menu
visible={open}
placement="bottom-end"
trigger={['click']}
width={235}
disablePortal={true}
onClickAway={() => {
setOpen(false);
}}
content={<>Dropdown Menu</>}
>
<DropdownButton
onClick={() => {
toast('Click button');
setOpen(false);
}}
onClickDropDown={() => setOpen(!open)}
>
Dropdown with Menu
</DropdownButton>
</Menu>
</>
);
};
Dropdown.args = {
onClick: () => toast('Click button'),
onClickDropDown: () => toast('Click dropdown'),
};
export const Test: StoryFn<ButtonProps> = () => {

View File

@@ -0,0 +1,35 @@
import { ArrowDownSmallIcon } from '@blocksuite/icons';
import {
type ButtonHTMLAttributes,
forwardRef,
type MouseEventHandler,
} from 'react';
import * as styles from './styles.css';
type DropdownButtonProps = {
onClickDropDown?: MouseEventHandler<SVGSVGElement>;
} & ButtonHTMLAttributes<HTMLButtonElement>;
export const DropdownButton = forwardRef<
HTMLButtonElement,
DropdownButtonProps
>(({ onClickDropDown, children, ...props }, ref) => {
const handleClickDropDown: MouseEventHandler<SVGSVGElement> = e => {
e.stopPropagation();
onClickDropDown?.(e);
};
return (
<button ref={ref} className={styles.dropdownBtn} {...props}>
<span>{children}</span>
<span className={styles.divider} />
<ArrowDownSmallIcon
className={styles.icon}
width={16}
height={16}
onClick={handleClickDropDown}
/>
</button>
);
});
DropdownButton.displayName = 'SimpleDropdownButton';

View File

@@ -0,0 +1,40 @@
import { style } from '@vanilla-extract/css';
export const dropdownBtn = style({
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
padding: '0 10px',
gap: '4px',
color: 'var(--affine-text-primary-color)',
fontWeight: 600,
background: 'var(--affine-button-gray-color)',
boxShadow: 'var(--affine-float-button-shadow)',
borderRadius: '8px',
fontSize: 'var(--affine-font-sm)',
// width: '100%',
height: '32px',
userSelect: 'none',
whiteSpace: 'nowrap',
cursor: 'pointer',
selectors: {
'&:hover': {
background: 'var(--affine-hover-color)',
},
},
});
export const divider = style({
width: '0.5px',
height: '16px',
background: 'var(--affine-border-color)',
});
export const icon = style({
borderRadius: '4px',
selectors: {
'&:hover': {
background: 'var(--affine-hover-color)',
},
},
});