Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[1.0.3 / D-TP] 팀 페이지 사이드바 디자인 보완 #955

Merged
merged 7 commits into from
Feb 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 13 additions & 161 deletions src/app/teams/[id]/panel/NavBar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client'

import { usePathname, useRouter } from 'next/navigation'
import { useRouter } from 'next/navigation'
import CuNavBar from '@/components/CuNavBar'
import {
BoardIcon,
Expand All @@ -10,20 +10,10 @@ import {
SettingIcon,
ShowcaseIcon,
} from '@/icons/TeamPage'
import {
Badge,
Box,
Stack,
ToggleButton,
Typography,
useMediaQuery,
} from '@mui/material'
import { ReactElement, useCallback, useEffect, useState } from 'react'
import { ToggleButtonGroup } from '@mui/material'
import { Box } from '@mui/material'
import useMedia from '@/hook/useMedia'
import * as style from './NavBar.style'
import * as navStyle from '@/components/NavBarBox.style'
import * as CuStyle from '@/components/CuNavBar.style'

const getTabValue = (path: string) => {
if (path.includes('/notice')) return 'notice'
Expand All @@ -34,160 +24,16 @@ const getTabValue = (path: string) => {
else return 'main'
}

interface ITabInfo {
label: string
mobileLabel?: string
onClick: () => void
value: string
icon: ReactElement
disabled?: boolean
new?: boolean
isBeta?: boolean
}

interface ICuNavBarProps {
getTabValue: (path: string) => string
tabData: ITabInfo[]
}

const MobileSidebar = ({ getTabValue, tabData }: ICuNavBarProps) => {
const pathName = usePathname()
const [value, setValue] = useState<string | undefined>(undefined)

const setTabValue = useCallback(() => {
setValue(getTabValue(pathName))
}, [pathName, getTabValue])

useEffect(() => {
setTabValue()
}, [setTabValue])

return (
<Box sx={{ marginBottom: '2rem', width: '70%' }}>
<ToggleButtonGroup
orientation={'horizontal'}
fullWidth={false}
value={value}
sx={{
display: 'flex',
justifyContent: 'space-between',
width: '100%',
padding: 0,
'& .MuiToggleButtonGroup-grouped': {
borderRadius: '0.5rem',
},
}}
exclusive
onChange={(_event, newValue) => {
if (newValue) setValue(newValue)
}}
>
{[
tabData.map((tab) => (
<MobileToggleButton
key={crypto.randomUUID()}
tab={tab}
selected={value === tab.value}
width={180 / tabData.length}
/>
)),
]}
</ToggleButtonGroup>
</Box>
)
}

const MobileToggleButton = ({
tab,
selected,
width,
}: {
tab: ITabInfo
selected: boolean
width: number
}) => {
const isNewTab = tab.new && !tab.disabled
return (
<ToggleButton
value={tab.value}
onClick={tab.onClick}
sx={{ ...CuStyle.mobileTab, width: `${width}%` }}
disabled={tab.disabled}
selected={selected}
>
<Stack direction={'column'} spacing={'0.12rem'} alignItems={'center'}>
<Badge
sx={isNewTab ? CuStyle.newBadge : CuStyle.betaBadge}
variant={'dot'}
invisible={!isNewTab && !tab.isBeta}
>
<Box sx={CuStyle.iconBoxBase}>{tab.icon}</Box>
</Badge>
<Typography variant={'Tag'}>{tab.mobileLabel ?? tab.label}</Typography>
</Stack>
</ToggleButton>
)
}

const TeamSidebar = ({ id }: { id: string }) => {
const router = useRouter()
const isTablet = useMediaQuery('(min-width: 997px)')
const { isPc } = useMedia()

if (!isTablet && isPc) {
return (
<MobileSidebar
getTabValue={getTabValue}
tabData={[
{
label: '메인',
onClick: () => router.push(`/teams/${id}`),
value: 'main',
icon: <MainIcon sx={style.main} />,
},
{
label: '공지사항',
onClick: () => router.push(`/teams/${id}/notice`),
value: 'notice',
icon: <NoticeIcon sx={style.notice} />,
},
{
label: '게시판',
onClick: () => router.push(`/teams/${id}/board`),
value: 'board',
icon: <BoardIcon sx={style.board} />,
},
{
label: '팀설정',
onClick: () => router.push(`/teams/${id}/setting`),
value: 'setting',
icon: <SettingIcon sx={style.setting} />,
},
{
label: '피어로그',
onClick: () => router.push(`/teams/${id}/peerlog`),
value: 'peerlog',
icon: <PeerlogIcon sx={style.peerlog} />,
isBeta: true,
disabled: true,
},
{
label: '쇼케이스',
onClick: () => router.push(`/teams/${id}/showcase`),
value: 'showcase',
icon: <ShowcaseIcon sx={style.showcase} />,
new: true,
},
]}
/>
)
}
const { isPc, isLargeTablet } = useMedia()

return (
<Box sx={isPc ? navStyle.pcNavBar : navStyle.mobileNavBar}>
<Box sx={getNavStyle(isLargeTablet, isPc)}>
<CuNavBar
getTabValue={getTabValue}
title={'나의 팀들'}
tabletMode
tabData={[
{
label: '메인',
Expand Down Expand Up @@ -218,20 +64,26 @@ const TeamSidebar = ({ id }: { id: string }) => {
onClick: () => router.push(`/teams/${id}/peerlog`),
value: 'peerlog',
icon: <PeerlogIcon sx={style.peerlog} />,
isBeta: true,
isSoon: true,
disabled: true,
},
{
label: '쇼케이스',
onClick: () => router.push(`/teams/${id}/showcase`),
value: 'showcase',
icon: <ShowcaseIcon sx={style.showcase} />,
new: true,
isNew: true,
},
]}
/>
</Box>
)
}

const getNavStyle = (isTablet: boolean, isPc: boolean) => {
if (isTablet) return navStyle.tabletNavBar
if (isPc) return navStyle.pcNavBar
return navStyle.mobileNavBar
}

export default TeamSidebar
53 changes: 40 additions & 13 deletions src/components/CuNavBar.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,23 @@ const tabBase = {

const selectedTab = {
'&.Mui-selected': {
backgroundColor: ['purple.tinted', 'background.tertiary'],
backgroundColor: 'purple.tinted',
'& span': {
color: ['purple.strong', 'text.normal'],
color: 'purple.normal',
},
'& svg': {
fill: (theme: Theme) => theme.palette.purple.strong,
fill: (theme: Theme) => theme.palette.purple.normal,
},
},
}

const disabledTab = {
'&.Mui-disabled': {
color: 'text.disable',
backgroundColor: 'transparent',
border: 'none',
'& span': {
color: 'text.disable',
},
'& svg': {
fill: (theme: Theme) => theme.palette.text.disable,
},
Expand All @@ -58,15 +60,15 @@ export const pcTab: SxProps = {
width: '100%',
padding: '0 1.5rem',
margin: '0.25rem 0',
'& span': {
color: 'text.assistive',
},
...tabBase,
...selectedTab,
...disabledTab,
'& span': {
color: 'text.assistive',
},
}

export const newTab = {
export const tabWithBadge = {
padding: '0 1.5rem 0 4.06rem',
}

Expand All @@ -93,10 +95,24 @@ export const iconBoxBase = {
},
}

export const newTextBadge = {
const textBadge = {
display: 'float',
marginLeft: '1rem !important', // stack의 spacing을 덮어씌우기 위해 !important 사용
color: 'yellow.strong',
}

export const disabledTextBadge = {
...textBadge,
color: (theme: Theme) => theme.palette.text.disable + ' !important', // 버튼 테마 설정을 덮어씌우기 위해 !important 사용
}

export const newTextBadge = {
...textBadge,
color: (theme: Theme) => theme.palette.yellow.strong + ' !important', // 버튼 테마 설정을 덮어씌우기 위해 !important 사용
}

export const soonTextBadge = {
...textBadge,
color: (theme: Theme) => theme.palette.text.disable + ' !important', // 버튼 테마 설정을 덮어씌우기 위해 !important 사용
}

const BADGE_TRANSLATE = 'translate(130%, -50%)'
Expand All @@ -106,7 +122,6 @@ export const badgeBase = {
width: '3px',
minWidth: '3px', // mui 기본 설정 디자인 오버라이딩
height: '3px',
backgroundColor: (theme: Theme) => theme.palette.yellow.strong,
// mui 기본 설정 디자인 오버라이딩
transform: `scale(1) ${BADGE_TRANSLATE}`,
WebkitTransform: `scale(1) ${BADGE_TRANSLATE}`,
Expand All @@ -123,12 +138,24 @@ export const badgeBase = {

export const newBadge = {
'& .MuiBadge-badge': {
backgroundColor: (theme: Theme) => theme.palette.yellow.strong,
backgroundColor: 'yellow.strong',
},
}

export const betaBadge = {
'& .MuiBadge-badge': {
backgroundColor: (theme: Theme) => theme.palette.red.strong,
backgroundColor: 'red.strong',
},
}

export const soonBadge = {
'& .MuiBadge-badge': {
backgroundColor: 'text.disable',
},
}

export const disabledBadge = {
'& .MuiBadge-badge': {
backgroundColor: 'text.disable',
},
}
Loading
Loading