mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
feat: add modals
This commit is contained in:
parent
c82bc48aab
commit
cddaff4f7e
55
frontend/app/element/modal.less
Normal file
55
frontend/app/element/modal.less
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
80
frontend/app/element/modal.tsx
Normal file
80
frontend/app/element/modal.tsx
Normal 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 };
|
@ -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);
|
||||||
|
@ -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} />
|
||||||
|
{modalUp && (
|
||||||
|
<WaveModal
|
||||||
|
title="Plot Definition"
|
||||||
|
onCancel={() => setModalUp(false)}
|
||||||
|
onSubmit={() => setModalUp(false)}
|
||||||
|
>
|
||||||
<textarea
|
<textarea
|
||||||
className="plot-config"
|
className="plot-config"
|
||||||
rows={5}
|
rows={5}
|
||||||
onChange={(e) => setPlotDef(e.target.value)}
|
onChange={(e) => setPlotDef(e.target.value)}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
|
defaultValue={plotDef}
|
||||||
/>
|
/>
|
||||||
|
</WaveModal>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user