feat: add modals

This commit is contained in:
Sylvia Crowe 2024-05-16 13:11:02 -07:00
parent c82bc48aab
commit cddaff4f7e
5 changed files with 180 additions and 7 deletions

View File

@ -0,0 +1,55 @@
.modal-container {
position: absolute;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 100;
background-color: rgba(21, 23, 21, 0.7);
.modal {
display: flex;
flex-direction: column;
border-radius: 10px;
padding: 0;
width: 450px;
max-height: 80vh;
margin-top: 25vh;
margin-left: auto;
margin-right: auto;
background: var(--modal-bg-color);
border: 1px solid var(--app-border-color);
.modal-header {
display: flex;
flex-direction: column;
padding: 20px 20px 10px;
border-bottom: 1px solid var(--modal-header-bottom-border-color);
.modal-title {
margin: 0 0 5px;
color: var(--app-text-primary-color);
font-size: var(--title-font-size);
}
p {
margin: 0;
font-size: 0.8rem;
color: var(--app-text-secondary-color);
}
}
.modal-content {
padding: 20px;
overflow: auto;
}
.modal-footer {
display: flex;
flex-direction: row;
justify-content: flex-end;
padding: 15px 20px;
gap: 20px;
}
}
}

View File

@ -0,0 +1,80 @@
import React from "react";
import { Button } from "@/element/button";
import "./modal.less";
interface ModalProps {
id?: string;
children: React.ReactNode;
onClickOut: () => void;
}
function Modal({ children, onClickOut, id = "modal", ...otherProps }: ModalProps) {
const handleOutsideClick = (e: React.SyntheticEvent<HTMLDivElement>) => {
if (typeof onClickOut === "function" && (e.target as Element).className === "modal-container") {
onClickOut();
}
};
return (
<div className="modal-container" onClick={handleOutsideClick}>
<dialog {...otherProps} id={id} className="modal">
{children}
</dialog>
</div>
);
}
interface ModalContentProps {
children: React.ReactNode;
}
function ModalContent({ children }: ModalContentProps) {
return <div className="modal-content">{children}</div>;
}
interface ModalHeaderProps {
title: React.ReactNode;
description?: string;
}
function ModalHeader({ title, description }: ModalHeaderProps) {
return (
<header className="modal-header">
{typeof title === "string" ? <h3 className="modal-title">{title}</h3> : title}
{description && <p>{description}</p>}
</header>
);
}
interface ModalFooterProps {
children: React.ReactNode;
}
function ModalFooter({ children }: ModalFooterProps) {
return <footer className="modal-footer">{children}</footer>;
}
interface WaveModalProps {
title: string;
description?: string;
id?: string;
onSubmit: () => void;
onCancel: () => void;
buttonLabel?: string;
children: React.ReactNode;
}
function WaveModal({ title, description, onSubmit, onCancel, buttonLabel = "Ok", children }: WaveModalProps) {
return (
<Modal id="text-box-modal" onClickOut={onCancel}>
<ModalHeader title={title} description={description} />
<ModalContent>{children}</ModalContent>
<ModalFooter>
<Button onClick={onSubmit}>{buttonLabel}</Button>
</ModalFooter>
</Modal>
);
}
export { WaveModal };

View File

@ -11,7 +11,6 @@
margin: 0; margin: 0;
padding: 0; padding: 0;
resize: none; resize: none;
max-height: 40%;
height: auto; height: auto;
background-color: var(--panel-bg-color); background-color: var(--panel-bg-color);
color: var(--main-text-color); color: var(--main-text-color);

View File

@ -1,6 +1,8 @@
import * as React from "react"; import * as React from "react";
import * as Plot from "@observablehq/plot"; import * as Plot from "@observablehq/plot";
import * as d3 from "d3"; import * as d3 from "d3";
import { Button } from "@/element/button";
import { WaveModal } from "@/element/modal";
import "./plotview.less"; import "./plotview.less";
@ -29,6 +31,9 @@ function evalAsync(Plot: any, d3: any, funcText: string): Promise<unknown> {
function PlotView() { function PlotView() {
const containerRef = React.useRef<HTMLInputElement>(); const containerRef = React.useRef<HTMLInputElement>();
const [plotDef, setPlotDef] = React.useState<string>(); const [plotDef, setPlotDef] = React.useState<string>();
const [tempDef, setTempDef] = React.useState<string>();
const [savedDef, setSavedDef] = React.useState<string>();
const [modalUp, setModalUp] = React.useState(false);
/* /*
const [data, setData] = React.useState(); const [data, setData] = React.useState();
@ -94,13 +99,23 @@ function PlotView() {
return ( return (
<div className="plot-view"> <div className="plot-view">
<Button onClick={() => setModalUp(true)}>Edit</Button>
<div className="plot-window" ref={containerRef} /> <div className="plot-window" ref={containerRef} />
<textarea {modalUp && (
className="plot-config" <WaveModal
rows={5} title="Plot Definition"
onChange={(e) => setPlotDef(e.target.value)} onCancel={() => setModalUp(false)}
spellCheck={false} onSubmit={() => setModalUp(false)}
/> >
<textarea
className="plot-config"
rows={5}
onChange={(e) => setPlotDef(e.target.value)}
spellCheck={false}
defaultValue={plotDef}
/>
</WaveModal>
)}
</div> </div>
); );
} }

View File

@ -3,6 +3,7 @@
:root { :root {
--main-text-color: #f7f7f7; --main-text-color: #f7f7f7;
--title-font-size: 18px;
--secondary-text-color: rgb(195, 200, 194); --secondary-text-color: rgb(195, 200, 194);
--main-bg-color: #000000; --main-bg-color: #000000;
--border-color: #333333; --border-color: #333333;
@ -16,4 +17,27 @@
--error-color: rgb(229, 77, 46); --error-color: rgb(229, 77, 46);
--warning-color: rgb(224, 185, 86); --warning-color: rgb(224, 185, 86);
--success-color: rgb(78, 154, 6); --success-color: rgb(78, 154, 6);
/* global colors */
--app-bg-color: black;
--app-accent-color: rgb(88, 193, 66);
--app-accent-bg-color: rgba(88, 193, 66, 0.25);
--app-accent-bg-darker-color: rgba(88, 193, 66, 0.5);
--app-text-color: rgb(211, 215, 207);
--app-text-primary-color: rgb(255, 255, 255);
--app-text-secondary-color: rgb(195, 200, 194);
--app-text-disabled-color: rgb(173, 173, 173);
--app-text-bg-color: rgb(23, 23, 23);
--app-text-bg-disabled-color: rgb(51, 51, 51);
--app-border-color: rgb(51, 51, 51);
--app-maincontent-bg-color: rgb(51, 51, 51);
--app-panel-bg-color: rgba(21, 23, 21, 1);
--app-panel-bg-color-dev: rgb(21, 23, 48);
--app-icon-color: rgb(139, 145, 138);
--app-icon-hover-color: rgb(255, 255, 255);
--app-selected-mask-color: rgba(255, 255, 255, 0.06);
/* modals colors */
--modal-bg-color: var(--app-bg-color);
--modal-header-bottom-border-color: rgba(241, 246, 243, 0.15);
} }