iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
1

建立側邊欄可以展開的 Items

MenuItem

import React from "react";
import styled from "styled-jss";
import propTypes from "prop-types";
import Icon from "../Icon";
import Typography from "../Typography";

const MenuIcon = styled(Icon)(({ theme }) => ({
  fontSize: 14,
  color: theme.colors.grey2
}));

const StyledMenuContainer = styled("div")({
  display: 'flex',
  cursor: 'pointer',
  flexDirection: 'row',
  justifyContent: 'space-between',
  padding: ({ theme }) => `${theme.getSpacing(1)}px ${theme.getSpacing(2)}px`,
  '&:hover': {
    backgroundColor: ({ theme }) => theme.colors.grey4
  }
});

const MenuText = styled(Typography)({
  color: ({ theme }) => `${theme.colors.grey2}`
});

const MenuExtent = styled(Icon)(({ theme, hasChild, open }) => ({
  color: theme.colors.grey2,
  opacity: hasChild ? 1 : 0,
  transition: 'all .2s ease',
  transform: open ? 'rotate(90deg)': 'rotate(0deg)',
}));

const MenuItem = ({ children, text, icon, open, hasChild, ...props }) => {
  return (
    <StyledMenuContainer {...props}>
      <MenuIcon icon={icon} />
      <MenuText variant='content'>{text}</MenuText>
      <MenuExtent open={open} hasChild={hasChild} icon='fa-angle-right' />
    </StyledMenuContainer>
  );
};

MenuItem.propTypes = {
  icon: propTypes.string,
  text: propTypes.string,
  hasChild: propTypes.bool,
};

MenuItem.defaultProps = {
  icon: '',
  text: '',
  hasChild: false
}

export default MenuItem;

Usage

import React, { Fragment, useState } from "react";
import isEmpty from "lodash/isEmpty";
import Menu from "../../lib/Menu";
import theme from "../../lib/theme";
import NavBar from "../../lib/NavBar";
import Content from "../../lib/Content";
import BrandNav from "../../lib/BrandNav";
import MenuItem from "../../lib/MenuItem";
import Collapse from "../../lib/Collapse";
import Container from "../../lib/Container";
import ThemeProvider from "../../lib/ThemeProvider";

const MenuConfig = [
  {
    text: "Menu 1",
    icon: "fa-user",
  },
  {
    text: "Menu 2",
    icon: "fa-user",
    children: [{ text: "Menu sec" }],
  },
  {
    text: "Menu 3",
    icon: "fa-user",
    children: [{ text: "Menu sec", children: [{ text: "Menu third" }] }],
  },
];

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

const MenuWithChild = ({ item, hasChild, ...props }) => {
  const [open, setOpen] = useState(false);

  const handleOnClick = () => {
    setOpen(!open)
  }

  return (
    <Fragment>
      <MenuItem hasChild open={open} text={item.text} icon={item.icon} onClick={handleOnClick} />
      <Collapse open={open}>
        <MenuItems items={item.children}/>
      </Collapse>
    </Fragment>
  );
};

const MenuItems = ({ items, ...props }) => {
  return items.map((item, index) => {
    const hasChild = !isEmpty(item.children) && item.children.length > 0;
    return hasChild ? (
      <MenuWithChild key={`MenuItem_${index}`} item={item} hasChild/>
    ) : (
      <MenuItem key={`MenuItem_${index}`} text={item.text} icon={item.icon} />
    );
  });
};

const Template = (props) => {
  return (
    <Provider>
      <Container
        width='100vw'
        height='100vh'
        maxHeight='400px'
        maxWidth='960px'
      >
        <NavBar></NavBar>
        <Menu>
          <BrandNav></BrandNav>
          <MenuItems items={MenuConfig} />
        </Menu>
        <Content>
          <h1> MenuItem Demo ...</h1>
        </Content>
      </Container>
    </Provider>
  );
};

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

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

結果如下:


上一篇
Day 20 建立 文字 與 Message
下一篇
Day 22 建立 Alert
系列文
30 天來點 Design System30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言