fix: css fixes

This commit is contained in:
2026-09-08 18:29:56 +05:00
parent 3f21f1c024
commit 420d03f58c
16 changed files with 130 additions and 129 deletions
@@ -46,6 +46,7 @@
} }
.tool-cards { .tool-cards {
display: grid; display: grid;
grid-template-columns: 1fr 1fr;
gap: var(--space-m); gap: var(--space-m);
} }
</style> </style>
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import { Filter, Search } from "@lucide/svelte"; import { Funnel, Search } from "@lucide/svelte";
interface Props { interface Props {
query: string; query: string;
@@ -18,6 +18,8 @@
{ value: "analyze", label: "ANALYZE" }, { value: "analyze", label: "ANALYZE" },
{ value: "generate", label: "GENERATE" }, { value: "generate", label: "GENERATE" },
]; ];
// TODO: Button component
</script> </script>
<div class="catalog-toolbar"> <div class="catalog-toolbar">
@@ -30,13 +32,15 @@
/> />
</label> </label>
<div class="catalog-filters"> <div class="catalog-filters">
<Filter size={15} /> <Funnel size={15} />
{#each FILTERS as f (f.value)} {#each FILTERS as f (f.value)}
<button <button
type="button" type="button"
class:active={category === f.value} class:active={category === f.value}
onclick={() => (category = f.value)}>{f.label}</button onclick={() => (category = f.value)}
> >
{f.label}
</button>
{/each} {/each}
</div> </div>
</div> </div>
@@ -79,7 +83,7 @@
} }
.catalog-filters button { .catalog-filters button {
border: var(--size-border) solid var(--color-border); border: var(--size-border) solid var(--color-border);
background: transparent; background: var(--color-panel);
color: var(--color-text-muted); color: var(--color-text-muted);
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
letter-spacing: var(--space-text-m); letter-spacing: var(--space-text-m);
+2 -2
View File
@@ -73,8 +73,8 @@
cursor: pointer; cursor: pointer;
text-align: center; text-align: center;
transition: transition:
border-color var(--duration-m) ease, border-color var(--duration-s) ease,
background var(--duration-m) ease; background var(--duration-s) ease;
} }
.dropzone:hover, .dropzone:hover,
.dropzone:focus-visible, .dropzone:focus-visible,
@@ -26,6 +26,7 @@
gap: var(--space-xl); gap: var(--space-xl);
padding: var(--space-l) var(--space-xl); padding: var(--space-l) var(--space-xl);
border-bottom: var(--size-border) solid var(--color-border); border-bottom: var(--size-border) solid var(--color-border);
margin-bottom: var(--space-m);
} }
.heading-text { .heading-text {
display: flex; display: flex;
@@ -1,8 +1,8 @@
<script lang="ts"> <script lang="ts">
import SchemaTextResult from "./SchemaTextResult.svelte";
import { toDataUrl } from "$lib/core/io"; import { toDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import { Check } from "@lucide/svelte"; import { Check, RefreshCw } from "@lucide/svelte";
import SchemaTextResult from "./SchemaTextResult.svelte";
interface Props { interface Props {
resultKind?: "image" | "text" | "verdict"; resultKind?: "image" | "text" | "verdict";
@@ -27,7 +27,14 @@
</script> </script>
<figure class="tile" style:grid-column={wide ? "1 / -1" : undefined}> <figure class="tile" style:grid-column={wide ? "1 / -1" : undefined}>
<figcaption><span>RESULT {running ? "…" : ""}</span></figcaption> <figcaption>
<span>
RESULT
{#if running}
<RefreshCw class="rotating" size="16" />
{/if}
</span>
</figcaption>
<div class="canvas" class:checker={resultKind === "image"}> <div class="canvas" class:checker={resultKind === "image"}>
{#if resultKind === "text" && textResult} {#if resultKind === "text" && textResult}
<div class="text-result-wrap"> <div class="text-result-wrap">
@@ -65,6 +72,9 @@
margin-bottom: var(--space-m); margin-bottom: var(--space-m);
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
color: var(--color-text-muted); color: var(--color-text-muted);
& :global(.rotating) {
animation: rotate var(--duration-l) linear infinite;
}
} }
.canvas { .canvas {
display: flex; display: flex;
@@ -72,7 +82,7 @@
justify-content: center; justify-content: center;
min-height: clamp(var(--space-brand), 30vh, 60vh); min-height: clamp(var(--space-brand), 30vh, 60vh);
border: var(--size-border) solid var(--color-border); border: var(--size-border) solid var(--color-border);
border-radius: var(--radius-m); border-radius: var(--radius-s);
overflow: hidden; overflow: hidden;
background: var(--color-background-muted); background: var(--color-background-muted);
color: var(--color-text-muted); color: var(--color-text-muted);
@@ -98,4 +108,13 @@
padding: var(--space-l); padding: var(--space-l);
box-sizing: border-box; box-sizing: border-box;
} }
@keyframes rotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
</style> </style>
@@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import SchemaTextSource from "./SchemaTextSource.svelte";
import { toDataUrl } from "$lib/core/io"; import { toDataUrl } from "$lib/core/io";
import type { PixelImage } from "$lib/core/types"; import type { PixelImage } from "$lib/core/types";
import SchemaTextSource from "./SchemaTextSource.svelte";
interface Props { interface Props {
mode: "file" | "text"; mode: "file" | "text";
@@ -58,7 +58,7 @@
justify-content: center; justify-content: center;
min-height: clamp(var(--space-brand), 30vh, 60vh); min-height: clamp(var(--space-brand), 30vh, 60vh);
border: var(--size-border) solid var(--color-border); border: var(--size-border) solid var(--color-border);
border-radius: var(--radius-m); border-radius: var(--radius-s);
overflow: hidden; overflow: hidden;
background: var(--color-background-muted); background: var(--color-background-muted);
color: var(--color-text-muted); color: var(--color-text-muted);
@@ -221,6 +221,7 @@
.schema-tool { .schema-tool {
padding: calc(var(--space-xxxl) + var(--space-l)) padding: calc(var(--space-xxxl) + var(--space-l))
clamp(var(--space-m), 4vw, var(--space-xxxl)); clamp(var(--space-m), 4vw, var(--space-xxxl));
flex: 1;
} }
.header { .header {
display: flex; display: flex;
+3 -3
View File
@@ -29,9 +29,9 @@
<style> <style>
.tool-card { .tool-card {
display: grid; display: grid;
grid-template-columns: var(--size-tool-icon) minmax(0, 1fr) var( grid-template-columns:
--space-xxl var(--size-tool-icon) minmax(0, 1fr) var(--space-xxl)
) var(--size-tool-arrow); var(--size-tool-arrow);
align-items: center; align-items: center;
gap: var(--space-l); gap: var(--space-l);
min-height: var(--size-tool-min-height); min-height: var(--size-tool-min-height);
@@ -13,6 +13,7 @@
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: var(--space-xl); padding: var(--space-xl);
background: var(--color-background);
border-top: var(--size-border) solid var(--color-border); border-top: var(--size-border) solid var(--color-border);
font: var(--font-size-s) var(--font-mono); font: var(--font-size-s) var(--font-mono);
color: var(--color-text-muted); color: var(--color-text-muted);
@@ -9,8 +9,10 @@
type="button" type="button"
class="lang-btn" class="lang-btn"
class:active={lang === "RU"} class:active={lang === "RU"}
onclick={() => (lang = "RU")}>RU</button onclick={() => (lang = "RU")}
><span class="lang-div">/</span> >
RU
</button>
<button <button
type="button" type="button"
class="lang-btn" class="lang-btn"
+1 -4
View File
@@ -3,11 +3,8 @@
</script> </script>
<nav class="nav"> <nav class="nav">
<a href={resolve("/preview")}>Home page</a>
<a href={resolve("/preview/list-tools")}>Catalog</a> <a href={resolve("/preview/list-tools")}>Catalog</a>
<a href={resolve("/preview/tools/linear-gradient-png")}>Gradient</a>
<a href={resolve("/preview/tools/remove-background-png")}>
Background remover
</a>
<a href={resolve("/preview/kit")}> UI Kit </a> <a href={resolve("/preview/kit")}> UI Kit </a>
</nav> </nav>
+7 -6
View File
@@ -2,14 +2,16 @@
import type { OutputMime } from "./core/io"; import type { OutputMime } from "./core/io";
import type { PixelImage } from "./core/types"; import type { PixelImage } from "./core/types";
import { convertEntries } from "./registry/convert";
import { geometryEntries } from "./registry/geometry";
import { alphaEntries } from "./registry/alpha"; import { alphaEntries } from "./registry/alpha";
import { colorEntries } from "./registry/color";
import { analyzeEntries } from "./registry/analyze"; import { analyzeEntries } from "./registry/analyze";
import { generateEntries } from "./registry/generate"; import { colorEntries } from "./registry/color";
import { textEntries } from "./registry/text"; import { convertEntries } from "./registry/convert";
import { filterEntries } from "./registry/filters"; import { filterEntries } from "./registry/filters";
import { generateEntries } from "./registry/generate";
import { geometryEntries } from "./registry/geometry";
import { textEntries } from "./registry/text";
// TODO: remove convert tools - move to load image \ download button flow
export type ParamDef = export type ParamDef =
| { | {
@@ -119,7 +121,6 @@ export const TOOLS: ToolEntry[] = [
..._analyze.slice(11, 13), ..._analyze.slice(11, 13),
]; ];
import { TOOL_ICONS } from "./tools/tool-icons";
import { TOOL_POPULARITY } from "./tools/tool-popularity"; import { TOOL_POPULARITY } from "./tools/tool-popularity";
for (const entry of TOOLS) { for (const entry of TOOLS) {
+3 -2
View File
@@ -176,8 +176,9 @@
--radius-s: 0px; --radius-s: 0px;
--radius-m: 4px; --radius-m: 4px;
--duration-s: 0.12s; --duration-s: 0.15s;
--duration-m: 0.15s; --duration-m: 0.3s;
--duration-l: 0.8s;
} }
[data-theme="dark"] { [data-theme="dark"] {
+3 -1
View File
@@ -56,12 +56,14 @@
</main> </main>
<style> <style>
main { .preview-root {
background-color: var(--color-background); background-color: var(--color-background);
background-image: background-image:
linear-gradient(var(--color-background-muted) 1px, transparent 1px), linear-gradient(var(--color-background-muted) 1px, transparent 1px),
linear-gradient(90deg, var(--color-background-muted) 1px, transparent 1px); linear-gradient(90deg, var(--color-background-muted) 1px, transparent 1px);
background-size: var(--space-xxxl) var(--space-xxxl); background-size: var(--space-xxxl) var(--space-xxxl);
min-height: 100vh; min-height: 100vh;
display: flex;
flex-direction: column;
} }
</style> </style>
+58 -88
View File
@@ -1,108 +1,78 @@
<script lang="ts"> <script lang="ts">
import TextField from "$lib/components/kit/fields/TextField.svelte"; import CatalogGroup from "$lib/components/kit/CatalogGroup.svelte";
import Panel from "$lib/components/kit/layout/Panel.svelte"; import CatalogHeader from "$lib/components/kit/CatalogHeader.svelte";
import SettingsFooter from "$lib/components/kit/SettingsFooter.svelte"; import CatalogToolbar from "$lib/components/kit/CatalogToolbar.svelte";
import ToolCard from "$lib/components/kit/ToolCard.svelte"; import ToolCard from "$lib/components/kit/ToolCard.svelte";
import Button from "$lib/components/kit/ui/Button.svelte"; import { PREVIEW_GROUPS, PREVIEW_TOTAL } from "$lib/preview/catalog";
import { TOOLS } from "$lib/registry-new"; import { TOOL_ICONS } from "$lib/preview/tool-icons";
import { Search } from "@lucide/svelte";
let query = $state(""); let query = $state("");
const results = $derived( let category = $state<string>("all");
TOOLS.filter((t) =>
(t.title + " " + t.description) const groups = $derived(
.toLowerCase() PREVIEW_GROUPS.map((g) => ({
.includes(query.toLowerCase()), id: g.id,
).slice(0, 24), label: g.label,
tools: g.tools.filter(
(t) =>
(category === "all" || category === g.id) &&
(query.trim() === "" ||
t.title.toLowerCase().includes(query.trim().toLowerCase()) ||
t.description.toLowerCase().includes(query.trim().toLowerCase())),
),
})).filter((g) => g.tools.length > 0),
); );
// TODO: make main page different from catalog - larger and simpler search, no categories
</script> </script>
<section class="workspace"> <div class="catalog-page">
<header class="ws-head"> <CatalogHeader total={PREVIEW_TOTAL} />
<span class="ws-eyebrow">EASY PNG TOOLS</span> <CatalogToolbar bind:query bind:category />
<h1 class="ws-title">Workspace</h1> <div class="catalog-groups">
<p class="ws-lede"> {#each groups as group (group.id)}
Откройте PNG-инструмент, загрузите изображение и получите результат без <CatalogGroup label={group.label} count={group.tools.length}>
установки и регистрации. {#each group.tools as tool, i (tool.id)}
</p>
</header>
<Panel title="Search" eyebrow="tools">
<div class="ws-search">
<div class="ws-field">
<TextField
label="Search tools"
bind:value={query}
placeholder="Search tools…"
/>
</div>
<Button
icon={Search}
variant="primary"
onclick={() => {}}
label="Search"
/>
</div>
<div class="ws-results">
{#each results as tool (tool.id)}
<ToolCard <ToolCard
title={tool.title} title={tool.title}
id={tool.id} id={tool.id}
description={tool.description} description={tool.description}
index={i + 1}
icon={TOOL_ICONS[tool.id]}
/> />
{/each} {/each}
</CatalogGroup>
{/each}
</div>
<footer class="catalog-footer">
ALL OPERATIONS RUN LOCALLY <span></span> YOUR FILES NEVER LEAVE THIS DEVICE
</footer>
</div> </div>
<SettingsFooter>
<Button onclick={() => {}} label="Open last project" />
</SettingsFooter>
</Panel>
</section>
<style> <style>
.workspace { .catalog-page {
max-width: var(--size-content-max); padding: var(--space-page-top)
margin: 0 auto; clamp(var(--space-xxl), 4vw, var(--space-page-bottom))
padding: var(--space-page-top) var(--space-xl) var(--space-page-bottom); var(--space-page-bottom);
display: flex;
flex-direction: column;
gap: var(--space-xxl);
} }
.ws-head { .catalog-groups {
display: flex;
flex-direction: column;
gap: var(--space-m);
}
.ws-eyebrow {
font-family: var(--font-mono);
font-size: var(--font-size-s);
letter-spacing: var(--space-text-2xl);
color: var(--color-text-muted);
}
.ws-title {
margin: 0;
font-size: var(--font-size-2xl);
font-weight: 700;
color: var(--color-text);
}
.ws-lede {
margin: 0;
max-width: 56ch;
color: var(--color-text-muted);
font-size: var(--font-size-l);
}
.ws-search {
display: flex;
gap: var(--space-m);
padding: var(--space-l) var(--space-xl);
align-items: center;
}
.ws-field {
flex: 1;
}
.ws-results {
display: grid; display: grid;
grid-template-columns: repeat(auto-fill, minmax(var(--size-card-min), 1fr)); gap: var(--space-page-top) var(--space-xxl);
gap: var(--space-l); }
padding: var(--space-m) var(--space-xl); .catalog-footer {
display: flex;
gap: var(--space-xxl);
flex-wrap: wrap;
margin-top: var(--space-page-top);
padding-top: var(--space-xxl);
border-top: var(--size-border) solid var(--color-border);
font: var(--font-size-xs) var(--font-mono);
letter-spacing: var(--space-text-l);
color: var(--color-text-muted);
}
@media (--bp-tablet) {
.catalog-groups {
grid-template-columns: 1fr;
}
} }
</style> </style>
@@ -1,10 +1,10 @@
<script lang="ts"> <script lang="ts">
import { PREVIEW_GROUPS, PREVIEW_TOTAL } from "$lib/preview/catalog"; import CatalogGroup from "$lib/components/kit/CatalogGroup.svelte";
import { TOOL_ICONS } from "$lib/preview/tool-icons";
import CatalogHeader from "$lib/components/kit/CatalogHeader.svelte"; import CatalogHeader from "$lib/components/kit/CatalogHeader.svelte";
import CatalogToolbar from "$lib/components/kit/CatalogToolbar.svelte"; import CatalogToolbar from "$lib/components/kit/CatalogToolbar.svelte";
import CatalogGroup from "$lib/components/kit/CatalogGroup.svelte";
import ToolCard from "$lib/components/kit/ToolCard.svelte"; import ToolCard from "$lib/components/kit/ToolCard.svelte";
import { PREVIEW_GROUPS, PREVIEW_TOTAL } from "$lib/preview/catalog";
import { TOOL_ICONS } from "$lib/preview/tool-icons";
let query = $state(""); let query = $state("");
let category = $state<string>("all"); let category = $state<string>("all");
@@ -22,6 +22,8 @@
), ),
})).filter((g) => g.tools.length > 0), })).filter((g) => g.tools.length > 0),
); );
// TODO: переделать расположение - категория выводится в 2 колонки, а не как сейчас - каждая категория - 1 колонка и две категории в ряд
</script> </script>
<div class="catalog-page"> <div class="catalog-page">
@@ -55,7 +57,6 @@
} }
.catalog-groups { .catalog-groups {
display: grid; display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-page-top) var(--space-xxl); gap: var(--space-page-top) var(--space-xxl);
} }
.catalog-footer { .catalog-footer {