1
0
Fork 0
This commit is contained in:
Pabloader 2026-04-10 08:43:14 +00:00
parent 23bc808cca
commit 810035547c
13 changed files with 477 additions and 572 deletions

View File

@ -18,7 +18,7 @@
"preact": "10.22.0",
},
"devDependencies": {
"@types/bun": "latest",
"@types/bun": "^1.3.11",
"@types/html-minifier": "4.0.5",
"@types/inquirer": "9.0.7",
"@types/web-bluetooth": "0.0.21",

View File

@ -22,7 +22,7 @@
"preact": "10.22.0"
},
"devDependencies": {
"@types/bun": "latest",
"@types/bun": "^1.3.11",
"@types/html-minifier": "4.0.5",
"@types/inquirer": "9.0.7",
"@types/web-bluetooth": "0.0.21",

View File

@ -0,0 +1,255 @@
@import "./global.css";
/* ─── Form Fields ─────────────────────────────────────────── */
.input {
width: 100%;
padding: 8px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 14px;
color: var(--text);
font-family: inherit;
&:focus {
outline: none;
border-color: var(--accent);
}
}
.textarea {
composes: input;
resize: vertical;
box-sizing: border-box;
min-height: 80px;
}
.select {
composes: input;
cursor: pointer;
}
.inputRow {
display: flex;
gap: 8px;
}
/* ─── Buttons ─────────────────────────────────────────────── */
.button {
padding: 8px 16px;
border-radius: var(--radius);
font-size: 14px;
font-family: inherit;
cursor: pointer;
border: none;
background: transparent;
transition: all var(--transition);
}
.buttonPrimary {
composes: button;
background: var(--accent);
color: var(--bg);
font-weight: 500;
&:hover {
background: var(--accent-alt);
}
}
.buttonSecondary {
composes: button;
border: 1px solid var(--border);
color: var(--text);
&:hover {
background: var(--bg-hover);
}
}
.buttonSmall {
padding: 4px 10px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 12px;
font-family: inherit;
color: var(--text);
cursor: pointer;
transition: all var(--transition);
&:hover {
border-color: var(--accent);
color: var(--accent);
}
}
.iconButton {
display: flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
background: transparent;
border: 1px solid var(--border);
border-radius: var(--radius);
color: var(--text-muted);
font-size: 16px;
cursor: pointer;
transition: all var(--transition);
flex-shrink: 0;
&:hover:not(:disabled) {
border-color: var(--accent);
color: var(--accent);
}
&:disabled {
opacity: 0.3;
cursor: not-allowed;
}
}
.deleteButton {
composes: iconButton;
&:hover:not(:disabled) {
background: var(--danger, var(--accent));
border-color: var(--danger, var(--accent));
color: var(--bg);
}
}
.confirmButton {
padding: 4px 10px;
border: 1px solid var(--accent);
border-radius: var(--radius);
font-size: 12px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
background: var(--accent);
color: var(--bg);
transition: all var(--transition);
&:hover {
background: var(--bg);
color: var(--accent);
}
}
.cancelButton {
padding: 4px 10px;
border: 1px solid var(--border);
border-radius: var(--radius);
font-size: 12px;
font-weight: 600;
font-family: inherit;
cursor: pointer;
background: transparent;
color: var(--text-muted);
transition: all var(--transition);
&:hover {
background: var(--bg-hover);
color: var(--text);
}
}
/* ─── Form Layout ─────────────────────────────────────────── */
.form {
display: flex;
flex-direction: column;
gap: 16px;
flex: 1;
}
.formGroup {
display: flex;
flex-direction: column;
gap: 4px;
}
.label {
display: block;
font-weight: bold;
margin-bottom: 4px;
}
/* ─── Cards ───────────────────────────────────────────────── */
.card {
background: var(--bg-secondary);
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 16px;
}
.cardHeader {
display: flex;
align-items: center;
gap: 12px;
}
/* ─── Editor Section Header ───────────────────────────────── */
.editorHeader {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 16px;
border-bottom: 1px solid var(--border);
}
/* ─── Badges ──────────────────────────────────────────────── */
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
background: var(--bg-active);
border-radius: 16px;
font-size: 13px;
color: var(--text);
}
.badgeRemove {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
padding: 0;
background: transparent;
border: none;
border-radius: 50%;
color: var(--text-muted);
cursor: pointer;
font-size: 14px;
line-height: 1;
&:hover {
background: var(--danger, var(--accent));
color: var(--bg);
}
}
/* ─── Utilities ───────────────────────────────────────────── */
.empty {
color: var(--text-muted);
font-style: italic;
font-size: 14px;
}
.divider {
height: 1px;
background: var(--border);
margin: 16px 0;
}

View File

@ -58,10 +58,24 @@
}
.saveBtn {
color: var(--accent-alt) !important;
padding: 8px 16px;
border: none;
border-radius: var(--radius);
background: var(--accent);
color: var(--bg);
transition: opacity var(--transition);
&:hover { opacity: 0.85; }
}
.deleteBtn {
color: var(--accent) !important;
padding: 8px 16px;
border: 1px solid var(--border);
border-radius: var(--radius);
background: transparent;
color: var(--text-muted);
margin-left: auto;
transition: all var(--transition);
&:hover { background: var(--accent); border-color: var(--accent); color: var(--bg); }
}

View File

@ -15,5 +15,23 @@
}
.saveBtn {
color: var(--accent-alt) !important;
padding: 8px 16px;
border: none;
border-radius: var(--radius);
background: var(--accent);
color: var(--bg);
transition: opacity var(--transition);
&:hover { opacity: 0.85; }
}
.clearBtn {
padding: 8px 16px;
border: 1px solid var(--border);
border-radius: var(--radius);
background: transparent;
color: var(--text);
transition: background var(--transition);
&:hover { background: var(--bg-hover); }
}

View File

@ -1,8 +1,9 @@
import clsx from "clsx";
import { useEffect, useState } from "preact/hooks";
import { X } from "lucide-preact";
import { useHordeState } from "../../contexts/state";
import { fetchLeaderboard, type LeaderboardEntry } from "../../utils/api";
import { formatNumber, formatTime } from "@common/utils";
import { Modal } from "@common/components/modal/Modal";
import modalStyles from "../../assets/modal.module.css";
import styles from "../../assets/leaderboard-modal.module.css";
@ -93,21 +94,10 @@ export const LeaderboardModal = ({ open, onClose }: Props) => {
return () => { cancelled = true; };
}, [open, user?.username]);
useEffect(() => {
if (!open) return;
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, [open]);
if (!open) return null;
return (
<div class={modalStyles.overlay} onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }}>
<div class={`${modalStyles.modal} ${styles.modal}`}>
<Modal open={open} onClose={onClose} class={clsx(modalStyles.modal, styles.modal)}>
<div class={modalStyles.header}>
<span class={modalStyles.title}>Leaderboard</span>
<button class={modalStyles.closeButton} onClick={onClose}><X size={16} /></button>
</div>
<div class={modalStyles.body}>
{loading && <p class={styles.loading}>Loading</p>}
@ -129,7 +119,7 @@ export const LeaderboardModal = ({ open, onClose }: Props) => {
<td>{r.username}</td>
<td>{formatNumber(r.kudos)}</td>
{user && (
<td class={r.diff !== undefined ? (r.diff > 0 ? styles.above : styles.below) : undefined}>
<td class={clsx(r.diff !== undefined && (r.diff > 0 ? styles.above : styles.below))}>
{r.diff !== undefined ? `+${formatNumber(r.diff)}` : '—'}
</td>
)}
@ -153,7 +143,6 @@ export const LeaderboardModal = ({ open, onClose }: Props) => {
</div>
);
})()}
</div>
</div>
</Modal>
);
};

View File

@ -1,7 +1,8 @@
import clsx from "clsx";
import { useEffect, useState } from "preact/hooks";
import { X } from "lucide-preact";
import { useHordeState } from "../../contexts/state";
import { fetchWorker, updateWorker, deleteWorker, type WorkerData } from "../../utils/api";
import { Modal } from "@common/components/modal/Modal";
import modalStyles from "../../assets/modal.module.css";
import styles from "../../assets/manage-workers-modal.module.css";
@ -47,15 +48,6 @@ export const ManageWorkersModal = ({ open, onClose }: Props) => {
return () => { cancelled = true; };
}, [open, user?.worker_ids.join(',')]);
useEffect(() => {
if (!open) return;
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, [open]);
if (!open || !user) return null;
const setEdit = (id: string, patch: Partial<WorkerEdit>) => {
setEdits(prev => ({ ...prev, [id]: { ...prev[id], ...patch } }));
};
@ -79,7 +71,7 @@ export const ManageWorkersModal = ({ open, onClose }: Props) => {
try {
await deleteWorker(id, apiKey);
setWorkerDetails(prev => prev.filter(w => w.id !== id));
dispatch({ type: 'SET_USER', user: { ...user, worker_ids: user.worker_ids.filter(i => i !== id) } });
dispatch({ type: 'SET_USER', user: { ...user!, worker_ids: user!.worker_ids.filter(i => i !== id) } });
} catch (e) {
console.error('[horde] delete worker error:', e);
} finally {
@ -88,15 +80,13 @@ export const ManageWorkersModal = ({ open, onClose }: Props) => {
};
return (
<div class={modalStyles.overlay} onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }}>
<div class={`${modalStyles.modal} ${styles.modal}`}>
<Modal open={open} onClose={onClose} class={clsx(modalStyles.modal, styles.modal)}>
<div class={modalStyles.header}>
<span class={modalStyles.title}>Manage Workers</span>
<button class={modalStyles.closeButton} onClick={onClose}><X size={16} /></button>
</div>
<div class={modalStyles.body}>
{loading && <p class={styles.loading}>Loading</p>}
{!loading && workerDetails.map(w => {
{!loading && user && workerDetails.map(w => {
const edit = edits[w.id] ?? { name: w.name, info: w.info ?? '', maintenance_mode: w.maintenance_mode };
return (
<div key={w.id} class={styles.workerForm}>
@ -137,7 +127,6 @@ export const ManageWorkersModal = ({ open, onClose }: Props) => {
);
})}
</div>
</div>
</div>
</Modal>
);
};

View File

@ -1,6 +1,8 @@
import { useEffect, useState } from "preact/hooks";
import { X } from "lucide-preact";
import clsx from "clsx";
import { useEffect } from "preact/hooks";
import { useHordeState } from "../../contexts/state";
import { useInputState } from "@common/hooks/useInputState";
import { Modal } from "@common/components/modal/Modal";
import modalStyles from "../../assets/modal.module.css";
import styles from "../../assets/options-modal.module.css";
@ -11,21 +13,12 @@ interface Props {
export const OptionsModal = ({ open, onClose }: Props) => {
const { state, dispatch } = useHordeState();
const [draft, setDraft] = useState(state.apiKey);
const [draft, setDraft] = useInputState(state.apiKey);
useEffect(() => {
if (open) setDraft(state.apiKey);
}, [open]);
useEffect(() => {
if (!open) return;
const handler = (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', handler);
return () => window.removeEventListener('keydown', handler);
}, [open]);
if (!open) return null;
const save = () => {
dispatch({ type: 'SET_API_KEY', apiKey: draft.trim() });
onClose();
@ -38,11 +31,9 @@ export const OptionsModal = ({ open, onClose }: Props) => {
};
return (
<div class={modalStyles.overlay} onMouseDown={e => { if (e.target === e.currentTarget) onClose(); }}>
<div class={`${modalStyles.modal} ${styles.modal}`}>
<Modal open={open} onClose={onClose} class={clsx(modalStyles.modal, styles.modal)}>
<div class={modalStyles.header}>
<span class={modalStyles.title}>Options</span>
<button class={modalStyles.closeButton} onClick={onClose}><X size={16} /></button>
</div>
<div class={modalStyles.body}>
<label class={styles.label}>
@ -50,7 +41,7 @@ export const OptionsModal = ({ open, onClose }: Props) => {
<input
type="password"
value={draft}
onInput={e => setDraft((e.target as HTMLInputElement).value)}
onInput={setDraft}
onKeyDown={e => { if (e.key === 'Enter') save(); }}
placeholder="Enter your AI Horde API key"
autoFocus
@ -59,9 +50,8 @@ export const OptionsModal = ({ open, onClose }: Props) => {
</div>
<div class={modalStyles.footer}>
<button class={styles.saveBtn} onClick={save}>Save</button>
{state.apiKey && <button onClick={clear}>Clear</button>}
</div>
</div>
{state.apiKey && <button class={styles.clearBtn} onClick={clear}>Clear</button>}
</div>
</Modal>
);
};

View File

@ -7,18 +7,11 @@
}
.empty {
color: var(--text-muted);
font-style: italic;
font-size: 14px;
composes: empty from '@common/assets/ui.module.css';
}
.chapterCard {
background: var(--bg-secondary);
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 16px;
composes: card from '@common/assets/ui.module.css';
}
.chapterTitle {
@ -59,24 +52,9 @@
}
.summaryEditable {
width: 100%;
composes: textarea from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
box-sizing: border-box;
min-height: 80px;
white-space: pre-wrap;
word-wrap: break-word;
resize: vertical;
&:focus {
outline: none;
border-color: var(--accent);
}
}

View File

@ -7,11 +7,7 @@
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 16px;
border-bottom: 1px solid var(--border);
composes: editorHeader from '@common/assets/ui.module.css';
}
.header h2 {
@ -22,19 +18,8 @@
}
.addButton {
padding: 8px 16px;
background: var(--accent);
color: var(--bg);
border: none;
composes: buttonPrimary from '@common/assets/ui.module.css';
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
&:hover {
background: var(--accent-alt);
}
}
.deleteConfirm {
@ -53,37 +38,12 @@
}
}
.confirmButton,
.cancelButton {
padding: 4px 10px;
border: 1px solid transparent;
border-radius: var(--radius);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: all var(--transition);
}
.confirmButton {
background: var(--accent);
color: var(--bg);
border-color: var(--accent);
&:hover {
background: var(--bg);
color: var(--accent);
}
composes: confirmButton from '@common/assets/ui.module.css';
}
.cancelButton {
background: transparent;
color: var(--text-muted);
border-color: var(--border);
&:hover {
background: var(--bg-hover);
color: var(--text);
}
composes: cancelButton from '@common/assets/ui.module.css';
}
.list {
@ -95,24 +55,15 @@
}
.empty {
color: var(--text-muted);
font-style: italic;
font-size: 14px;
composes: empty from '@common/assets/ui.module.css';
}
.characterCard {
background: var(--bg-secondary);
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 16px;
composes: card from '@common/assets/ui.module.css';
}
.cardHeader {
display: flex;
align-items: center;
gap: 12px;
composes: cardHeader from '@common/assets/ui.module.css';
}
.nameInput {
@ -133,29 +84,15 @@
}
.deleteButton {
composes: deleteButton from '@common/assets/ui.module.css';
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-muted);
font-size: 20px;
cursor: pointer;
transition: all var(--transition);
&:hover {
background: var(--accent);
border-color: var(--accent);
color: var(--bg);
}
}
.field {
display: flex;
flex-direction: column;
composes: formGroup from '@common/assets/ui.module.css';
gap: 8px;
}
@ -224,70 +161,23 @@
}
.generateButton {
padding: 4px 10px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
font-size: 12px;
color: var(--text);
cursor: pointer;
transition: all var(--transition);
&:hover {
border-color: var(--accent);
color: var(--accent);
}
composes: buttonSmall from '@common/assets/ui.module.css';
}
.textarea {
width: 100%;
composes: textarea from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
resize: vertical;
box-sizing: border-box;
&:focus {
outline: none;
border-color: var(--accent);
}
}
.select {
width: 100%;
composes: select from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
cursor: pointer;
&:focus {
outline: none;
border-color: var(--accent);
}
}
.smallButton {
padding: 4px 10px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
font-size: 12px;
color: var(--text);
cursor: pointer;
transition: all 0.2s;
&:hover {
border-color: var(--accent);
color: var(--accent);
}
composes: buttonSmall from '@common/assets/ui.module.css';
}
.nicknames {
@ -303,35 +193,11 @@
}
.badge {
display: inline-flex;
align-items: center;
gap: 6px;
padding: 4px 10px;
background: var(--bg-active);
border-radius: 16px;
font-size: 13px;
color: var(--text);
composes: badge from '@common/assets/ui.module.css';
}
.badgeRemove {
display: flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
padding: 0;
background: transparent;
border: none;
border-radius: 50%;
color: var(--text-muted);
cursor: pointer;
font-size: 14px;
line-height: 1;
&:hover {
background: var(--danger);
color: var(--bg);
}
composes: badgeRemove from '@common/assets/ui.module.css';
}
.relations {

View File

@ -7,11 +7,7 @@
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 16px;
border-bottom: 1px solid var(--border);
composes: editorHeader from '@common/assets/ui.module.css';
}
.header h2 {
@ -22,19 +18,8 @@
}
.addButton {
padding: 8px 16px;
background: var(--accent);
color: var(--bg);
border: none;
composes: buttonPrimary from '@common/assets/ui.module.css';
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
&:hover {
background: var(--accent-alt);
}
}
.deleteConfirm {
@ -53,37 +38,12 @@
}
}
.confirmButton,
.cancelButton {
padding: 4px 10px;
border: 1px solid transparent;
border-radius: var(--radius);
font-size: 12px;
font-weight: 600;
cursor: pointer;
transition: all var(--transition);
}
.confirmButton {
background: var(--accent);
color: var(--bg);
border-color: var(--accent);
&:hover {
background: var(--bg);
color: var(--accent);
}
composes: confirmButton from '@common/assets/ui.module.css';
}
.cancelButton {
background: transparent;
color: var(--text-muted);
border-color: var(--border);
&:hover {
background: var(--bg-hover);
color: var(--text);
}
composes: cancelButton from '@common/assets/ui.module.css';
}
.list {
@ -95,24 +55,15 @@
}
.empty {
color: var(--text-muted);
font-style: italic;
font-size: 14px;
composes: empty from '@common/assets/ui.module.css';
}
.locationCard {
background: var(--bg-secondary);
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
gap: 16px;
composes: card from '@common/assets/ui.module.css';
}
.cardHeader {
display: flex;
align-items: center;
gap: 12px;
composes: cardHeader from '@common/assets/ui.module.css';
}
.nameInput {
@ -133,29 +84,15 @@
}
.deleteButton {
composes: deleteButton from '@common/assets/ui.module.css';
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-muted);
font-size: 20px;
cursor: pointer;
transition: all var(--transition);
&:hover {
background: var(--accent);
border-color: var(--accent);
color: var(--bg);
}
}
.field {
display: flex;
flex-direction: column;
composes: formGroup from '@common/assets/ui.module.css';
gap: 8px;
}
@ -174,52 +111,17 @@
}
.select {
width: 100%;
composes: select from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
cursor: pointer;
&:focus {
outline: none;
border-color: var(--accent);
}
}
.generateButton {
padding: 4px 10px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
font-size: 12px;
color: var(--text);
cursor: pointer;
transition: all var(--transition);
&:hover {
border-color: var(--accent);
color: var(--accent);
}
composes: buttonSmall from '@common/assets/ui.module.css';
}
.textarea {
width: 100%;
composes: textarea from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
resize: vertical;
box-sizing: border-box;
&:focus {
outline: none;
border-color: var(--accent);
}
}

View File

@ -7,11 +7,7 @@
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 16px;
border-bottom: 1px solid var(--border);
composes: editorHeader from '@common/assets/ui.module.css';
}
.header h2 {
@ -44,19 +40,8 @@
}
.addButton {
padding: 8px 16px;
background: var(--accent);
color: var(--bg);
border: none;
composes: buttonPrimary from '@common/assets/ui.module.css';
border-radius: 6px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: opacity 0.2s;
&:hover {
background: var(--accent-alt);
}
}
.list {
@ -68,25 +53,17 @@
}
.empty {
color: var(--text-muted);
font-style: italic;
font-size: 14px;
composes: empty from '@common/assets/ui.module.css';
}
.entryCard {
background: var(--bg-secondary);
border-radius: 8px;
padding: 20px;
display: flex;
flex-direction: column;
composes: card from '@common/assets/ui.module.css';
gap: 12px;
}
.cardHeader {
display: flex;
align-items: center;
composes: cardHeader from '@common/assets/ui.module.css';
justify-content: space-between;
gap: 12px;
}
.titleRow {
@ -131,49 +108,15 @@
}
.moveButton {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
composes: iconButton from '@common/assets/ui.module.css';
background: var(--bg);
border: 1px solid var(--border);
border-radius: 4px;
color: var(--text);
font-size: 14px;
cursor: pointer;
transition: all var(--transition);
&:hover:not(:disabled) {
border-color: var(--accent);
color: var(--accent);
}
&:disabled {
opacity: 0.3;
cursor: not-allowed;
}
}
.deleteButton {
width: 28px;
height: 28px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: 1px solid var(--border);
border-radius: 4px;
color: var(--text-muted);
composes: deleteButton from '@common/assets/ui.module.css';
font-size: 18px;
cursor: pointer;
transition: all var(--transition);
&:hover {
background: var(--danger);
border-color: var(--danger);
color: var(--bg);
}
}
.content {
@ -181,20 +124,7 @@
}
.textarea {
width: 100%;
composes: textarea from '@common/assets/ui.module.css';
padding: 10px 12px;
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
font-size: 14px;
color: var(--text);
font-family: inherit;
resize: vertical;
min-height: 80px;
box-sizing: border-box;
&:focus {
outline: none;
border-color: var(--accent);
}
}

View File

@ -107,16 +107,11 @@
}
.form {
display: flex;
flex-direction: column;
gap: 16px;
flex: 1;
composes: form from '@common/assets/ui.module.css';
}
.formGroup {
display: flex;
flex-direction: column;
gap: 4px;
composes: formGroup from '@common/assets/ui.module.css';
}
.formGroupFill {
@ -124,9 +119,7 @@
}
.label {
display: block;
margin-bottom: 4px;
font-weight: bold;
composes: label from '@common/assets/ui.module.css';
}
.selectMultiline {
@ -143,23 +136,21 @@
padding-inline-start: 16px;
}
.input,
.select,
.textarea {
width: 100%;
padding: 8px;
border-radius: 4px;
border: 1px solid var(--border);
background: var(--bg);
color: var(--text);
.input {
composes: input from '@common/assets/ui.module.css';
}
.select {
composes: select from '@common/assets/ui.module.css';
}
.textarea {
composes: textarea from '@common/assets/ui.module.css';
resize: none;
font-family: inherit;
font-size: inherit;
line-height: 1.5;
flex: 1;
min-height: unset;
}
.footer {
@ -171,26 +162,20 @@
}
.button {
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
composes: button from '@common/assets/ui.module.css';
}
.buttonSecondary {
border: 1px solid var(--border);
background: transparent;
color: var(--text);
composes: buttonSecondary from '@common/assets/ui.module.css';
}
.buttonPrimary {
border: none;
background: var(--accent);
composes: buttonPrimary from '@common/assets/ui.module.css';
color: var(--accent-text);
}
.inputRow {
display: flex;
gap: 8px;
composes: inputRow from '@common/assets/ui.module.css';
}
.inputRow .input {
@ -203,7 +188,7 @@
justify-content: center;
padding: 8px;
border: 1px solid var(--border);
border-radius: 4px;
border-radius: var(--radius);
background: var(--bg);
color: var(--text);
cursor: pointer;
@ -216,9 +201,7 @@
}
.divider {
height: 1px;
background: var(--border);
margin: 16px 0;
composes: divider from '@common/assets/ui.module.css';
}
.tokenList {
@ -229,27 +212,18 @@
}
.tokenItem {
display: flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
background: var(--bg-active);
composes: badge from '@common/assets/ui.module.css';
border: 1px solid var(--border);
border-radius: 4px;
color: var(--text);
border-radius: var(--radius);
}
.tokenRemoveButton {
background: none;
border: none;
cursor: pointer;
composes: badgeRemove from '@common/assets/ui.module.css';
padding: 0 2px;
font-size: 14px;
color: var(--text-muted);
}
.emptyText {
color: var(--text-muted);
composes: empty from '@common/assets/ui.module.css';
}
@media (max-width: 600px) {