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':