musealpha / uiprototype2 /src /components /SettingsPanel.tsx
asdf98's picture
Upload 112 files
3d7d9b5 verified
import {
X,
Settings,
Keyboard,
Monitor,
Shield,
HardDrive,
Info,
} from "lucide-react";
import { useAppStore } from "../store";
import { useState } from "react";
type Tab =
| "general"
| "appearance"
| "shortcuts"
| "storage"
| "privacy"
| "about";
export const SettingsPanel = () => {
const { isSettingsOpen, setIsSettingsOpen } = useAppStore();
const [activeTab, setActiveTab] = useState<Tab>("general");
const tabs: { id: Tab; label: string; icon: React.ReactNode }[] = [
{ id: "general", label: "General", icon: <Settings size={16} /> },
{ id: "appearance", label: "Appearance", icon: <Monitor size={16} /> },
{
id: "shortcuts",
label: "Keyboard Shortcuts",
icon: <Keyboard size={16} />,
},
{ id: "storage", label: "Storage & Data", icon: <HardDrive size={16} /> },
{ id: "privacy", label: "Privacy & Security", icon: <Shield size={16} /> },
{ id: "about", label: "About", icon: <Info size={16} /> },
];
return (
<div
className={`absolute right-0 top-0 h-full w-[600px] z-40 bg-panel-bg shadow-2xl border-l border-panel-border flex flex-col transform transition-transform duration-500 ease-[cubic-bezier(0.19,1,0.22,1)] ${isSettingsOpen ? "translate-x-0" : "translate-x-full"}`}
>
<div className="h-14 border-b border-white/5 flex items-center justify-between px-6 bg-black/20 shrink-0">
<h2 className="text-ui-primary font-medium flex items-center gap-2">
<Settings size={16} className="text-ui-secondary" /> Settings
</h2>
<button
onClick={() => setIsSettingsOpen(false)}
className="text-ui-secondary hover:text-ui-primary p-1 rounded-md hover:bg-white/5 transition-colors"
>
<X size={18} />
</button>
</div>
<div className="flex flex-1 overflow-hidden">
{/* Sidebar */}
<div className="w-[200px] bg-black/10 border-r border-white/5 p-4 flex flex-col gap-1 overflow-y-auto custom-scrollbar shrink-0">
{tabs.map((tab) => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex items-center gap-3 px-3 py-2 rounded-lg text-sm transition-colors text-left ${activeTab === tab.id ? "bg-accent-blue text-white font-medium" : "text-ui-secondary hover:text-ui-primary hover:bg-white/5"}`}
>
{tab.icon}
{tab.label}
</button>
))}
</div>
{/* Content */}
<div className="flex-1 p-8 overflow-y-auto custom-scrollbar text-ui-primary text-sm">
<div
key={activeTab}
className="transition-all duration-200"
>
{activeTab === "general" && (
<div className="space-y-8">
<section>
<h3 className="text-base font-medium mb-4 text-white">
Startup & Behavior
</h3>
<div className="space-y-4">
<label className="flex items-center justify-between group cursor-pointer">
<div>
<div className="font-medium">
Open last board on startup
</div>
<div className="text-ui-secondary text-xs mt-0.5">
Automatically load the most recently used board
</div>
</div>
<div className="w-10 h-6 bg-accent-blue rounded-full relative transition-colors">
<div className="absolute right-1 top-1 w-4 h-4 bg-white rounded-full shadow" />
</div>
</label>
<label className="flex items-center justify-between group cursor-pointer">
<div>
<div className="font-medium">
Hardware Acceleration
</div>
<div className="text-ui-secondary text-xs mt-0.5">
Use GPU to render canvas (requires restart)
</div>
</div>
<div className="w-10 h-6 bg-accent-blue rounded-full relative transition-colors">
<div className="absolute right-1 top-1 w-4 h-4 bg-white rounded-full shadow" />
</div>
</label>
</div>
</section>
</div>
)}
{activeTab === "appearance" && (
<div className="space-y-8">
<section>
<h3 className="text-base font-medium mb-4 text-white">
Theme
</h3>
<div className="grid grid-cols-2 gap-4">
<div className="border border-accent-blue bg-black/20 p-4 rounded-lg cursor-pointer">
<div className="w-full h-20 bg-[#1C1C1E] rounded mb-3 border border-panel-border overflow-hidden flex">
<div className="w-1/3 bg-[#2A2A2E] border-r border-[#3A3A3E]" />
</div>
<div className="text-center font-medium">
Dark (Default)
</div>
</div>
<div className="border border-white/10 bg-black/20 p-4 rounded-lg cursor-pointer opacity-50 hover:opacity-100 transition-opacity">
<div className="w-full h-20 bg-gray-100 rounded mb-3 border border-gray-300 overflow-hidden flex">
<div className="w-1/3 bg-gray-200 border-r border-gray-300" />
</div>
<div className="text-center font-medium">Light</div>
</div>
</div>
</section>
<section>
<h3 className="text-base font-medium mb-4 text-white">
Canvas
</h3>
<div className="space-y-4">
<label className="flex items-center justify-between group cursor-pointer">
<div>
<div className="font-medium">Show grid</div>
<div className="text-ui-secondary text-xs mt-0.5">
Display a subtle dot grid on the canvas
</div>
</div>
<div className="w-10 h-6 bg-white/10 rounded-full relative transition-colors">
<div className="absolute left-1 top-1 w-4 h-4 bg-ui-secondary rounded-full shadow" />
</div>
</label>
</div>
</section>
</div>
)}
{activeTab === "shortcuts" && (
<div className="space-y-6">
<section>
<h3 className="text-base font-medium mb-4 text-white">
Global Shortcuts
</h3>
<div className="space-y-2">
{[
{ action: "Toggle Browser Panel", key: "B" },
{ action: "Toggle Library Panel", key: "L" },
{ action: "Open Settings", key: "Ctrl + ," },
{ action: "Pan Canvas", key: "Space + Drag" },
{ action: "Zoom Canvas", key: "Mouse Scroll" },
{ action: "Undo", key: "Ctrl + Z" },
{ action: "Redo", key: "Ctrl + Shift + Z" },
].map((kb) => (
<div
key={kb.action}
className="flex items-center justify-between py-2 border-b border-white/5"
>
<span className="text-ui-secondary">{kb.action}</span>
<span className="px-2 py-1 bg-black/30 border border-white/10 rounded text-xs font-mono text-ui-primary">
{kb.key}
</span>
</div>
))}
</div>
</section>
<div className="text-xs text-ui-secondary bg-accent-blue/10 text-accent-blue p-3 rounded-lg flex items-center gap-2">
<Info size={14} /> Custom shortcuts are planned for a future
update.
</div>
</div>
)}
{activeTab === "storage" && (
<div className="space-y-8">
<section>
<h3 className="text-base font-medium mb-4 text-white">
Local Library
</h3>
<div className="space-y-4">
<div className="bg-black/20 p-4 rounded-lg border border-white/5">
<div className="flex justify-between items-center mb-2">
<div className="font-medium text-white">
Image Storage Mode
</div>
<span className="text-xs font-medium text-accent-blue bg-accent-blue/10 px-2 py-0.5 rounded">
Embedded
</span>
</div>
<p className="text-ui-secondary text-xs">
Images are copied into the .refstudio save archive.
Makes boards easier to share but increases file size.
</p>
</div>
<button className="w-full py-2 bg-white/5 hover:bg-white/10 rounded-lg border border-white/10 transition-colors text-sm font-medium">
Clear Image Cache
</button>
</div>
</section>
<section>
<h3 className="text-base font-medium mb-4 text-white text-accent-amber">
Danger Zone
</h3>
<div className="border border-accent-amber/30 rounded-lg p-4 bg-accent-amber/5">
<div className="mb-3">
<div className="font-medium text-accent-amber">
Reset All Application Data
</div>
<div className="text-ui-secondary text-xs mt-1">
This will permanently delete all local boards,
settings, and library tags. This action cannot be
undone.
</div>
</div>
<button
className="bg-accent-amber text-black font-semibold px-4 py-2 rounded text-xs hover:bg-accent-amber/90 transition-colors"
onClick={() => {
if (
confirm(
"Are you sure you want to delete all data? This cannot be undone.",
)
) {
localStorage.clear();
window.location.reload();
}
}}
>
Factory Reset
</button>
</div>
</section>
</div>
)}
{activeTab === "privacy" && (
<div className="space-y-8">
<section>
<h3 className="text-base font-medium mb-4 text-white">
Privacy Preferences
</h3>
<p className="text-ui-secondary text-xs leading-relaxed mb-6">
Refstudio is designed to be local-first. We believe your
references belong to you. We do not track your usage,
collect telemetry, or analyze your boards.
</p>
<div className="space-y-4">
<label className="flex items-center justify-between group cursor-pointer">
<div>
<div className="font-medium">
Check for updates automatically
</div>
<div className="text-ui-secondary text-xs mt-0.5">
Pings our server once a day to check for new
versions
</div>
</div>
<div className="w-10 h-6 bg-accent-blue rounded-full relative transition-colors">
<div className="absolute right-1 top-1 w-4 h-4 bg-white rounded-full shadow" />
</div>
</label>
<label className="flex items-center justify-between group cursor-pointer opacity-50">
<div>
<div className="font-medium">
Share anonymous crash reports
</div>
<div className="text-ui-secondary text-xs mt-0.5">
Help us fix bugs by sending stack traces when the
app crashes
</div>
</div>
<div className="w-10 h-6 bg-white/10 rounded-full relative transition-colors">
<div className="absolute left-1 top-1 w-4 h-4 bg-ui-secondary rounded-full shadow" />
</div>
</label>
</div>
</section>
</div>
)}
{activeTab === "about" && (
<div className="space-y-8 flex flex-col items-center text-center mt-12">
<div className="w-20 h-20 bg-gradient-to-br from-[#1C1C1E] to-[#2A2A2E] border border-[#3A3A3E] rounded-2xl flex items-center justify-center shadow-2xl mb-4">
<Monitor size={32} className="text-accent-blue" />
</div>
<div>
<h1 className="text-2xl font-semibold text-white">
Refstudio
</h1>
<p className="text-ui-secondary mt-1">Version 1.0.0-beta</p>
</div>
<div className="max-w-xs text-ui-secondary text-sm leading-relaxed">
The zero-friction reference board for visual artists.
Local-first, private by default, and uncompromisingly fast.
</div>
<div className="flex gap-4 mt-4">
<a
href="#"
className="text-accent-blue hover:underline text-sm font-medium"
>
Website
</a>
<a
href="#"
className="text-accent-blue hover:underline text-sm font-medium"
>
Release Notes
</a>
<a
href="#"
className="text-accent-blue hover:underline text-sm font-medium"
>
License
</a>
</div>
</div>
)}
</div>
</div>
</div>
</div>
);
};