Initial commit from prod-batam
This commit is contained in:
27
platform/ui/src/components/Dialog/Body.tsx
Normal file
27
platform/ui/src/components/Dialog/Body.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Typography from '../Typography';
|
||||
|
||||
const Body = ({ text, className }) => {
|
||||
const theme = 'bg-primary-dark';
|
||||
return (
|
||||
<div className={classNames('relative flex-auto', theme, className)}>
|
||||
<Typography
|
||||
variant="inherit"
|
||||
color="initial"
|
||||
className="text-[14px] !leading-[1.2]"
|
||||
>
|
||||
{text}
|
||||
</Typography>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Body.propTypes = {
|
||||
text: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Body;
|
||||
84
platform/ui/src/components/Dialog/Dialog.tsx
Normal file
84
platform/ui/src/components/Dialog/Dialog.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Footer from './Footer';
|
||||
import Body from './Body';
|
||||
import Header from './Header';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const Dialog = ({
|
||||
title,
|
||||
text,
|
||||
onClose,
|
||||
noCloseButton,
|
||||
actions,
|
||||
onShow,
|
||||
onSubmit,
|
||||
header: HeaderComponent = Header,
|
||||
body: BodyComponent = Body,
|
||||
footer: FooterComponent = Footer,
|
||||
value: defaultValue = {},
|
||||
}) => {
|
||||
const [value, setValue] = useState(defaultValue);
|
||||
|
||||
const theme = 'bg-primary-dark';
|
||||
const flex = 'flex flex-col';
|
||||
const border = 'border-0 rounded';
|
||||
const outline = 'outline-none focus:outline-none';
|
||||
const position = 'relative';
|
||||
const width = 'w-full';
|
||||
const padding = 'px-[20px] pb-[20px] pt-[13px]';
|
||||
|
||||
useEffect(() => {
|
||||
if (onShow) {
|
||||
onShow();
|
||||
}
|
||||
}, [onShow]);
|
||||
|
||||
return (
|
||||
<div className={classNames(theme, flex, border, outline, position, width, padding)}>
|
||||
<HeaderComponent
|
||||
title={title}
|
||||
noCloseButton={noCloseButton}
|
||||
onClose={onClose}
|
||||
value={value}
|
||||
setValue={setValue}
|
||||
/>
|
||||
<BodyComponent
|
||||
text={text}
|
||||
value={value}
|
||||
setValue={setValue}
|
||||
/>
|
||||
<FooterComponent
|
||||
actions={actions}
|
||||
onSubmit={onSubmit}
|
||||
value={value}
|
||||
setValue={setValue}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Dialog.propTypes = {
|
||||
title: PropTypes.string,
|
||||
text: PropTypes.string,
|
||||
onClose: PropTypes.func,
|
||||
noCloseButton: PropTypes.bool,
|
||||
header: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
||||
body: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
||||
footer: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
value: PropTypes.object,
|
||||
actions: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
value: PropTypes.any,
|
||||
type: PropTypes.oneOf(['primary', 'secondary', 'cancel']).isRequired,
|
||||
})
|
||||
).isRequired,
|
||||
onShow: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Dialog;
|
||||
50
platform/ui/src/components/Dialog/Footer.tsx
Normal file
50
platform/ui/src/components/Dialog/Footer.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Button, { ButtonEnums } from '../Button';
|
||||
|
||||
const Footer = ({ actions = [], className, onSubmit = () => {}, value }) => {
|
||||
const flex = 'flex items-center justify-end';
|
||||
const padding = 'pt-[20px]';
|
||||
|
||||
return (
|
||||
<div className={classNames(flex, padding, className)}>
|
||||
{actions?.map((action, index) => {
|
||||
const isFirst = index === 0;
|
||||
|
||||
const onClickHandler = event => onSubmit({ action, value, event });
|
||||
|
||||
return (
|
||||
<Button
|
||||
key={index}
|
||||
name={action.text}
|
||||
className={classNames({ 'ml-2': !isFirst }, action.classes)}
|
||||
type={action.type}
|
||||
onClick={onClickHandler}
|
||||
>
|
||||
{action.text}
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const noop = () => {};
|
||||
|
||||
Footer.propTypes = {
|
||||
className: PropTypes.string,
|
||||
onSubmit: PropTypes.func.isRequired,
|
||||
actions: PropTypes.arrayOf(
|
||||
PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
text: PropTypes.string.isRequired,
|
||||
value: PropTypes.any,
|
||||
type: PropTypes.oneOf([ButtonEnums.type.primary, ButtonEnums.type.secondary]).isRequired,
|
||||
classes: PropTypes.arrayOf(PropTypes.string),
|
||||
})
|
||||
).isRequired,
|
||||
};
|
||||
|
||||
export default Footer;
|
||||
49
platform/ui/src/components/Dialog/Header.tsx
Normal file
49
platform/ui/src/components/Dialog/Header.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Typography from '../Typography';
|
||||
import Icon from '../Icon';
|
||||
|
||||
const CloseButton = ({ onClick }) => {
|
||||
return (
|
||||
<Icon
|
||||
data-cy="close-button"
|
||||
onClick={onClick}
|
||||
name="close"
|
||||
className="text-primary-active cursor-pointer"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CloseButton.propTypes = {
|
||||
onClick: PropTypes.func,
|
||||
};
|
||||
|
||||
const Header = ({ title, noCloseButton = false, onClose }) => {
|
||||
const theme = 'bg-primary-dark';
|
||||
const flex = 'flex items-center justify-between';
|
||||
const padding = 'pb-[20px]';
|
||||
|
||||
return (
|
||||
<div className={classNames(theme, flex, padding)}>
|
||||
<Typography
|
||||
variant="h6"
|
||||
color="primaryLight"
|
||||
className="!leading-[1.2]"
|
||||
>
|
||||
{title}
|
||||
</Typography>
|
||||
{!noCloseButton && <CloseButton onClick={onClose} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Header.propTypes = {
|
||||
className: PropTypes.string,
|
||||
title: PropTypes.string,
|
||||
noCloseButton: PropTypes.bool,
|
||||
onClose: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Header;
|
||||
@@ -0,0 +1,73 @@
|
||||
import Dialog from '../Dialog';
|
||||
import { ArgsTable, Story, Canvas, Meta } from '@storybook/addon-docs';
|
||||
import { createComponentTemplate } from '../../../storybook/functions/create-component-story';
|
||||
|
||||
export const argTypes = {
|
||||
component: Dialog,
|
||||
title: 'Modals/Dialog',
|
||||
};
|
||||
|
||||
<Meta
|
||||
title="Modals/Dialog"
|
||||
component={Dialog}
|
||||
/>
|
||||
|
||||
export const DialogTemplate = createComponentTemplate(Dialog);
|
||||
|
||||
<Heading
|
||||
title="Dialog"
|
||||
componentRelativePath="Dialog/Dialog.tsx"
|
||||
/>
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Props](#props)
|
||||
- [Usage](#usage)
|
||||
- [Contribute](#contribute)
|
||||
|
||||
## Overview
|
||||
|
||||
Dialog is a modal dialog component which enabled to show a modal dialog.
|
||||
|
||||
<Canvas>
|
||||
<Story name="Overview">{DialogTemplate.bind({})}</Story>
|
||||
</Canvas>
|
||||
|
||||
## Props
|
||||
|
||||
<ArgsTable of={Dialog} />
|
||||
|
||||
## Usage
|
||||
|
||||
It can be used to show a modal dialog to submit a form or show a message.
|
||||
|
||||
<Canvas>
|
||||
<Story
|
||||
name="Submit"
|
||||
args={{
|
||||
title: 'Dialog Title',
|
||||
text: 'Dialog Text',
|
||||
onClose: () => {
|
||||
window.alert('Dialog closed');
|
||||
},
|
||||
noCloseButton: false,
|
||||
actions: [
|
||||
{
|
||||
id: 'cancel',
|
||||
text: 'Cancel',
|
||||
type: 'cancel',
|
||||
},
|
||||
{
|
||||
id: 'submit',
|
||||
text: 'Submit',
|
||||
type: 'primary',
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
{DialogTemplate.bind({})}
|
||||
</Story>
|
||||
</Canvas>
|
||||
|
||||
## Contribute
|
||||
|
||||
<Footer componentRelativePath="Dialog/__stories__/dialog.stories.mdx" />
|
||||
2
platform/ui/src/components/Dialog/index.js
Normal file
2
platform/ui/src/components/Dialog/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import Dialog from './Dialog';
|
||||
export default Dialog;
|
||||
Reference in New Issue
Block a user