diff --git a/apps/client/src/pages/onBoarding/OnBoarding.tsx b/apps/client/src/pages/onBoarding/OnBoarding.tsx new file mode 100644 index 00000000..22c6e40f --- /dev/null +++ b/apps/client/src/pages/onBoarding/OnBoarding.tsx @@ -0,0 +1,5 @@ +const OnBoarding = () => { + return
OnBoarding
; +}; + +export default OnBoarding; diff --git a/apps/client/src/pages/onBoarding/components/.gitkeep b/apps/client/src/pages/onBoarding/components/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/apps/client/src/pages/onBoarding/components/timePicker/TimePicker.tsx b/apps/client/src/pages/onBoarding/components/timePicker/TimePicker.tsx new file mode 100644 index 00000000..7bad9d23 --- /dev/null +++ b/apps/client/src/pages/onBoarding/components/timePicker/TimePicker.tsx @@ -0,0 +1,90 @@ +import { + Button, + WheelPicker, + WheelPickerOption, + WheelPickerWrapper, +} from '@pinback/design-system/ui'; +import { MouseEventHandler, useState } from 'react'; + +const createArray = (length: number, add = 0): WheelPickerOption[] => + Array.from({ length }, (_, i) => { + const value = i + add; + return { + label: value.toString().padStart(2, '0'), + value: value.toString(), + }; + }); + +const hourOptions = createArray(12, 1); +const minuteOptions = createArray(60); +const meridiemOptions: WheelPickerOption[] = [ + { label: 'AM', value: 'AM' }, + { label: 'PM', value: 'PM' }, +]; + +interface TimePickerProps { + onSave: (time: { hour: string; minute: string; meridiem: string }) => void; + onCancel: () => void; + onClick: MouseEventHandler; +} + +const TimePicker = ({ onSave, onCancel, onClick }: TimePickerProps) => { + const [selectedHour, setSelectedHour] = useState(hourOptions[0].value); + const [selectedMinute, setSelectedMinute] = useState(minuteOptions[0].value); + const [selectedMeridiem, setSelectedMeridiem] = useState( + meridiemOptions[0].value + ); + + return ( +
+ + setSelectedHour(value)} + /> +

+ : +

+ setSelectedMinute(value)} + /> +
+ setSelectedMeridiem(value)} + /> + +
+ + +
+
+ ); +}; + +export default TimePicker; diff --git a/apps/client/src/routes/router.tsx b/apps/client/src/routes/router.tsx index 9a6f26dc..3f8f59ed 100644 --- a/apps/client/src/routes/router.tsx +++ b/apps/client/src/routes/router.tsx @@ -1,6 +1,7 @@ import Category from '@pages/category/Category'; import Level from '@pages/level/Level'; import MyBookmark from '@pages/myBookmark/MyBookmark'; +import OnBoarding from '@pages/onBoarding/OnBoarding'; import Remind from '@pages/remind/Remind'; import { ROUTES_CONFIG } from '@routes/routesConfig'; import { createBrowserRouter } from 'react-router-dom'; @@ -27,6 +28,10 @@ export const router = createBrowserRouter([ path: ROUTES_CONFIG.level.path, element: , }, + { + path: ROUTES_CONFIG.onBoarding.path, + element: , + }, ], }, ]); diff --git a/apps/client/src/routes/routesConfig.ts b/apps/client/src/routes/routesConfig.ts index c1f183c0..f14054d8 100644 --- a/apps/client/src/routes/routesConfig.ts +++ b/apps/client/src/routes/routesConfig.ts @@ -15,4 +15,8 @@ export const ROUTES_CONFIG = { title: '레벨', path: '/level', }, + onBoarding: { + title: '온보딩', + path: '/onBoarding', + }, }; diff --git a/packages/design-system/components.json b/packages/design-system/components.json index 5e90a7fb..21d537ff 100644 --- a/packages/design-system/components.json +++ b/packages/design-system/components.json @@ -17,5 +17,8 @@ "lib": "@/lib", "hooks": "@/hooks" }, - "iconLibrary": "lucide" + "iconLibrary": "lucide", + "registries": { + "@ncdai": "https://chanhdai.com/r/{name}.json" + } } diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 32424ccb..56fe26dc 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -48,9 +48,11 @@ "typescript": "5.9.2", "typescript-eslint": "^8.39.1", "vite": "^7.1.2", + "vite-tsconfig-paths": "^5.1.4", "vitest": "^3.2.4" }, "dependencies": { + "@ncdai/react-wheel-picker": "^1.0.15", "@pivanov/vite-plugin-svg-sprite": "^3.1.3", "@radix-ui/react-progress": "^1.1.7", "@radix-ui/react-slot": "^1.2.3", diff --git a/packages/design-system/src/components/badge/Badge.stories.tsx b/packages/design-system/src/components/badge/Badge.stories.tsx index 0cda36f3..f005d292 100644 --- a/packages/design-system/src/components/badge/Badge.stories.tsx +++ b/packages/design-system/src/components/badge/Badge.stories.tsx @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react-vite'; import { within, userEvent } from '@storybook/test'; -import Badge, { type BadgeProps } from './Badge'; +import Badge from './Badge'; const meta: Meta = { title: 'Components/Badge', diff --git a/packages/design-system/src/components/button/Button.tsx b/packages/design-system/src/components/button/Button.tsx index cda7e826..8ac3a7bf 100644 --- a/packages/design-system/src/components/button/Button.tsx +++ b/packages/design-system/src/components/button/Button.tsx @@ -1,5 +1,5 @@ -import { cn } from '@/lib'; import { cva } from 'class-variance-authority'; +import { cn } from '../../lib/utils'; interface ButtonProps extends React.ButtonHTMLAttributes { variant?: 'primary' | 'secondary'; diff --git a/packages/design-system/src/components/card/MyBookmarkCard.tsx b/packages/design-system/src/components/card/MyBookmarkCard.tsx index 4d2a641c..b64e2b42 100644 --- a/packages/design-system/src/components/card/MyBookmarkCard.tsx +++ b/packages/design-system/src/components/card/MyBookmarkCard.tsx @@ -1,5 +1,5 @@ -import { Icon } from '@/icons'; import chippiNoImage from '../../assets/chippi_no_image.svg'; +import { Icon } from '../../icons'; import BaseCard from './BaseCard'; interface MyBookmarkCardProps { diff --git a/packages/design-system/src/components/card/RemindCard.tsx b/packages/design-system/src/components/card/RemindCard.tsx index 8b2e8125..f1f53528 100644 --- a/packages/design-system/src/components/card/RemindCard.tsx +++ b/packages/design-system/src/components/card/RemindCard.tsx @@ -1,5 +1,5 @@ -import { Icon } from '@/icons'; import chippiNoImage from '../../assets/chippi_no_image.svg'; +import { Icon } from '../../icons'; import BaseCard from './BaseCard'; interface RemindCardProps { diff --git a/packages/design-system/src/components/index.ts b/packages/design-system/src/components/index.ts index 1398dfaa..559f94ad 100644 --- a/packages/design-system/src/components/index.ts +++ b/packages/design-system/src/components/index.ts @@ -4,8 +4,10 @@ export { default as Card } from './card/Card'; export { default as Chip } from './chip/Chip'; export { default as Input } from './input/Input'; export { default as Level } from './level/Level'; +export { Progress } from './progress/Progress'; export { Switch } from './switch/Switch'; export { Textarea } from './textarea/Textarea'; -export { Progress } from './progress/Progress'; export { default as AutoDismissToast } from './toast/hooks/uesFadeOut'; export { default as Toast } from './toast/Toast'; +export { WheelPicker, WheelPickerWrapper } from './wheelPicker/WheelPicker'; +export type { WheelPickerOption } from './wheelPicker/WheelPicker'; diff --git a/packages/design-system/src/components/progress/Progress.tsx b/packages/design-system/src/components/progress/Progress.tsx index b2829bce..b6e22c89 100644 --- a/packages/design-system/src/components/progress/Progress.tsx +++ b/packages/design-system/src/components/progress/Progress.tsx @@ -1,7 +1,7 @@ -import * as React from 'react'; import * as ProgressPrimitive from '@radix-ui/react-progress'; import { cva, type VariantProps } from 'class-variance-authority'; -import { cn } from '@/lib/utils'; +import * as React from 'react'; +import { cn } from '../../lib/utils'; const track = cva('relative w-full overflow-hidden rounded-full', { variants: { diff --git a/packages/design-system/src/components/switch/Switch.tsx b/packages/design-system/src/components/switch/Switch.tsx index 3ce0bbe1..675d7ef2 100644 --- a/packages/design-system/src/components/switch/Switch.tsx +++ b/packages/design-system/src/components/switch/Switch.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; import * as SwitchPrimitive from '@radix-ui/react-switch'; -import { cn } from '@lib/utils'; +import * as React from 'react'; +import { cn } from '../../lib/utils'; function Switch({ className, diff --git a/packages/design-system/src/components/textarea/Textarea.tsx b/packages/design-system/src/components/textarea/Textarea.tsx index 1197d224..03f88217 100644 --- a/packages/design-system/src/components/textarea/Textarea.tsx +++ b/packages/design-system/src/components/textarea/Textarea.tsx @@ -1,6 +1,5 @@ -// Textarea.tsx import * as React from 'react'; -import { cn } from '@/lib/utils'; +import { cn } from '../../lib/utils'; export interface TextareaProps extends Omit, 'maxLength'> { diff --git a/packages/design-system/src/components/toast/Toast.tsx b/packages/design-system/src/components/toast/Toast.tsx index 4e4573a4..d815dc7d 100644 --- a/packages/design-system/src/components/toast/Toast.tsx +++ b/packages/design-system/src/components/toast/Toast.tsx @@ -1,4 +1,4 @@ -import { cn } from '@/lib/utils'; +import { cn } from '../../lib/utils'; export interface ToastProps { text: string; diff --git a/packages/design-system/src/components/toast/hooks/uesFadeOut.tsx b/packages/design-system/src/components/toast/hooks/uesFadeOut.tsx index 0f3ad16d..16e4c7f2 100644 --- a/packages/design-system/src/components/toast/hooks/uesFadeOut.tsx +++ b/packages/design-system/src/components/toast/hooks/uesFadeOut.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from 'react'; -import { cn } from '@/lib/utils'; +import { cn } from '../../../lib/utils'; export interface AutoDismissToastProps { children: React.ReactNode; diff --git a/packages/design-system/src/components/wheelPicker/WheelPicker.tsx b/packages/design-system/src/components/wheelPicker/WheelPicker.tsx new file mode 100644 index 00000000..ab7c5d59 --- /dev/null +++ b/packages/design-system/src/components/wheelPicker/WheelPicker.tsx @@ -0,0 +1,45 @@ +import '@ncdai/react-wheel-picker/style.css'; + +import * as WheelPickerPrimitive from '@ncdai/react-wheel-picker'; + +import { cn } from '../../lib/utils'; + +type WheelPickerOption = WheelPickerPrimitive.WheelPickerOption; +type WheelPickerClassNames = WheelPickerPrimitive.WheelPickerClassNames; + +function WheelPickerWrapper({ + className, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function WheelPicker({ + classNames, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +export { WheelPicker, WheelPickerWrapper }; +export type { WheelPickerClassNames, WheelPickerOption }; diff --git a/packages/design-system/tsconfig.json b/packages/design-system/tsconfig.json index aa5e3f90..76362065 100644 --- a/packages/design-system/tsconfig.json +++ b/packages/design-system/tsconfig.json @@ -6,8 +6,7 @@ "outDir": "dist", "baseUrl": ".", "paths": { - "@/*": ["./src/*"], - "@lib/*": ["./src/lib/*"] + "@/*": ["./src/*"] }, "jsx": "react-jsx" }, diff --git a/packages/design-system/vite.config.ts b/packages/design-system/vite.config.ts index 63558d81..2a366382 100644 --- a/packages/design-system/vite.config.ts +++ b/packages/design-system/vite.config.ts @@ -1,11 +1,12 @@ import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite'; /// +import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; import tailwindcss from '@tailwindcss/vite'; import react from '@vitejs/plugin-react'; +import { fileURLToPath } from 'node:url'; import path from 'path'; import { defineConfig } from 'vite'; -import { fileURLToPath } from 'node:url'; -import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; +import tsconfigPaths from 'vite-tsconfig-paths'; const dirname = typeof __dirname !== 'undefined' ? __dirname @@ -16,18 +17,13 @@ export default defineConfig({ plugins: [ react(), tailwindcss(), + tsconfigPaths(), svgSpritePlugin({ iconDirs: ['src/icons/source'], symbolId: 'icon-[name]', inject: 'body-last', }), ], - resolve: { - alias: { - '@': path.resolve(__dirname, 'src'), - '@lib': path.resolve(__dirname, '/src/lib'), - }, - }, build: { lib: { entry: 'src/components/index.ts', diff --git a/packages/tailwind-config/shared-styles.css b/packages/tailwind-config/shared-styles.css index c60d65db..ef2c3991 100644 --- a/packages/tailwind-config/shared-styles.css +++ b/packages/tailwind-config/shared-styles.css @@ -161,6 +161,11 @@ @theme { --color-*: initial; + /* default */ + --color-white: #ffffff; + --color-black: #000000; + --color-transparent: transparent; + /* Main Color */ --color-main0: #f9fffb; --color-main100: #c9f2e1; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8cef1f68..d0b72f7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -293,6 +293,9 @@ importers: packages/design-system: dependencies: + '@ncdai/react-wheel-picker': + specifier: ^1.0.15 + version: 1.0.15(react@19.1.1) '@pivanov/vite-plugin-svg-sprite': specifier: ^3.1.3 version: 3.1.3(vite@7.1.2(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.4)(yaml@1.10.2)) @@ -411,6 +414,9 @@ importers: vite: specifier: 7.1.2 version: 7.1.2(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.4)(yaml@1.10.2) + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.9.2)(vite@7.1.2(@types/node@22.15.3)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.4)(yaml@1.10.2)) vitest: specifier: ^3.2.4 version: 3.2.4(@types/node@22.15.3)(@vitest/browser@3.2.4)(jiti@2.5.1)(lightningcss@1.30.1)(tsx@4.20.4)(yaml@1.10.2) @@ -863,6 +869,11 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@ncdai/react-wheel-picker@1.0.15': + resolution: {integrity: sha512-zSLDzBY3xKGzRNoZTNe0mMp5D3loVJPmCmnpRpn7NYC1wBGdH23QkrCh42tEDWYPcNd++XQ4xSqU28BRMbdKlQ==} + peerDependencies: + react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc + '@neoconfetti/react@1.0.0': resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==} @@ -3646,6 +3657,7 @@ packages: prettier@3.6.2: resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} engines: {node: '>=14'} + hasBin: true pretty-format@27.5.1: resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} @@ -4884,6 +4896,10 @@ snapshots: '@tybys/wasm-util': 0.10.0 optional: true + '@ncdai/react-wheel-picker@1.0.15(react@19.1.1)': + dependencies: + react: 19.1.1 + '@neoconfetti/react@1.0.0': {} '@next/eslint-plugin-next@15.4.2':