diff --git a/.storybook/storybook.scss b/.storybook/storybook.scss index 66a093d0..7aea5c1d 100644 --- a/.storybook/storybook.scss +++ b/.storybook/storybook.scss @@ -132,6 +132,16 @@ #story--react-ebs-ui-organisms-layout-sidebar--regular { min-height: 50vh; } + + #story--react-ebs-ui-molecules-loader--regular .ebs-loader { + height: 200px; + } + + .ebs-loader { + > .ebs-loader__spinner.fixed { + position: absolute; + } + } } .ebs-select__wrapper { @@ -140,7 +150,8 @@ } @media (max-width: 500px) { - .ebs-select__wrapper, .ebs-space__item { + .ebs-select__wrapper, + .ebs-space__item { width: 100%; } -} \ No newline at end of file +} diff --git a/package.json b/package.json index bb20b8af..b193f117 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ebs-design", - "version": "0.0.1-beta.98", + "version": "0.0.1-beta.99", "description": "EBS Design System React UI elements.", "author": "EBS Integrator (https://ebs-integrator.com/)", "maintainers": [ @@ -47,7 +47,7 @@ "build:storybook": "build-storybook -o docs-build -s ./.storybook/images" }, "dependencies": { - "@storybook/addon-controls": "^6.3.6", + "@storybook/addon-controls": "^6.3.7", "classnames": "^2.2.6", "dayjs": "^1.9.4", "rc-field-form": "^1.17.4", @@ -66,15 +66,15 @@ "react-dom": ">= 16.8" }, "devDependencies": { - "@storybook/addon-actions": "^6.3.6", - "@storybook/addon-docs": "^6.3.6", - "@storybook/addon-essentials": "^6.3.6", - "@storybook/addon-links": "^6.3.6", - "@storybook/addons": "^6.3.6", + "@storybook/addon-actions": "^6.3.7", + "@storybook/addon-docs": "^6.3.7", + "@storybook/addon-essentials": "^6.3.7", + "@storybook/addon-links": "^6.3.7", + "@storybook/addons": "^6.3.7", "@storybook/preset-create-react-app": "^3.2.0", "@storybook/preset-typescript": "^3.0.0", - "@storybook/react": "^6.3.6", - "@storybook/theming": "^6.3.6", + "@storybook/react": "^6.3.7", + "@storybook/theming": "^6.3.7", "@svgr/rollup": "^2.4.1", "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.3.2", diff --git a/src/components/atoms/Alert/Alert.stories.tsx b/src/components/atoms/Alert/Alert.stories.tsx index ecaded32..6f687533 100644 --- a/src/components/atoms/Alert/Alert.stories.tsx +++ b/src/components/atoms/Alert/Alert.stories.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { Template } from 'components/storybook'; -import { Alert, Container, Row, Col } from '../'; +import { Alert, AlertProps } from './Alert'; import { exportStory } from '../../../libs'; export default { @@ -8,61 +9,20 @@ export default { component: Alert, }; -export const regular = (): React.ReactElement => ( - - - - - Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam, ratione! - - - - - - - - - - - - - +export const Regular: React.FC & { args: AlertProps } = ({ children, ...props }) => ( + ); -export const closable = (): React.ReactElement => ( - - - - - - - - - - - - - - - - -); - -export const outlined = (): React.ReactElement => ( - - - - - - - - - - - - - - - - -); +Regular.args = { + message: 'Message', + icon: true, + closable: true, + outlined: false, + type: 'success', + onClose: () => console.log, + children: 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Veniam, ratione!', +}; diff --git a/src/components/atoms/Alert/Alert.tsx b/src/components/atoms/Alert/Alert.tsx index e5243637..97f2a9cf 100644 --- a/src/components/atoms/Alert/Alert.tsx +++ b/src/components/atoms/Alert/Alert.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; - import cn from 'classnames'; + import { Icon } from '../'; export type AlertType = 'success' | 'info' | 'warning' | 'error'; -export interface AlertProps { + +export interface AlertProps extends React.HTMLAttributes { type?: AlertType; - className?: string; message?: string; - description?: string; closable?: boolean; outlined?: boolean; icon?: boolean; @@ -24,6 +23,7 @@ export const Alert: React.FC = ({ closable, className, children, + ...props }) => { const [closed, setClosed] = React.useState(false); @@ -36,6 +36,7 @@ export const Alert: React.FC = ({ { 'ebs-alert--outlined': outlined }, className, )} + {...props} > {icon && } diff --git a/src/components/atoms/Animated.tsx b/src/components/atoms/Animated.tsx index 06804969..990567c0 100644 --- a/src/components/atoms/Animated.tsx +++ b/src/components/atoms/Animated.tsx @@ -2,11 +2,11 @@ import * as React from 'react'; import cn from 'classnames'; import AnimateHeight from 'react-animate-height'; -interface Props { +export interface AnimatedProps + extends Omit, 'aria-hidden'>, 'onAnimationStart'>, 'onAnimationEnd'> { startFrom?: string | number; debounce?: number; duration?: number; - className?: string; loading?: boolean; disabled?: boolean; @@ -14,7 +14,13 @@ interface Props { children: any; } -export const Animated: React.FC = ({ startFrom = '0%', debounce = 1, duration = 500, className, ...props }) => { +export const Animated: React.FC = ({ + startFrom = '0%', + debounce = 1, + duration = 500, + className, + ...props +}) => { const [loading, setLoading] = React.useState(true); const timer = React.useRef(); @@ -41,7 +47,7 @@ export const Animated: React.FC = ({ startFrom = '0%', debounce = 1, dura } return ( - + {props.children} ); diff --git a/src/components/atoms/Avatar/Avatar.stories.tsx b/src/components/atoms/Avatar/Avatar.stories.tsx index af079294..097ba850 100644 --- a/src/components/atoms/Avatar/Avatar.stories.tsx +++ b/src/components/atoms/Avatar/Avatar.stories.tsx @@ -1,109 +1,53 @@ import * as React from 'react'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Template } from 'components/storybook'; -import { Avatar, AvatarCard, AvatarInline } from './'; -import { AvatarSize } from './AvatarCard'; +import { Avatar, AvatarProps } from './Avatar'; +import { AvatarCard, CardProps } from './AvatarCard'; +import { AvatarInline } from './AvatarInline'; import { exportStory } from '../../../libs'; export default { title: exportStory('Avatar', 'atoms'), component: Avatar, subcomponents: { AvatarCard, AvatarInline }, + argTypes: { + icon: { control: 'text' }, + shortAlt: { control: 'text' }, + }, }; -const sizes = ['small', 'big']; - -export const regularWithPhoto = (): React.ReactElement => ( - - {(size) => ( - - )} - -); - -export const regularWithOutPhoto = (): React.ReactElement => ( - - {(size) => } - -); - -export const regularCicledWithPhoto = (): React.ReactElement => ( - - {(size) => ( - - )} - -); - -export const regularCicledWithoutPhoto = (): React.ReactElement => ( - - {(size) => } - -); - -export const statusActive = (): React.ReactElement => ( - - {(size) => } - -); - -export const statusUnactive = (): React.ReactElement => ( - - {(size) => } - +export const Regular: React.FC & { args: AvatarProps } = ({ children, ...props }) => ( + ); -export const cardWithPhoto = (): React.ReactElement => ( - - {(size) => ( - - )} - -); +Regular.args = { + type: 'regular', + img: + 'https://s3.amazonaws.com/TWFiles/328702/userAvatar/tf_ae0f94af-4f65-47f5-bc9e-e5cebb5537e2.photo_2018-08-07_16-57-45.jpg', + alt: 'Wladimir Zhosan', + size: 'small', +}; -export const cardWithOutPhoto = (): React.ReactElement => ( - - {(size) => } - +export const Card: React.FC & { args: CardProps } = ({ children, ...props }) => ( + ); -export const cardWithStatus = (): React.ReactElement => ( - - {(size) => } - -); +Card.args = Regular.args; -export const avatarInline = (): React.ReactElement => ( - - {(size) => ( - - )} - +export const Inline: React.FC & { args: CardProps } = ({ children, ...props }) => ( + ); -export const avatarInlineDynamicColor = (): React.ReactElement => ( - - {(size) => ( - - )} - -); +Inline.args = { + status: 'active', + description: 'Administrator', + alt: Regular.args.alt, + type: Regular.args.type, + size: Regular.args.size, +}; diff --git a/src/components/atoms/Avatar/Avatar.tsx b/src/components/atoms/Avatar/Avatar.tsx index d17ededf..cf4120a2 100644 --- a/src/components/atoms/Avatar/Avatar.tsx +++ b/src/components/atoms/Avatar/Avatar.tsx @@ -4,10 +4,9 @@ import { colorFromString, firstLetters } from 'libs'; export type AvatarType = 'regular' | 'primary' | 'light' | 'dynamic'; -export interface AvatarProps { +export interface AvatarProps extends React.HTMLAttributes { type?: AvatarType; size?: 'small' | 'big'; - className?: string; circle?: boolean; shortAlt?: React.ReactNode; shortLetters?: number; @@ -28,15 +27,17 @@ export const Avatar: React.FC = ({ alt = '', img, status, + ...props }) => { const shortAlt = React.useMemo(() => ($shortAlt ? $shortAlt : alt ? firstLetters(alt, shortLetters) : alt), [alt]); return (
{img ? ( {alt} diff --git a/src/components/atoms/Avatar/AvatarCard.tsx b/src/components/atoms/Avatar/AvatarCard.tsx index 92280649..bd4005d3 100644 --- a/src/components/atoms/Avatar/AvatarCard.tsx +++ b/src/components/atoms/Avatar/AvatarCard.tsx @@ -4,10 +4,9 @@ import { Avatar, AvatarType } from './Avatar'; export type AvatarSize = 'small' | 'big'; -export interface CardProps { +export interface CardProps extends React.HTMLAttributes { type?: AvatarType; size?: AvatarSize; - className?: string; shortAlt?: React.ReactNode; alt?: string; icon?: React.ReactNode; @@ -27,8 +26,9 @@ export const AvatarCard: React.FC = ({ shortAlt, alt = '', status, + ...props }) => ( -
+
{alt}
diff --git a/src/components/atoms/Avatar/AvatarInline.tsx b/src/components/atoms/Avatar/AvatarInline.tsx index a70674ff..b2dda6f2 100644 --- a/src/components/atoms/Avatar/AvatarInline.tsx +++ b/src/components/atoms/Avatar/AvatarInline.tsx @@ -15,6 +15,7 @@ export const AvatarInline: React.FC = ({ status, description, reversed = false, + ...props }) => (
= ({ }, className, )} + {...props} > {!reversed && ( ( - - - -
Badges
- - - - - - - - - - - - - - - - - - - - - - - - - - -
-
+export const Regular: React.FC & { args: BadgeProps } = ({ children, ...props }) => ( + ); + +Regular.args = { + type: 'success', + text: 'Example', + count: undefined, + className: '', +}; diff --git a/src/components/atoms/Badge/Badge.tsx b/src/components/atoms/Badge/Badge.tsx index 370d8c8f..b9589e39 100644 --- a/src/components/atoms/Badge/Badge.tsx +++ b/src/components/atoms/Badge/Badge.tsx @@ -3,16 +3,15 @@ import cn from 'classnames'; export type BadgeType = 'regular' | 'success' | 'info' | 'warning' | 'danger'; -interface Props { +export interface BadgeProps extends React.HTMLAttributes { count?: number; text?: string; type?: BadgeType; - className?: string; } -export const Badge: React.FC = ({ count, text, type = 'regular', className, children }) => { +export const Badge: React.FC = ({ count, text, type = 'regular', className, children, ...props }) => { return ( -
+
{(count || text) && (
{count || text}
diff --git a/src/components/atoms/Button/Button.stories.tsx b/src/components/atoms/Button/Button.stories.tsx index 07376500..ac144a71 100644 --- a/src/components/atoms/Button/Button.stories.tsx +++ b/src/components/atoms/Button/Button.stories.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; -import { Icon as SVGIcon, Row, Col } from 'components/atoms'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Icon } from 'components/atoms'; +import { Template } from 'components/storybook'; -import { Button, ButtonSize, ButtonGroup } from './Button'; +import { Button, ButtonGroup, ButtonProps } from './Button'; import { exportStory } from '../../../libs'; export default { @@ -11,226 +11,22 @@ export default { subcomponents: { ButtonGroup }, }; -export const Primary = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - +export const Regular: React.FC & { args: ButtonProps } = ({ children, ...props }) => ( + ); -export const Fill = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); - -export const Ghost = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); - -export const Dark = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); - -export const Text = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); - -export const Icon = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); - -export const WithIcon = (): React.ReactNode => ( - - {(size) => ( - - - - - - - - - - - - - - - - - - )} - -); +Regular.args = { + type: 'primary', + size: 'medium', + children: 'Example', + form: '', + icon: '', + buttonClass: '', + loading: false, + submit: false, + block: false, + onClick: () => console.log, + prefix: , +}; diff --git a/src/components/atoms/Button/Button.tsx b/src/components/atoms/Button/Button.tsx index 16337989..a3c6d462 100644 --- a/src/components/atoms/Button/Button.tsx +++ b/src/components/atoms/Button/Button.tsx @@ -7,15 +7,13 @@ export type ButtonSize = 'small' | 'medium' | 'large'; export type ButtonType = 'text' | 'primary' | 'fill' | 'ghost' | 'dark' | 'light'; -export interface ButtonProps { +export interface ButtonProps extends Omit, 'type'>, 'prefix'> { onClick?: () => void; prefix?: React.ReactNode; size?: ButtonSize; type?: ButtonType; loading?: boolean; submit?: boolean; - disabled?: boolean; - className?: string; buttonClass?: string; form?: string; icon?: string; @@ -71,6 +69,8 @@ export const Button: React.FC = ({ ); }; -export const ButtonGroup: React.FC<{ className?: string }> = ({ children, className }) => ( -
{children}
+export const ButtonGroup: React.FC> = ({ children, className, ...props }) => ( +
+ {children} +
); diff --git a/src/components/atoms/Card/Card.stories.tsx b/src/components/atoms/Card/Card.stories.tsx index ce330c1a..653bef27 100644 --- a/src/components/atoms/Card/Card.stories.tsx +++ b/src/components/atoms/Card/Card.stories.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { Button, Space } from 'components/atoms'; import { Table } from 'components/organisms'; -import { Card } from './Card'; +import { Card, CardProps } from './Card'; import { exportStory } from '../../../libs'; const { Header: CardHeader, Footer: CardFooter, Body: CardBody } = Card; @@ -11,6 +11,12 @@ export default { title: exportStory('Card', 'atoms'), component: Card, subcomponents: { CardHeader, CardBody, CardFooter }, + argTypes: { + size: { + options: ['small', 'medium', 'large'], + control: { type: 'select' }, + }, + }, }; const data = [ @@ -38,8 +44,8 @@ const columns = [ }, ]; -export const Regular = (): React.ReactElement => ( - +export const Regular: React.FC & { args: CardProps } = ({ children, ...props }) => ( + @@ -65,3 +71,9 @@ export const Regular = (): React.ReactElement => ( ); + +Regular.args = { + size: 'medium', + collapsible: true, + className: '', +}; diff --git a/src/components/atoms/Card/Card.tsx b/src/components/atoms/Card/Card.tsx index cb3ab573..005f3eab 100644 --- a/src/components/atoms/Card/Card.tsx +++ b/src/components/atoms/Card/Card.tsx @@ -6,7 +6,6 @@ import { CardBody, CardBodyProps } from './CardBody'; import { CardFooter, CardFooterProps } from './CardFooter'; export interface CardProps extends React.HTMLAttributes { - className?: string; size?: SizeType; collapsible?: boolean; collapsed?: boolean; diff --git a/src/components/atoms/Card/CardBody.tsx b/src/components/atoms/Card/CardBody.tsx index 9e3bc580..fcaf14bd 100644 --- a/src/components/atoms/Card/CardBody.tsx +++ b/src/components/atoms/Card/CardBody.tsx @@ -3,17 +3,15 @@ import cn from 'classnames'; import AnimateHeight from 'react-animate-height'; import { CardContext } from './Card'; -export interface CardBodyProps { - className?: string; -} +export type CardBodyProps = React.HTMLAttributes; -export const CardBody: React.FC = ({ className, children }) => { +export const CardBody: React.FC> = ({ className, children, ...props }) => { const { height, collapsible } = React.useContext(CardContext); // Return animated card body for collapse if (collapsible) { return ( -
+
{children} diff --git a/src/components/atoms/Card/CardFooter.tsx b/src/components/atoms/Card/CardFooter.tsx index 809e080d..c0aa1703 100644 --- a/src/components/atoms/Card/CardFooter.tsx +++ b/src/components/atoms/Card/CardFooter.tsx @@ -1,11 +1,12 @@ import * as React from 'react'; import cn from 'classnames'; -export interface CardFooterProps { - className?: string; +export interface CardFooterProps extends React.HTMLAttributes { bordered?: boolean; } -export const CardFooter: React.FC = ({ className, bordered, children }) => ( -
{children}
+export const CardFooter: React.FC = ({ className, bordered, children, ...props }) => ( +
+ {children} +
); diff --git a/src/components/atoms/Card/CardHeader.tsx b/src/components/atoms/Card/CardHeader.tsx index aaec44a3..ef494342 100644 --- a/src/components/atoms/Card/CardHeader.tsx +++ b/src/components/atoms/Card/CardHeader.tsx @@ -3,13 +3,12 @@ import cn from 'classnames'; import { Icon } from 'components/atoms'; import { CardContext } from './Card'; -export interface CardHeaderProps { - className?: string; +export interface CardHeaderProps extends React.HTMLAttributes { bordered?: boolean; onClick?: () => void; } -export const CardHeader: React.FC = ({ className, bordered, onClick, children }) => { +export const CardHeader: React.FC = ({ className, bordered, onClick, children, ...props }) => { const { collapsible, height, setHeight } = React.useContext(CardContext); // Card header classNames @@ -41,7 +40,7 @@ export const CardHeader: React.FC = ({ className, bordered, onC }; return ( -
+
{children}
diff --git a/src/components/atoms/Chips/Chips.scss b/src/components/atoms/Chips/Chips.scss index 328ae689..f21b11c6 100644 --- a/src/components/atoms/Chips/Chips.scss +++ b/src/components/atoms/Chips/Chips.scss @@ -17,6 +17,10 @@ background-color: $primary-color; border-color: $primary-color; color: $white; + + .ebs-icon { + color: $white; + } } } diff --git a/src/components/atoms/Chips/Chips.stories.tsx b/src/components/atoms/Chips/Chips.stories.tsx index ba225707..00d9a629 100644 --- a/src/components/atoms/Chips/Chips.stories.tsx +++ b/src/components/atoms/Chips/Chips.stories.tsx @@ -1,105 +1,31 @@ import * as React from 'react'; import { Icon } from 'components/atoms'; +import { Template } from 'components/storybook'; -import { Chips } from './Chips'; +import { Chips, ChipsProps } from './Chips'; import { exportStory } from '../../../libs'; export default { title: exportStory('Chips', 'atoms'), component: Chips, + argTypes: { + text: { control: 'text' }, + prefix: { control: 'text' }, + suffix: { control: 'text' }, + }, }; -export const Regular = (): React.ReactElement => { +export const Regular: React.FC = ({ + children, + prefix = , + text = 'Simple Chips', + ...props +}) => { const [checked, setChecked] = React.useState(false); return ( -
-
-
Chips
- -
-
Switcher
- -
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
- -
-
Chips + Prefix
- -
-
Switcher
- } /> -
- -
-
Inactive
- } /> -
- -
-
Active
- } /> -
- -
-
Disabled & Inactive
- } /> -
- -
-
Disabled & Active
- } /> -
-
- -
-
Chips + Suffix
- -
-
Switcher
- } /> -
- -
-
Inactive
- } /> -
- -
-
Active
- } /> -
- -
-
Disabled & Inactive
- } /> -
- -
-
Disabled & Active
- } /> -
-
-
+ ); }; diff --git a/src/components/atoms/Chips/Chips.tsx b/src/components/atoms/Chips/Chips.tsx index dc9dab2c..254bd256 100644 --- a/src/components/atoms/Chips/Chips.tsx +++ b/src/components/atoms/Chips/Chips.tsx @@ -1,17 +1,25 @@ import * as React from 'react'; import cn from 'classnames'; -interface Props { - className?: string; +export interface ChipsProps extends Omit, 'prefix'>, 'onChange'> { prefix?: React.ReactNode; suffix?: React.ReactNode; - disabled?: boolean; + text?: React.ReactNode; checked?: boolean; + disabled?: boolean; onChange?: (value: boolean) => void; - text?: React.ReactNode; } -export const Chips: React.FC = ({ className, prefix, suffix, disabled, checked, onChange, text }) => { +export const Chips: React.FC = ({ + className, + prefix, + suffix, + disabled, + checked, + onChange, + text, + ...props +}) => { const onClickHandler = (): void => (!disabled && onChange !== undefined ? onChange(!checked) : undefined); return ( @@ -22,6 +30,7 @@ export const Chips: React.FC = ({ className, prefix, suffix, disabled, ch disabled: disabled, })} onClick={onClickHandler} + {...props} > {prefix &&
{prefix}
} diff --git a/src/components/atoms/Collapse/Collapse.stories.tsx b/src/components/atoms/Collapse/Collapse.stories.tsx index 06f5c77c..a54ff52b 100644 --- a/src/components/atoms/Collapse/Collapse.stories.tsx +++ b/src/components/atoms/Collapse/Collapse.stories.tsx @@ -1,57 +1,68 @@ import * as React from 'react'; import { Icon, Space } from 'components/atoms'; - -import { Collapse } from './Collapse'; import { exportStory } from 'libs'; +import { Collapse, CollapseProps } from './Collapse'; + const { Group: CollapseGroup, Header: CollapseHeader, Body: CollapseBody } = Collapse; export default { title: exportStory('Collapse', 'atoms'), component: Collapse, subcomponents: { CollapseGroup, CollapseHeader, CollapseBody }, + argTypes: { + size: { + options: ['small', 'medium', 'large'], + control: { type: 'select' }, + }, + }, }; -export const Regular = (): React.ReactElement => ( - - Collapse element - -

- Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia sed unde, aut nobis tempora debitis explicabo - dicta qui nulla corrupti. -

-
+export const Regular: React.FC & { args: CollapseProps } = ({ children, ...props }) => ( + + Example + {children} ); -export const Group = (): React.ReactElement => ( +export const Group: React.FC & { args: CollapseProps } = ({ children, ...props }) => ( - + - Condition 1 + Example 1 - Example collapse + {children} - + - Condition 2 + Example 2 - Example collapse + {children} - + - Condition 3 + Example 3 - Example collapse + {children} ); + +Regular.args = { + size: 'medium', + collapsed: true, + bordered: false, + children: + 'Lorem ipsum dolor sit amet consectetur adipisicing elit. Mollitia sed unde, aut nobis tempora debitis explicabo dicta qui nulla corrupti.', +}; + +Group.args = Regular.args; diff --git a/src/components/atoms/Collapse/Collapse.tsx b/src/components/atoms/Collapse/Collapse.tsx index c68bc64e..0d48f1d9 100644 --- a/src/components/atoms/Collapse/Collapse.tsx +++ b/src/components/atoms/Collapse/Collapse.tsx @@ -5,13 +5,10 @@ import { CollapseGroup, CollapseGroupProps } from './CollapseGroup'; import { CollapseHeader, CollapseHeaderProps } from './CollapseHeader'; import { CollapseBody, CollapseBodyProps } from './CollapseBody'; -export interface CollapseProps { +export interface CollapseProps extends React.HTMLAttributes { collapsed?: boolean; - className?: string; size?: SizeType; - style?: React.CSSProperties; bordered?: boolean; - onClick?: (collapsed?: boolean) => void; } export interface CollapseComposition { @@ -37,13 +34,17 @@ const Collapse: React.FC & CollapseComposition = ({ collapsed = false, bordered = false, className, - style, children, + ...props }) => { const [height, setHeight] = React.useState(collapsed ? 0 : 'auto'); + React.useEffect(() => { + setHeight(collapsed ? 0 : 'auto'); + }, [collapsed]); + return ( -
+
{children}
); diff --git a/src/components/atoms/Collapse/CollapseBody.tsx b/src/components/atoms/Collapse/CollapseBody.tsx index cb1f257a..99c2483d 100644 --- a/src/components/atoms/Collapse/CollapseBody.tsx +++ b/src/components/atoms/Collapse/CollapseBody.tsx @@ -3,16 +3,13 @@ import cn from 'classnames'; import AnimateHeight from 'react-animate-height'; import { CollapseContext } from './Collapse'; -export interface CollapseBodyProps { - className?: string; - style?: React.CSSProperties; -} +export type CollapseBodyProps = React.HTMLAttributes; -export const CollapseBody: React.FC = ({ className, style, children }) => { +export const CollapseBody: React.FC = ({ className, style, children, ...props }) => { const { height } = React.useContext(CollapseContext); return ( -
+
{children} diff --git a/src/components/atoms/Collapse/CollapseGroup.tsx b/src/components/atoms/Collapse/CollapseGroup.tsx index facda44a..5fb2bc81 100644 --- a/src/components/atoms/Collapse/CollapseGroup.tsx +++ b/src/components/atoms/Collapse/CollapseGroup.tsx @@ -1,13 +1,10 @@ import * as React from 'react'; import cn from 'classnames'; -export interface CollapseGroupProps { - className?: string; - style?: React.CSSProperties; -} +export type CollapseGroupProps = React.HTMLAttributes; -export const CollapseGroup: React.FC = ({ className, style, children }) => ( -
+export const CollapseGroup: React.FC = ({ className, style, children, ...props }) => ( +
{children}
); diff --git a/src/components/atoms/Collapse/CollapseHeader.tsx b/src/components/atoms/Collapse/CollapseHeader.tsx index ffe218bb..1b43be0a 100644 --- a/src/components/atoms/Collapse/CollapseHeader.tsx +++ b/src/components/atoms/Collapse/CollapseHeader.tsx @@ -3,13 +3,11 @@ import cn from 'classnames'; import { Icon } from 'components/atoms'; import { CollapseContext } from './Collapse'; -export interface CollapseHeaderProps { - className?: string; - style?: React.CSSProperties; +export interface CollapseHeaderProps extends React.HTMLAttributes { onClick?: () => void; } -export const CollapseHeader: React.FC = ({ className, style, onClick, children }) => { +export const CollapseHeader: React.FC = ({ className, style, onClick, children, ...props }) => { const { bordered, height, setHeight } = React.useContext(CollapseContext); // Collapse card body @@ -36,7 +34,7 @@ export const CollapseHeader: React.FC = ({ className, style 'ebs-collapse__header--bordered': bordered, })} onClick={handleClick} - style={style} + {...props} >
{children}
diff --git a/src/components/atoms/Extra/Extra.tsx b/src/components/atoms/Extra/Extra.tsx index cf8316c7..5ce1c0fc 100644 --- a/src/components/atoms/Extra/Extra.tsx +++ b/src/components/atoms/Extra/Extra.tsx @@ -3,17 +3,20 @@ import cn from 'classnames'; export type ExtraStatus = 'success' | 'warning' | 'danger' | 'info' | 'text'; -export interface Props { - className?: string; +export interface ExtraProps extends React.HTMLAttributes { disabled?: boolean; status?: ExtraStatus; text?: React.ReactNode; } -export const Extra: React.FC = ({ className, status = 'text', disabled, text }) => { +export const Extra: React.FC = ({ className, status = 'text', disabled, text, ...props }) => { if (!text) { return null; } - return
{text}
; + return ( +
+ {text} +
+ ); }; diff --git a/src/components/atoms/Grid/Col/Col.tsx b/src/components/atoms/Grid/Col/Col.tsx index 25c12112..562a79e2 100644 --- a/src/components/atoms/Grid/Col/Col.tsx +++ b/src/components/atoms/Grid/Col/Col.tsx @@ -10,7 +10,6 @@ export interface ColProps extends Grid { lg?: ColType | ColSizeType; xl?: ColType | ColSizeType; xxl?: ColType | ColSizeType; - style?: React.CSSProperties; } export const Col: React.FC = ({ diff --git a/src/components/atoms/Grid/Container/Container.tsx b/src/components/atoms/Grid/Container/Container.tsx index 5530897b..0440203e 100644 --- a/src/components/atoms/Grid/Container/Container.tsx +++ b/src/components/atoms/Grid/Container/Container.tsx @@ -5,7 +5,6 @@ import { getClassName } from '../utils'; export interface ContainerProps extends Grid { size?: ColSize; - style?: React.CSSProperties; } export const Container: React.FC = ({ diff --git a/src/components/atoms/Grid/Grid.stories.tsx b/src/components/atoms/Grid/Grid.stories.tsx index 0fcd0d34..f345680b 100644 --- a/src/components/atoms/Grid/Grid.stories.tsx +++ b/src/components/atoms/Grid/Grid.stories.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; -import { Container } from './Container/Container'; -import { Row } from './Row/Row'; -import { Col } from './Col/Col'; +import { Container, ContainerProps } from './Container/Container'; +import { Row, RowProps } from './Row/Row'; +import { Col, ColProps } from './Col/Col'; import { exportStory } from '../../../libs'; import './ExampleGrid.scss'; @@ -13,26 +13,32 @@ export default { subcomponents: { Row, Col }, }; -export const _Container = (): React.ReactElement => Container; +export const _Container: React.FC = ({ children, ...props }) => ( + + Container + +); -export const _Row = (): React.ReactElement => ( +export const _Row: React.FC = ({ children, ...props }) => (
- Row + + Row +
); -export const _Col = (): React.ReactElement => ( +export const _Col: React.FC = ({ children, ...props }) => ( - +
Col
- +
Col
- +
Col
@@ -47,22 +53,22 @@ export const _Col = (): React.ReactElement => ( - +
Col
- +
Col
- +
Col
- +
Col
- +
Col 12
diff --git a/src/components/atoms/Grid/Row/Row.tsx b/src/components/atoms/Grid/Row/Row.tsx index b60520c5..45b2feb7 100644 --- a/src/components/atoms/Grid/Row/Row.tsx +++ b/src/components/atoms/Grid/Row/Row.tsx @@ -5,7 +5,6 @@ import { getClassName } from '../utils'; export interface RowProps extends Grid { size?: ColsType; - style?: React.CSSProperties; } export const Row: React.FC = ({ size, offset, g, gx, gy, className, style, children, ...props }) => { diff --git a/src/components/atoms/Grid/interface.ts b/src/components/atoms/Grid/interface.ts index 8b0fa984..7b6e8d47 100644 --- a/src/components/atoms/Grid/interface.ts +++ b/src/components/atoms/Grid/interface.ts @@ -7,8 +7,7 @@ export type Gutter = 0 | 1 | 2 | 3 | 4 | 5; export type ColSizeType = { [key: string]: ColType }; -export interface Grid { - className?: string; +export interface Grid extends React.HTMLAttributes { offset?: Offset | ColSizeType; g?: Gutter | ColSizeType; gx?: Gutter | ColSizeType; diff --git a/src/components/atoms/Icon/Icon.tsx b/src/components/atoms/Icon/Icon.tsx index d15e7397..b108bf85 100644 --- a/src/components/atoms/Icon/Icon.tsx +++ b/src/components/atoms/Icon/Icon.tsx @@ -3,15 +3,14 @@ import { icons } from './iconsList'; import cn from 'classnames'; export type modelType = 'regular' | 'bold'; -export interface Props { +export interface IconProps extends React.HTMLAttributes { onClick?: () => void; type?: string; - className?: string; component?: any; model?: modelType; } -export const Icon: React.FC = ({ +export const Icon: React.FC = ({ onClick, type = 'none', model = 'regular', diff --git a/src/components/atoms/Input/Input.stories.tsx b/src/components/atoms/Input/Input.stories.tsx index 13c04912..0ff93f32 100644 --- a/src/components/atoms/Input/Input.stories.tsx +++ b/src/components/atoms/Input/Input.stories.tsx @@ -1,506 +1,31 @@ import * as React from 'react'; -import { Icon } from 'components/atoms'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Template } from 'components/storybook'; -import { Input, InputSize } from './Input'; +import { Input, InputProps } from './Input'; import { exportStory } from '../../../libs'; export default { title: exportStory('Input', 'atoms'), component: Input, + argTypes: { + label: { control: 'text' }, + extra: { control: 'text' }, + prefix: { control: 'text' }, + suffix: { control: 'text' }, + }, }; -export const Regular = (): React.ReactElement => { - const [inputValues, setInputValues] = React.useState({ - numMin: 0, - numMax: 0, - }); +export const Regular: React.FC & { args: InputProps } = ({ children, ...props }) => { + const [value, setValue] = React.useState(); return ( - - {(size) => ( -
-
-
Text Input
- -
-
Inactive
- -
- -
-
Active
- null} /> -
- -
-
Clearable
- null} - /> -
- -
-
Error
- -
- -
-
Disabled
- -
- -
Number Input
- -
-
Number
- { - setInputValues((s) => ({ ...s, numMin: value as number })); - }} - /> -
- -
-
Number
- setInputValues((s) => ({ ...s, numMax: value as number }))} - /> -
-
- -
-
Text Input + Label
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
- -
-
Text Input + Extra
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
- -
-
Text Input + Label + Extra
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
-
- )} -
+ ); }; -export const IconRight = (): React.ReactElement => ( - - {(size) => ( -
-
-
Text Input
- -
-
Inactive
- } placeholder="Text field" /> -
- -
-
Active
- } - placeholder="Text field" - value="Text field" - onChange={(): null => null} - /> -
- -
-
Error
- } hasError placeholder="Text field" /> -
- -
-
Disabled
- } disabled placeholder="Text field" /> -
-
- -
-
Text Input + Label
- -
-
Inactive
- } label="Label" placeholder="Text field" /> -
- -
-
Active
- } - label="Label" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - label="Label" - hasError - placeholder="Text field" - /> -
-
-
Disabled
- } - label="Label" - disabled - placeholder="Text field" - /> -
-
- -
-
Text Input + Extra
- -
-
Inactive
- } extra="Extra" placeholder="Text field" /> -
- -
-
Active
- } - extra="Extra" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - extra="Extra" - hasError - placeholder="Text field" - /> -
- -
-
Disabled
- } - extra="Extra" - disabled - placeholder="Text field" - /> -
-
- -
-
Text Input + Label + Extra
- -
-
Inactive
- } - label="Label" - extra="Extra" - placeholder="Text field" - /> -
- -
-
Active
- } - label="Label" - extra="Extra" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - label="Label" - extra="Extra" - hasError - placeholder="Text field" - /> -
- -
-
Disabled
- } - label="Label" - extra="Extra" - disabled - placeholder="Text field" - /> -
-
-
- )} -
-); - -export const IconLeft = (): React.ReactElement => ( - - {(size) => ( -
-
-
Text Input
- -
-
Inactive
- } placeholder="Text field" /> -
- -
-
Active
- } - placeholder="Text field" - value="Text field" - onChange={(): null => null} - /> -
- -
-
Error
- } hasError placeholder="Text field" /> -
- -
-
Disabled
- } disabled placeholder="Text field" /> -
-
- -
-
Text Input + Label
- -
-
Inactive
- } label="Label" placeholder="Text field" /> -
- -
-
Active
- } - label="Label" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - label="Label" - hasError - placeholder="Text field" - /> -
- -
-
Disabled
- } - label="Label" - disabled - placeholder="Text field" - /> -
-
- -
-
Text Input + Extra
- -
-
Inactive
- } extra="Extra" placeholder="Text field" /> -
- -
-
Active
- } - extra="Extra" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - extra="Extra" - hasError - placeholder="Text field" - /> -
- -
-
Disabled
- } - extra="Extra" - disabled - placeholder="Text field" - /> -
-
- -
-
Text Input + Label + Extra
- -
-
Inactive
- } - label="Label" - extra="Extra" - placeholder="Text field" - /> -
- -
-
Active
- } - label="Label" - extra="Extra" - placeholder="Text field" - value="Text field" - /> -
- -
-
Error
- } - label="Label" - extra="Extra" - hasError - placeholder="Text field" - /> -
- -
-
Disabled
- } - label="Label" - extra="Extra" - disabled - placeholder="Text field" - /> -
-
-
- )} -
-); +Regular.args = { + size: 'medium', + placeholder: 'Example', +}; diff --git a/src/components/atoms/Label/Label.stories.tsx b/src/components/atoms/Label/Label.stories.tsx index a9d3e5db..cc1bc56c 100644 --- a/src/components/atoms/Label/Label.stories.tsx +++ b/src/components/atoms/Label/Label.stories.tsx @@ -1,281 +1,25 @@ import * as React from 'react'; +import { Template } from 'components/storybook'; -import { Label } from './Label'; +import { Label, LabelProps } from './Label'; import { exportStory } from '../../../libs'; export default { title: exportStory('Label', 'atoms'), component: Label, + argTypes: { + text: { control: 'text' }, + prefix: { control: 'text' }, + suffix: { control: 'text' }, + }, }; -export const Regular = (): React.ReactElement => ( -
-
-
Label & Text Status
- -
-
Regular
-
- -
-
Disabled
-
-
- -
-
Label & Success Status
- -
-
Regular
-
- -
-
Disabled
-
-
- -
-
Label & Warning Status
- -
-
Regular
-
- -
-
Disabled
-
-
- -
-
Label & Danger Status
- -
-
Regular
-
- -
-
Disabled
-
-
- -
-
Label & Info Status
- -
-
Regular
-
- -
-
Disabled
-
-
-
-); - -export const Ghost = (): React.ReactElement => ( -
-
-
Label & Text Status
- -
-
Regular
-
- -
-
Regular circle
-
- -
-
Disabled
-
-
- -
-
Label & Success Status
- -
-
Regular
-
- -
-
Regular circle
-
- -
-
Disabled
-
-
- -
-
Label & Warning Status
- -
-
Regular
-
- -
-
Regular circle
-
- -
-
Disabled
-
-
- -
-
Label & Danger Status
- -
-
Regular
-
- -
-
Regular circle
-
- -
-
Disabled
-
-
- -
-
Label & Info Status
- -
-
Regular
-
- -
-
Regular circle
-
- -
-
Disabled
-
-
-
+export const Regular: React.FC & { args: LabelProps } = ({ children, ...props }) => ( + ); -export const Filled = (): React.ReactElement => ( -
-
-
Label & Text Status
- -
-
Filled
-
- -
-
Filled circle
-
- -
-
Disabled
-
-
- -
-
Label & Success Status
- -
-
Filled
-
- -
-
Filled circle
-
- -
-
Disabled
-
-
- -
-
Label & Warning Status
- -
-
Filled
-
- -
-
Filled circle
-
- -
-
Disabled
-
-
- -
-
Label & Danger Status
- -
-
Filled
-
- -
-
Filled circle
-
- -
-
Disabled
-
-
- -
-
Label & Info Status
- -
-
Filled
-
- -
-
Filled circle
-
- -
-
Disabled
-
-
-
-); +Regular.args = { + text: 'Example', +}; diff --git a/src/components/atoms/Label/Label.tsx b/src/components/atoms/Label/Label.tsx index 4778b7de..7b744143 100644 --- a/src/components/atoms/Label/Label.tsx +++ b/src/components/atoms/Label/Label.tsx @@ -5,12 +5,10 @@ export type LabelType = 'regular' | 'fill' | 'ghost' | 'primary'; export type LabelStatus = 'success' | 'warning' | 'danger' | 'info'; -export interface Props { - className?: string; +export interface LabelProps extends Omit, 'prefix'> { type?: LabelType; circle?: boolean; status?: LabelStatus; - style?: React.CSSProperties; prefix?: React.ReactNode; suffix?: React.ReactNode; disabled?: boolean; @@ -21,20 +19,20 @@ export interface Props { onClickSuffix?: () => void; } -export const Label: React.FC = ({ +export const Label: React.FC = ({ className, type = 'regular', status, circle, icon, text, - style, prefix, suffix, onClick, onClickPrefix, onClickSuffix, disabled, + ...props }) => { if (!text && !icon) { return null; @@ -51,8 +49,8 @@ export const Label: React.FC = ({ 'has-suffix': suffix, disabled: disabled, })} - style={style} onClick={onClick} + {...props} > {prefix && (
diff --git a/src/components/atoms/ListGroup/ListGroup.stories.tsx b/src/components/atoms/ListGroup/ListGroup.stories.tsx index e33002bb..3d2fb69d 100644 --- a/src/components/atoms/ListGroup/ListGroup.stories.tsx +++ b/src/components/atoms/ListGroup/ListGroup.stories.tsx @@ -1,6 +1,8 @@ import * as React from 'react'; +import { Container, Row, Col } from 'components/atoms'; -import { ListGroup } from './ListGroup'; +import { ListGroup, ListGroupProps } from './ListGroup'; +import { ListGroupItemProps } from './ListGroupItem'; import { exportStory } from 'libs'; const { Item: ListGroupItem } = ListGroup; @@ -11,14 +13,34 @@ export default { subcomponents: { ListGroupItem }, }; -export const Group = (): React.ReactElement => ( - - Example 1 - Example 2 - Example 3 - Example 4 - Example 5 - +export const Group: React.FC & { args: ListGroupProps } = ({ children, ...props }) => ( + + + + + Example 1 + Example 2 + Example 3 + Example 4 + Example 5 + + + + ); -export const Item = (): React.ReactElement => Example; +Group.args = { + className: '', +}; + +export const Item: React.FC & { args: ListGroupItemProps } = ({ children, ...props }) => ( + + + + Example + + + +); + +Item.args = Group.args; diff --git a/src/components/atoms/ListGroup/ListGroup.tsx b/src/components/atoms/ListGroup/ListGroup.tsx index 08f5bd7a..a36a91f4 100644 --- a/src/components/atoms/ListGroup/ListGroup.tsx +++ b/src/components/atoms/ListGroup/ListGroup.tsx @@ -6,12 +6,12 @@ export interface ListGroupComposition { Item: React.FC; } -export interface ListGroupProps { - className?: string; -} +export type ListGroupProps = React.HTMLAttributes; -const ListGroup: React.FC & ListGroupComposition = ({ className, children }) => ( -
{children}
+const ListGroup: React.FC & ListGroupComposition = ({ className, children, ...props }) => ( +
+ {children} +
); ListGroup.displayName = 'ListGroup'; diff --git a/src/components/atoms/ListGroup/ListGroupItem.tsx b/src/components/atoms/ListGroup/ListGroupItem.tsx index 5c52b8ac..f9624a2a 100644 --- a/src/components/atoms/ListGroup/ListGroupItem.tsx +++ b/src/components/atoms/ListGroup/ListGroupItem.tsx @@ -1,10 +1,10 @@ import * as React from 'react'; import cn from 'classnames'; -export interface ListGroupItemProps { - className?: string; -} +export type ListGroupItemProps = React.HTMLAttributes; -export const ListGroupItem: React.FC = ({ className, children }) => ( -
{children}
+export const ListGroupItem: React.FC = ({ className, children, ...props }) => ( +
+ {children} +
); diff --git a/src/components/atoms/Mask/Mask.tsx b/src/components/atoms/Mask/Mask.tsx index 3ec6451d..adeca53a 100644 --- a/src/components/atoms/Mask/Mask.tsx +++ b/src/components/atoms/Mask/Mask.tsx @@ -1,10 +1,9 @@ import * as React from 'react'; -export interface Props { +export interface MaskProps extends React.HTMLAttributes { onClick?: () => void; - style?: React.CSSProperties; } -export const Mask: React.FC = ({ onClick, style }) => ( -
+export const Mask: React.FC = ({ onClick, ...props }) => ( +
); diff --git a/src/components/atoms/Radio/Radio.stories.tsx b/src/components/atoms/Radio/Radio.stories.tsx index 863cee63..c8270637 100644 --- a/src/components/atoms/Radio/Radio.stories.tsx +++ b/src/components/atoms/Radio/Radio.stories.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { Template } from 'components/storybook'; -import { Radio } from './Radio'; +import { Radio, RadioProps } from './Radio'; import { exportStory } from '../../../libs'; export default { @@ -10,68 +11,22 @@ export default { const options = [{ text: 'Simple Radio', value: 1 }]; -export const Regular = (): React.ReactElement => { - const [checked, setChecked] = React.useState(''); +export const Regular: React.FC & { args: RadioProps } = ({ children, ...props }) => { + const [checked, setChecked] = React.useState(); return ( -
-
-
Radio
- -
-
Switcher
- -
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
- -
-
Radio & Align right
- -
-
Switcher
- -
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
-
+ ); }; + +Regular.args = { + className: '', + radioAlign: 'left', + textClass: '', + textStyle: {}, + value: undefined, + options, + onChange: (value?: string | number) => console.log(value), +}; diff --git a/src/components/atoms/Radio/Radio.tsx b/src/components/atoms/Radio/Radio.tsx index 63b88b47..a7264640 100644 --- a/src/components/atoms/Radio/Radio.tsx +++ b/src/components/atoms/Radio/Radio.tsx @@ -12,18 +12,17 @@ export interface Option { disabled?: boolean; } -export interface Props { - className?: string; - radioAlign?: RadioAlign; +export interface RadioProps extends Omit, 'value'>, 'onChange'> { + name?: string; textClass?: string; - textStyle?: React.CSSProperties; - onChange?: (e?: any) => void; + radioAlign?: RadioAlign; value?: RadioValue; options?: Option[]; - name?: string; + textStyle?: React.CSSProperties; + onChange?: (value?: string | number) => void; } -export const Radio = React.forwardRef( +export const Radio = React.forwardRef( ({ className, radioAlign = 'left', textClass = '', textStyle, options, value, onChange, ...props }, ref) => { const name = props.name || React.useMemo(() => makeid(), []); @@ -58,10 +57,10 @@ export const Radio = React.forwardRef( name={name} value={option.value} onChange={onChangeHandler} - {...(value !== undefined && option.value !== undefined - ? { checked: `${value}` === `${option.value}` } - : {})} disabled={option.disabled} + {...(value !== undefined && option.value !== undefined + ? { ...props, checked: `${value}` === `${option.value}` } + : props)} />
diff --git a/src/components/atoms/Space/Space.stories.tsx b/src/components/atoms/Space/Space.stories.tsx index 97bb0bc7..d29ad0a2 100644 --- a/src/components/atoms/Space/Space.stories.tsx +++ b/src/components/atoms/Space/Space.stories.tsx @@ -1,16 +1,22 @@ import * as React from 'react'; import { Button } from 'components/atoms'; -import { Space } from './Space'; +import { Space, SpaceProps } from './Space'; import { exportStory } from '../../../libs'; export default { title: exportStory('Space', 'atoms'), component: Space, + argTypes: { + size: { + options: ['small', 'medium', 'large'], + control: { type: 'select' }, + }, + }, }; -export const Regular = (): React.ReactElement => ( - +export const Regular: React.FC & { args: SpaceProps } = ({ children, ...props }) => ( +

green

@@ -19,3 +25,11 @@ export const Regular = (): React.ReactElement => (
); + +Regular.args = { + size: 'medium', + direction: 'horizontal', + wrap: false, + align: 'center', + justify: 'start', +}; diff --git a/src/components/atoms/Space/Space.tsx b/src/components/atoms/Space/Space.tsx index 81a148f8..88b3ca97 100644 --- a/src/components/atoms/Space/Space.tsx +++ b/src/components/atoms/Space/Space.tsx @@ -6,9 +6,7 @@ import { SizeType } from 'types'; export type SpaceSize = SizeType | number; export type SpaceDirection = 'horizontal' | 'vertical'; -export interface SpaceProps { - className?: string; - style?: React.CSSProperties; +export interface SpaceProps extends React.HTMLAttributes { size?: SpaceSize | [SpaceSize, SpaceSize]; direction?: SpaceDirection; align?: 'start' | 'end' | 'center' | 'baseline'; diff --git a/src/components/atoms/Switch/Switch.stories.tsx b/src/components/atoms/Switch/Switch.stories.tsx index 093f4a51..24893d23 100644 --- a/src/components/atoms/Switch/Switch.stories.tsx +++ b/src/components/atoms/Switch/Switch.stories.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { Template } from 'components/storybook'; -import { Switch } from './Switch'; +import { Switch, SwitchProps } from './Switch'; import { exportStory } from '../../../libs'; export default { @@ -8,39 +9,14 @@ export default { component: Switch, }; -export const Regular = (): React.ReactElement => { - const [checked, setChecked] = React.useState(false); +export const Regular: React.FC & { args: SwitchProps } = ({ children, ...props }) => ( + +); - return ( -
-
-
Switch
- -
-
Switcher
- -
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
-
- ); +Regular.args = { + checked: false, + children: 'Example', }; diff --git a/src/components/atoms/Switch/Switch.tsx b/src/components/atoms/Switch/Switch.tsx index 51058a2b..d518d3bf 100644 --- a/src/components/atoms/Switch/Switch.tsx +++ b/src/components/atoms/Switch/Switch.tsx @@ -1,14 +1,13 @@ import * as React from 'react'; import cn from 'classnames'; -interface Props { - className?: string; +export interface SwitchProps extends Omit, 'onChange'> { disabled?: boolean; checked?: boolean; onChange?: (value: boolean) => void; } -export const Switch: React.FC = ({ className, disabled, checked, onChange }) => { +export const Switch: React.FC = ({ className, disabled, checked, onChange, ...props }) => { const onClickHandler = (): void => (!disabled && onChange !== undefined ? onChange(!checked) : undefined); return ( @@ -17,6 +16,7 @@ export const Switch: React.FC = ({ className, disabled, checked, onChange disabled: disabled, })} onClick={onClickHandler} + {...props} > {checked &&
} diff --git a/src/components/atoms/Tabs/Panel.tsx b/src/components/atoms/Tabs/Panel.tsx index 4c405fab..b13158e7 100644 --- a/src/components/atoms/Tabs/Panel.tsx +++ b/src/components/atoms/Tabs/Panel.tsx @@ -2,16 +2,19 @@ import * as React from 'react'; import cn from 'classnames'; import { useTabs } from './Tabs'; -export interface PanelProps { +export interface PanelProps extends React.HTMLAttributes { tabKey: string; - className?: string; } /** * Individual panel component. */ -export const Panel: React.FC = ({ tabKey, className, children }) => { +export const Panel: React.FC = ({ tabKey, className, children, ...props }) => { const { activeTab } = useTabs(); - return activeTab === tabKey ?
{children}
: null; + return activeTab === tabKey ? ( +
+ {children} +
+ ) : null; }; diff --git a/src/components/atoms/Tabs/Tab.tsx b/src/components/atoms/Tabs/Tab.tsx index 99180e7e..873de47f 100644 --- a/src/components/atoms/Tabs/Tab.tsx +++ b/src/components/atoms/Tabs/Tab.tsx @@ -2,18 +2,17 @@ import * as React from 'react'; import cn from 'classnames'; import { useTabs } from './Tabs'; -export interface TabProps { +export interface TabProps extends Omit, 'onClick'> { tabKey: string; label: React.ReactNode; disabled?: boolean; - className?: string; onClick?: (tabKey: string) => void; } /** * This component allows changing of the active Tab. */ -export const Tab: React.FC = ({ tabKey, disabled, label, className, onClick }) => { +export const Tab: React.FC = ({ tabKey, disabled, label, className, onClick, ...props }) => { const { activeTab, setActiveTab } = useTabs(); const handleClick = (): void => { @@ -30,6 +29,7 @@ export const Tab: React.FC = ({ tabKey, disabled, label, className, on
{label}
diff --git a/src/components/atoms/Tabs/Tabs.stories.tsx b/src/components/atoms/Tabs/Tabs.stories.tsx index 2ee618f4..6712542a 100644 --- a/src/components/atoms/Tabs/Tabs.stories.tsx +++ b/src/components/atoms/Tabs/Tabs.stories.tsx @@ -1,16 +1,19 @@ import * as React from 'react'; -import { Tabs } from './Tabs'; +import { Tabs, TabsProps } from './Tabs'; import { exportStory } from 'libs'; export default { title: exportStory('Tabs', 'atoms'), component: Tabs, + argTypes: { + activeTab: { + options: ['first', 'third'], + control: { type: 'select' }, + }, + }, }; -export const regular = (): React.ReactElement => { - // eslint-disable-next-line react-hooks/rules-of-hooks - const [active, setActive] = React.useState('first'); - +export const Regular: React.FC & { args: TabsProps } = ({ children, ...props }) => { const data = [ { label: First tab, @@ -38,18 +41,22 @@ export const regular = (): React.ReactElement => { ]; return ( -
- - {data.map((item) => ( - - ))} -

Custom elements for all tabs

- {data.map((item) => ( - - {item.content} - - ))} -
-
+ + {data.map((item) => ( + + ))} +

Custom elements for all tabs

+ {data.map((item) => ( + + {item.content} + + ))} +
); }; + +Regular.args = { + className: '', + activeTab: 'first', + setActiveTab: (key: string) => console.log(key), +}; diff --git a/src/components/atoms/Tabs/Tabs.tsx b/src/components/atoms/Tabs/Tabs.tsx index 0361f772..d86ae8f3 100644 --- a/src/components/atoms/Tabs/Tabs.tsx +++ b/src/components/atoms/Tabs/Tabs.tsx @@ -3,15 +3,14 @@ import cn from 'classnames'; import { Panel, PanelProps } from './Panel'; import { Tab, TabProps } from './Tab'; -export interface TabsProps { +export interface TabsComposition { Tab: React.FC; Panel: React.FC; } -export interface TabsMainProps { +export interface TabsProps extends React.HTMLAttributes { activeTab?: string; setActiveTab?: (key: string) => void; - className?: string; } export interface TabsContext { @@ -21,7 +20,7 @@ export interface TabsContext { const TabsContext = React.createContext(undefined); -const Tabs: React.FC & TabsProps = ({ activeTab, setActiveTab, className, children }) => { +const Tabs: React.FC & TabsComposition = ({ activeTab, setActiveTab, className, children, ...props }) => { const memoizedContextValue = React.useMemo( () => ({ activeTab, @@ -31,7 +30,7 @@ const Tabs: React.FC & TabsProps = ({ activeTab, setActiveTab, cl ); return ( - +
{children && React.Children.map(children, (child) => { diff --git a/src/components/atoms/Tooltip/Tooltip.scss b/src/components/atoms/Tooltip/Tooltip.scss index 5ad5a7b4..4a346e2c 100644 --- a/src/components/atoms/Tooltip/Tooltip.scss +++ b/src/components/atoms/Tooltip/Tooltip.scss @@ -15,11 +15,15 @@ } } + &__wrapper.ebs-tooltip--overtop { + z-index: 9999; + } + &__wrapper { @include elevation-2; background-color: $white; border-radius: rem($border-radius); - z-index: 9999; + z-index: 9997; color: $text-color; background-color: $white; } diff --git a/src/components/atoms/Tooltip/Tooltip.stories.tsx b/src/components/atoms/Tooltip/Tooltip.stories.tsx index e61c0dfe..7a254ae4 100644 --- a/src/components/atoms/Tooltip/Tooltip.stories.tsx +++ b/src/components/atoms/Tooltip/Tooltip.stories.tsx @@ -12,188 +12,28 @@ export default { }, }; -export const Regular = (): React.ReactElement => ( -
-
-
Tooltip Standart
- -
-
Top alignment
- -
- - - - - - - - - - - -
-
- -
-
Right alignment
- -
- - - - - - - - - - - -
-
- -
-
Bottom alignment
- -
- - - - - - - - - - - -
-
- -
-
Left alignment
- -
- - - - - - - - - - - -
-
-
-
-); - -export const Titled = (): React.ReactElement => ( -
-
-
Tooltip Standart & Title
- -
-
Top alignment
- -
- - - - - - - - - - - -
-
- -
-
Right alignment
- -
- - - - - - - - - - - -
-
- -
-
Bottom alignment
- -
- - - - - - - - - - - -
-
- -
-
Left alignment
- -
- - - - - - - - - - - -
-
-
-
-); - -export const Playground: React.FC & { args: TooltipProps } = ({ +export const Regular: React.FC & { args: TooltipProps } = ({ children, ...props }): React.ReactElement => { return (
- +
- +
- +
); }; -Playground.args = { +Regular.args = { tooltip: 'Tooltip content', inline: true, trigger: 'hover', diff --git a/src/components/atoms/Tooltip/Tooltip.tsx b/src/components/atoms/Tooltip/Tooltip.tsx index 33d98323..7871c05b 100644 --- a/src/components/atoms/Tooltip/Tooltip.tsx +++ b/src/components/atoms/Tooltip/Tooltip.tsx @@ -42,6 +42,7 @@ export type TooltipConfig = Partial<{ }>; export interface TooltipProps extends TooltipConfig { + className?: string; bodyClass?: string; title?: React.ReactNode; tooltip?: React.ReactNode; @@ -52,6 +53,7 @@ export interface TooltipProps extends TooltipConfig { } export const Tooltip: React.FC = ({ + className, bodyClass, children, title, @@ -76,7 +78,7 @@ export const Tooltip: React.FC = ({
diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 00000000..9c01c785 --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,13 @@ +// Atoms +export * from './atoms'; + +// Molecules +export * from './molecules'; + +// Organisms +export * from './organisms'; + +// Export types +export type { DatePickerProps, RangePickerProps, DatePickerComposition } from './molecules/DatePicker/types'; +export type { ColumnType, TableProps } from './organisms/Table/Table'; +export type { FormInstance, FormProps } from './organisms/Form'; diff --git a/src/components/molecules/Checkbox/Checkbox.stories.tsx b/src/components/molecules/Checkbox/Checkbox.stories.tsx index 01d42570..801087fe 100644 --- a/src/components/molecules/Checkbox/Checkbox.stories.tsx +++ b/src/components/molecules/Checkbox/Checkbox.stories.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; +import { Template } from 'components/storybook'; -import { Checkbox } from './Checkbox'; +import { Checkbox, CheckboxProps } from './Checkbox'; import { CheckboxGroup } from './CheckboxGroup'; import { exportStory } from '../../../libs'; @@ -10,166 +11,13 @@ export default { subcomponents: { CheckboxGroup }, }; -export const Regular = (): React.ReactElement => { - const [checked, setChecked] = React.useState(false); +export const Regular: React.FC & { args: CheckboxProps } = ({ children, ...props }) => ( + +); - return ( -
-
-
Checkbox
- -
-
Switcher
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
- -
-
Checkbox & Align right
- -
-
Switcher
- -
- -
-
Active
- -
- -
-
Disabled & Inactive
- -
- -
-
Disabled & Active
- -
-
-
- ); -}; - -export const Indeterminate = (): React.ReactElement => { - const [checked, setChecked] = React.useState(1); - - return ( -
-
-
Checkbox Indeterminate
- -
-
Switcher
- setChecked((s) => (s < 3 ? s + 1 : 1))} - text="Simple checkbox" - /> -
- -
-
Active
- -
- -
-
Disabled
- -
-
- -
-
Checkbox & Align right
- -
-
Switcher
- setChecked((s) => (s < 3 ? s + 1 : 1))} - text="Simple checkbox" - /> -
- -
-
Active
- -
- -
-
Disabled
- -
-
-
- ); -}; - -const options = [ - { value: 1, text: 'Simple checkbox 1' }, - { value: 2, text: 'Simple checkbox 2' }, -]; - -export const Group = (): React.ReactElement => { - const [values, setValues] = React.useState<(string | number)[]>([]); - - return ( -
-
-
Checkbox Group
- -
-
Switcher
- -
- -
-
Active
- -
- -
-
Disabled
- -
-
- -
-
Checkbox Group & Align right
- -
-
Switcher
- -
- -
-
Active
- -
- -
-
Disabled
- -
-
-
- ); +Regular.args = { + text: 'Example', + checkAlign: 'left', }; diff --git a/src/components/molecules/Checkbox/Checkbox.tsx b/src/components/molecules/Checkbox/Checkbox.tsx index 32158603..53ab438c 100644 --- a/src/components/molecules/Checkbox/Checkbox.tsx +++ b/src/components/molecules/Checkbox/Checkbox.tsx @@ -12,20 +12,22 @@ export interface Option { disabled?: boolean; } -export interface Props { - className?: string; +export interface CheckboxProps extends Omit, 'onChange'> { checkAlign?: CheckAlign; name?: string; value?: CheckboxValue; + text?: React.ReactNode; indeterminate?: boolean; checked?: boolean; - onChange?: (value: boolean) => void; - text?: React.ReactNode; disabled?: boolean; + onChange?: (value: boolean) => void; } -export const Checkbox = React.forwardRef( - ({ className, checkAlign = 'left', name, value, indeterminate, checked, onChange, text, disabled }, ref) => { +export const Checkbox = React.forwardRef( + ( + { className, checkAlign = 'left', name, value, indeterminate, checked, onChange, text, disabled, ...props }, + ref, + ) => { const onChangeHandler = ({ target }: React.ChangeEvent): void => { if (onChange !== undefined) { onChange(target.checked); @@ -39,6 +41,7 @@ export const Checkbox = React.forwardRef( indeterminate: indeterminate, disabled: disabled, })} + {...props} > , 'onChange'> { checkboxClass?: string; checkAlign?: CheckAlign; options?: Option[]; values: CheckboxGroupValue; - onChange?: (value: CheckboxGroupValue) => void; disabled?: boolean; + onChange?: (value: CheckboxGroupValue) => void; } export const CheckboxGroup: React.FC = ({ @@ -29,6 +28,7 @@ export const CheckboxGroup: React.FC = ({ values, onChange, disabled, + ...props }) => { const name = React.useMemo(() => makeid(), []); @@ -43,7 +43,7 @@ export const CheckboxGroup: React.FC = ({ } return ( -
+
{options.map((option) => ( { - const [date, setDate] = React.useState(''); - const [time, setTime] = React.useState(''); - const [range, setRange] = React.useState(); +export const Regular: React.FC & { args: DatePickerProps } = ({ children, ...props }) => { + const [value, setValue] = React.useState(''); return ( - - {(size) => ( -
-
-
DatePicker
- -
-
Date
- setDate(v as string)} - isClearable - dateFormat="dd-MM-yyyy" - /> -
- -
-
Time
- setTime(v as string)} - /> -
- -
-
Range
- setRange(v as any)} - /> -
- -
-
Range Input
- setRange(v as any)} - /> -
-
-
- )} -
+ ); }; -export const WithForm = (): React.ReactElement => { - const [form] = useForm(); - - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - - return ( - - {(size) => ( -
-
-
-
DatePicker
- -
-
Date
- - - -
- -
-
Time
- - - -
- -
-
Range
- - - -
- - -
-
-
- )} -
- ); +Regular.args = { + size: 'medium', + adjustDateOnChange: undefined, + allowSameDay: undefined, + ariaLabelClose: '', + ariaLabelledBy: '', + autoComplete: undefined, + autoFocus: true, + calendarClassName: '', + chooseDayAriaLabelPrefix: '', + className: '', + clearButtonTitle: undefined, + closeOnScroll: undefined, + customInput: undefined, + customInputRef: undefined, + customTimeInput: undefined, + dateFormat: undefined, + dateFormatCalendar: undefined, + disabledDayAriaLabelPrefix: undefined, + disabled: undefined, + disabledKeyboardNavigation: undefined, + dropdownMode: 'scroll', + endDate: null, + excludeDates: [], + excludeTimes: [], + fixedHeight: undefined, + forceShowMonthNavigation: true, + highlightDates: [], + id: undefined, + includeDates: [], + includeTimes: [], + injectTimes: [], + inline: false, + isClearable: true, + focusSelectedMonth: undefined, + locale: 'en', + maxDate: undefined, + maxTime: undefined, + minDate: undefined, + minTime: undefined, + monthsShown: undefined, + name: undefined, + nextMonthButtonLabel: undefined, + nextYearButtonLabel: undefined, + open: undefined, + openToDate: undefined, + peekNextMonth: undefined, + placeholderText: 'Date field', + popperClassName: '', + popperModifiers: undefined, + popperPlacement: undefined, + popperProps: {}, + preventOpenOnFocus: undefined, + previousMonthButtonLabel: undefined, + previousYearButtonLabel: undefined, + readOnly: undefined, + required: undefined, + scrollableMonthYearDropdown: undefined, + scrollableYearDropdown: undefined, + selected: null, + selectsEnd: undefined, + selectsStart: undefined, + selectsRange: undefined, + shouldCloseOnSelect: undefined, + showDisabledMonthNavigation: undefined, + showFullMonthYearPicker: undefined, + showMonthDropdown: undefined, + showMonthYearDropdown: undefined, + showMonthYearPicker: undefined, + showPopperArrow: undefined, + showPreviousMonths: undefined, + showQuarterYearPicker: undefined, + showTimeInput: undefined, + showTimeSelect: undefined, + showTimeSelectOnly: undefined, + showTwoColumnMonthYearPicker: undefined, + showWeekNumbers: undefined, + showYearDropdown: true, + showYearPicker: undefined, + startDate: null, + startOpen: undefined, + strictParsing: undefined, + tabIndex: undefined, + timeCaption: undefined, + timeFormat: undefined, + timeInputLabel: undefined, + timeIntervals: undefined, + title: undefined, + todayButton: undefined, + useShortMonthInDropdown: undefined, + useWeekdaysShort: undefined, + weekAriaLabelPrefix: undefined, + value: undefined, + weekLabel: undefined, + withPortal: undefined, + portalId: undefined, + wrapperClassName: '', + yearDropdownItemNumber: undefined, + excludeScrollbar: undefined, + enableTabLoop: undefined, + yearItemNumber: undefined, }; -export const Range = (): React.ReactElement => { - const [value, setValue] = React.useState(); +export const RangeInput: React.FC & { args: DatePickerProps } = ({ children, ...props }) => ( + +); - const handleChange = (date): void => { - setValue(date); - }; +RangeInput.args = Regular.args; - return ( - - {(size) => ( -
-
-
Calendar
- -
-
Range
- -
+export const Range: React.FC & { args: RangePickerProps } = ({ children, ...props }) => ( + +); -
-
Range Input
- -
-
-
- )} -
- ); -}; +Range.args = Regular.args; diff --git a/src/components/molecules/DatePicker/DatePicker.tsx b/src/components/molecules/DatePicker/DatePicker.tsx index 09d07acb..47f3ebba 100644 --- a/src/components/molecules/DatePicker/DatePicker.tsx +++ b/src/components/molecules/DatePicker/DatePicker.tsx @@ -1,18 +1,18 @@ import * as React from 'react'; import ReactDatePicker, { registerLocale } from 'react-datepicker'; import cn from 'classnames'; -import { DatePickerProps, DatePickerComposition } from './types'; +import { DatePickerProps, DatePickerComposition, DateType } from './types'; import { getDefaultDateFormat, parseDate, getOutputDate } from './utils'; import RangePicker from './RangePicker'; import RangeInputPicker from './RangeInputPicker'; const InternalDatePicker = React.forwardRef( ({ size = 'medium', value, ...props }, ref) => { - const [val, setVal] = React.useState(''); + const [val, setVal] = React.useState(''); React.useEffect(() => { if (value !== val) { - setVal(value); + setVal(value || null); } }, [value]); @@ -39,12 +39,13 @@ const InternalDatePicker = React.forwardRef( showYearDropdown {...props} ref={ref} - value={val} + value={val as any} onChange={handleChange} selected={parseDate(val, dateFormat)} className={cn(`ebs-datepicker ebs-datepicker--${size}`, props.className)} wrapperClassName={cn('ebs-datepicker__wrapper', props.wrapperClassName)} popperClassName={cn('ebs-datepicker__popper', props.popperClassName)} + calendarClassName={cn('ebs-datepicker__calendar', props.calendarClassName)} > {props.children} @@ -57,4 +58,4 @@ const DatePicker = InternalDatePicker as DatePickerComposition; DatePicker.Range = RangePicker; DatePicker.RangeInput = RangeInputPicker; -export { DatePicker, registerLocale }; +export { InternalDatePicker, DatePicker, registerLocale }; diff --git a/src/components/molecules/DatePicker/RangePicker.tsx b/src/components/molecules/DatePicker/RangePicker.tsx index 77feb6f7..8abdce07 100644 --- a/src/components/molecules/DatePicker/RangePicker.tsx +++ b/src/components/molecules/DatePicker/RangePicker.tsx @@ -51,6 +51,7 @@ const RangePicker = React.forwardRef( style={props.style} > ( /> = Omit & R; -export type DateType = Date | [Date, Date] | string | /* for selectsRange */ null; +export type DateType = Date | [Date, Date] | string | null; export type DateValueType = Date | null | undefined; export type DatePickerProps = Modify< ReactDatePickerProps, { size?: SizeType; - value?: any; // Value is used by form field and value can be other than string + value?: any; onChange?: (date: DateType, event?: React.SyntheticEvent) => void; } >; diff --git a/src/components/molecules/InputPhone/InputPhone.stories.tsx b/src/components/molecules/InputPhone/InputPhone.stories.tsx index fb933095..d3733574 100644 --- a/src/components/molecules/InputPhone/InputPhone.stories.tsx +++ b/src/components/molecules/InputPhone/InputPhone.stories.tsx @@ -1,120 +1,68 @@ import * as React from 'react'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Template } from 'components/storybook'; -import { InputPhone } from './InputPhone'; +import { InputPhone, InputPhoneProps } from './InputPhone'; import { exportStory } from '../../../libs'; -import { SizeType } from 'types'; export default { title: exportStory('InputPhone', 'molecules'), component: InputPhone, + argTypes: { + label: { control: 'text' }, + extra: { control: 'text' }, + }, }; -export const Regular: React.FC = () => ( - - {(size) => ( -
-
-
Input Phone
+export const Regular: React.FC & { args: InputPhoneProps } = ({ children, ...props }) => { + const [value, setValue] = React.useState(''); -
-
Inactive
- -
- -
-
Active
- -
- -
-
Clearable
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
- -
-
Input Phone + Label
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
- -
-
Input Phone + Extra
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
- -
-
Disabled
- -
-
- -
-
Input Phone + Label & Extra
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Error
- -
+ return ( + + ); +}; -
-
Disabled
- -
-
-
- )} -
-); +Regular.args = { + size: 'medium', + country: 'md', + isClearable: true, + value: '', + onlyCountries: [], + preferredCountries: [], + excludeCountries: [], + placeholder: 'Phone field', + searchPlaceholder: '', + searchNotFound: 'Not found', + disabled: undefined, + autoFormat: undefined, + enableAreaCodes: undefined, + enableTerritories: undefined, + disableCountryCode: undefined, + disableDropdown: undefined, + enableLongNumbers: undefined, + countryCodeEditable: undefined, + enableSearch: undefined, + disableSearchIcon: undefined, + regions: undefined, + inputProps: {}, + localization: {}, + masks: {}, + areaCodes: {}, + preserveOrder: [], + defaultMask: undefined, + alwaysDefaultMask: undefined, + prefix: undefined, + copyNumbersOnly: undefined, + renderStringAsFlag: undefined, + autocompleteSearch: undefined, + jumpCursorToEnd: undefined, + priority: undefined, + enableAreaCodeStretch: undefined, + enableClickOutside: undefined, + showDropdown: undefined, + defaultErrorMessage: undefined, + specialLabel: undefined, + disableInitialCountryGuess: undefined, + disableCountryGuess: undefined, +}; diff --git a/src/components/molecules/InputPhone/InputPhone.tsx b/src/components/molecules/InputPhone/InputPhone.tsx index 620f1bbf..448f1b0f 100644 --- a/src/components/molecules/InputPhone/InputPhone.tsx +++ b/src/components/molecules/InputPhone/InputPhone.tsx @@ -4,7 +4,7 @@ import PhoneInput, { PhoneInputProps } from 'react-phone-input-2'; import { Extra, Label } from 'components/atoms'; import { SizeType } from 'types'; -export interface Props extends PhoneInputProps { +export interface InputPhoneProps extends PhoneInputProps { className?: string; size?: SizeType; dropdownClass?: string; @@ -14,7 +14,7 @@ export interface Props extends PhoneInputProps { isClearable?: boolean; } -export const InputPhone: React.FC = ({ +export const InputPhone: React.FC = ({ className, dropdownClass, size = 'medium', diff --git a/src/components/molecules/InputSearch/InputSearch.stories.tsx b/src/components/molecules/InputSearch/InputSearch.stories.tsx index 84056ac6..1fd68445 100644 --- a/src/components/molecules/InputSearch/InputSearch.stories.tsx +++ b/src/components/molecules/InputSearch/InputSearch.stories.tsx @@ -1,113 +1,35 @@ import * as React from 'react'; -import { InputSize } from 'components/atoms/Input/Input'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Template } from 'components/storybook'; -import { InputSearch } from './InputSearch'; +import { InputSearch, InputSearchProps } from './InputSearch'; import { exportStory } from '../../../libs'; export default { title: exportStory('InputSearch', 'molecules'), component: InputSearch, + argTypes: { + label: { control: 'text' }, + prefix: { control: 'text' }, + suffix: { control: 'text' }, + extra: { control: 'text' }, + }, }; -export const Regular = (): React.ReactElement => ( - - {(size) => ( -
-
-
Input Search & Stroke
+export const Regular: React.FC & { args: InputSearchProps } = ({ children, ...props }) => { + const [value, setValue] = React.useState(''); -
-
Inactive
- -
- -
-
Active
- -
- -
-
Clearable
- -
- -
-
Disabled
- -
-
- -
-
Input Search & Fill
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Clearable
- -
- -
-
Disabled
- -
-
-
- )} -
-); - -export const IconAlignment = (): React.ReactElement => ( - - {(size) => ( -
-
-
Input Search & Left Alignment & Stroke
- -
-
Inactive
- -
- -
-
Active
- -
- -
-
Disabled
- -
-
- -
-
Input Search & Left Alignment & Fill
- -
-
Inactive
- -
- -
-
Active
- -
+ return ( + + ); +}; -
-
Disabled
- -
-
-
- )} -
-); +Regular.args = { + size: 'medium', + placeholder: 'Text field', + iconAlign: 'suffix', + styleType: 'stroke', + autoFocus: true, + isClearable: true, +}; diff --git a/src/components/molecules/Loader/Loader.stories.tsx b/src/components/molecules/Loader/Loader.stories.tsx index bf2833de..3571b594 100644 --- a/src/components/molecules/Loader/Loader.stories.tsx +++ b/src/components/molecules/Loader/Loader.stories.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { Template } from 'components/storybook'; -import { Loader, SpinnerSize } from './Loader'; +import { Loader, LoaderProps } from './Loader'; import { exportStory } from '../../../libs'; const { Inline, Spinner } = Loader; @@ -10,31 +10,40 @@ export default { title: exportStory('Loader', 'molecules'), component: Loader, subcomponents: { Inline, Spinner }, + argTypes: { + size: { + options: ['small', 'middle', 'regular'], + control: { type: 'select' }, + }, + }, }; -export const Regular: React.FC = () => { - const [loading, setLoading] = React.useState(true); +export const Regular: React.FC & { args: LoaderProps } = ({ children, ...props }) => ( + +); - const onToggleHandler = (): void => setLoading((s) => !s); +Regular.args = { + size: 'regular', + loading: true, + fade: true, + fixed: true, + height: '100%', +}; - return ( - - {(size) => ( - <> -

Toggle

+export const _Inline: React.FC & { args: LoaderProps } = ({ children, ...props }) => ( + +); - -

Test

-
- - )} -
- ); -}; +_Inline.args = Regular.args; -export const _Inline = (): React.ReactElement => ; -export const _Spinner = (): React.ReactElement => ( - - {(size) => } - +export const _Spinner: React.FC & { args: LoaderProps } = ({ children, ...props }) => ( + ); + +_Spinner.args = Regular.args; diff --git a/src/components/molecules/Loader/Loader.tsx b/src/components/molecules/Loader/Loader.tsx index 18f93559..8969e71c 100644 --- a/src/components/molecules/Loader/Loader.tsx +++ b/src/components/molecules/Loader/Loader.tsx @@ -9,13 +9,12 @@ export interface LoaderComposition { Spinner: React.FC; } -export interface LoaderProps { +export interface LoaderProps extends React.HTMLAttributes { fade?: boolean; size?: SpinnerSize; loading: boolean; fixed?: boolean; height?: number | string; - children?: React.ReactNode; } const Loader: React.FC & LoaderComposition = ({ @@ -25,9 +24,10 @@ const Loader: React.FC & LoaderComposition = ({ loading, height = 350, children, + ...props }) => { return ( -
+
{fade ? ( diff --git a/src/components/molecules/Loader/LoaderInline.tsx b/src/components/molecules/Loader/LoaderInline.tsx index 59f85aa2..3bb2b399 100644 --- a/src/components/molecules/Loader/LoaderInline.tsx +++ b/src/components/molecules/Loader/LoaderInline.tsx @@ -1,9 +1,12 @@ import * as React from 'react'; import { LoaderSpinner } from './LoaderSpinner'; -export const LoaderInline: React.FC = ({ children = 'Loading ...' }) => { +export const LoaderInline: React.FC> = ({ + children = 'Loading ...', + ...props +}) => { return ( - + {children} diff --git a/src/components/molecules/Loader/LoaderSpinner.tsx b/src/components/molecules/Loader/LoaderSpinner.tsx index 94101c01..a04d3016 100644 --- a/src/components/molecules/Loader/LoaderSpinner.tsx +++ b/src/components/molecules/Loader/LoaderSpinner.tsx @@ -2,12 +2,11 @@ import * as React from 'react'; import cn from 'classnames'; import { SpinnerSize } from './Loader'; -export interface LoaderSpinnerProps { +export interface LoaderSpinnerProps extends React.HTMLAttributes { size?: SpinnerSize; - className?: string; fixed?: boolean; } -export const LoaderSpinner: React.FC = ({ fixed, size = 'regular', className }) => ( -
+export const LoaderSpinner: React.FC = ({ fixed, size = 'regular', className, ...props }) => ( +
); diff --git a/src/components/molecules/Notify/Notify.scss b/src/components/molecules/Notify/Notify.scss index 91389188..ec177d31 100644 --- a/src/components/molecules/Notify/Notify.scss +++ b/src/components/molecules/Notify/Notify.scss @@ -108,9 +108,7 @@ background-color: $danger-color; .ebs-icon { - path:last-child { - fill: $danger-color; - } + color: $white; } } @@ -121,5 +119,9 @@ &--warning { background-color: $warning-color; } + + .ebs-icon:not(.ebs-icon--close) { + font-size: rem($gutter-size * 1.5); + } } } diff --git a/src/components/molecules/Notify/Notify.stories.tsx b/src/components/molecules/Notify/Notify.stories.tsx index f53c94ca..75900415 100644 --- a/src/components/molecules/Notify/Notify.stories.tsx +++ b/src/components/molecules/Notify/Notify.stories.tsx @@ -1,70 +1,57 @@ import * as React from 'react'; -import { Space, Button, Label } from 'components/atoms'; -import SizeSwitcher from 'components/SizeSwitcher'; -import { SpaceSize } from 'components/atoms/Space/Space'; +import { Button, Label } from 'components/atoms'; +import { Template } from 'components/storybook'; import { useNotify } from 'hooks'; import { NotifyContainer, NotifyProvider } from './Notify'; -import { NotifyItem } from './NotifyItem'; +import { NotifyItem, NotifyItemProps } from './NotifyItem'; import { exportStory } from '../../../libs'; export default { title: exportStory('Notify', 'molecules'), - component: NotifyContainer, + component: NotifyItem, subcomponents: { NotifyItem }, }; -const description = 'This is an example component'; - -export const Regular = (): React.ReactNode => { - const Notify: React.FC = () => { +export const Regular: React.FC & { args: NotifyItemProps } = ({ children, ...props }) => { + const Notify: React.FC = ({ ...params }) => { const notify = useNotify(); return ( - <> - {(size) => } - - - - - - - - - + ); }; return ( - + + ); }; + +Regular.args = { + title: 'Example', + description: 'This is an example component', + size: 'medium', + direction: 'vertical', +}; diff --git a/src/components/molecules/Notify/NotifyItem.tsx b/src/components/molecules/Notify/NotifyItem.tsx index 82a4fec6..c4081d79 100644 --- a/src/components/molecules/Notify/NotifyItem.tsx +++ b/src/components/molecules/Notify/NotifyItem.tsx @@ -31,7 +31,7 @@ export const NotifyItem: React.FC = ({ icon = 'check'; break; case 'danger': - icon = 'alert'; + icon = 'error'; break; case 'info': icon = 'info'; diff --git a/src/components/molecules/Select/Context.tsx b/src/components/molecules/Select/Context.tsx index 3dae8329..898aef08 100644 --- a/src/components/molecules/Select/Context.tsx +++ b/src/components/molecules/Select/Context.tsx @@ -11,6 +11,7 @@ interface StateProps { search: string | boolean; style?: React.CSSProperties; offsetBottom?: number; + maxHeight?: number; isOpen: boolean; isLoaded: boolean; } diff --git a/src/components/molecules/Select/Hook.tsx b/src/components/molecules/Select/Hook.tsx index fe343717..55b1d7c6 100644 --- a/src/components/molecules/Select/Hook.tsx +++ b/src/components/molecules/Select/Hook.tsx @@ -14,9 +14,7 @@ interface Props extends ContextProps { dropdownOptions?: React.ReactNode; hasValue?: boolean; textValue?: Option[] | Option; - isBox: boolean; - isScrolling?: boolean; - isMouseScrolling?: number; + isBox?: boolean; onClear: () => void; onDeleteSelect: (key: number | string) => void; onChangeNewOption: (value: string | number) => void; diff --git a/src/components/molecules/Select/Select.scss b/src/components/molecules/Select/Select.scss index 9401d4e3..76207411 100644 --- a/src/components/molecules/Select/Select.scss +++ b/src/components/molecules/Select/Select.scss @@ -16,13 +16,20 @@ } &--box { - position: relative; - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; - } + .ebs-select { + position: relative; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } - &--box + &__options { - position: unset; + .ebs-select__options { + position: relative; + box-shadow: none; + border: 1px solid $border-color; + border-top: none; + border-top-left-radius: 0; + border-top-right-radius: 0; + } } &--tags { diff --git a/src/components/molecules/Select/Select.stories.tsx b/src/components/molecules/Select/Select.stories.tsx index 2e8a8b3f..0eb44096 100644 --- a/src/components/molecules/Select/Select.stories.tsx +++ b/src/components/molecules/Select/Select.stories.tsx @@ -1,23 +1,27 @@ import * as React from 'react'; -import { AvatarInline, Space, Icon } from 'components/atoms'; -import { Form, useForm } from 'components/organisms'; -import SizeSwitcher from 'components/SizeSwitcher'; +import { AvatarInline, Icon } from 'components/atoms'; +import { Template } from 'components/storybook'; import { capitalize, makeid } from 'libs/string'; -import { SizeType } from 'types'; -import { Select } from './Select'; +import { SelectComponent as Select } from './Select'; +import { Select as _Select, SelectProps, Options } from './components'; import { Option } from './interfaces'; import { exportStory } from '../../../libs'; +const { Pagination, Search } = Select; + export default { title: exportStory('Select', 'molecules'), - component: Select, + component: _Select, + subcomponents: { Options, Pagination, Search }, + argTypes: { + label: { control: 'text' }, + }, }; const limit = 20; -export const Regular = (): React.ReactNode => { - const [form] = useForm(); +export const Regular: React.FC & { args: SelectProps } = ({ children, ...props }) => { const [search, setSearch] = React.useState(''); const [list, setList] = React.useState([]); const [page, setPage] = React.useState(1); @@ -50,232 +54,41 @@ export const Regular = (): React.ReactNode => { }); }, [page]); - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - return ( - - {(size) => ( - -
- - - -
-
- )} -
+ ); }; -export const OptionsBox = (): React.ReactNode => { - const [form] = useForm(); - const [search, setSearch] = React.useState(''); - const [list, setList] = React.useState([]); - const [page, setPage] = React.useState(1); - const [total, setTotal] = React.useState(0); - const [loading, setLoaded] = React.useState(true); - - React.useEffect(() => { - setLoaded(true); - - fetch(`https://randomuser.me/api/1.2/?page=${page}&results=${limit}&seed=abc&inc=id,name,picture`) - .then((response) => response.json()) - .then(({ results }) => { - const newList: Option[] = []; - results.forEach((item) => { - newList.push({ - value: makeid(), - text: ( - - ), - }); - }); - - setTotal(1000); - setList(newList); - setLoaded(false); - }); - }, [page]); - - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - - return ( - - {(size) => ( - -
- - - -
-
- )} -
- ); -}; - -export const OptionsMultiple = (): React.ReactNode => { - const [form] = useForm(); - const [search, setSearch] = React.useState(''); - const [loading, setLoaded] = React.useState(true); - const [list, setList] = React.useState([]); - const [page, setPage] = React.useState(1); - const [total, setTotal] = React.useState(0); - - React.useEffect(() => { - setLoaded(true); - - fetch(`https://randomuser.me/api/1.2/?page=${page}&results=${limit}&seed=abc&inc=id,name,picture`) - .then((response) => response.json()) - .then(({ results }) => { - const newList: Option[] = []; - results.forEach((item) => { - newList.push({ - value: makeid(), - text: ( - - ), - }); - }); - - setTotal(1000); - setList(newList); - setLoaded(false); - }); - }, [page]); - - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - - return ( - - {(size) => ( - -
- - - -
-
- )} -
- ); +Regular.args = { + mode: 'single', + optionsMode: 'dropdown', + valueMode: 'regular', + size: 'medium', + placeholder: 'Select', + newPlaceholder: 'Add new...', + emptyLabel: 'No found', + loading: false, + disabled: false, + isClearable: true, + prefix: , + suffix: undefined, }; -export const InfiniteScrollPagination = (): React.ReactNode => { - const [form] = useForm(); +export const InfiniteScrollPagination: React.FC & { args: SelectProps } = ({ children, ...props }) => { const [search, setSearch] = React.useState(''); const [list, setList] = React.useState([]); const [page, setPage] = React.useState(1); @@ -308,188 +121,23 @@ export const InfiniteScrollPagination = (): React.ReactNode => { }); }, [page]); - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - return ( - - {(size) => ( - -
- - - -
-
- )} -
+ ); }; -export const TagsMode = (): React.ReactNode => { - const [form] = useForm(); - const [, setSearch] = React.useState(''); - const [list, setList] = React.useState([]); - const [page, setPage] = React.useState(1); - const [total, setTotal] = React.useState(0); - const [loading, setLoaded] = React.useState(true); - - React.useEffect(() => { - setLoaded(true); - - fetch(`https://randomuser.me/api/1.2/?page=${page}&results=${limit}&seed=abc&inc=id,name,picture`) - .then((response) => response.json()) - .then(({ results }) => { - const newList: Option[] = []; - results.forEach((item) => { - newList.push({ - value: makeid(), - text: `${capitalize(item.name.first)} ${capitalize(item.name.last)}`, - }); - }); - - setTotal(1000); - setList(newList); - setLoaded(false); - }); - }, [page]); - - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - - return ( - - {(size) => ( - -
- - - -
-
- )} -
- ); -}; - -export const InlineValueMode = (): React.ReactNode => { - const [form] = useForm(); - const [, setSearch] = React.useState(''); - const [list, setList] = React.useState([]); - const [page, setPage] = React.useState(1); - const [total, setTotal] = React.useState(0); - const [loading, setLoaded] = React.useState(true); - - React.useEffect(() => { - setLoaded(true); - - fetch(`https://randomuser.me/api/1.2/?page=${page}&results=${limit}&seed=abc&inc=id,name,picture`) - .then((response) => response.json()) - .then(({ results }) => { - const newList: Option[] = []; - results.forEach((item) => { - newList.push({ - value: makeid(), - text: `${capitalize(item.name.first)} ${capitalize(item.name.last)}`, - }); - }); - - setTotal(1000); - setList(newList); - setLoaded(false); - }); - }, [page]); - - const handleChange = (values): void => { - console.log('values :>> ', values); - }; - - return ( - - {(size) => ( - -
- - - -
-
- )} -
- ); -}; +InfiniteScrollPagination.args = Regular.args; diff --git a/src/components/molecules/Select/Select.tsx b/src/components/molecules/Select/Select.tsx index e269d86e..981cbeb5 100644 --- a/src/components/molecules/Select/Select.tsx +++ b/src/components/molecules/Select/Select.tsx @@ -1,11 +1,11 @@ import * as React from 'react'; import { - Component, - ComponentProps, + Select, + SelectProps, Search, SearchProps, - Options, + OptionsComponent, OptionsProps, OptionsComposition, Pagination, @@ -19,18 +19,18 @@ export interface Composition { Pagination: React.FC; } -const Select: React.FC & Composition = (props) => { +const SelectComponent: React.FC & Composition = (props) => { return ( - +