mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
refactor: separate components
This commit is contained in:
@@ -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>
|
||||
@@ -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,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";
|
||||
|
||||
@@ -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>
|
||||
@@ -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];
|
||||
Reference in New Issue
Block a user