diff --git a/assets/css/display.css b/assets/css/display.css new file mode 100644 index 0000000..9f78b52 --- /dev/null +++ b/assets/css/display.css @@ -0,0 +1,80 @@ +/* Studio 2 display skins — Classic | Studio. Layout tokens only; palette matches main.css. */ + +:root, +[data-display='classic'], +[data-display='studio'] { + --display-bg: #09090b; + --display-fg: #e4e4e7; + --display-muted: #a1a1aa; + --display-border: rgba(255, 255, 255, 0.1); + --display-amber: #fbbf24; + --display-amber-fg: #09090b; + --display-radius: 8px; + --display-focus: rgba(252, 211, 77, 0.5); +} + +[data-display='classic'] { + --chrome-gap: 0.5rem; + --rail-h: 2.25rem; + --card-pad: 0.75rem; + --display-type-title: 1.75rem; + --display-type-body: 0.875rem; +} + +[data-display='studio'] { + --chrome-gap: 1rem; + --rail-h: 3rem; + --card-pad: 1rem; + --display-type-title: 1.875rem; + --display-type-body: 0.9375rem; +} + +[data-display] .display-rail { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + min-height: var(--rail-h); +} + +[data-display] .display-rail__seg { + min-height: var(--rail-h); + border-radius: var(--display-radius); + border: 1px solid var(--display-border); + padding: 0.5rem 1rem; + font-size: var(--display-type-body); + outline: none; + transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease; +} + +[data-display] .display-rail__seg:focus-visible { + box-shadow: 0 0 0 2px var(--display-focus); +} + +[data-display] .display-rail__seg[aria-pressed='true'], +[data-display] .display-rail__seg[data-active='true'] { + border-color: var(--display-amber); + background: var(--display-amber); + color: var(--display-amber-fg); +} + +[data-display] .display-rail__seg:disabled, +[data-display] .display-rail__seg[aria-disabled='true'] { + opacity: 0.55; + cursor: not-allowed; +} + +[data-display='studio'] .display-rail__seg { + font-weight: 600; + padding: 0.625rem 1.25rem; +} + +[data-display] .display-cta { + border-radius: calc(var(--display-radius) + 4px); + background: var(--display-amber); + color: var(--display-amber-fg); + font-weight: 600; +} + +[data-display] .display-cta:focus-visible { + box-shadow: 0 0 0 2px var(--display-focus); +} diff --git a/components/SettingsForm.vue b/components/SettingsForm.vue index 643b195..1ef255e 100644 --- a/components/SettingsForm.vue +++ b/components/SettingsForm.vue @@ -20,6 +20,37 @@ :class="noticeError ? 'border-red-400/30 bg-red-950/40 text-red-100' : 'border-emerald-400/20 bg-emerald-950/30 text-emerald-100'" >{{ notice }}

+
+

Display

+

Layout only. Jobs, engines, and library IDs stay the same.

+
+ + +
+
+

GPU & defaults

@@ -422,11 +453,12 @@ export interface SettingsFolder { unlocked: boolean } -type SettingsPanel = 'gpu' | 'storage' | 'login' | 'folders' | 'loras' | 'keeps' | 'prompts' +type SettingsPanel = 'display' | 'gpu' | 'storage' | 'login' | 'folders' | 'loras' | 'keeps' | 'prompts' type LoraKindFilter = 'all' | 'image' | 'video' const route = useRoute() const router = useRouter() +const { storedDisplayMode, setDisplayMode } = useDisplayMode() const folders = ref([]) const authMode = ref('') @@ -435,7 +467,7 @@ const notice = ref('') const noticeError = ref(false) let noticeTimer: ReturnType | null = null -const panelIds: SettingsPanel[] = ['gpu', 'storage', 'login', 'folders', 'loras', 'keeps', 'prompts'] +const panelIds: SettingsPanel[] = ['display', 'gpu', 'storage', 'login', 'folders', 'loras', 'keeps', 'prompts'] function parsePanel(raw: unknown): SettingsPanel { const value = String(raw || '') @@ -456,6 +488,7 @@ const activePanel = computed({ const navItems = computed(() => { const items: Array<{ id: SettingsPanel; label: string }> = [ + { id: 'display', label: 'Display' }, { id: 'gpu', label: 'GPU & defaults' }, { id: 'storage', label: 'Storage' } ] diff --git a/components/studio2/Bench.vue b/components/studio2/Bench.vue index ed6bd6c..e3fed91 100644 --- a/components/studio2/Bench.vue +++ b/components/studio2/Bench.vue @@ -1,5 +1,5 @@