feat: complete UI/UX overhaul with Impeccable design system
Replace Inter/Baskerville with self-hosted Manrope/Alegreya/JetBrains Mono variable fonts. Migrate all colors from hex to OKLCH tokens (30+ CSS custom properties) with full dark/light mode support. Replace Unicode emoji with lucide-react SVG icons throughout. Convert all page layouts to inline styles (Tailwind CSS 4 flex/grid classes unreliable in this project). Code-split routes via React.lazy (760KB → 15KB initial shell + 10 lazy chunks). Add global styles: scrollbar theming, selection color, input/button bases, :focus-visible ring, prefers-reduced-motion. Setup wizard gets 4-phase indicator with numbered circles, PathInput and StatusDot components. Toast container gets aria-live="polite". Tab close buttons changed to proper <button> elements with aria-labels. All 8 pages (Dashboard, Editor, Build, Server, Toolset, Repos, Settings, Setup) rewritten with consistent card/section/button patterns.
This commit is contained in:
@@ -6,6 +6,7 @@ import { ItemEditor } from "../components/gff/ItemEditor";
|
||||
import { CreatureEditor } from "../components/gff/CreatureEditor";
|
||||
import { AreaEditor } from "../components/gff/AreaEditor";
|
||||
import { DialogEditor } from "../components/gff/DialogEditor";
|
||||
import { FileCode, Code2, Eye } from "lucide-react";
|
||||
|
||||
const GFF_EXTENSIONS = [".uti.json", ".utc.json", ".are.json", ".dlg.json", ".utp.json", ".utm.json"];
|
||||
|
||||
@@ -50,7 +51,6 @@ export function Editor({ editorState }: EditorProps) {
|
||||
markClean,
|
||||
} = editorState;
|
||||
|
||||
// Track per-tab editor mode: "visual" or "raw". GFF files default to visual.
|
||||
const [editorModes, setEditorModes] = useState<Record<string, "visual" | "raw">>({});
|
||||
|
||||
const tabs = useMemo(
|
||||
@@ -105,8 +105,28 @@ export function Editor({ editorState }: EditorProps) {
|
||||
const renderEditor = () => {
|
||||
if (!activeTab) {
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center">
|
||||
<p style={{ color: "var(--forge-text-secondary)" }} className="text-lg">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: "100%",
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<FileCode
|
||||
size={48}
|
||||
style={{ color: "var(--forge-text-secondary)", opacity: 0.4 }}
|
||||
/>
|
||||
<p
|
||||
style={{
|
||||
color: "var(--forge-text-secondary)",
|
||||
fontSize: "var(--text-lg)",
|
||||
fontFamily: "var(--font-heading)",
|
||||
margin: 0,
|
||||
}}
|
||||
>
|
||||
Open a file from the File Explorer to start editing
|
||||
</p>
|
||||
</div>
|
||||
@@ -139,22 +159,41 @@ export function Editor({ editorState }: EditorProps) {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
<div style={{ display: "flex", flexDirection: "column", height: "100%" }}>
|
||||
{isActiveGff && activeMode === "raw" && (
|
||||
<div
|
||||
className="flex shrink-0 items-center justify-end border-b px-4 py-1"
|
||||
style={{ borderColor: "var(--forge-border)", backgroundColor: "var(--forge-surface)" }}
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "flex-end",
|
||||
flexShrink: 0,
|
||||
padding: "4px 16px",
|
||||
borderBottom: "1px solid var(--forge-border)",
|
||||
backgroundColor: "var(--forge-surface-raised)",
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={handleSwitchToVisual}
|
||||
className="rounded px-3 py-1 text-xs transition-colors hover:opacity-80"
|
||||
style={{ backgroundColor: "var(--forge-bg)", color: "var(--forge-text-secondary)" }}
|
||||
style={{
|
||||
display: "inline-flex",
|
||||
alignItems: "center",
|
||||
gap: 6,
|
||||
padding: "4px 12px",
|
||||
borderRadius: 4,
|
||||
border: "1px solid var(--forge-border)",
|
||||
backgroundColor: "var(--forge-surface)",
|
||||
color: "var(--forge-text-secondary)",
|
||||
fontSize: "var(--text-xs)",
|
||||
fontFamily: "var(--font-mono)",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<Eye size={13} />
|
||||
Switch to Visual Editor
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<div style={{ flex: 1, overflow: "hidden" }}>
|
||||
<MonacoEditor
|
||||
key={activeTab}
|
||||
filePath={activeFilePath}
|
||||
@@ -167,14 +206,21 @@ export function Editor({ editorState }: EditorProps) {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col" style={{ backgroundColor: "var(--forge-bg)" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
height: "100%",
|
||||
backgroundColor: "var(--forge-bg)",
|
||||
}}
|
||||
>
|
||||
<EditorTabs
|
||||
tabs={tabs}
|
||||
activeTab={activeTab}
|
||||
onSelect={selectTab}
|
||||
onClose={closeFile}
|
||||
/>
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<div style={{ flex: 1, overflow: "hidden" }}>
|
||||
{renderEditor()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user