This commit is contained in:
Nate Kelley 2025-03-01 13:44:06 -07:00
parent 4ccd54f3af
commit 001c1aa894
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
2 changed files with 139 additions and 36 deletions

View File

@ -0,0 +1,122 @@
import type { Meta, StoryObj } from '@storybook/react';
import { BusterListSelectedOptionPopupContainer } from './BusterListSelectedOptionPopupContainer';
import React from 'react';
import { AppMaterialIcons } from '@/components/ui';
import { cn } from '@/lib/classMerge';
const meta: Meta<typeof BusterListSelectedOptionPopupContainer> = {
title: 'UI/List/ListSelectedOptionPopup',
component: BusterListSelectedOptionPopupContainer,
tags: ['autodocs'],
parameters: {
layout: 'centered'
},
argTypes: {
selectedRowKeys: { control: 'object' },
onSelectChange: { action: 'onSelectChange' },
buttons: { control: 'object' },
show: { control: 'boolean' }
},
decorators: [
(Story) => (
<div className="bg-background relative h-[200px] w-full min-w-[500px]">
<Story />
</div>
)
]
};
export default meta;
type Story = StoryObj<typeof BusterListSelectedOptionPopupContainer>;
// Sample data
const sampleSelectedRowKeys = ['1', '2', '3'];
// Custom button component for the stories
const CustomButton: React.FC<{
icon: 'delete' | 'edit' | 'add' | 'visibility';
label: string;
onClick: () => void;
}> = ({ icon, label, onClick }) => {
return (
<div
onClick={onClick}
className={cn(
'flex cursor-pointer items-center space-x-1 px-2 py-0.5',
'bg-bg-container rounded-md',
'border-border-default border border-dashed',
'text-text-secondary hover:text-text-default transition-colors duration-200'
)}>
<AppMaterialIcons icon={icon} />
<span>{label}</span>
</div>
);
};
export const Default: Story = {
args: {
selectedRowKeys: sampleSelectedRowKeys,
onSelectChange: (keys) => console.log('Selection changed:', keys),
show: true
}
};
export const WithButtons: Story = {
args: {
selectedRowKeys: sampleSelectedRowKeys,
onSelectChange: (keys) => console.log('Selection changed:', keys),
buttons: [
<CustomButton
key="delete"
icon="delete"
label="Delete"
onClick={() => alert('Delete clicked')}
/>,
<CustomButton key="edit" icon="edit" label="Edit" onClick={() => alert('Edit clicked')} />
],
show: true
}
};
export const Hidden: Story = {
args: {
selectedRowKeys: [],
onSelectChange: (keys) => console.log('Selection changed:', keys),
show: false
}
};
export const ForceShow: Story = {
args: {
selectedRowKeys: [],
onSelectChange: (keys) => console.log('Selection changed:', keys),
buttons: [
<CustomButton key="add" icon="add" label="Add" onClick={() => alert('Add clicked')} />
],
show: true
},
name: 'Force Show (Even With Empty Selection)'
};
export const SingleSelection: Story = {
args: {
selectedRowKeys: ['1'],
onSelectChange: (keys) => console.log('Selection changed:', keys),
buttons: [
<CustomButton
key="view"
icon="visibility"
label="View"
onClick={() => alert('View clicked')}
/>,
<CustomButton
key="delete"
icon="delete"
label="Delete"
onClick={() => alert('Delete clicked')}
/>
],
show: true
}
};

View File

@ -1,9 +1,9 @@
import { AppMaterialIcons } from '@/components/ui';
import { Text } from '@/components/ui';
import { useAntToken } from '@/styles/useAntToken';
import { createStyles } from 'antd-style';
import { Xmark } from '@/components/ui/icons';
import { Text } from '@/components/ui/typography';
import React from 'react';
import { PopupContainer, PopupSplitter } from '@/components/ui/popup/PopupContainer';
import { cn } from '@/lib/classMerge';
export const BusterListSelectedOptionPopupContainer: React.FC<{
selectedRowKeys: string[];
@ -11,8 +11,6 @@ export const BusterListSelectedOptionPopupContainer: React.FC<{
buttons?: React.ReactNode[];
show?: boolean;
}> = ({ selectedRowKeys, onSelectChange, buttons = [], show: showProp }) => {
const token = useAntToken();
const show = showProp ?? selectedRowKeys.length > 0;
return (
@ -30,52 +28,35 @@ export const BusterListSelectedOptionPopupContainer: React.FC<{
);
};
const useStyles = createStyles(({ token, css }) => ({
closeSelectedButton: css`
transition: color 0.2s ease;
color: ${token.colorTextSecondary};
&:hover {
color: ${token.colorText};
}
`
}));
const SelectedButton: React.FC<{
selectedRowKeys: string[];
onSelectChange: (selectedRowKeys: string[]) => void;
}> = ({ selectedRowKeys, onSelectChange }) => {
const token = useAntToken();
const { styles, cx } = useStyles();
const text = `${selectedRowKeys.length} selected`;
return (
<div
className="flex items-center"
style={{
backgroundColor: token.colorBgContainer,
borderRadius: token.borderRadius,
padding: `0 ${0}px 0 ${token.paddingXS}px`,
height: token.controlHeight,
border: `0.5px dashed ${token.colorBorder}`
}}>
className={cn(
'flex items-center',
'bg-bg-container rounded pl-2',
'min-h-[28px]',
'border-border-default border border-dashed'
)}>
<Text>{text}</Text>
<div
className="ml-1.5"
style={{
borderLeft: `0.5px dashed ${token.colorBorder}`,
height: token.controlHeight - 2
}}
/>
<div className="border-border-default ml-1.5 min-h-[28px] border-l border-dashed" />
<div
onClick={() => {
onSelectChange([]);
}}
className={cx(
'flex cursor-pointer items-center justify-center px-0.5',
styles.closeSelectedButton
className={cn(
'flex cursor-pointer items-center justify-center px-1',
'text-text-secondary hover:text-text-default transition-colors duration-200'
)}>
<AppMaterialIcons icon="close" />
<div className="text-base">
<Xmark />
</div>
</div>
</div>
);