-
Notifications
You must be signed in to change notification settings - Fork 1
Feat(client): Time picker 구현 #49
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
Changes from all commits
dd5f147
85bc419
c9bea41
44a7c36
cd66402
a35caa3
244191f
6c73342
2be22bd
a3c7d60
f675350
c086a33
2b17f59
a379f82
3c9d62c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| const OnBoarding = () => { | ||
| return <div>OnBoarding</div>; | ||
| }; | ||
|
|
||
| export default OnBoarding; |
| 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; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이건 어떤 역할을 하나요?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "lucide" 아이콘 라이브러리를 사용하고, "@ncdai"라는 스코프를 가진 컴포넌트를 특정 URL에서 가져오도록 설정하는 내용이라고 하네요! |
||
| } | ||
| 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]', | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,7 @@ | |
| "outDir": "dist", | ||
| "baseUrl": ".", | ||
| "paths": { | ||
| "@/*": ["./src/*"], | ||
| "@lib/*": ["./src/lib/*"] | ||
| "@/*": ["./src/*"] | ||
| }, | ||
|
Comment on lines
+9
to
10
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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/**' -SLength of output: 185 @lib 별칭 제거 후 경로 일관성 확보 packages/design-system/components.json (15행)에 🤖 Prompt for AI Agents |
||
| "jsx": "react-jsx" | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -161,6 +161,11 @@ | |||||||||||||||||||||
| @theme { | ||||||||||||||||||||||
| --color-*: initial; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| /* default */ | ||||||||||||||||||||||
| --color-white: #ffffff; | ||||||||||||||||||||||
| --color-black: #000000; | ||||||||||||||||||||||
| --color-transparent: transparent; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
Comment on lines
+164
to
+168
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Biome 파서 오류로 CI 깨짐: @theme 블록 안의 커스텀 프로퍼티 선언을 :root로 감싸주세요. Biome(2.1.2)가 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
Suggested change
🧰 Tools🪛 Biome (2.1.2)[error] 165-165: expected Remove --color-white (parse) [error] 165-165: Unexpected value or character. Expected one of: (parse) [error] 165-165: expected Remove ; (parse) [error] 166-166: expected 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 Remove --color-transparent (parse) [error] 167-167: expected Remove ; (parse) [error] 167-167: Unexpected unknown pseudo-class transparent See MDN web docs for more details. (lint/correctness/noUnknownPseudoClass) 🤖 Prompt for AI Agents |
||||||||||||||||||||||
| /* Main Color */ | ||||||||||||||||||||||
| --color-main0: #f9fffb; | ||||||||||||||||||||||
| --color-main100: #c9f2e1; | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

There was a problem hiding this comment.
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:
💡 Result:
Short answer
Relevant docs
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 지원 확인 및 형식 수정registries는 맵이 아니라 레지스트리 객체 배열이어야 하며, 각 객체에 필수로name과baseUrl을 지정해야 합니다.registry add/init/build및-r <registry-name>플래그)을 지원하는지 검증🤖 Prompt for AI Agents