refactor: separate components

This commit is contained in:
2026-10-04 08:48:14 +05:00
parent f89811c116
commit c4eab38866
63 changed files with 529 additions and 645 deletions
+46 -2
View File
@@ -1,6 +1,10 @@
<script lang="ts">
import type { Component } from "svelte";
import { ButtonVariantDefine, type ButtonVariant } from "../define";
import {
ButtonVariantDefine,
type ButtonVariant,
type ButtonSize,
} from "./define";
import Icon from "./Icon.svelte";
interface Props {
@@ -8,21 +12,27 @@
ariaLabel?: string;
onclick?: () => void;
variant?: ButtonVariant;
size?: ButtonSize;
icon?: Component<{ size?: number; class?: string }>;
disabled?: boolean;
type?: "button" | "submit";
}
let {
label,
ariaLabel = label,
onclick,
variant = ButtonVariantDefine.PRIMARY,
size = "m",
icon,
disabled = false,
type = "button",
}: Props = $props();
</script>
<button
class="btn btn--{variant}"
class="btn btn--{variant} btn--{size}"
class:btn--icon={!label}
{type}
{disabled}
aria-label={ariaLabel}
onclick={() => onclick?.()}
@@ -51,12 +61,36 @@
color: var(--color-background);
}
.btn--s {
gap: var(--space-m);
padding: var(--space-m) var(--space-l);
border-width: var(--size-border);
border-radius: var(--radius-m);
font-size: var(--font-size-s);
font-family: var(--font-mono);
font-weight: normal;
}
.btn--s.btn--icon {
padding: var(--space-s);
}
.btn--outline {
background: transparent;
color: var(--color-main-tint);
border-color: var(--color-main-tint);
}
.btn--s.btn--outline {
color: var(--color-text-muted);
border-color: var(--color-border);
}
.btn--s.btn--outline:hover {
color: var(--color-text);
border-color: var(--color-text-muted);
}
.btn--accent {
background: var(--color-accent);
color: var(--color-background);
@@ -69,6 +103,16 @@
border-color: var(--color-danger);
}
.btn--clear {
background: none;
border-color: transparent;
color: var(--color-text-muted);
}
.btn--clear:hover {
color: var(--color-text);
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
@@ -0,0 +1,56 @@
<script lang="ts">
interface Props {
label: string;
active?: boolean;
variant?: "filled" | "outline";
onclick?: () => void;
}
let { label, active = false, variant = "filled", onclick }: Props = $props();
</script>
<button
type="button"
class="chip chip--{variant}"
class:active
aria-pressed={active}
onclick={() => onclick?.()}
>
{label}
</button>
<style>
.chip {
border: var(--size-border) solid var(--color-border);
background: var(--color-panel);
color: var(--color-text-muted);
font: var(--font-size-s) var(--font-mono);
letter-spacing: var(--space-text-m);
text-transform: uppercase;
padding: var(--space-s) var(--space-m);
border-radius: var(--radius-m);
cursor: pointer;
}
.chip--filled.active {
background: var(--color-main);
color: var(--color-background);
border-color: var(--color-main);
}
.chip--outline {
padding: var(--space-m) 0;
background: var(--color-background);
border-radius: var(--radius-s);
text-transform: none;
}
.chip--outline:hover {
color: var(--color-text);
border-color: var(--color-main);
}
.chip--outline.active {
color: var(--color-main);
border-color: var(--color-main);
}
</style>
+16 -2
View File
@@ -1,6 +1,10 @@
<script lang="ts">
import type { Component } from "svelte";
import { ButtonVariantDefine, type ButtonVariant } from "../define";
import {
ButtonVariantDefine,
type ButtonVariant,
type ButtonSize,
} from "./define";
import Button from "./Button.svelte";
interface Props {
@@ -8,6 +12,7 @@
label: string;
onclick?: () => void;
variant?: ButtonVariant;
size?: ButtonSize;
disabled?: boolean;
}
@@ -16,8 +21,17 @@
label,
onclick,
variant = ButtonVariantDefine.PRIMARY,
size = "m",
disabled = false,
}: Props = $props();
</script>
<Button label="" {onclick} {variant} {disabled} {icon} ariaLabel={label} />
<Button
label=""
{onclick}
{variant}
{size}
{disabled}
{icon}
ariaLabel={label}
/>
+1 -1
View File
@@ -1,7 +1,7 @@
<script lang="ts">
import { Moon, Sun } from "@lucide/svelte";
import { t } from "$lib/i18n/t";
import IconButton from "../ui/IconButton.svelte";
import IconButton from "./IconButton.svelte";
interface Props {
theme: "light" | "dark";
-29
View File
@@ -1,29 +0,0 @@
<script lang="ts">
import { resolve } from "$app/paths";
import { t } from "$lib/i18n/t";
</script>
<nav class="nav">
<a href={resolve("/")}>{t("header.home")}</a>
<a href={resolve("/list-tools")}>{t("header.catalog")}</a>
<a href={resolve("/kit")}>{t("header.uiKit")}</a>
</nav>
<style>
.nav {
display: flex;
align-items: center;
gap: var(--space-xxl);
margin-right: var(--space-xxxl);
margin-left: auto;
}
.nav a {
color: var(--color-text);
font: bold var(--font-size-s) var(--font-mono);
white-space: nowrap;
text-decoration: none;
}
.nav a:hover {
color: var(--color-main);
}
</style>
@@ -0,0 +1,47 @@
<script lang="ts">
import { Upload } from "@lucide/svelte";
import Icon from "./Icon.svelte";
interface Props {
label: string;
accept?: string;
onfile: (file: File) => void;
}
let { label, accept = "image/*", onfile }: Props = $props();
</script>
<label class="upload">
<Icon icon={Upload} size={14} />
{label}
<input
type="file"
{accept}
onchange={(e) => {
const f = (e.target as HTMLInputElement).files?.[0];
if (f) onfile(f);
}}
/>
</label>
<style>
.upload {
display: inline-flex;
align-items: center;
gap: var(--space-m);
padding: var(--space-m) var(--space-l);
border: var(--size-border) solid var(--color-border);
border-radius: var(--radius-m);
font: var(--font-size-s) var(--font-mono);
color: var(--color-text-muted);
cursor: pointer;
}
.upload:hover {
color: var(--color-text);
border-color: var(--color-text-muted);
}
.upload input {
display: none;
}
</style>
+18
View File
@@ -0,0 +1,18 @@
export const ButtonVariantDefine = {
PRIMARY: "primary",
OUTLINE: "outline",
ACCENT: "accent",
DANGER: "danger",
CLEAR: "clear",
} as const;
export type ButtonVariant =
(typeof ButtonVariantDefine)[keyof typeof ButtonVariantDefine];
export const ButtonSizeDefine = {
M: "m",
S: "s",
} as const;
export type ButtonSize =
(typeof ButtonSizeDefine)[keyof typeof ButtonSizeDefine];