diff --git a/package.json b/package.json index 7debbcd0..33824f11 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ "dependencies": { "@emotion/react": "11.10.0", "@emotion/styled": "11.10.0", + "@mui/icons-material": "5.11.11", "@mui/material": "5.10.7", "i18next": "21.9.2", "next": "12.3.1", diff --git a/src/components/modals/ModalHeaderMenu/index.tsx b/src/components/modals/ModalHeaderMenu/index.tsx new file mode 100644 index 00000000..cce848f2 --- /dev/null +++ b/src/components/modals/ModalHeaderMenu/index.tsx @@ -0,0 +1,87 @@ +import { Box, Modal, Slide, ButtonBase, Typography, IconButton } from '@mui/material' +import CloseIcon from '@mui/icons-material/Close' +import Link from 'next/link' +import { useRouter } from 'next/router' +import { Logo } from 'src/components/atoms' +import { Colors } from 'src/styles/color' +import { HeaderMenuItem } from 'src/components/organisms/Header' + +export interface ModalHeaderMenuProps { + open: boolean + onClose: () => void + menuList: HeaderMenuItem[] +} + +export const ModalHeaderMenu = ({ open, onClose, menuList }: ModalHeaderMenuProps) => { + const router = useRouter() + + return ( + + + + + + + + + + + + + {menuList.map((list, i) => { + return ( + + + + {list.onClick ? ( + + + {list.label} + + + ) : ( + + {list.label} + + )} + + + + ) + })} + + + + + ) +} diff --git a/src/components/molecules/HeaderMenu/index.tsx b/src/components/molecules/HeaderMenu/index.tsx new file mode 100644 index 00000000..7be96151 --- /dev/null +++ b/src/components/molecules/HeaderMenu/index.tsx @@ -0,0 +1,49 @@ +import React from 'react' +import { Typography, Box } from '@mui/material' +import Link from 'next/link' +import { useRouter } from 'next/router' +import { HeaderItemColor, HeaderMenuItem, HeaderItemBehaviorStyles } from 'src/components/organisms/Header' + +export interface HeaderMenuProps { + menuList: HeaderMenuItem[] + itemColor: HeaderItemColor + itemBehaviorStyles: HeaderItemBehaviorStyles +} + +export const HeaderMenu = ({ menuList, itemColor, itemBehaviorStyles }: HeaderMenuProps) => { + const router = useRouter() + + return ( + + {menuList.map((list, i) => { + return list.href ? ( + + + + {list.label} + + + + ) : ( + + {list.label} + + ) + })} + + ) +} diff --git a/src/components/organisms/Header/index.tsx b/src/components/organisms/Header/index.tsx index 5829c172..3629f469 100644 --- a/src/components/organisms/Header/index.tsx +++ b/src/components/organisms/Header/index.tsx @@ -1,48 +1,70 @@ -import React from 'react' -import i18n from 'src/i18n/configs' -import { AppBar, Toolbar, Typography, Box } from '@mui/material' +import React, { useState, useMemo } from 'react' +import MenuRoundedIcon from '@mui/icons-material/MenuRounded' +import { AppBar, Toolbar, Box, IconButton } from '@mui/material' import { Colors } from 'src/styles/color' -import { useTranslation } from 'react-i18next' import { Logo } from 'src/components/atoms' import { useScrollY, useSize } from 'src/modules/hooks' +import { HeaderMenu } from 'src/components/molecules/HeaderMenu' +import { ModalHeaderMenu } from 'src/components/modals/ModalHeaderMenu' +import { handleChangeLanguage } from 'src/i18n/util' +import { useTranslation } from 'react-i18next' -const handleChangeLanguage = () => { - switch (i18n.language) { - case 'ja': - i18n.changeLanguage('en') - return - case 'en': - i18n.changeLanguage('ja') - return - } -} - -interface HeaderItemColors { +export interface HeaderItemColor { default: string hover: string activeBg: string } -// TODO: 各ページへのリンクを実装, スマートフォンモード実装 +export type HeaderMenuItem = { + href?: string + label: string + onClick?: () => void +} + +export type HeaderItemBehaviorStyles = { + '&:hover': { + cursor: string + color: string + } + '&:active': { + color: string + backgroundColor: string + } +} + export const Header = () => { - const isScrolled = useScrollY() > 0 - const headerItemColors: HeaderItemColors = isScrolled - ? { default: Colors.text.white, hover: Colors.text.white_hover, activeBg: Colors.header.active.white } - : { default: Colors.text.primary, hover: Colors.text.primary_hover, activeBg: Colors.header.active.default } + const [modalMenuOpen, setModalMenuOpen] = useState(false) const { t } = useTranslation() + const isScrolled = useScrollY() > 0 const { isPCOrOver } = useSize() const isLogoDisplayed = isPCOrOver || isScrolled - const headerItemBehaviorStyles = { + const headerItemColor: HeaderItemColor = isScrolled + ? { default: Colors.text.white, hover: Colors.text.white_hover, activeBg: Colors.header.active.white } + : { default: Colors.text.primary, hover: Colors.text.primary_hover, activeBg: Colors.header.active.default } + const headerItemBehaviorStyles: HeaderItemBehaviorStyles = { '&:hover': { cursor: 'pointer', - color: headerItemColors.hover + color: headerItemColor.hover }, '&:active': { - color: headerItemColors.hover, - backgroundColor: headerItemColors.activeBg + color: headerItemColor.hover, + backgroundColor: headerItemColor.activeBg } } + const menuList: HeaderMenuItem[] = useMemo(() => { + return [ + { href: '/', label: 'Home' }, + { href: '/sessions', label: 'Sessions' }, + { href: '/timetable', label: 'Timetable' }, + { href: '/floor_guide', label: 'Floor Guide' }, + { + label: t('change_language'), + onClick: handleChangeLanguage + } + ] + }, [t]) + return ( {/* グラデーション背景 */} @@ -62,9 +84,9 @@ export const Header = () => { { /> )} - - - {t('change_language')} - - + {isPCOrOver ? ( + + ) : ( + + setModalMenuOpen(true)}> + + + + )} + setModalMenuOpen(false)} menuList={menuList} /> ) } diff --git a/src/components/pages/PageTop/index.tsx b/src/components/pages/PageTop/index.tsx index 04346725..5a7630a6 100644 --- a/src/components/pages/PageTop/index.tsx +++ b/src/components/pages/PageTop/index.tsx @@ -2,13 +2,7 @@ import type { NextPage } from 'next' import { Layout } from 'src/components/commons' import { useTranslation } from 'react-i18next' import { useSessionize } from 'src/modules/sessionize/hooks' -import { - MainVisual, - TopDescription, - SponsorsSection, - CommunityBoothSection, - SpeakersSection -} from 'src/components/organisms' +import { MainVisual, TopDescription, SponsorsSection, CommunityBoothSection } from 'src/components/organisms' export const PageTop: NextPage = () => { const { t } = useTranslation() @@ -21,7 +15,6 @@ export const PageTop: NextPage = () => { - diff --git a/src/i18n/util.ts b/src/i18n/util.ts new file mode 100644 index 00000000..79182ac7 --- /dev/null +++ b/src/i18n/util.ts @@ -0,0 +1,12 @@ +import i18n from 'src/i18n/configs' + +export const handleChangeLanguage = () => { + switch (i18n.language) { + case 'ja': + i18n.changeLanguage('en') + return + case 'en': + i18n.changeLanguage('ja') + return + } +} diff --git a/src/pages/floor_guide.tsx b/src/pages/floor_guide.tsx new file mode 100644 index 00000000..797c0108 --- /dev/null +++ b/src/pages/floor_guide.tsx @@ -0,0 +1,11 @@ +import { PageTop } from 'src/components/pages' + +type InitialProps = {} +type Props = {} & InitialProps + +const Index = (_: Props) => { + /* TODO: 各ページの実装 */ + return +} + +export default Index diff --git a/src/pages/sessions.tsx b/src/pages/sessions.tsx new file mode 100644 index 00000000..797c0108 --- /dev/null +++ b/src/pages/sessions.tsx @@ -0,0 +1,11 @@ +import { PageTop } from 'src/components/pages' + +type InitialProps = {} +type Props = {} & InitialProps + +const Index = (_: Props) => { + /* TODO: 各ページの実装 */ + return +} + +export default Index diff --git a/src/pages/timetable.tsx b/src/pages/timetable.tsx new file mode 100644 index 00000000..797c0108 --- /dev/null +++ b/src/pages/timetable.tsx @@ -0,0 +1,11 @@ +import { PageTop } from 'src/components/pages' + +type InitialProps = {} +type Props = {} & InitialProps + +const Index = (_: Props) => { + /* TODO: 各ページの実装 */ + return +} + +export default Index diff --git a/src/styles/theme.ts b/src/styles/theme.ts index 2c394ef2..28815729 100644 --- a/src/styles/theme.ts +++ b/src/styles/theme.ts @@ -1,19 +1,8 @@ import { createTheme, ThemeOptions } from '@mui/material/styles' import { Colors } from './color' -const defaultTheme = createTheme() - -const { breakpoints } = defaultTheme - -export const theme: ThemeOptions = { - ...defaultTheme, - components: { - MuiTypography: { - defaultProps: { - color: Colors.text.primary - } - } - }, +const { breakpoints } = createTheme() +const defaultTheme = createTheme({ typography: { h2: { fontSize: '50px', @@ -59,4 +48,30 @@ export const theme: ThemeOptions = { } } } +}) + +export const theme: ThemeOptions = { + ...defaultTheme, + components: { + MuiTypography: { + defaultProps: { + color: Colors.text.primary, + fontFamily: [ + 'Poppins', + 'Montserrat', + '-apple-system', + 'BlinkMacSystemFont', + 'Segoe UI', + 'Roboto', + 'Oxygen', + 'Ubuntu', + 'Cantarell', + 'Fira Sans', + 'Droid Sans', + 'Helvetica Neue', + 'sans-serif' + ].join(',') + } + } + } } diff --git a/yarn.lock b/yarn.lock index e9ec9271..1d00e280 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1103,6 +1103,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.21.0": + version "7.21.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673" + integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw== + dependencies: + regenerator-runtime "^0.13.11" + "@babel/runtime@^7.3.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.3": version "7.19.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78" @@ -1651,6 +1658,13 @@ resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-5.10.7.tgz#b0dd472438cf769ba10c44ce44b35b597bfa0e17" integrity sha512-3N0UYVy3MbrHzM3j6f7fIUCZ+bQ1/sSZq143tLxwSssW3Z4AqE83brpr5flEY1Lx+Aowv/cPyQMmZxzRlFCGqw== +"@mui/icons-material@5.11.11": + version "5.11.11" + resolved "https://registry.yarnpkg.com/@mui/icons-material/-/icons-material-5.11.11.tgz#d4e01bd405b0dac779f5e060586277f91f3acb6e" + integrity sha512-Eell3ADmQVE8HOpt/LZ3zIma8JSvPh3XgnhwZLT0k5HRqZcd6F/QDHc7xsWtgz09t+UEFvOYJXjtrwKmLdwwpw== + dependencies: + "@babel/runtime" "^7.21.0" + "@mui/material@5.10.7": version "5.10.7" resolved "https://registry.yarnpkg.com/@mui/material/-/material-5.10.7.tgz#08e72c554bd528f9f5fef604eea542551f9e5986" @@ -9941,6 +9955,11 @@ regenerator-runtime@^0.11.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== +regenerator-runtime@^0.13.11: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== + regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52"