Skip to content
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
5 changes: 5 additions & 0 deletions apps/client/src/pages/onBoarding/OnBoarding.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const OnBoarding = () => {
return <div>OnBoarding</div>;
};

export default OnBoarding;
Empty file.
Original file line number Diff line number Diff line change
@@ -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<HTMLDivElement>;
}

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 (
<div
onClick={onClick}
className="common-shadow flex w-[26rem] flex-col items-center px-[1.6rem]"
>
<WheelPickerWrapper className="flex h-[16.8rem] !items-center py-[0.8rem]">
<WheelPicker
options={hourOptions}
aria-label="시"
infinite
optionItemHeight={56}
onValueChange={(value: string) => setSelectedHour(value)}
/>
<p className="bod y2-m z-2 mx-[0.8rem] flex h-[5.6rem] items-center justify-center">
:
</p>
<WheelPicker
options={minuteOptions}
aria-label="분"
infinite
optionItemHeight={56}
onValueChange={(value: string) => setSelectedMinute(value)}
/>
<div className="mx-[0.4rem]" />
<WheelPicker
options={meridiemOptions}
aria-label="오전/오후"
optionItemHeight={56}
onValueChange={(value: string) => setSelectedMeridiem(value)}
/>
</WheelPickerWrapper>
<div className="flex w-full gap-[1.2rem] pb-[2.4rem] pt-[0.8rem]">
<Button variant="secondary" onClick={onCancel}>
취소
</Button>
<Button
variant="primary"
onClick={() =>
onSave({
hour: selectedHour,
minute: selectedMinute,
meridiem: selectedMeridiem,
})
}
>
확인
</Button>
</div>
</div>
);
};

export default TimePicker;
5 changes: 5 additions & 0 deletions apps/client/src/routes/router.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -27,6 +28,10 @@ export const router = createBrowserRouter([
path: ROUTES_CONFIG.level.path,
element: <Level />,
},
{
path: ROUTES_CONFIG.onBoarding.path,
element: <OnBoarding />,
},
],
},
]);
4 changes: 4 additions & 0 deletions apps/client/src/routes/routesConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ export const ROUTES_CONFIG = {
title: '레벨',
path: '/level',
},
onBoarding: {
title: '온보딩',
path: '/onBoarding',
},
};
5 changes: 4 additions & 1 deletion packages/design-system/components.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,8 @@
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
"iconLibrary": "lucide",
"registries": {
"@ncdai": "https://chanhdai.com/r/{name}.json"
}
Comment on lines +20 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

shadcn components.json의 registries 커스텀 URL 사용 — CLI 호환성 확인

해당 필드는 개발 시 스캐폴딩 용도로만 쓰이는 게 이상적입니다. 사용 중인 shadcn CLI 버전이 "registries" 맵 형태와 커스텀 레지스트리 URL을 지원하는지 확인해주세요. 외부 도메인(https://chanhdai.com) 신뢰·가용성도 한 번 검토하면 좋겠습니다.

최신 스키마 확인용 웹 질의:


🌐 Web query:

shadcn components.json "registries" field schema and support for custom registries in current CLI

💡 Result:

Short answer

  • components.json "registries" is an array of registry objects (minimum fields: name and baseUrl) that tell the CLI where to fetch registries from. [1][2]
  • You can host custom registries as JSON (registry.json / registry-item.json) that conform to shadcn's registry schemas; the CLI expects those JSON endpoints and will resolve registry dependencies automatically. [3][5]
  • The CLI supports adding/using custom registries (e.g., shadxn/shadcn CLI: registry add / registry init / registry build; and add components with -r ). Auth must be handled by your registry server (token query param is suggested). [4][5]

Relevant docs

  • components.json / registries usage. [1]
  • Registry overview (requirements, hosting JSON, run-your-own). [2]
  • registry-item.json schema (item/files/registryDependencies and automatic resolution). [3]
  • CLI registry commands (registry add/init/build and using -r to install from a registry). [4]
  • Getting started / auth and publishing guidance. [5]

If you want, I can fetch the exact JSON schema URLs (registry.json and registry-item.json $schema links) and show an example components.json + sample registry.json you can deploy.


components.json의 registries 필드 스키마 및 CLI 지원 확인 및 형식 수정

  • 최신 shadcn CLI 스키마에 따르면 registries는 맵이 아니라 레지스트리 객체 배열이어야 하며, 각 객체에 필수로 namebaseUrl을 지정해야 합니다.
  • 예시 (packages/design-system/components.json):
    "registries": [
      { "name": "@ncdai", "baseUrl": "https://chanhdai.com/r" }
    ]
  • 사용 중인 shadcn CLI 버전이 커스텀 레지스트리 기능(registry add/init/build-r <registry-name> 플래그)을 지원하는지 검증
  • 호스트 도메인의 신뢰성·가용성 및 인증 방식(token 쿼리 파라미터 권장) 점검 필요
🤖 Prompt for AI Agents
In packages/design-system/components.json around lines 20–23, the registries
field currently uses a map but should be an array of registry objects per the
latest shadcn CLI schema; replace the map with an array of objects each
containing required "name" and "baseUrl" (e.g. { "name": "@ncdai", "baseUrl":
"https://chanhdai.com/r" }), update any code/CI that reads this file to the new
shape, verify the installed shadcn CLI version supports custom registries and
the registry-related flags/commands, and validate the registry host for
availability/trust and recommend using a token passed as a query parameter for
authentication.

Comment on lines +20 to +23
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 어떤 역할을 하나요?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"lucide" 아이콘 라이브러리를 사용하고, "@ncdai"라는 스코프를 가진 컴포넌트를 특정 URL에서 가져오도록 설정하는 내용이라고 하네요!

해당 React Wheel Picker 라이브러리에서 아래와 같이 설정이 필요하다고 말해줘서 추가했어요.
image

}
2 changes: 2 additions & 0 deletions packages/design-system/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -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<typeof Badge> = {
title: 'Components/Badge',
Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/components/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { cn } from '@/lib';
import { cva } from 'class-variance-authority';
import { cn } from '../../lib/utils';

interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary';
Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/components/card/RemindCard.tsx
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion packages/design-system/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
4 changes: 2 additions & 2 deletions packages/design-system/src/components/progress/Progress.tsx
Original file line number Diff line number Diff line change
@@ -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: {
Expand Down
4 changes: 2 additions & 2 deletions packages/design-system/src/components/switch/Switch.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand Down
3 changes: 1 addition & 2 deletions packages/design-system/src/components/textarea/Textarea.tsx
Original file line number Diff line number Diff line change
@@ -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<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength'> {
Expand Down
2 changes: 1 addition & 1 deletion packages/design-system/src/components/toast/Toast.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn } from '@/lib/utils';
import { cn } from '../../lib/utils';

export interface ToastProps {
text: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
45 changes: 45 additions & 0 deletions packages/design-system/src/components/wheelPicker/WheelPicker.tsx
Original file line number Diff line number Diff line change
@@ -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<typeof WheelPickerPrimitive.WheelPickerWrapper>) {
return (
<WheelPickerPrimitive.WheelPickerWrapper
className={cn('flex', className)}
{...props}
/>
);
}

function WheelPicker({
classNames,
...props
}: React.ComponentProps<typeof WheelPickerPrimitive.WheelPicker>) {
return (
<WheelPickerPrimitive.WheelPicker
classNames={{
...classNames,
optionItem: cn(
'text-gray300 !font-medium !text-[1.6rem] !leading-[150%] !tracking-[-0.025em]',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

! 붙여서 스타일 지정하는게 아쉽지만 스타일이 숨김처리된 부분이 있어서 이렇게밖에 하지 못하는게 어쩔 수 없네요 다른 방법이 있나 저도 더 찾아보겠습니다-!

classNames?.optionItem
),
highlightWrapper: cn(
'bg-white border-y-[0.5px] border-gray300 !font-medium !text-[1.6rem] !leading-[150%] !tracking-[-0.025em]',
classNames?.highlightWrapper
),
}}
{...props}
/>
);
}

export { WheelPicker, WheelPickerWrapper };
export type { WheelPickerClassNames, WheelPickerOption };
3 changes: 1 addition & 2 deletions packages/design-system/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
"outDir": "dist",
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"],
"@lib/*": ["./src/lib/*"]
"@/*": ["./src/*"]
},
Comment on lines +9 to 10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

경로별칭 축소(@lib 제거) 일관성 확인 필요

@/는 유지되지만, 본 PR에서는 상대경로로 전환 중입니다. 잔존 @lib/, '@/lib/*' 참조가 없는지 확인해 주세요.


🏁 Script executed:

#!/bin/bash
# design-system 내 잔존 별칭 검색
rg -nP "@lib/|@/lib/" packages/design-system -g '!**/dist/**' -S
# 앱 레벨에서도 혹시 참조 중인지 확인
rg -nP "@lib/|@/lib/" apps -g '!**/dist/**' -S

Length of output: 185


@lib 별칭 제거 후 경로 일관성 확보

packages/design-system/components.json (15행)에 "@/lib/utils" 참조가 남아 있으니 상대경로 또는 @/* 별칭으로 교체해주세요.

🤖 Prompt for AI Agents
packages/design-system/tsconfig.json around lines 9-10: components.json still
references "@/lib/utils" after removing any @lib alias; open
packages/design-system/components.json (line ~15) and replace the "@/lib/utils"
import with a consistent relative path (e.g., "./src/lib/utils" or
"../src/lib/utils" as appropriate to that file's location) so paths are
consistent with the current "@/*": ["./src/*"] mapping, or alternatively add a
specific "@/lib/*": ["./src/lib/*"] entry to tsconfig.json if you prefer to keep
the "@/lib/..." alias.

"jsx": "react-jsx"
},
Expand Down
12 changes: 4 additions & 8 deletions packages/design-system/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import svgSpritePlugin from '@pivanov/vite-plugin-svg-sprite';
/// <reference types="vitest/config" />
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
Expand All @@ -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',
Expand Down
5 changes: 5 additions & 0 deletions packages/tailwind-config/shared-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@
@theme {
--color-*: initial;

/* default */
--color-white: #ffffff;
--color-black: #000000;
--color-transparent: transparent;

Comment on lines +164 to +168
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Biome 파서 오류로 CI 깨짐: @theme 블록 안의 커스텀 프로퍼티 선언을 :root로 감싸주세요.

Biome(2.1.2)가 Tailwind v4 @theme의 루트 레벨 커스텀 프로퍼티 선언을 제대로 파싱하지 못해 parse 에러가 납니다. 동일 파일의 기존 토큰들은 변경 라인이 아니라 리포팅되지 않았을 뿐, 새로 추가된 3개 라인에서 빌드가 막힙니다. :root로 한 번 감싸면 Biome이 “스타일 규칙”으로 인식해 통과합니다(Tailwind v4도 스코프드 토큰을 지원하므로 동작 동일).

적용 diff:

   /* default */
-  --color-white: #ffffff;
-  --color-black: #000000;
-  --color-transparent: transparent;
+  :root {
+    --color-white: #ffffff;
+    --color-black: #000000;
+    --color-transparent: transparent;
+  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/* default */
--color-white: #ffffff;
--color-black: #000000;
--color-transparent: transparent;
/* default */
:root {
--color-white: #ffffff;
--color-black: #000000;
--color-transparent: transparent;
}
🧰 Tools
🪛 Biome (2.1.2)

[error] 165-165: expected , but instead found --color-white

Remove --color-white

(parse)


[error] 165-165: Unexpected value or character.

Expected one of:

(parse)


[error] 165-165: expected , but instead found ;

Remove ;

(parse)


[error] 166-166: expected , but instead found --color-black

Remove --color-black

(parse)


[error] 166-166: Unexpected value or character.

Expected one of:

(parse)


[error] 166-166: Expected an identifier but instead found '000000'.

Expected an identifier here.

(parse)


[error] 167-167: expected , but instead found --color-transparent

Remove --color-transparent

(parse)


[error] 167-167: expected , but instead found ;

Remove ;

(parse)


[error] 167-167: Unexpected unknown pseudo-class transparent

See MDN web docs for more details.

(lint/correctness/noUnknownPseudoClass)

🤖 Prompt for AI Agents
In packages/tailwind-config/shared-styles.css around lines 164 to 168, the three
custom property declarations currently at root level inside the @theme block
must be wrapped in a :root selector; update that section so the declarations
(--color-white, --color-black, --color-transparent) are placed inside a :root {
... } block within the existing @theme block so the parser accepts them.

/* Main Color */
--color-main0: #f9fffb;
--color-main100: #c9f2e1;
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading