??8Y=+;OG-x`jCG(*p-SYpALKQyzns)WDoOuy
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
EKW=7I;s5{u
literal 0
HcmV?d00001
diff --git a/public/images/partners/platinum-2.png b/public/images/partners/platinum-2.png
new file mode 100755
index 0000000000000000000000000000000000000000..42f2a0423c842c6baf93281c1f2ca0f74928c2b4
GIT binary patch
literal 10443
zcmeHN`Cn4$_ZKopt<0>++-ZeV%jfgUgP#
z`(%}6B_t&F+1vegRYC#`myiHuNlO90gqx^811_M5tG4GP%DYv05)zsc_P_mlE!LYq
zlF+Ahenjfa^Pe96@Y`=64nBlWiMEtCodO@&zCZZaoxi@_uA9AF9oCL|kzh75$c??8Y=+;OG-x`jCG(*p-SYpALKQyzns)WDoOuy
zi6MUREiggG_u1U@xk_+8SY&Ebe1
zwI*TyoT}yKLZ;8gm*lPWv6i0XO<{}A)*376USsY*adYO7JSF-LhfhK}I}5hw98KO7
z&n0Upq*V3w6mHb9-2x$!~ZAMkw-!DuW(pw
zly2Zy#GY;S>$lbS-mp8z)Yw{SYuQ%w(Uvzt4g{l3nH**uy$Q^kK1^>Kcik2rxh>vP
zY$vC>(=+-^V5)tD}ujmZFbN7{NTT
zCvkFqum`ieB64=JaPhq3>9x{VxOt7H;}EwC1Qxkl(_Z&91`PH9+qrM}S((z^Jmp-t
z*8kOGY>oLfqHuk9^6G@ETzzt1!(7w)V-XJTTdPFAU%q$%EIFG6Y$?^OXi&;WVZa4G9XMC>$|;TS;lsgKg$%yt_C6
zTi+BGZmG^OaPCyqcjWpo7PGbbPn8VO-URUyOCzb~P$EoSU&MJh^yqX`?A~@KEAgUM
z#fOuoVU0_!OX4@>AuT22R4T%}Y5v}6RSUsL;mUjMj7Qmq*$aZYW-&i@`f>A?c<#e&
zH@Dh*ViZ+e4$(Fg*>yl3)JypFq{lt-LB!gW+OjKS^`@Qi(CLfihq_n(=qYexe$GQ>
zSru+B7H3{qa1_Ia9>3y1eHFLTI)q9Ky`s8|Vro+-yxl0+BI(bXi`*>?Z!=E+PyHsJ
zO#xwl;noH>bLjntGrkb~Al`4oU!{K>$8S??UisjgJlP;T^RO>uF5Gu2jTkc;$ITMI
zU7u_A5i|6q0weIedy3w_WK?owl=MX>$=;uSSiS&&ZUa-vX$0xs6*Y{BXQ#Bns{Y_!
z|7okNMwMi}Am}));r6@?>DH2+-faaq>G(d0>TeZ|>Q`xWDMS88smeuqY`f!`v-Wzs
z@1WNg?RS$UODmH2=(c?eOkIA@k+|{nvj&LwOVfZuf2KxaZnSz{3|snMWC1E=YPk+x
znVfv5q(yRzj$W{T{(2cVcj@w_PbD(332l>A8RUF)yy7m`b3v`Q^3b)9RzGKzz7Y+}
z$MNd=dql_DIgyVoDuN>p))<8bVJI^)aQE`z8Ium`hMk$0DX6rmSdtuHYCESF^82zB
z`OqjkHd7WZ6E%2XG2Wl#B;VF-Rph4;E9J+lFrqJcVURK8*EC
zEmS*yN*<@@9nT{%(%0BWx>_w?m_Ui>wzza#)De7i|IBlOzs|@L|2UuM_=QpDhW=Se
z2Dw^hk4FW2;i>;R;D+(T_F?*5uRU;L;Keb2slc96|Gg(7CpU(u+V1_B`0xkIg2~=)v};G?IIc$qQ-(&vDGB;b1B6AsUSXe=t$6
zY)=b7RaMz^be~Aw<>3wKd|Da|tG=sGb+U36*xA`rPI}c;)vCI0&gdO9XL@UaU7Jcz
z9P3XjP8rGB6C=ovIgb2b9+I%R%8e1*{lYKmJi&>)mt**>NNVu#^0RxLM*V5IIar*A
zol-LaRpvOPgJgu+Z)18Lq}$g*yu{8qp?>QRifAvBSFr%o=8SQ%IH7?6(QWhl5!1Fz
zzx!G$->4DHpy(SFjmroI%f|z)dwFrbolz+hNaX##udGAvL~3A=T&2s~vNwSpS|J}Z
z47k&tLV6mqo9YR*3c5z48xhW(3pDq?7@+NizNrXihGV`^uWKjy7)u@ereF;_ikdq@
zzvx=9RvGO$z^pwhMQkKP^qNx^8haj$3>BmbFo1n)Z`*gObi_~oj*G(xo&deIkugi+
zoKypw?T5SD3yHzMN3?Smvwn4LlB9JSO(YXc%lr}^Qr
zmec4vXjDHwn_72KA*VXK`+8cFR98%a@<=mcO0bOd;o=aA^M5?i<+ZW1_ouBhF#aEHda2yOh|6!v|KI8CB93HMju|z
zsjO!S%XgE1dC_AeC5*WfR9h)ys&tnWQSIRS4>K=#et=aZ#+Vxko0sX38<4F~ejDG_
z`Y>fVquX*$k)o^$dy8_S(KAl!jxy;D%a8u7QB8<$O;A$!sY%p0S2nv+RrE2bq1N<>
zNFV9nMld~YN9Okj$$|X1E8_rxj{ZRIWrPhL@I#qG|5N4`?MKA5%b~hVZd*d@sVsI^
ztSDo;Ohf>?u9=McPQPqTncsNM&Hu)!pDlSRFl%1mMIR`
zHN{V`QGvyM)lL;2@XBnpkC-3~+rUjlK%^
zI4h&aKNioY944SG;`N<)t(6|!pFM}}_ZfzVl&Pze{09!E)#8hnZ7;PV1PKIdrtQ*?OF;Vxbo7=x~
zgdU-3Hycr2Ih<;+tBn)E^vu5Fr!jv=J_8ub!Zg++2-kZ;A>2+R5omk0Kg?t(X}~CWDE=yFr$ZWBpClBy+~dKvdZM8nm?$9a5Hnb
z8SdMg4~g^Y1XABP
zl=!6EpS7C3Rhx1jmiZYH_8X7jK7Ak4B|>C+cQ_+52EokznEAVmfRI_@+ju*WZt)Kj
z!yRQd#niXL$Rv3Aa@Ud0G}u&t)bU?K`G#i2h0TlsPmfev$=d}c9<5)PWhMyBk(!!f
zj{|Z(({zkuuXjO6bO;o+4^FZH*Rdbq
zwz*9to96)~0sI^JqiZ*5FhORkz;LufYs}q@@M2PDxZmC2t53o87{31LP!rQRG>vUW
z2-4SMmvZa`#=Xd5D-+i?v8zF&a&+{hFA!C<}L5bBjHlx$<-kg)Xi$*EQg-;S90{
z8@grTLpSt&FVomiS&i=X-Q@dCdLgPR4(fCDPi*dZ5M&Ek`rA>?zgDMBh<2zJ-T07+2#sjc?jY_9n|<)4`QUKX2Bf*gC54dCV3PN=)%DbwLW3?K
z7aT%LmA=^x$R|NJS;LP4S0@uKwdtp)gAK-d%yJj9OFs$31aB~2i7fcOl(BsXah;k-
zBBlF|#`6q5?DL_nKJE=C^V48lX%4LVR`;dp@Vf8R+`0OPHyaZWE%qf&BF`qDmoBpC
zvJiO+9UWg1W{{uj`nnl$&ILpEZybr&u|YTE@%3j4=sKz6Hdzsc6j%i_;$A#6xP&1f
zDwkT!)$i$`1jK3369DiEfb3^B9>~@7Vj{hvM@?0@!!Xj~zyZ+oG6>xhL30?dsj&$j
zIj{%LNq69_7IEtWPv##gbe}ZG1o9zwiedfi3RXsO6}@FI;NgA-BM*yP$&(gf*YvAf
zBH$eHg0!#8Yds)>x*zXve+2OTtQ;s>VLM(%c
zgtJ2EOG0!n(XhwmsY%5Z-|89+L(hYkF`h7|gqxdDGC&03W+i;g+^DT(iv@U&0b_B_
z9{@6VaRBN7EpJezIHdkir;fYTfu(W8{v_}!YDEQ_GlGL)Zo|~P_|L|kHT^nesajz=4bSTI
zVlE}e_0(=3?#?;rc6!OdN&aKik5wUesa&P&`%fV`3LC@v@%&>GHBtQA7dx$mjUNBhJ
zc57k`#vS_G$~*S!z40P=?QC|WZl?FwFZOfC5O+WFRxXYCE$fK#JrX$dW|mK~ICl3J
z0o$lE^YPiSL}BbBLa(mXLnD=1Q-gva!NVl9nfz
z)dml9AE?9)2vS48;Ngmd;pd&{~YOC9zj2j@M4t|GgRh0e
zj`-?j1e8~QrrP=S&;Iq0!031AOzuY`3m(?R%%=pke#XeNMhdqQU;$6Ci@-xdI{5M7
z1|xy5M%m~6a|xGohGr+AOeT-X2_3LlYk#o)@>Ct5f(CU;tvaOYrr%vL(<4kRX0(G|
zpcZS2btl%D_QKMy(saa#OZh3}lt1#apQPKW^Rm;gVGbB*C!QX2n<9AZeu&=X%43DL
zWHqil_K540r&L9x1+*qIi5nkv$4xRT-S312HoEU|F!B9~EAaFB=or7cnesX@#@-bk)DGthQZ
zBxtXxIh|<)D@!XCTK-6J(AucoG649O6)cHxY#nYmN#ejg1{JcrF{_-HSvAy)?mR+j
zyLY_LDI~7@fKFT1PzMD@{R0KY(G@pRq%DEi5>BVBkFMLqUtllC$_v#}M
zMzxSsdirV}mhlC_eq1~O*nxXfjyqXDXL#OdKeJ0JAjJ2IEWD)9cFC`(PmskT^|Y5AUy#@Uj5=|gFMA(
z9It^Tiig%;PlI&%_EsnSs5KQ6N0GRc(DgZ>)FHBwhOeH_%fgjRT2ySTU7~ECGBcbR
zEOQ<0v7y(ht1~uoa1(7CpQ*Y|oykw3(M%#JfrE3CBwOrC9B(WFyQ0c_eRy@fy3k2g
z#MnA=c|(&PGeL2lz8DhN;3hjms?Fa_KttzjXbw>0ghGvCNGD4O)M)zOGy&BVB%J-}
z?+LHMw{)XP#cSn~oj(ScsLbSzKlY(@WPD){ozYuNAo#8h14;z?t{sEsY!*65k6pM@8U)d{rc-pl!bV)FEd(h@E0!ST=YQ4$Lfxc_|@PFK$tDc
zv+7Eh{S0x?%xdx3TzBg+?KW81E5THgB$;E2)H~?uOAL7z7~5q=2`nCY61Tm;WpDjhgjiz`c>e`!TKvym
zB}XNt(*P7MOufAH<*SS|e1C-#^$&^LK;M=raqYN_IT9$Kfnv&E9MJsaWKEk2C{ehr
zBq>Q&ig#C$k$;5%%3e8_L11TKrE^qWtAgey9ZkRmR#k69fJzu--K$hae&CcQk}oNY
z250Y)hG*}W=+d@+?r2SW86hwLOIiYdo+b(Ok*`Th!+*3JJ%^=ffj}Kdpm}V44~uoV
zJ)tiNjI{o@LuieBid7_pHVrU38IB@haCK={7|VRQetge}hX)b#tn*NGDL=N*45KZm^Y
EKW=7I;s5{u
literal 0
HcmV?d00001
diff --git a/src/components/commons/Layout/index.tsx b/src/components/commons/Layout/index.tsx
index b1a016ad..3fa92d43 100644
--- a/src/components/commons/Layout/index.tsx
+++ b/src/components/commons/Layout/index.tsx
@@ -56,7 +56,7 @@ export const Layout: NextPage = ({ children }) => {
-
+
{children}
diff --git a/src/components/pages/PagePartner/index.tsx b/src/components/pages/PagePartner/index.tsx
new file mode 100644
index 00000000..ad531783
--- /dev/null
+++ b/src/components/pages/PagePartner/index.tsx
@@ -0,0 +1,31 @@
+import { Box, Typography } from '@mui/material'
+import { NextPage } from 'next'
+import Image from 'next/image'
+import { Layout } from 'src/components/commons'
+import { Header } from 'src/components/organisms'
+
+export type PartnerRank = 'platinum' | 'gold'
+
+type Props = {
+ id: string
+ name: string
+ description: string
+}
+
+export const PagePartner = ({ id, name, description }: Props) => {
+ return (
+
+
+
+
+
+ {name}
+
+
+
+ {description}
+
+
+
+ )
+}
diff --git a/src/pages/partners/[rank]/[id].tsx b/src/pages/partners/[rank]/[id].tsx
new file mode 100644
index 00000000..1b8f80a7
--- /dev/null
+++ b/src/pages/partners/[rank]/[id].tsx
@@ -0,0 +1,51 @@
+import { GetStaticPaths, GetStaticProps } from 'next'
+import { PagePartner } from 'src/components/pages/PagePartner'
+
+import partners from 'data/partners.json'
+
+export type Rank = keyof typeof partners
+
+type PageProps = {
+ id: string
+ name: string
+ description: string
+ rank: Extract
+}
+
+export const PartnerPage = (props: PageProps) => {
+ return
+}
+
+type PathProps = Pick
+
+export const getStaticPaths: GetStaticPaths = async () => {
+ const platinumPartners = partners.platinum.map(p => ({ params: { rank: 'platinum' as const, id: p.id } }))
+ const goldPartners = partners.gold.map(p => ({ params: { rank: 'gold' as const, id: p.id } }))
+
+ return {
+ paths: [...platinumPartners, ...goldPartners],
+ fallback: false
+ }
+}
+
+/**
+ * partners.json から path params に対応した情報の抜き出し page の props として返す
+ */
+export const getStaticProps: GetStaticProps = async ({ params }) => {
+ const rank = params?.rank as Rank | undefined
+ if (!rank) throw new Error(`rank is required : ${params}`)
+ if (rank !== 'platinum' && rank !== 'gold') throw new Error('invalid rank')
+
+ const id = params?.id as string | undefined
+ if (!id) throw new Error(`id is required : ${params}`)
+
+ const { name, description } = partners[rank].find(p => p.id === id) ?? {}
+ if (!name) throw new Error(`name is required : ${params}`)
+ if (!description) throw new Error(`description is required : ${params}`)
+
+ return {
+ props: { id, name, rank, description }
+ }
+}
+
+export default PartnerPage
From 95ce0e00b0005ec253cfc213be40bcdbb1d09345 Mon Sep 17 00:00:00 2001
From: maito1201 <49754654+maito1201@users.noreply.github.com>
Date: Sun, 12 Mar 2023 19:51:01 +0900
Subject: [PATCH 09/15] feat: header with link (#172)
---
package.json | 1 +
.../modals/ModalHeaderMenu/index.tsx | 87 +++++++++++++++
src/components/molecules/HeaderMenu/index.tsx | 49 +++++++++
src/components/organisms/Header/index.tsx | 101 +++++++++++-------
src/components/pages/PageTop/index.tsx | 9 +-
src/i18n/util.ts | 12 +++
src/pages/floor_guide.tsx | 11 ++
src/pages/sessions.tsx | 11 ++
src/pages/timetable.tsx | 11 ++
src/styles/theme.ts | 41 ++++---
yarn.lock | 19 ++++
11 files changed, 290 insertions(+), 62 deletions(-)
create mode 100644 src/components/modals/ModalHeaderMenu/index.tsx
create mode 100644 src/components/molecules/HeaderMenu/index.tsx
create mode 100644 src/i18n/util.ts
create mode 100644 src/pages/floor_guide.tsx
create mode 100644 src/pages/sessions.tsx
create mode 100644 src/pages/timetable.tsx
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"
From adf00da807106ce91671a94790cffd1f907fae22 Mon Sep 17 00:00:00 2001
From: Taiga KIYOKAWA <40013676+taigakiyokawa@users.noreply.github.com>
Date: Sat, 1 Apr 2023 10:58:30 +0900
Subject: [PATCH 10/15] chore: Remove CommunityBoothSection from PageTop (#174)
---
src/components/pages/PageTop/index.tsx | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/components/pages/PageTop/index.tsx b/src/components/pages/PageTop/index.tsx
index 5a7630a6..27811937 100644
--- a/src/components/pages/PageTop/index.tsx
+++ b/src/components/pages/PageTop/index.tsx
@@ -16,7 +16,6 @@ export const PageTop: NextPage = () => {
-