diff options
Diffstat (limited to 'FrontEnd/src/views')
-rw-r--r-- | FrontEnd/src/views/common/button/Button.css | 1 | ||||
-rw-r--r-- | FrontEnd/src/views/common/dialog/Dialog.css | 11 | ||||
-rw-r--r-- | FrontEnd/src/views/common/dialog/Dialog.tsx | 27 | ||||
-rw-r--r-- | FrontEnd/src/views/common/dialog/OperationDialog.css | 29 | ||||
-rw-r--r-- | FrontEnd/src/views/common/dialog/OperationDialog.tsx | 32 | ||||
-rw-r--r-- | FrontEnd/src/views/common/input/InputGroup.css | 43 | ||||
-rw-r--r-- | FrontEnd/src/views/common/input/InputGroup.tsx | 44 | ||||
-rw-r--r-- | FrontEnd/src/views/common/theme.css | 2 |
8 files changed, 101 insertions, 88 deletions
diff --git a/FrontEnd/src/views/common/button/Button.css b/FrontEnd/src/views/common/button/Button.css index 12c6903e..fe619f9d 100644 --- a/FrontEnd/src/views/common/button/Button.css +++ b/FrontEnd/src/views/common/button/Button.css @@ -5,6 +5,7 @@ border-radius: 0.2em;
border: 1px solid;
cursor: pointer;
+ background-color: var(--cru-surface-color);
}
.cru-button:not(.outline) {
diff --git a/FrontEnd/src/views/common/dialog/Dialog.css b/FrontEnd/src/views/common/dialog/Dialog.css index 99e1a516..8f12614b 100644 --- a/FrontEnd/src/views/common/dialog/Dialog.css +++ b/FrontEnd/src/views/common/dialog/Dialog.css @@ -6,7 +6,6 @@ right: 0;
bottom: 0;
display: flex;
- padding: 2em;
overflow: auto;
}
@@ -14,8 +13,8 @@ position: absolute;
z-index: -1;
left: 0;
- top: 0;
right: 0;
+ top: 0;
bottom: 0;
background-color: var(--cru-surface-dim-color);
opacity: 0.8;
@@ -25,7 +24,7 @@ max-width: 100%;
min-width: 30vw;
- margin: auto;
+ margin: 2em auto;
border: var(--cru-key-container-color) 1px solid;
border-radius: 5px;
@@ -33,6 +32,12 @@ background-color: var(--cru-surface-color);
}
+@media (min-width: 576px) {
+ .cru-dialog-container {
+ max-width: 800px;
+ }
+}
+
.cru-dialog-bottom-area {
display: flex;
justify-content: flex-end;
diff --git a/FrontEnd/src/views/common/dialog/Dialog.tsx b/FrontEnd/src/views/common/dialog/Dialog.tsx index 31dd113b..9ce344dc 100644 --- a/FrontEnd/src/views/common/dialog/Dialog.tsx +++ b/FrontEnd/src/views/common/dialog/Dialog.tsx @@ -38,23 +38,18 @@ export default function Dialog({ timeout={300} classNames="cru-dialog" > - <div - className={classNames("cru-dialog-overlay", `cru-${color}`)} - onPointerDown={ - disableCloseOnClickOnOverlay - ? undefined - : () => { - onClose(); - } - } - > - <div className="cru-dialog-background" /> + <div className={classNames("cru-dialog-overlay", `cru-${color}`)}> <div - className="cru-dialog-container" - onPointerDown={(e) => e.stopPropagation()} - > - {children} - </div> + className="cru-dialog-background" + onClick={ + disableCloseOnClickOnOverlay + ? undefined + : () => { + onClose(); + } + } + /> + <div className="cru-dialog-container">{children}</div> </div> </CSSTransition>, portalElement, diff --git a/FrontEnd/src/views/common/dialog/OperationDialog.css b/FrontEnd/src/views/common/dialog/OperationDialog.css index 19c5d806..43cdb692 100644 --- a/FrontEnd/src/views/common/dialog/OperationDialog.css +++ b/FrontEnd/src/views/common/dialog/OperationDialog.css @@ -9,32 +9,15 @@ color: var(--cru-surface-on-color);
}
-.cru-operation-dialog-main-area {
- margin-top: 0.5em;
-}
-
-.cru-operation-dialog-group {
- display: block;
- margin: 0.4em 0;
-}
-
-.cru-operation-dialog-label {
- display: block;
- color: var(--cru-primary-color);
+.cru-dialog-middle-area {
+ margin: 0.5em 0;
}
-.cru-operation-dialog-inline-label {
- margin-inline-start: 0.5em;
+.cru-dialog-bottom-area {
+ margin-top: 0.5em;
}
-.cru-operation-dialog-error-text {
+.cru-operation-dialog-input-group {
display: block;
- font-size: 0.8em;
- color: var(--cru-danger-color);
+ margin: 0.5em 0;
}
-
-.cru-operation-dialog-helper-text {
- display: block;
- font-size: 0.8em;
- color: var(--cru-primary-color);
-}
\ No newline at end of file diff --git a/FrontEnd/src/views/common/dialog/OperationDialog.tsx b/FrontEnd/src/views/common/dialog/OperationDialog.tsx index 97d135e9..8aab45d9 100644 --- a/FrontEnd/src/views/common/dialog/OperationDialog.tsx +++ b/FrontEnd/src/views/common/dialog/OperationDialog.tsx @@ -7,15 +7,17 @@ import Button from "../button/Button"; import { useInputs, InputGroup, - InitializeInfo as InputInitializer, + Initializer as InputInitializer, InputValueDict, - InputScheme, + InputErrorDict, } from "../input/InputGroup"; import LoadingButton from "../button/LoadingButton"; import Dialog from "./Dialog"; import "./OperationDialog.css"; +export type { InputInitializer, InputValueDict, InputErrorDict }; + interface OperationDialogPromptProps { message?: Text; customMessage?: ReactNode; @@ -40,13 +42,13 @@ export interface OperationDialogProps<TData> { close: () => void; color?: ThemeColor; + inputColor?: ThemeColor; title: Text; inputPrompt?: Text; successPrompt?: (data: TData) => ReactNode; failurePrompt?: (error: unknown) => ReactNode; - inputInit?: InputInitializer; - inputScheme?: InputScheme; + inputs: InputInitializer; onProcess: (inputs: InputValueDict) => Promise<TData>; onSuccessAndClose?: (data: TData) => void; @@ -57,25 +59,16 @@ function OperationDialog<TData>(props: OperationDialogProps<TData>) { open, close, color, + inputColor, title, inputPrompt, successPrompt, failurePrompt, - inputInit, - inputScheme, + inputs, onProcess, onSuccessAndClose, } = props; - if (process.env.NODE_ENV === "development") { - if (inputScheme == null && inputInit == null) { - throw Error("Scheme or Init? Choose one and create one."); - } - if (inputScheme != null && inputInit != null) { - throw Error("Scheme or Init? Choose one and drop one"); - } - } - const c = useC(); type Step = @@ -93,14 +86,13 @@ function OperationDialog<TData>(props: OperationDialogProps<TData>) { const [step, setStep] = useState<Step>({ type: "input" }); const { inputGroupProps, hasError, setAllDisabled, confirm } = useInputs({ - /* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */ - init: inputInit ?? { scheme: inputScheme! }, + init: inputs, }); function onClose() { if (step.type !== "process") { close(); - if (step.type === "success" && props.onSuccessAndClose) { + if (step.type === "success" && onSuccessAndClose) { onSuccessAndClose?.(step.data); } } else { @@ -136,11 +128,11 @@ function OperationDialog<TData>(props: OperationDialogProps<TData>) { body = ( <div className="cru-operation-dialog-main-area"> - <div> + <div className="cru-dialog-middle-area"> <OperationDialogPrompt customMessage={c(inputPrompt)} /> <InputGroup containerClassName="cru-operation-dialog-input-group" - color={color} + color={inputColor ?? "primary"} {...inputGroupProps} /> </div> diff --git a/FrontEnd/src/views/common/input/InputGroup.css b/FrontEnd/src/views/common/input/InputGroup.css index f9d6ac8b..1763ea53 100644 --- a/FrontEnd/src/views/common/input/InputGroup.css +++ b/FrontEnd/src/views/common/input/InputGroup.css @@ -1,25 +1,54 @@ -.cru-input-panel-group { +.cru-input-group { display: block; +} + +.cru-input-container { margin: 0.4em 0; } -.cru-input-panel-label { +.cru-input-label { display: block; - color: var(--cru-primary-color); + color: var(--cru-key-color); + font-size: 0.9em; + margin-bottom: 0.3em; } -.cru-input-panel-inline-label { +.cru-input-label-inline { margin-inline-start: 0.5em; } -.cru-input-panel-error-text { +.cru-input-type-text input { + appearance: none; + display: block; + border: 1px solid var(--cru-surface-outline-color); + color: var(--cru-surface-on-color); + background-color: var(--cru-surface-color); + margin: 0; + padding: 0; + font-size: 1.2em; +} + +.cru-input-type-text input:hover { + border-color: var(--cru-key-color); +} + +.cru-input-type-text input:focus { + border-color: var(--cru-key-color); +} + +.cru-input-type-text input:disabled { + border-color: var(--cru-surface-on-color); +} + +.cru-input-error { display: block; font-size: 0.8em; color: var(--cru-danger-color); + margin-top: 0.4em; } -.cru-input-panel-helper-text { +.cru-input-helper { display: block; font-size: 0.8em; color: var(--cru-primary-color); -} +}
\ No newline at end of file diff --git a/FrontEnd/src/views/common/input/InputGroup.tsx b/FrontEnd/src/views/common/input/InputGroup.tsx index 232edfc9..eed8266b 100644 --- a/FrontEnd/src/views/common/input/InputGroup.tsx +++ b/FrontEnd/src/views/common/input/InputGroup.tsx @@ -98,14 +98,16 @@ export type State = { data: InputData; }; -export type DataInitializeInfo = Partial<InputData>; +export type DataInitialization = Partial<InputData>; -export type InitializeInfo = { +export type Initialization = { scheme: InputScheme; - dataInit?: DataInitializeInfo; + dataInit?: DataInitialization; }; -export type Initialize +export type GeneralInitialization = Initialization | InputScheme | InputInfo[]; + +export type Initializer = GeneralInitialization | (() => GeneralInitialization); export interface InputGroupProps { color?: ThemeColor; @@ -136,9 +138,7 @@ export type ConfirmResult = errors: InputErrorDict; }; -export function useInputs(options: { - init: InitializeInfo | (() => InitializeInfo); -}): { +export function useInputs(options: { init: Initializer }): { inputGroupProps: InputGroupProps; hasError: boolean; confirm: () => ConfirmResult; @@ -158,8 +158,14 @@ export function useInputs(options: { throw new Error("Unknown input type"); } - function initialize(info: InitializeInfo): State { - const { scheme, dataInit } = info; + function initialize(generalInitialization: GeneralInitialization): State { + const initialization: Initialization = Array.isArray(generalInitialization) + ? { scheme: { inputs: generalInitialization } } + : "scheme" in generalInitialization + ? generalInitialization + : { scheme: generalInitialization }; + + const { scheme, dataInit } = initialization; const { inputs, validator } = scheme; const keys = inputs.map((input) => input.key); @@ -185,8 +191,8 @@ export function useInputs(options: { } const values: InputValueDict = {}; - const disabled: InputDisabledDict = clean(info.dataInit?.disabled); - const dirties: InputDirtyDict = clean(info.dataInit?.dirties); + const disabled: InputDisabledDict = clean(dataInit?.disabled); + const dirties: InputDirtyDict = clean(dataInit?.dirties); for (let i = 0; i < inputs.length; i++) { const input = inputs[i]; @@ -195,7 +201,7 @@ export function useInputs(options: { values[key] = initializeValue(input, dataInit?.values?.[key]); } - let errors = info.dataInit?.errors; + let errors = dataInit?.errors; if (errors != null) { if (process.env.NODE_ENV === "development") { @@ -331,13 +337,13 @@ export function InputGroup({ )} > {inputs.map((item, index) => { - const { type, value, label, error, helper, disabled } = item; + const { key, type, value, label, error, helper, disabled } = item; const getContainerClassName = ( ...additionalClassNames: classNames.ArgumentArray ) => classNames( - `cru-input-container cru-input-${type}`, + `cru-input-container cru-input-type-${type}`, error && "error", ...additionalClassNames, ); @@ -350,7 +356,7 @@ export function InputGroup({ const { password } = item; return ( <div - key={index} + key={key} className={getContainerClassName(password && "password")} > {label && <label className="cru-input-label">{c(label)}</label>} @@ -369,7 +375,7 @@ export function InputGroup({ ); } else if (type === "bool") { return ( - <div key={index} className={getContainerClassName()}> + <div key={key} className={getContainerClassName()}> <input type="checkbox" checked={value} @@ -386,7 +392,7 @@ export function InputGroup({ ); } else if (type === "select") { return ( - <div key={index} className={getContainerClassName()}> + <div key={key} className={getContainerClassName()}> <label className="cru-input-label">{c(label)}</label> <select value={value} @@ -396,9 +402,9 @@ export function InputGroup({ }} disabled={disabled} > - {item.options.map((option, i) => { + {item.options.map((option) => { return ( - <option value={option.value} key={i}> + <option value={option.value} key={option.value}> {option.icon} {c(option.label)} </option> diff --git a/FrontEnd/src/views/common/theme.css b/FrontEnd/src/views/common/theme.css index 6478ed7a..1aa56a8c 100644 --- a/FrontEnd/src/views/common/theme.css +++ b/FrontEnd/src/views/common/theme.css @@ -3,6 +3,8 @@ :root { --cru-default-font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; --cru-page-padding: 1em 2em; + + --cru-border-radius: 4px; --cru-card-border-radius: 4px; --cru-secondary-text-color: var(--cru-surface-on-color); |