canvas option팝업 추가

This commit is contained in:
김창수 2024-09-09 17:05:06 +09:00
parent 8a45143d50
commit 1bba9bde8a
19 changed files with 418 additions and 69 deletions

View File

@ -0,0 +1,3 @@
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 6.5L3.5 4L1 1.5" stroke="#898989" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 166 B

View File

@ -0,0 +1,3 @@
<svg width="5" height="8" viewBox="0 0 5 8" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 6.5L3.5 4L1 1.5" stroke="#101010" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 166 B

View File

@ -0,0 +1,3 @@
<svg width="11" height="9" viewBox="0 0 11 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 3.18182L4.5 7L10 1" stroke="#101010" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 171 B

View File

@ -0,0 +1,3 @@
<svg width="11" height="9" viewBox="0 0 11 9" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 3.18182L4.5 7L10 1" stroke="#898989" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 171 B

View File

@ -0,0 +1,10 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_55_91)">
<path d="M8.99915 9L1 1M1.00085 9L9 1" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_55_91">
<rect width="10" height="10" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 361 B

View File

@ -1,18 +1,24 @@
'use client'
import CanvasLayout from '@/components/canvas/CanvasLayout' import CanvasLayout from '@/components/canvas/CanvasLayout'
import CanvasMenu from '@/components/canvas/CanvasMenu' import CanvasMenu from '@/components/canvas/CanvasMenu'
import SettingModal01 from '@/components/canvas/modal/settoing01/SettingModal01'
import Header from '@/components/header/Header' import Header from '@/components/header/Header'
import '@/styles/style.scss' import '@/styles/style.scss'
import { useState } from 'react'
export default function CanvasPage() { export default function CanvasPage() {
const [modalOpen, setModalOpen] = useState('option');
return( return(
<div className="wrap"> <div className="wrap">
<Header/> <Header/>
<div className="content"> <div className="content">
<div className="canvas-wrap"> <div className="canvas-wrap">
<CanvasMenu/> <CanvasMenu modalOpen={modalOpen} setModalOpen={setModalOpen}/>
<div className="canvas-content"> <div className="canvas-content">
<CanvasLayout/> <CanvasLayout/>
</div> </div>
{modalOpen === 'option' && <SettingModal01 modalOpen={modalOpen} setModalOpen={setModalOpen}/>}
</div> </div>
</div> </div>
</div> </div>

View File

@ -15,6 +15,8 @@ export default function InputWrapPage (){
<div className="form-btn"> <div className="form-btn">
<button className="btn-frame deepgray">屋根面の割り当て</button> <button className="btn-frame deepgray">屋根面の割り当て</button>
<button className="btn-frame gray">屋根面の割り当て</button> <button className="btn-frame gray">屋根面の割り当て</button>
<button className="btn-frame modal">屋根面の割り当て</button>
<button className="btn-frame modal act">屋根面の割り当て</button>
<button className="btn-frame small dark">移動</button> <button className="btn-frame small dark">移動</button>
</div> </div>
</div> </div>
@ -47,6 +49,33 @@ export default function InputWrapPage (){
<ColorPicker/> <ColorPicker/>
</div> </div>
</div> </div>
<div className="input-wrap">
<h1>Check-Btn</h1>
<div className="form-Check-btn">
<button className="check-btn">
<span className="check-area"></span>
<span className="title-area">ü割り当て表示</span>
</button>
<button className="check-btn act">
<span className="check-area"></span>
<span className="title-area">ü割り当て表示</span>
</button>
</div>
</div>
<div className="input-wrap">
<h1>Arrow-Btn</h1>
<div className="form-Arrow-btn">
<button className="arr-btn">
<span>文字フォントの変更</span>
</button>
<button className="arr-btn act">
<span>文字フォントの変更</span>
</button>
<button className="arr-btn act">
<span>文字フォントの変更</span>
</button>
</div>
</div>
</div> </div>
) )
} }

View File

@ -1,5 +1,4 @@
import RecoilRootWrapper from './RecoilWrapper' import RecoilRootWrapper from './RecoilWrapper'
import QModal from '@/components/common/modal/QModal'
import '@/styles/common.scss' import '@/styles/common.scss'
// import '@/styles/style.scss' // import '@/styles/style.scss'
@ -14,7 +13,6 @@ export default function RootLayout({ children }) {
<body> <body>
<RecoilRootWrapper> <RecoilRootWrapper>
{children} {children}
<QModal />
</RecoilRootWrapper> </RecoilRootWrapper>
</body> </body>
</html> </html>

View File

@ -1,42 +0,0 @@
'use client'
import { useRecoilState } from 'recoil'
import { modalContent, modalState } from '@/store/modalAtom'
export default function ModalPage() {
const [open, setOpen] = useRecoilState(modalState)
const [contents, setContent] = useRecoilState(modalContent)
const ipsum = (
<>
<p>title</p>
<p>
저작자·발명가·과학기술자와 예술가의 권리는 법률로써 보호한다. 헌법은 1988 2 25일부터 시행한다. 다만, 헌법을 시행하기 위하여 필요한
법률의 제정·개정과 헌법에 의한 대통령 국회의원의 선거 기타 헌법시행에 관한 준비는 헌법시행 전에 있다.
</p>
<p>
국가는 주택개발정책등을 통하여 모든 국민이 쾌적한 주거생활을 있도록 노력하여야 한다. 통신·방송의 시설기준과 신문의 기능을 보장하기
위하여 필요한 사항은 법률로 정한다.
</p>
<p>
국회에서 의결된 법률안은 정부에 이송되어 15 이내에 대통령이 공포한다. 선거에 관한 경비는 법률이 정하는 경우를 제외하고는 정당 또는
후보자에게 부담시킬 없다.
</p>
</>
)
return (
<>
<div>
<button
onClick={() => {
setContent(ipsum)
setOpen(true)
}}
>
OPEN MODAL
</button>
</div>
</>
)
}

View File

@ -1,3 +1,4 @@
export default function CanvasFrame () { export default function CanvasFrame () {
return( return(
<div className="canvas-frame"> <div className="canvas-frame">

View File

@ -3,7 +3,7 @@ import { useState } from "react";
import Qselect from "../common/select/Qselect"; import Qselect from "../common/select/Qselect";
import MenuDepth01 from "./MenuDepth01"; import MenuDepth01 from "./MenuDepth01";
export default function CanvasMenu() { export default function CanvasMenu({setModalOpen}) {
const [menuNumber, setMenuNumber] = useState(null); const [menuNumber, setMenuNumber] = useState(null);
const SelectOption = [ const SelectOption = [
{name: '瓦53A',}, {name: '瓦53A'} {name: '瓦53A',}, {name: '瓦53A'}
@ -45,7 +45,7 @@ export default function CanvasMenu() {
<button className="btn01 "></button> <button className="btn01 "></button>
<button className="btn02 active"></button> <button className="btn02 active"></button>
<button className="btn03"></button> <button className="btn03"></button>
<button className="btn04"></button> <button className="btn04" onClick={() => setModalOpen('option')}></button>
<button className="btn05"></button> <button className="btn05"></button>
<button className="btn06"></button> <button className="btn06"></button>
</div> </div>

View File

@ -0,0 +1,49 @@
import { HandleBtnClick } from "./SettingModal01"
const buttonList01 = [
{id: 1, name: '割り当て表示'},
{id: 2, name: '実寸表示'},
{id: 3, name: '図面表示'},
{id: 4, name: '寸法表示なし'},
{id: 5, name: 'グリッド表示'},
{id: 6, name: '架台表示'},
{id: 7, name: '文字表示'},
{id: 8, name: '座標表示'},
{id: 9, name: '流れ方向表示'},
{id: 10, name: '図面切替表示'},
{id: 11, name: 'ü廊下寸法表示'},
]
const buttonList02 = [
{id: 1, name: 'ボーダーのみ'},
{id: 2, name: 'ラインハッチ'},
{id: 3, name: 'All painted'},
]
export default function FirstOption (){
return(
<>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title light">図面に表示する項目をクリックすると適用されます</h3>
<div className="flex-check-box for2">
{buttonList01.map((item)=>(
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
<span className="check-area"></span>
<span className="title-area">{item.name}</span>
</button>
))}
</div>
</div>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">画面表示</h3>
<div className="flex-check-box for-line">
{buttonList02.map((item)=>(
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
<span className="check-area"></span>
<span className="title-area">{item.name}</span>
</button>
))}
</div>
</div>
</>
)
}

View File

@ -0,0 +1,50 @@
import { HandleBtnClick } from "./SettingModal01"
const buttonList01 = [
{id: 1, name: '文字フォントの変更'},
{id: 2, name: 'フロー方向フォントの変更'},
{id: 3, name: '寸法フォントの変更'},
{id: 4, name: '回路番号フォントの変更'},
]
const buttonList02 = [
{id: 1, name: '極小'},
{id: 2, name: '牛'},
{id: 3, name: '中'},
{id: 4, name: 'ティーン'},
]
export default function SecondOption (){
return(
<>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">フォントとサイズの変更</h3>
<div className="flex-check-box for2">
{buttonList01.map((item)=>(
<button className="arr-btn">
<span>{item.name}</span>
</button>
))}
</div>
</div>
<div className="modal-check-btn-wrap">
<h3 className="check-wrap-title">吸着範囲の設定</h3>
<div className="flex-check-box for-line">
{buttonList02.map((item)=>(
<button key={item.id} className="check-btn" onClick={(e) => HandleBtnClick(e)}>
<span className="check-area"></span>
<span className="title-area">{item.name}</span>
</button>
))}
</div>
<div className="flex-check-box for-line">
<button className="arr-btn">
<span>寸法線の設定</span>
</button>
<button className="arr-btn">
<span>図面サイズの設定</span>
</button>
</div>
</div>
</>
)
}

View File

@ -0,0 +1,56 @@
'use client'
import { useState } from "react";
import FirstOption from "./FirstOption";
import SecondOption from "./SecondOption";
import WithDraggable from "@/components/common/draggable/withDraggable";
export const HandleBtnClick = (e) => {
const button = e.target.closest('button');
if(!button.classList.contains('act')){
button.classList.add('act');
}else{
button.classList.remove('act');
}
}
export default function SettingModal01 ({modalOpen, setModalOpen}){
const [buttonAct, setButtonAct] = useState(1);
const [close, setClose] = useState(false)
const HandleClickClose = () => {
setClose(true)
setTimeout(() => {
setModalOpen('');
setClose(false);
}, 180)
}
return(
<WithDraggable isShow={true}>
<div className={`modal-pop-wrap sm ${modalOpen === 'option' && close === false ? 'mount' : ''}${close ? 'unmount' : ''} `}>
<div className="modal-head">
<h1 className="title">Canvas設定</h1>
<button className="modal-close" onClick={HandleClickClose}>닫기</button>
</div>
<div className="modal-body">
<div className="modal-btn-wrap">
<button
className={`btn-frame modal ${buttonAct === 1 ? 'act' : ''}`}
onClick={() => setButtonAct(1)}
>
ディスプレイ設定
</button>
<button
className={`btn-frame modal ${buttonAct === 2 ? 'act' : ''}`}
onClick={() => setButtonAct(2)}
>
フォントと図面サイズの設定
</button>
</div>
{buttonAct === 1 && <FirstOption/>}
{buttonAct === 2 && <SecondOption/>}
</div>
</div>
</WithDraggable>
)
}

View File

@ -1,20 +0,0 @@
'use client'
import { useRecoilState, useRecoilValue } from 'recoil'
import { Modal } from 'react-responsive-modal'
import { modalContent, modalState } from '@/store/modalAtom'
import 'react-responsive-modal/styles.css'
export default function QModal() {
const [open, setOpen] = useRecoilState(modalState)
const children = useRecoilValue(modalContent)
return (
<Modal open={open} onClose={() => setOpen(false)} center>
{children}
</Modal>
)
}

View File

@ -1,6 +1,7 @@
.input-content{ .input-content{
max-width: 1600px; max-width: 1600px;
margin: 0 auto; margin: 0 auto;
padding-bottom: 100px;
.input-wrap{ .input-wrap{
padding: 50px 50px 0; padding: 50px 50px 0;
h1{ h1{
@ -22,5 +23,13 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
} }
.form-Arrow-btn,
.form-Check-btn{
padding: 10px;
background-color: #272727;
> button{
margin-bottom: 10px;
}
}
} }
} }

91
src/styles/_modal.scss Normal file
View File

@ -0,0 +1,91 @@
@keyframes mountpop{
from{opacity: 0; scale: 0.95;}
to{opacity: 1; scale: 1;}
}
@keyframes unmountpop{
from{opacity: 1; scale: 1;}
to{opacity: 0; scale: 0.95;}
}
.modal-pop-wrap{
position: fixed;
top: 200px;
right: 100px;
width: 100%;
min-width: 380px;
max-width: fit-content;
height: -webkit-fit-content;
height: -moz-fit-content;
height: fit-content;
border: 1px solid #000;
border-radius: 4px;
background-color: #272727;
z-index: 9999999;
&.sm{
max-width: 450px;
}
&.mount{
animation: mountpop .17s ease-in-out forwards;
}
&.unmount{
animation: unmountpop .17s ease-in-out forwards;
}
}
.modal-head{
display: flex;
align-items: center;
padding: 10px 24px;
background-color: #000;
cursor: pointer;
h1.title{
font-size: 13px;
color: #fff;
font-weight: 700;
}
.modal-close{
margin-left: auto;
color: #fff;
text-indent: -999999999px;
width: 10px;
height: 10px;
background: url(../../public/static/images/canvas/modal_close.svg)no-repeat center;
}
}
.modal-body{
padding: 15px;
.modal-btn-wrap{
display: flex;
align-items: center;
gap: 5px;
button{
flex: 1;
}
}
.modal-check-btn-wrap{
margin-top: 15px;
.check-wrap-title{
font-size: 12px;
color: #fff;
font-weight: 600;
&.light{
font-weight: 400;
}
}
.flex-check-box{
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
&.for2{
button{
width: calc(50% - 5px);
}
}
&.for-line{
button{
flex: 1;
}
}
}
}
}

View File

@ -137,7 +137,7 @@ button{
border: 1px solid #000; border: 1px solid #000;
text-align: center; text-align: center;
font-family: 'Pretendard', sans-serif; font-family: 'Pretendard', sans-serif;
transition: color .12s ease-in-out; transition: all .17s ease-in-out;
cursor: pointer; cursor: pointer;
&.block{ &.block{
width: 100%; width: 100%;
@ -161,6 +161,27 @@ button{
background-color: #1C1C1C; background-color: #1C1C1C;
border: 1px solid #484848; border: 1px solid #484848;
} }
&.modal{
background-color: #272727;
border: 1px solid #484848;
color: #aaa;
&:hover{
background-color: #1083E3;
border: 1px solid #1083E3;
color: #fff;
font-weight: 500;
}
}
&.act{
background-color: #1083E3;
border: 1px solid #1083E3;
color: #fff;
font-weight: 500;
}
&.block{
display: block;
width: 100%;
}
} }
// select // select
@ -278,3 +299,81 @@ input[type=text]{
} }
} }
} }
// check-btn
.check-btn{
display: flex;
align-items: center;
height: 30px;
background-color: #3A3A3A;
border-radius: 3px;
transition: all .17s ease-in-out;
.check-area{
flex: none;
width: 30px;
height: 100%;
border-right: 1px solid #272727;
background: url(../../public/static/images/canvas/check-grey.svg)no-repeat center;
background-size: 11px 9px;
}
.title-area{
padding: 0 10px;
font-size: 12px;
color: #898989;
font-weight: 400;
}
&.block{
width: 100%;
}
&:hover,
&.act{
background-color: #fff;
.check-area{
border-right: 1px solid #101010;
background: url(../../public/static/images/canvas/check-black.svg)no-repeat center;
}
.title-area{
color: #101010;
font-weight: 600;
}
}
}
// arr-btn
.arr-btn{
display: block;
height: 30px;
border-radius: 3px;
background-color: #3A3A3A;
padding: 0 11px;
text-align: left;
transition: all .17s ease-in-out;
span{
position: relative;
font-size: 12px;
color: #898989;
font-weight: 400;
padding-right: 15px;
&:after{
content: '';
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
width: 5px;
height: 8px;
background: url(../../public/static/images/canvas/arr_btn_ico.svg)no-repeat center;
}
}
&:hover,
&.act{
background-color: #fff;
span{
color: #101010;
font-weight: 500;
&:after{
background: url(../../public/static/images/canvas/arr_btn_ico_black.svg)no-repeat center;
}
}
}
}

View File

@ -1,2 +1,3 @@
@import '_layout.scss'; @import '_layout.scss';
@import '_contents.scss'; @import '_contents.scss';
@import '_modal.scss';