File tree Expand file tree Collapse file tree 5 files changed +222
-0
lines changed
src/common/component/JobDropDown Expand file tree Collapse file tree 5 files changed +222
-0
lines changed Original file line number Diff line number Diff line change 1+ import { style } from '@vanilla-extract/css' ;
2+ import { recipe } from '@vanilla-extract/recipes' ;
3+
4+ import { fonts , colors } from '@/style/token' ;
5+
6+ export const jobContainer = style ( {
7+ display : 'flex' ,
8+ justifyContent : 'space-between' ,
9+ alignItems : 'center' ,
10+ width : '52.2rem' ,
11+ height : '5rem' ,
12+ padding : '1.4rem 2rem' ,
13+ border : `1px solid ${ colors . grey4 } ` ,
14+ borderRadius : '8px' ,
15+ backgroundColor : colors . grey4 ,
16+ cursor : 'pointer' ,
17+ } ) ;
18+
19+ export const jobText = recipe ( {
20+ base : {
21+ ...fonts . body03 ,
22+ textAlign : 'center' ,
23+ } ,
24+ variants : {
25+ state : {
26+ default : {
27+ color : colors . grey10 ,
28+ } ,
29+ clicked : {
30+ color : colors . grey6 ,
31+ } ,
32+ } ,
33+ } ,
34+ defaultVariants : {
35+ state : 'default' ,
36+ } ,
37+ } ) ;
38+
39+ export const dropdownIcon = recipe ( {
40+ base : {
41+ width : '2rem' ,
42+ height : '2rem' ,
43+ } ,
44+ variants : {
45+ state : {
46+ default : {
47+ color : colors . grey10 ,
48+ transform : 'rotate(0deg)' ,
49+ } ,
50+ clicked : {
51+ color : colors . grey6 ,
52+ transform : 'rotate(180deg)' ,
53+ } ,
54+ } ,
55+ } ,
56+ defaultVariants : {
57+ state : 'default' ,
58+ } ,
59+ } ) ;
60+
61+ export const textContainer = style ( {
62+ width : '52.2rem' ,
63+ height : '5rem' ,
64+ padding : '1.4rem 2rem' ,
65+ marginTop : '1.6rem' ,
66+ backgroundColor : colors . grey4 ,
67+ border : 'none' ,
68+ borderRadius : '8px' ,
69+ color : colors . grey10 ,
70+ ...fonts . body03 ,
71+
72+ selectors : {
73+ '&::placeholder' : {
74+ color : colors . grey6 ,
75+ } ,
76+ '&:focus' : {
77+ outline : 'none' ,
78+ } ,
79+ } ,
80+ } ) ;
Original file line number Diff line number Diff line change 1+ import { useState } from 'react' ;
2+
3+ import { IcDropdown } from '@/assets/svg' ;
4+ import JobList from '@/common/component/JobDropDown/JobList' ;
5+ import {
6+ jobContainer ,
7+ jobText ,
8+ dropdownIcon ,
9+ textContainer ,
10+ } from '@/common/component/JobDropDown/JobDropDown.css' ;
11+ import { PLACE_HOLDER , JOB_LIST } from '@/common/component/JobDropDown/constants/job' ;
12+ import type { JobType , JobValue } from '@/common/component/JobDropDown/constants/job' ;
13+
14+ const JobDropDown = ( ) => {
15+ const [ isOpen , setIsOpen ] = useState ( false ) ;
16+ const [ selectedJob , setSelectedJob ] = useState < JobValue > ( PLACE_HOLDER ) ;
17+
18+ const isPlaceHolder = typeof selectedJob === 'string' ;
19+
20+ const toggleDropdown = ( ) => {
21+ setIsOpen ( ( prev ) => ! prev ) ;
22+ } ;
23+
24+ const handleJob = ( job : JobType ) => {
25+ setSelectedJob ( job ) ;
26+ setIsOpen ( false ) ;
27+ } ;
28+
29+ const state = isOpen ? 'clicked' : 'default' ;
30+ const isTextOpen = ! isPlaceHolder && selectedJob . id === JOB_LIST [ JOB_LIST . length - 1 ] . id ;
31+
32+ return (
33+ < >
34+ < button className = { jobContainer } onClick = { toggleDropdown } >
35+ < span className = { jobText ( { state } ) } > { isPlaceHolder ? selectedJob : selectedJob . job } </ span >
36+ < IcDropdown className = { dropdownIcon ( { state } ) } />
37+ </ button >
38+
39+ { isOpen && < JobList jobList = { JOB_LIST } selectedJob = { selectedJob } onSelect = { handleJob } /> }
40+ { isTextOpen && < input placeholder = "정보를 입력해주세요" className = { textContainer } /> }
41+ </ >
42+ ) ;
43+ } ;
44+
45+ export default JobDropDown ;
Original file line number Diff line number Diff line change 1+ import { style } from '@vanilla-extract/css' ;
2+ import { recipe } from '@vanilla-extract/recipes' ;
3+
4+ import { colors , fonts , zIndex } from '@/style/token' ;
5+
6+ export const listContainer = style ( {
7+ display : 'flex' ,
8+ flexDirection : 'column' ,
9+ width : '52.2rem' ,
10+ height : '24rem' ,
11+ backgroundColor : colors . grey2 ,
12+ borderRadius : '8px' ,
13+ overflowY : 'auto' ,
14+ overflowX : 'hidden' ,
15+ cursor : 'pointer' ,
16+ zIndex : zIndex . dropdown ,
17+ } ) ;
18+
19+ export const listItem = style ( {
20+ display : 'flex' ,
21+ justifyContent : 'flex-start' ,
22+ alignItems : 'center' ,
23+ height : '5rem' ,
24+ padding : '1.4rem 2rem' ,
25+ borderBottom : `solid 1px ${ colors . grey3 } ` ,
26+
27+ selectors : {
28+ '&:last-child' : {
29+ borderBottom : 'none' ,
30+ } ,
31+ '&:hover' : {
32+ backgroundColor : colors . grey1 ,
33+ } ,
34+ } ,
35+ } ) ;
36+
37+ export const listText = recipe ( {
38+ variants : {
39+ state : {
40+ selected : {
41+ ...fonts . body03 ,
42+ color : colors . grey10 ,
43+ } ,
44+ default : {
45+ ...fonts . body01 ,
46+ color : colors . grey6 ,
47+ } ,
48+ } ,
49+ } ,
50+ defaultVariants : {
51+ state : 'default' ,
52+ } ,
53+ } ) ;
Original file line number Diff line number Diff line change 1+ import { listContainer , listItem , listText } from '@/common/component/JobDropDown/JobList.css' ;
2+ import type { JobType , JobValue } from '@/common/component/JobDropDown/constants/job' ;
3+
4+ type JobProps = {
5+ jobList : JobType [ ] ;
6+ selectedJob : JobValue ;
7+ onSelect : ( type : JobType ) => void ;
8+ } ;
9+
10+ const JobList = ( { jobList, selectedJob, onSelect } : JobProps ) => {
11+ return (
12+ < div className = { listContainer } >
13+ { jobList . map ( ( job : JobType ) => {
14+ const state = selectedJob === job ? 'selected' : 'default' ;
15+
16+ return (
17+ < button key = { job . id } className = { listItem } onClick = { ( ) => onSelect ( job ) } >
18+ < span className = { listText ( { state } ) } > { job . job } </ span >
19+ </ button >
20+ ) ;
21+ } ) }
22+ </ div >
23+ ) ;
24+ } ;
25+
26+ export default JobList ;
Original file line number Diff line number Diff line change 1+ export const JOB_LIST = [
2+ { id : 1 , job : '의사' } ,
3+ { id : 2 , job : '변호사' } ,
4+ { id : 3 , job : '개발자' } ,
5+ { id : 4 , job : '학생' } ,
6+ { id : 5 , job : '백수' } ,
7+ { id : 6 , job : '사업가' } ,
8+ { id : 7 , job : '운동선수' } ,
9+ { id : 8 , job : '기타 (직접 작성)' } ,
10+ ] ;
11+
12+ export const PLACE_HOLDER = '직업을 선택하세요' as const ;
13+
14+ export type JobType = {
15+ id : number ;
16+ job : string ;
17+ } ;
18+ export type JobValue = JobType | typeof PLACE_HOLDER ;
You can’t perform that action at this time.
0 commit comments