iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
1

Alert

import React, { Fragment } from 'react';
import propTypes from 'prop-types';
import styled from 'styled-jss';
import Card from '../Card';
import Icon from '../Icon';
import Button from '../Button';
import CardBody from '../CardBody';
import CardHeader from '../CardHeader';
import CardFooter from '../CardFooter';

const ICON_MAP = {
  info: "fa-info-circle",
  success: "fa-check-circle",
  warning: "fa-exclamation-circle",
  danger: "fa-exclamation-triangle",
};

const footerStyle = {
    display: 'flex',
    justifyContent: 'space-between',
}

const getIconColor = (theme) => ({
  info: theme.colors.info,
  success: theme.colors.success,
  danger: theme.colors.danger,
  warning: theme.colors.warning,
});

const StyledIcon = styled(Icon)(({ theme, type }) => ({
  fontSize: 60,
  display: 'block',
  textAlign: 'center',
  marginBottom: theme.getSpacing(1),
  color: getIconColor(theme)[type],
}));

const StyledMask = styled('div')({
    top: 0,
    left: 0,
    width: '100vw',
    height: '100vh',
    zIndex: 1000,
    display: 'flex',
    position: 'fixed',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: 'rgba(0, 0, 0, 0.5)'
});

const StyledDialog = styled('div')({
    position: 'relative'
});

const Alert = ({ open, title, subtitle, type, children, cancelText, confirmText, onConfirm, onCancel, ...props }) => {

    if (!open) return <Fragment />;

    return (
        <StyledMask>
            <StyledDialog>
                <Card>
                    <CardBody>
                        <StyledIcon type={type} icon={ICON_MAP[type]} />
                        {children}
                    </CardBody>
                    <CardFooter style={footerStyle}>
                        <Button type='text' onClick={onCancel}>{cancelText}</Button>
                        <Button type='filled' onClick={onConfirm}>{confirmText}</Button>
                    </CardFooter>
                </Card>
            </StyledDialog>
        </StyledMask>
    )
}

Alert.propTypes = {
    open: propTypes.bool,
    title: propTypes.string,
    subtitle: propTypes.string,
    confirmText: propTypes.string,
    cancelText: propTypes.string,
    onConfirm: propTypes.func,
    onCancel: propTypes.func,
    onEnter: propTypes.func,
    onExited: propTypes.func,
}

Alert.defaultProps = {
    open: true,
    title: '',
    subtitle: '',
    confirmText: '確認',
    cancelText: '取消',
    onConfirm: () => false,
    onCancel: () => false,
    onEnter: () => false,
    onExited: () => false,
}

export default Alert;

Usage


import React, { Fragment, useState } from "react";
import theme from "../../lib/theme";
import Alert from "../../lib/Alert";
import Button from "../../lib/Button";
import ThemeProvider from "../../lib/ThemeProvider";

const Provider = (props) => {
    return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
};

const Template = args => {

    const [open, setOpen] = useState(false);

    return (
        <Provider>
            <Fragment>
                <Alert
                  open={open}
                  type='info'
                  onCancel={() => setOpen(false)}
                  onConfirm={() => setOpen(false)}>
                    顯示信息彈窗的內容..
                </Alert>
                <Button onClick={() => setOpen(true)}>Open Alert</Button>
            </Fragment>
        </Provider>
    );
}

export const Default = Template.bind({});

export default {
    component: Alert,
    title: "Components/Alert",
};

結果如下:


上一篇
Day 21 建立 MenuItem
下一篇
Day 23 建立 Input
系列文
30 天來點 Design System30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言