diff --git a/src/ui/bottom-navigation/bottom-navigation.css.ts b/src/ui/bottom-navigation/bottom-navigation.css.ts new file mode 100644 index 000000000..6076ed0be --- /dev/null +++ b/src/ui/bottom-navigation/bottom-navigation.css.ts @@ -0,0 +1,42 @@ +import { style } from '@vanilla-extract/css'; +import { globalVars } from '../theme.css.ts'; +import { typography } from './../typography.css.ts'; + +export const bottomNav = style({ + width: '375px', + height: '84px', + display: 'flex', + justifyContent: 'center', + gap: '47px', + padding: '8px 0px 0px 0px', + backgroundColor: globalVars.color.white, + border: `0.5px solid ${globalVars.color.grey200}`, +}); + +export const menuItem = style({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'flex-start', + cursor: 'pointer', + transition: 'color 0.2s ease-in-out', + width: '50px', + height: '50px', + gap: '2px', + backgroundColor: globalVars.color.white, + border: 'none', +}); + +export const active = style({ + color: globalVars.color.mainblue500, +}); + +export const icon = style({ + width: '24px', + height: '24px', +}); + +export const label = style([ + typography('caption_2_10_r'), + { textAlign: 'center', whiteSpace: 'nowrap' }, +]); diff --git a/src/ui/bottom-navigation/bottom-navigation.stories.tsx b/src/ui/bottom-navigation/bottom-navigation.stories.tsx new file mode 100644 index 000000000..88ce92197 --- /dev/null +++ b/src/ui/bottom-navigation/bottom-navigation.stories.tsx @@ -0,0 +1,42 @@ +import { useState } from 'react'; +import type { Meta, StoryObj } from '@storybook/react'; +import { BottomNavigation, MenuItem } from './bottom-navigation.tsx'; + +const meta: Meta = { + title: 'ui/BottomNavigation', + component: BottomNavigation, + parameters: { + layout: 'fullscreen', + }, + argTypes: { + selected: { + control: 'select', + options: ['home', 'pill', 'consultation', 'mypage', null], + }, + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + selected: null, + }, +}; + +export const SelectedHome: Story = { + args: { + selected: 'home', + }, +}; + +const BottomNavigationWithState = () => { + const [selected, setSelected] = useState(null); + return ; +}; + +export const WithState: Story = { + render: () => , +}; diff --git a/src/ui/bottom-navigation/bottom-navigation.tsx b/src/ui/bottom-navigation/bottom-navigation.tsx new file mode 100644 index 000000000..ea6791db5 --- /dev/null +++ b/src/ui/bottom-navigation/bottom-navigation.tsx @@ -0,0 +1,71 @@ +import { useState } from 'react'; +import { + Chat, + ChatActive, + MyHome, + MyHomeActive, + MyPage, + MyPageActive, + MyPill, + MyPillActive, +} from '../../assets/index.ts'; +import { cx } from '../util.ts'; +import * as styles from './bottom-navigation.css.ts'; + +export type MenuItem = 'home' | 'pill' | 'consultation' | 'mypage'; + +interface BottomNavigationProps { + selected?: MenuItem | null; + onSelect?: (id: MenuItem) => void; +} + +const renderIcon = (id: MenuItem, isActive: boolean) => { + const icons = { + home: isActive ? MyHomeActive : MyHome, + pill: isActive ? MyPillActive : MyPill, + consultation: isActive ? ChatActive : Chat, + mypage: isActive ? MyPageActive : MyPage, + }; + + const IconComponent = icons[id]; + return ; +}; + +export const BottomNavigation = ({ + selected, + onSelect, +}: BottomNavigationProps) => { + const [internalSelected, setInternalSelected] = useState( + selected ?? null, + ); + + const menuItems = [ + { id: 'home', label: '홈' }, + { id: 'pill', label: '내약통' }, + { id: 'consultation', label: '상담' }, + { id: 'mypage', label: '마이페이지' }, + ] as const; + + const handleClick = (id: MenuItem) => { + setInternalSelected(id); + onSelect?.(id); + }; + + return ( + + ); +}; diff --git a/src/ui/bottom-navigation/index.ts b/src/ui/bottom-navigation/index.ts new file mode 100644 index 000000000..ed55e0bec --- /dev/null +++ b/src/ui/bottom-navigation/index.ts @@ -0,0 +1 @@ +export { BottomNavigation } from './bottom-navigation.tsx';