fix: view dropdown incorrect button position and floating icon button doesn't match design (#1458)
* fix: view dropdown incorrect button position * fix: className instead of style drill down * fix: view drop down width
This commit is contained in:
@ -12,17 +12,19 @@ export type ButtonGroupProps = Pick<
|
|||||||
ButtonProps,
|
ButtonProps,
|
||||||
'variant' | 'size' | 'accent'
|
'variant' | 'size' | 'accent'
|
||||||
> & {
|
> & {
|
||||||
|
className?: string;
|
||||||
children: ReactNode[];
|
children: ReactNode[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ButtonGroup({
|
export function ButtonGroup({
|
||||||
|
className,
|
||||||
children,
|
children,
|
||||||
variant,
|
variant,
|
||||||
size,
|
size,
|
||||||
accent,
|
accent,
|
||||||
}: ButtonGroupProps) {
|
}: ButtonGroupProps) {
|
||||||
return (
|
return (
|
||||||
<StyledButtonGroupContainer>
|
<StyledButtonGroupContainer className={className}>
|
||||||
{React.Children.map(children, (child, index) => {
|
{React.Children.map(children, (child, index) => {
|
||||||
if (!React.isValidElement(child)) return null;
|
if (!React.isValidElement(child)) return null;
|
||||||
|
|
||||||
|
|||||||
@ -53,6 +53,7 @@ const StyledButton = styled.button<
|
|||||||
: focus
|
: focus
|
||||||
? `0 0 0 3px ${theme.color.blue10}`
|
? `0 0 0 3px ${theme.color.blue10}`
|
||||||
: 'none'};
|
: 'none'};
|
||||||
|
box-sizing: border-box;
|
||||||
color: ${({ theme, disabled, focus }) => {
|
color: ${({ theme, disabled, focus }) => {
|
||||||
return !disabled
|
return !disabled
|
||||||
? focus
|
? focus
|
||||||
@ -62,22 +63,22 @@ const StyledButton = styled.button<
|
|||||||
}};
|
}};
|
||||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
||||||
font-family: ${({ theme }) => theme.font.family};
|
font-family: ${({ theme }) => theme.font.family};
|
||||||
font-weight: ${({ theme }) => theme.font.weight.regular};
|
font-weight: ${({ theme }) => theme.font.weight.regular};
|
||||||
gap: ${({ theme }) => theme.spacing(1)};
|
gap: ${({ theme }) => theme.spacing(1)};
|
||||||
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
height: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
transition: background 0.1s ease;
|
transition: background 0.1s ease;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
|
||||||
width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
width: ${({ size }) => (size === 'small' ? '24px' : '32px')};
|
||||||
|
|
||||||
&:hover {
|
&:hover .floating-icon-button-hovered {
|
||||||
background: ${({ theme, disabled }) =>
|
display: flex;
|
||||||
!disabled ? theme.background.transparent.lighter : 'transparent'};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
@ -90,6 +91,18 @@ const StyledButton = styled.button<
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const StyledHover = styled.div`
|
||||||
|
background: ${({ theme }) => theme.background.transparent.lighter};
|
||||||
|
border-radius: calc(${({ theme }) => theme.border.radius.sm} - 2px);
|
||||||
|
bottom: 2px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: none;
|
||||||
|
left: 2px;
|
||||||
|
position: absolute;
|
||||||
|
right: 2px;
|
||||||
|
top: 2px;
|
||||||
|
`;
|
||||||
|
|
||||||
export function FloatingIconButton({
|
export function FloatingIconButton({
|
||||||
className,
|
className,
|
||||||
icon: initialIcon,
|
icon: initialIcon,
|
||||||
@ -122,6 +135,7 @@ export function FloatingIconButton({
|
|||||||
position={position}
|
position={position}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
>
|
>
|
||||||
|
{!disabled && <StyledHover className="floating-icon-button-hovered" />}
|
||||||
{icon}
|
{icon}
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -16,9 +16,9 @@ const StyledFloatingIconButtonGroupContainer = styled.div`
|
|||||||
|
|
||||||
export type FloatingIconButtonGroupProps = Pick<
|
export type FloatingIconButtonGroupProps = Pick<
|
||||||
FloatingIconButtonProps,
|
FloatingIconButtonProps,
|
||||||
'size'
|
'size' | 'className'
|
||||||
> & {
|
> & {
|
||||||
children: React.ReactElement[];
|
children: React.ReactNode[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export function FloatingIconButtonGroup({
|
export function FloatingIconButtonGroup({
|
||||||
@ -49,6 +49,10 @@ export function FloatingIconButtonGroup({
|
|||||||
additionalProps.size = size;
|
additionalProps.size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!React.isValidElement(child)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return React.cloneElement(child, additionalProps);
|
return React.cloneElement(child, additionalProps);
|
||||||
})}
|
})}
|
||||||
</StyledFloatingIconButtonGroupContainer>
|
</StyledFloatingIconButtonGroupContainer>
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { ComponentProps } from 'react';
|
import { ComponentProps } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
import { ButtonGroup } from '@/ui/button/components/ButtonGroup';
|
import { FloatingIconButtonGroup } from '@/ui/button/components/FloatingIconButtonGroup';
|
||||||
import { hoverBackground } from '@/ui/theme/constants/effects';
|
import { hoverBackground } from '@/ui/theme/constants/effects';
|
||||||
|
|
||||||
export type DropdownMenuItemAccent = 'regular' | 'danger';
|
export type DropdownMenuItemAccent = 'regular' | 'danger';
|
||||||
@ -34,9 +35,13 @@ const StyledItem = styled.li<{ accent: DropdownMenuItemAccent }>`
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
|
|
||||||
width: calc(100% - 2 * var(--horizontal-padding));
|
width: calc(100% - 2 * var(--horizontal-padding));
|
||||||
|
|
||||||
|
&:hover .actions-hover-container {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const StyledActions = styled(ButtonGroup)`
|
const StyledActions = styled(motion.div)`
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: ${({ theme }) => theme.spacing(1)};
|
right: ${({ theme }) => theme.spacing(1)};
|
||||||
@ -57,8 +62,16 @@ export function DropdownMenuItem({
|
|||||||
<StyledItem {...props} accent={accent}>
|
<StyledItem {...props} accent={accent}>
|
||||||
{children}
|
{children}
|
||||||
{actions && (
|
{actions && (
|
||||||
<StyledActions variant="tertiary" size="small">
|
<StyledActions
|
||||||
{actions}
|
className="actions-hover-container"
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
exit={{ opacity: 0 }}
|
||||||
|
transition={{ duration: 0.2 }}
|
||||||
|
>
|
||||||
|
<FloatingIconButtonGroup size="small">
|
||||||
|
{actions}
|
||||||
|
</FloatingIconButtonGroup>
|
||||||
</StyledActions>
|
</StyledActions>
|
||||||
)}
|
)}
|
||||||
</StyledItem>
|
</StyledItem>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { useTheme } from '@emotion/react';
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
import { useRecoilCallback, useSetRecoilState } from 'recoil';
|
||||||
|
|
||||||
import { IconButton } from '@/ui/button/components/IconButton';
|
import { FloatingIconButton } from '@/ui/button/components/FloatingIconButton';
|
||||||
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
import { DropdownMenuItem } from '@/ui/dropdown/components/DropdownMenuItem';
|
||||||
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
import { StyledDropdownMenuItemsContainer } from '@/ui/dropdown/components/StyledDropdownMenuItemsContainer';
|
||||||
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
import { StyledDropdownMenuSeparator } from '@/ui/dropdown/components/StyledDropdownMenuSeparator';
|
||||||
@ -199,19 +199,20 @@ export const TableViewsDropdownButton = ({
|
|||||||
onIsUnfoldedChange={setIsUnfolded}
|
onIsUnfoldedChange={setIsUnfolded}
|
||||||
anchor="left"
|
anchor="left"
|
||||||
HotkeyScope={HotkeyScope}
|
HotkeyScope={HotkeyScope}
|
||||||
|
menuWidth="auto"
|
||||||
>
|
>
|
||||||
<StyledDropdownMenuItemsContainer>
|
<StyledDropdownMenuItemsContainer>
|
||||||
{tableViews.map((view) => (
|
{tableViews.map((view) => (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={view.id}
|
key={view.id}
|
||||||
actions={[
|
actions={[
|
||||||
<IconButton
|
<FloatingIconButton
|
||||||
key="edit"
|
key="edit"
|
||||||
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
onClick={(event) => handleEditViewButtonClick(event, view.id)}
|
||||||
icon={<IconPencil size={theme.icon.size.sm} />}
|
icon={<IconPencil size={theme.icon.size.sm} />}
|
||||||
/>,
|
/>,
|
||||||
tableViews.length > 1 ? (
|
tableViews.length > 1 ? (
|
||||||
<IconButton
|
<FloatingIconButton
|
||||||
key="delete"
|
key="delete"
|
||||||
onClick={(event) =>
|
onClick={(event) =>
|
||||||
handleDeleteViewButtonClick(event, view.id)
|
handleDeleteViewButtonClick(event, view.id)
|
||||||
|
|||||||
Reference in New Issue
Block a user