feat: separate topbar, fix important styles
This commit is contained in:
@@ -0,0 +1,81 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import IconButton from "./IconButton.svelte";
|
||||||
|
import Segmented from "./Segmented.svelte";
|
||||||
|
import StatusDot from "./StatusDot.svelte";
|
||||||
|
import { CircleHelp, Moon, Sun } from "@lucide/svelte";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
theme: "light" | "dark";
|
||||||
|
ontoggle: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { theme, ontoggle }: Props = $props();
|
||||||
|
|
||||||
|
let lang = $state("RU");
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<header class="topbar">
|
||||||
|
<div class="brand">
|
||||||
|
<span class="brand-mark">EP</span>
|
||||||
|
<span>easy-png-tools</span>
|
||||||
|
</div>
|
||||||
|
<div class="top-actions">
|
||||||
|
<span class="status"><StatusDot /> AUTO PIPELINE</span>
|
||||||
|
<IconButton icon={CircleHelp} label="Help" onclick={() => {}} />
|
||||||
|
<IconButton
|
||||||
|
icon={theme === "light" ? Moon : Sun}
|
||||||
|
label="Toggle theme"
|
||||||
|
onclick={ontoggle}
|
||||||
|
/>
|
||||||
|
<Segmented
|
||||||
|
bind:value={lang}
|
||||||
|
options={[
|
||||||
|
{ value: "RU", label: "RU" },
|
||||||
|
{ value: "EN", label: "EN" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.topbar {
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 20;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
height: 64px;
|
||||||
|
padding: 0 clamp(20px, 4vw, 64px);
|
||||||
|
background: var(--panel);
|
||||||
|
border-bottom: 1px solid var(--line);
|
||||||
|
}
|
||||||
|
.brand {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
font: 600 14px var(--font-mono);
|
||||||
|
}
|
||||||
|
.brand-mark {
|
||||||
|
background: var(--blue);
|
||||||
|
color: #fff;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
font-size: 11px;
|
||||||
|
display: grid;
|
||||||
|
place-items: center;
|
||||||
|
}
|
||||||
|
.top-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 16px;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 7px;
|
||||||
|
color: var(--muted);
|
||||||
|
font: 10px var(--font-mono);
|
||||||
|
letter-spacing: 0.08em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -17,6 +17,15 @@ body {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Форм-контролы не наследуют шрифт семьи по умолчанию (браузер ставит Arial). */
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea,
|
||||||
|
optgroup {
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
/* Новый дизайн: токены (§2 плана redesign).
|
/* Новый дизайн: токены (§2 плана redesign).
|
||||||
Файл грузится только layout'ом новой ветки (preview/+layout), поэтому
|
Файл грузится только layout'ом новой ветки (preview/+layout), поэтому
|
||||||
глобально не конфликтует со старым app.css. */
|
глобально не конфликтует со старым app.css. */
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
import "$lib/styles/design2.css";
|
import "$lib/styles/design2.css";
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from "svelte";
|
||||||
import AppShell from "$lib/components/kit/AppShell.svelte";
|
import AppShell from "$lib/components/kit/AppShell.svelte";
|
||||||
import IconButton from "$lib/components/kit/IconButton.svelte";
|
import TopBar from "$lib/components/kit/TopBar.svelte";
|
||||||
import { Sun, Moon } from "@lucide/svelte";
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { children }: Props = $props();
|
let { children }: Props = $props();
|
||||||
|
|
||||||
let theme = $state<"light" | "dark">("light");
|
let theme = $state<"light" | "dark">("light");
|
||||||
@@ -17,24 +17,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="preview-root" data-theme={theme}>
|
<div class="preview-root" data-theme={theme}>
|
||||||
|
<TopBar {theme} ontoggle={toggle} />
|
||||||
<AppShell>{@render children()}</AppShell>
|
<AppShell>{@render children()}</AppShell>
|
||||||
<div class="theme-switch">
|
|
||||||
<IconButton
|
|
||||||
icon={theme === "light" ? Moon : Sun}
|
|
||||||
label="Toggle theme"
|
|
||||||
onclick={toggle}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
|
||||||
.preview-root {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
.theme-switch {
|
|
||||||
position: fixed;
|
|
||||||
top: 1rem;
|
|
||||||
right: 1rem;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { Upload, Settings2, RotateCcw, ChevronDown } from "@lucide/svelte";
|
||||||
CircleHelp,
|
|
||||||
Moon,
|
|
||||||
Upload,
|
|
||||||
Settings2,
|
|
||||||
RotateCcw,
|
|
||||||
ChevronDown,
|
|
||||||
} from "@lucide/svelte";
|
|
||||||
import StepCard from "$lib/components/kit/StepCard.svelte";
|
import StepCard from "$lib/components/kit/StepCard.svelte";
|
||||||
import Segmented from "$lib/components/kit/Segmented.svelte";
|
import Segmented from "$lib/components/kit/Segmented.svelte";
|
||||||
import SliderField from "$lib/components/kit/SliderField.svelte";
|
import SliderField from "$lib/components/kit/SliderField.svelte";
|
||||||
@@ -28,7 +21,6 @@
|
|||||||
let outlineColor = $state("#16202B");
|
let outlineColor = $state("#16202B");
|
||||||
let radius = $state(18);
|
let radius = $state(18);
|
||||||
let preserveAspect = $state(true);
|
let preserveAspect = $state(true);
|
||||||
let lang = $state("RU");
|
|
||||||
|
|
||||||
const previewTiles = [
|
const previewTiles = [
|
||||||
{ label: "SOURCE", caption: "original.png · 1200 × 800", bg: "#8d9aa5" },
|
{ label: "SOURCE", caption: "original.png · 1200 × 800", bg: "#8d9aa5" },
|
||||||
@@ -64,28 +56,6 @@
|
|||||||
<meta name="robots" content="noindex, nofollow" />
|
<meta name="robots" content="noindex, nofollow" />
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
||||||
<div class="topbar">
|
|
||||||
<div class="brand">
|
|
||||||
<span class="brand-mark">EP</span>
|
|
||||||
<span>easy-png-tools</span>
|
|
||||||
<span class="version">/ DEMO</span>
|
|
||||||
</div>
|
|
||||||
<div class="top-actions">
|
|
||||||
<span class="status"><StatusDot /> AUTO PIPELINE</span>
|
|
||||||
<IconButton icon={CircleHelp} label="Help" onclick={() => {}} />
|
|
||||||
<IconButton icon={Moon} label="Toggle theme" onclick={() => {}} />
|
|
||||||
<div class="language">
|
|
||||||
<Segmented
|
|
||||||
bind:value={lang}
|
|
||||||
options={[
|
|
||||||
{ value: "RU", label: "RU" },
|
|
||||||
{ value: "EN", label: "EN" },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="page-grid">
|
<div class="page-grid">
|
||||||
<section class="workspace">
|
<section class="workspace">
|
||||||
<div class="eyebrow">PNG PROCESSING <span>/</span> WORKSPACE</div>
|
<div class="eyebrow">PNG PROCESSING <span>/</span> WORKSPACE</div>
|
||||||
@@ -275,51 +245,6 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.topbar {
|
|
||||||
border-bottom: 1px solid var(--line);
|
|
||||||
background: var(--panel);
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
height: 64px;
|
|
||||||
padding: 0 clamp(20px, 4vw, 64px);
|
|
||||||
}
|
|
||||||
.brand {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
font: 600 14px var(--font-mono);
|
|
||||||
}
|
|
||||||
.brand-mark {
|
|
||||||
background: var(--blue);
|
|
||||||
color: #fff;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
font-size: 11px;
|
|
||||||
display: grid;
|
|
||||||
place-items: center;
|
|
||||||
}
|
|
||||||
.version {
|
|
||||||
color: var(--blue);
|
|
||||||
font: 10px var(--font-mono);
|
|
||||||
letter-spacing: 0.12em;
|
|
||||||
}
|
|
||||||
.top-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
}
|
|
||||||
.status {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 7px;
|
|
||||||
color: var(--muted);
|
|
||||||
font: 10px var(--font-mono);
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
}
|
|
||||||
.language :global(.segmented) {
|
|
||||||
height: 32px;
|
|
||||||
}
|
|
||||||
.page-grid {
|
.page-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: minmax(0, 1.05fr) minmax(520px, 0.95fr);
|
grid-template-columns: minmax(0, 1.05fr) minmax(520px, 0.95fr);
|
||||||
|
|||||||
Reference in New Issue
Block a user