Modal.js
import { useState } from 'react';
import styled from 'styled-components';
export const ModalContainer = styled.div`
// TODO : Modal을 구현하는데 전체적으로 필요한 CSS를 구현합니다.
display: flex;
justify-content: center;
align-items: center;
height: 100%;
position: relative;
`;
export const ModalBackdrop = styled.div`
// TODO : Modal이 떴을 때의 배경을 깔아주는 CSS를 구현합니다.
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
height: 100%;
width: 100%;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
position: fixed;
z-index: 1;
`;
export const ModalBtn = styled.button`
background-color: #4000c7;
text-decoration: none;
border: none;
padding: 20px;
color: white;
border-radius: 30px;
cursor: grab;
`;
export const CloseBtn = styled.button`
background-color: transparent;
border-color: transparent;
`;
export const ModalView = styled.div.attrs(props => ({
role: 'dialog'
}))`
// TODO : Modal창 CSS를 구현합니다.
display: flex;
justify-content: center;
align-items: center;
background-color: white;
border-radius: 1rem;
flex-direction: column;
position: relative;
width: 200px;
height: 100px;
color: purple;
`;
export const Modal = () => {
const [isOpen, setIsOpen] = useState(false);
const openModalHandler = () => {
setIsOpen(!(isOpen))
};
return (
<>
<ModalContainer>
<ModalBtn onClick={openModalHandler}
>
{isOpen ? 'Opened!' : 'Open Modal'}
{}
</ModalBtn>
{isOpen ? <ModalBackdrop onClick={openModalHandler}>
<ModalView>
<CloseBtn onClick={openModalHandler}>X</CloseBtn>
<br></br>
<div>HELLO CODESTATES!</div>
<br></br>
</ModalView>
</ModalBackdrop>: null}
{}
</ModalContainer>
</>
);
};
Toggle.js
import { useState } from 'react';
import styled from 'styled-components';
const ToggleContainer = styled.div`
position: relative;
margin-top: 8rem;
left: 48.5%;
cursor: pointer;
> .toggle-container {
width: 50px;
height: 24px;
border-radius: 30px;
background-color: #8b8b8b;
// TODO : .toggle--checked 클래스가 활성화 되었을 경우의 CSS를 구현합니다.
background-position: right;
background: linear-gradient(to left, #8b8b8b 50%, purple 50%) right;
background-size: 200%;
transition: 0.5s;
&.toggle--checked {
background-position: left;
background: linear-gradient(to right, purple 50%, #8b8b8b 50%) left;
background-size: 200%;
transition: 0.5s;
}
}
> .toggle-circle {
position: absolute;
top: 1px;
left: 1px;
width: 22px;
height: 22px;
border-radius: 50%;
background-color: #ffffff;
right: 27px;
transition: 0.5s;
// TODO : .toggle--checked 클래스가 활성화 되었을 경우의 CSS를 구현합니다.
&.toggle--checked {
left: 27px;
transition: 0.5s;
}
}
`
const Desc = styled.div`
// TODO : 설명 부분의 CSS를 구현합니다.
text-align: center;
`;
export const Toggle = () => {
const [isOn, setisOn] = useState(false);
const toggleHandler = () => {
setisOn(!(isOn))
};
return (
<>
<ToggleContainer onClick={toggleHandler}
>
{}
{}
<div Class={`toggle-container ${isOn ? "toggle--checked" : null}`}/>
<div Class={`toggle-circle ${isOn ? "toggle--checked" : null}`}/>
</ToggleContainer>
{}
<Desc>
{isOn ? 'Toggle Switch ON' : 'Toggle Switch OFF'}
</Desc>
{}
</>
);
};
Tab.js
import { useState } from 'react';
import styled from 'styled-components';
const TabMenu = styled.ul`
background-color: #dcdcdc;
color: rgba(73, 73, 73, 0.5);
font-weight: bold;
display: flex;
flex-direction: row;
justify-items: center;
align-items: center;
list-style: none;
margin-bottom: 7rem;
.submenu {
${'' }
padding-top: 1rem;
padding-bottom: 1rem;
padding-left: 1rem;
padding-right: 10rem;
}
.focused {
${'' }
color: white;
background-color: purple;
}
& div.desc {
text-align: center;
}
`;
const Desc = styled.div`
text-align: center;
`;
export const Tab = () => {
const menuArr = [
{ name: 'Tab1', content: 'Tab menu ONE' },
{ name: 'Tab2', content: 'Tab menu TWO' },
{ name: 'Tab3', content: 'Tab menu THREE' },
];
const [curtab, setcurtab] = useState(0)
const selectMenuHandler = (index) => {
setcurtab(index)
};
return (
<>
<div>
<TabMenu>
{}
{}
{menuArr.map((menu, index) => {
return (
<li
key={index}
className={index === curtab ? 'submenu focused' : 'submenu'}
onClick={() => selectMenuHandler(index)}>{menu.name}
</li>
)
})}
</TabMenu>
<Desc>
{}
<p>{menuArr[curtab].content}</p>
</Desc>
</div>
</>
);
};
Tag.js
import { useState } from 'react';
import styled from 'styled-components';
export const TagsInput = styled.div`
margin: 8rem auto;
display: flex;
align-items: flex-start;
flex-wrap: wrap;
min-height: 48px;
width: 480px;
padding: 0 8px;
border: 1px solid rgb(214, 216, 218);
border-radius: 6px;
> ul {
display: flex;
flex-wrap: wrap;
padding: 0;
margin: 8px 0 0 0;
> .tag {
width: auto;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
padding: 0 8px;
font-size: 14px;
list-style: none;
border-radius: 6px;
margin: 0 8px 8px 0;
background: #4000c7;
> .tag-close-icon {
display: block;
width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
font-size: 14px;
margin-left: 8px;
color: #4000c7;
border-radius: 50%;
background: #fff;
cursor: pointer;
}
}
}
> input {
flex: 1;
border: none;
height: 46px;
font-size: 14px;
padding: 4px 0 0 0;
:focus {
outline: transparent;
}
}
&:focus-within {
border: 1px solid #4000c7;
}
`;
export const Tag = () => {
const initialTags = ['CodeStates', 'kimcoding'];
const [tags, setTags] = useState(initialTags);
const removeTags = (indexToRemove) => {
setTags(tags.filter((el) => {
return el !== tags[indexToRemove]
}))
};
const addTags = (event) => {
let value = event.target.value.trim()
if (event.key === 'Enter' && !(tags.includes(value)) && value !== '') {
setTags([...tags, value])
value=''
}
else if (event.key === 'Enter' && value ==='') {
value=''
}
}
return (
<>
<TagsInput>
<ul id='tags'>
{tags.map((tag, index) => (
<li key={index} className='tag'>
<span className='tag-title'>{tag}</span>
<span className='tag-close-icon' onClick={() => removeTags(index)}>X
{}
</span>
</li>
))}
</ul>
<input
className='tag-input'
type='text'
onKeyUp={(el)=> el.key === 'Enter' ? addTags(el) : null}
placeholder='Press enter to add tags'
/>
</TagsInput>
</>
);
};