feat: DialogProvider component (#198)

* feat: somewhat working DialogProvider

* feat: handle multiple dialogs properly, initial focus

let's just ignore that showFocus=true doesn't work with "nested" dialogs

Co-authored-by: Razboy20 <Razboy20@users.noreply.github.com>

* feat: rework code

* feat: add default styles to prompts

* refactor: fix stylings

---------

Co-authored-by: Razboy20 <Razboy20@users.noreply.github.com>
Co-authored-by: Razboy20 <razboy20@gmail.com>
This commit is contained in:
Samuel Gunter
2024-05-20 13:00:00 -07:00
committed by GitHub
parent bcb5a8c469
commit d1b921a5b0
5 changed files with 331 additions and 4 deletions

View File

@@ -0,0 +1,169 @@
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from '@views/components/common/Button';
import DialogProvider, { usePrompt } from '@views/components/common/DialogProvider/DialogProvider';
import Text from '@views/components/common/Text/Text';
import React, { useState } from 'react';
import MaterialSymbolsExpandAllRoundedIcon from '~icons/material-symbols/expand-all-rounded';
const meta = {
title: 'Components/Common/DialogProvider',
component: DialogProvider,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
args: {},
argTypes: {},
} satisfies Meta<typeof DialogProvider>;
export default meta;
type Story = StoryObj<typeof meta>;
export const Default: Story = {
args: { children: undefined },
render: () => (
<DialogProvider>
<InnerComponent />
</DialogProvider>
),
};
const InnerComponent = () => {
const showDialog = usePrompt();
const myShow = () => {
showDialog({
title: 'Dialog Title',
description: 'Dialog Description',
// eslint-disable-next-line react/no-unstable-nested-components
buttons: close => (
<Button variant='filled' color='ut-burntorange' onClick={close}>
Close
</Button>
),
});
};
return (
<Button variant='filled' color='ut-burntorange' icon={MaterialSymbolsExpandAllRoundedIcon} onClick={myShow}>
Open Dialog
</Button>
);
};
export const FiveDialogs: Story = {
args: { children: undefined },
render: () => (
<DialogProvider>
<Text variant='p'>They&apos;ll open with 100ms delay</Text>
<FiveDialogsInnerComponent />
</DialogProvider>
),
};
const FiveDialogsInnerComponent = () => {
const showDialog = usePrompt();
const myShow = () => {
for (let i = 0; i < 5; i++) {
setTimeout(
() =>
showDialog({
title: `Dialog #${i}`,
description:
'Deleting Main Schedule is permanent and will remove all added courses from that schedule.',
// eslint-disable-next-line react/no-unstable-nested-components
buttons: close => (
<Button variant='filled' color='ut-burntorange' onClick={close}>
Close
</Button>
),
}),
100 * i
);
}
};
return (
<Button variant='filled' color='ut-burntorange' icon={MaterialSymbolsExpandAllRoundedIcon} onClick={myShow}>
Open Dialogs
</Button>
);
};
export const NestedDialogs: Story = {
args: { children: undefined },
render: () => (
<DialogProvider>
<NestedDialogsInnerComponent />
</DialogProvider>
),
};
const NestedDialogsInnerComponent = () => {
const showDialog = usePrompt();
const myShow = () => {
showDialog({
title: 'Dialog Title',
description: 'Dialog Description',
// eslint-disable-next-line react/no-unstable-nested-components
buttons: close => (
<>
<NestedDialogsInnerComponent />
<Button variant='filled' color='ut-burntorange' onClick={close}>
Close
</Button>
</>
),
});
};
return (
<Button variant='filled' color='ut-burntorange' icon={MaterialSymbolsExpandAllRoundedIcon} onClick={myShow}>
Open Next Dialog
</Button>
);
};
export const DialogWithOnClose: Story = {
args: { children: undefined },
render: () => (
<DialogProvider>
<DialogWithOnCloseInnerComponent />
</DialogProvider>
),
};
const DialogWithOnCloseInnerComponent = () => {
const showDialog = usePrompt();
const [timesClosed, setTimesClosed] = useState(0);
const myShow = () => {
showDialog({
title: 'Dialog Title',
description: 'Dialog Description',
// eslint-disable-next-line react/no-unstable-nested-components
buttons: close => (
<Button variant='filled' color='ut-burntorange' onClick={close}>
Close
</Button>
),
onClose: () => {
setTimesClosed(prev => prev + 1);
},
});
};
return (
<>
<h1>
You closed the button below {timesClosed} {timesClosed === 1 ? 'time' : 'times'}
</h1>
<Button variant='filled' color='ut-burntorange' icon={MaterialSymbolsExpandAllRoundedIcon} onClick={myShow}>
Open Dialog
</Button>
</>
);
};