Extract modal to ui kit
This commit is contained in:
parent
810035547c
commit
3f675966a6
|
|
@ -0,0 +1,125 @@
|
||||||
|
@import './global.css';
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
width: 100%;
|
||||||
|
max-width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
max-height: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
outline: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&::backdrop {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
background: var(--bg);
|
||||||
|
color: var(--text);
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 960px;
|
||||||
|
height: 80vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--text);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.closeButton {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
color: var(--text-muted);
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
border-radius: var(--radius);
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: var(--text);
|
||||||
|
background: var(--bg-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 160px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
border-right: 1px solid var(--border);
|
||||||
|
padding: 8px;
|
||||||
|
gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 16px 20px;
|
||||||
|
border-top: 1px solid var(--border);
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.body {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar {
|
||||||
|
flex-direction: row;
|
||||||
|
width: 100%;
|
||||||
|
overflow-x: auto;
|
||||||
|
border-right: none;
|
||||||
|
border-bottom: 1px solid var(--border);
|
||||||
|
padding: 4px 8px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
scrollbar-width: none;
|
||||||
|
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
padding: 12px 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
import type { ComponentChildren } from "preact";
|
||||||
|
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||||
|
import { X } from "lucide-preact";
|
||||||
|
import clsx from "clsx";
|
||||||
|
|
||||||
|
import styles from '../assets/modal.module.css';
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
open: boolean;
|
||||||
|
title?: string;
|
||||||
|
onClose?: () => void;
|
||||||
|
sidebar?: ComponentChildren;
|
||||||
|
footer?: ComponentChildren;
|
||||||
|
class?: string;
|
||||||
|
className?: string;
|
||||||
|
children?: ComponentChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Modal = ({ children, open, title, onClose, sidebar, footer, ['class']: cls, className }: IProps) => {
|
||||||
|
const ref = useRef<HTMLDialogElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (open) {
|
||||||
|
ref.current?.showModal();
|
||||||
|
} else {
|
||||||
|
ref.current?.close();
|
||||||
|
}
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
|
const handleBackdropMouseDown = useCallback((e: MouseEvent) => {
|
||||||
|
if (e.target === ref.current) onClose?.();
|
||||||
|
}, [onClose]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<dialog ref={ref} class={styles.dialog} onMouseDown={handleBackdropMouseDown}>
|
||||||
|
<div class={clsx(styles.modal, cls ?? className)} onMouseDown={(e) => e.stopPropagation()}>
|
||||||
|
{(title != null || onClose) && (
|
||||||
|
<div class={styles.header}>
|
||||||
|
{title && <h2 class={styles.title}>{title}</h2>}
|
||||||
|
{onClose && (
|
||||||
|
<button class={styles.closeButton} onClick={onClose}>
|
||||||
|
<X size={18} />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div class={styles.body}>
|
||||||
|
{sidebar && <div class={styles.sidebar}>{sidebar}</div>}
|
||||||
|
<div class={styles.content}>{children}</div>
|
||||||
|
</div>
|
||||||
|
{footer && <div class={styles.footer}>{footer}</div>}
|
||||||
|
</div>
|
||||||
|
</dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
.dialog {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
margin: auto;
|
|
||||||
width: 100%;
|
|
||||||
max-width: 1000px;
|
|
||||||
height: fit-content;
|
|
||||||
max-height: 80dvh;
|
|
||||||
overflow: hidden;
|
|
||||||
background-color: var(--backgroundColor, #333333);
|
|
||||||
color: var(--color, white);
|
|
||||||
border: var(--border, 1px solid white);
|
|
||||||
outline: none;
|
|
||||||
padding: 0;
|
|
||||||
border-radius: var(--border-radius, 0);
|
|
||||||
|
|
||||||
&::backdrop {
|
|
||||||
backdrop-filter: blur(5px);
|
|
||||||
}
|
|
||||||
|
|
||||||
>.content {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
max-height: 80dvh;
|
|
||||||
overflow: hidden;
|
|
||||||
|
|
||||||
padding: 30px;
|
|
||||||
|
|
||||||
>.close {
|
|
||||||
font-family: var(--emojiFont, sans-serif);
|
|
||||||
font-size: 12px;
|
|
||||||
position: absolute;
|
|
||||||
top: 10px;
|
|
||||||
right: 10px;
|
|
||||||
cursor: pointer;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
import type { ComponentChildren } from "preact";
|
|
||||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
|
||||||
|
|
||||||
import styles from './Modal.module.css';
|
|
||||||
|
|
||||||
interface IProps {
|
|
||||||
open: boolean;
|
|
||||||
class?: string;
|
|
||||||
className?: string;
|
|
||||||
onClose?: () => void;
|
|
||||||
children?: ComponentChildren;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Modal = ({ children, open, onClose, ['class']: cls, className }: IProps) => {
|
|
||||||
const ref = useRef<HTMLDialogElement>(null);
|
|
||||||
const handleClickWrapper = useCallback((e: MouseEvent) => {
|
|
||||||
if (e.currentTarget instanceof HTMLDialogElement) {
|
|
||||||
onClose?.();
|
|
||||||
} else {
|
|
||||||
e.stopPropagation();
|
|
||||||
}
|
|
||||||
}, [onClose]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (open) {
|
|
||||||
ref.current?.showModal();
|
|
||||||
} else {
|
|
||||||
ref.current?.close();
|
|
||||||
}
|
|
||||||
}, [open]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<dialog ref={ref} onMouseDown={handleClickWrapper} class={styles.dialog}>
|
|
||||||
<div class={`${styles.content} ${cls ?? className ?? ''}`} onMouseDown={handleClickWrapper}>
|
|
||||||
<div class={styles.close} onClick={onClose}>❌</div>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
width: 480px;
|
width: 480px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.loading, .error {
|
.loading,
|
||||||
|
.error {
|
||||||
color: var(--text-muted);
|
color: var(--text-muted);
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
@ -18,7 +19,8 @@
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: 7px 10px;
|
padding: 7px 10px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,9 @@
|
||||||
color: var(--bg);
|
color: var(--bg);
|
||||||
transition: opacity var(--transition);
|
transition: opacity var(--transition);
|
||||||
|
|
||||||
&:hover { opacity: 0.85; }
|
&:hover {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.deleteBtn {
|
.deleteBtn {
|
||||||
|
|
@ -77,5 +79,9 @@
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
transition: all var(--transition);
|
transition: all var(--transition);
|
||||||
|
|
||||||
&:hover { background: var(--accent); border-color: var(--accent); color: var(--bg); }
|
&:hover {
|
||||||
|
background: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--bg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,7 +22,9 @@
|
||||||
color: var(--bg);
|
color: var(--bg);
|
||||||
transition: opacity var(--transition);
|
transition: opacity var(--transition);
|
||||||
|
|
||||||
&:hover { opacity: 0.85; }
|
&:hover {
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.clearBtn {
|
.clearBtn {
|
||||||
|
|
@ -33,5 +35,7 @@
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
transition: background var(--transition);
|
transition: background var(--transition);
|
||||||
|
|
||||||
&:hover { background: var(--bg-hover); }
|
&:hover {
|
||||||
|
background: var(--bg-hover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +59,8 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.userStats, .networkStats {
|
.userStats,
|
||||||
|
.networkStats {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
@ -83,7 +84,8 @@
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
th, td {
|
th,
|
||||||
|
td {
|
||||||
padding: 5px 6px;
|
padding: 5px 6px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid var(--border);
|
border-bottom: 1px solid var(--border);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,8 @@ button {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input, textarea {
|
input,
|
||||||
|
textarea {
|
||||||
background: var(--bg-active);
|
background: var(--bg-active);
|
||||||
border: 1px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { useEffect, useState } from "preact/hooks";
|
||||||
import { useHordeState } from "../../contexts/state";
|
import { useHordeState } from "../../contexts/state";
|
||||||
import { fetchLeaderboard, type LeaderboardEntry } from "../../utils/api";
|
import { fetchLeaderboard, type LeaderboardEntry } from "../../utils/api";
|
||||||
import { formatNumber, formatTime } from "@common/utils";
|
import { formatNumber, formatTime } from "@common/utils";
|
||||||
import { Modal } from "@common/components/modal/Modal";
|
import { Modal } from "@common/components/Modal";
|
||||||
import modalStyles from "../../assets/modal.module.css";
|
import modalStyles from "../../assets/modal.module.css";
|
||||||
import styles from "../../assets/leaderboard-modal.module.css";
|
import styles from "../../assets/leaderboard-modal.module.css";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import clsx from "clsx";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { useHordeState } from "../../contexts/state";
|
import { useHordeState } from "../../contexts/state";
|
||||||
import { fetchWorker, updateWorker, deleteWorker, type WorkerData } from "../../utils/api";
|
import { fetchWorker, updateWorker, deleteWorker, type WorkerData } from "../../utils/api";
|
||||||
import { Modal } from "@common/components/modal/Modal";
|
import { Modal } from "@common/components/Modal";
|
||||||
import modalStyles from "../../assets/modal.module.css";
|
import modalStyles from "../../assets/modal.module.css";
|
||||||
import styles from "../../assets/manage-workers-modal.module.css";
|
import styles from "../../assets/manage-workers-modal.module.css";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import clsx from "clsx";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect } from "preact/hooks";
|
||||||
import { useHordeState } from "../../contexts/state";
|
import { useHordeState } from "../../contexts/state";
|
||||||
import { useInputState } from "@common/hooks/useInputState";
|
import { useInputState } from "@common/hooks/useInputState";
|
||||||
import { Modal } from "@common/components/modal/Modal";
|
import { Modal } from "@common/components/Modal";
|
||||||
import modalStyles from "../../assets/modal.module.css";
|
import modalStyles from "../../assets/modal.module.css";
|
||||||
import styles from "../../assets/options-modal.module.css";
|
import styles from "../../assets/options-modal.module.css";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,77 +1,3 @@
|
||||||
.overlay {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background: rgba(0, 0, 0, 0.5);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
background: var(--bg);
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 90%;
|
|
||||||
max-width: 960px;
|
|
||||||
height: 80vh;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding: 16px 20px;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: var(--text);
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.closeButton {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
font-size: 20px;
|
|
||||||
color: var(--text-muted);
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
border-radius: 4px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: var(--text);
|
|
||||||
background: var(--bg-hover);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.body {
|
|
||||||
display: flex;
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
width: 160px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
border-right: 1px solid var(--border);
|
|
||||||
padding: 8px;
|
|
||||||
gap: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuItem {
|
.menuItem {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -98,14 +24,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.content {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
padding: 20px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.form {
|
.form {
|
||||||
composes: form from '@common/assets/ui.module.css';
|
composes: form from '@common/assets/ui.module.css';
|
||||||
}
|
}
|
||||||
|
|
@ -153,14 +71,6 @@
|
||||||
min-height: unset;
|
min-height: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
|
||||||
padding: 16px 20px;
|
|
||||||
border-top: 1px solid var(--border);
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
composes: button from '@common/assets/ui.module.css';
|
composes: button from '@common/assets/ui.module.css';
|
||||||
}
|
}
|
||||||
|
|
@ -227,25 +137,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.body {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar {
|
|
||||||
flex-direction: row;
|
|
||||||
width: 100%;
|
|
||||||
overflow-x: auto;
|
|
||||||
border-right: none;
|
|
||||||
border-bottom: 1px solid var(--border);
|
|
||||||
padding: 4px 8px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sidebar::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menuItem {
|
.menuItem {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
@ -254,8 +145,4 @@
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer {
|
|
||||||
padding: 12px 16px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { X } from "lucide-preact";
|
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
import { Modal } from "@common/components/Modal";
|
||||||
import styles from "../assets/settings-modal.module.css";
|
import styles from "../assets/settings-modal.module.css";
|
||||||
import { BannedTokensSettings } from "./settings/banned-tokens";
|
import { BannedTokensSettings } from "./settings/banned-tokens";
|
||||||
import { ChatSystemInstructionSettings } from "./settings/chat-system-instruction";
|
import { ChatSystemInstructionSettings } from "./settings/chat-system-instruction";
|
||||||
|
|
@ -15,72 +15,44 @@ interface Props {
|
||||||
|
|
||||||
type Tab = "banned-tokens" | "system-instruction" | "chat-system-instruction" | "continue-prompt" | "connection" | "user";
|
type Tab = "banned-tokens" | "system-instruction" | "chat-system-instruction" | "continue-prompt" | "connection" | "user";
|
||||||
|
|
||||||
|
const TABS: { id: Tab; label: string }[] = [
|
||||||
|
{ id: "connection", label: "Connection" },
|
||||||
|
{ id: "user", label: "User" },
|
||||||
|
{ id: "system-instruction", label: "System Instruction" },
|
||||||
|
{ id: "continue-prompt", label: "Continue Prompt" },
|
||||||
|
{ id: "chat-system-instruction", label: "Chat System Instruction" },
|
||||||
|
{ id: "banned-tokens", label: "Banned Tokens" },
|
||||||
|
];
|
||||||
|
|
||||||
export const SettingsModal = ({ onClose }: Props) => {
|
export const SettingsModal = ({ onClose }: Props) => {
|
||||||
const [activeTab, setActiveTab] = useState<Tab>("connection");
|
const [activeTab, setActiveTab] = useState<Tab>("connection");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={styles.overlay} onClick={onClose}>
|
<Modal
|
||||||
<div class={styles.modal} onClick={(e) => e.stopPropagation()}>
|
open
|
||||||
<div class={styles.header}>
|
onClose={onClose}
|
||||||
<h2 class={styles.title}>Settings</h2>
|
title="Settings"
|
||||||
<button class={styles.closeButton} onClick={onClose}>
|
sidebar={TABS.map(({ id, label }) => (
|
||||||
<X size={20} />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class={styles.body}>
|
|
||||||
<nav class={styles.sidebar}>
|
|
||||||
<button
|
<button
|
||||||
class={clsx(styles.menuItem, activeTab === "connection" && styles.active)}
|
key={id}
|
||||||
onClick={() => setActiveTab("connection")}
|
class={clsx(styles.menuItem, activeTab === id && styles.active)}
|
||||||
|
onClick={() => setActiveTab(id)}
|
||||||
>
|
>
|
||||||
Connection
|
{label}
|
||||||
</button>
|
</button>
|
||||||
<button
|
))}
|
||||||
class={clsx(styles.menuItem, activeTab === "user" && styles.active)}
|
footer={
|
||||||
onClick={() => setActiveTab("user")}
|
<button onClick={onClose} class={clsx(styles.button, styles.buttonSecondary)}>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
User
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class={clsx(styles.menuItem, activeTab === "system-instruction" && styles.active)}
|
|
||||||
onClick={() => setActiveTab("system-instruction")}
|
|
||||||
>
|
|
||||||
System Instruction
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class={clsx(styles.menuItem, activeTab === "continue-prompt" && styles.active)}
|
|
||||||
onClick={() => setActiveTab("continue-prompt")}
|
|
||||||
>
|
|
||||||
Continue Prompt
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class={clsx(styles.menuItem, activeTab === "chat-system-instruction" && styles.active)}
|
|
||||||
onClick={() => setActiveTab("chat-system-instruction")}
|
|
||||||
>
|
|
||||||
Chat System Instruction
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
class={clsx(styles.menuItem, activeTab === "banned-tokens" && styles.active)}
|
|
||||||
onClick={() => setActiveTab("banned-tokens")}
|
|
||||||
>
|
|
||||||
Banned Tokens
|
|
||||||
</button>
|
|
||||||
</nav>
|
|
||||||
<div class={styles.content}>
|
|
||||||
{activeTab === "user" && <UserSettings />}
|
{activeTab === "user" && <UserSettings />}
|
||||||
{activeTab === "banned-tokens" && <BannedTokensSettings />}
|
{activeTab === "banned-tokens" && <BannedTokensSettings />}
|
||||||
{activeTab === "system-instruction" && <SystemInstructionSettings />}
|
{activeTab === "system-instruction" && <SystemInstructionSettings />}
|
||||||
{activeTab === "chat-system-instruction" && <ChatSystemInstructionSettings />}
|
{activeTab === "chat-system-instruction" && <ChatSystemInstructionSettings />}
|
||||||
{activeTab === "continue-prompt" && <ContinuePromptSettings />}
|
{activeTab === "continue-prompt" && <ContinuePromptSettings />}
|
||||||
{activeTab === "connection" && <ConnectionSettings />}
|
{activeTab === "connection" && <ConnectionSettings />}
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
<div class={styles.footer}>
|
|
||||||
<button onClick={onClose} class={clsx(styles.button, styles.buttonSecondary)}>
|
|
||||||
Done
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue