mirror of
https://github.com/Ku6epXBOCTuK/easy-png-tools.git
synced 2026-11-13 17:08:20 +00:00
feat: flatten components/kit -> components folder
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
<script lang="ts">
|
||||
import { Check } from "@lucide/svelte";
|
||||
|
||||
// TODO: сделать эти типы общими для кнопок \ бейджей \ етц???
|
||||
const ToneVariantDefine = {
|
||||
DEFAULT: "default",
|
||||
ACCENT: "accent",
|
||||
SUCCESS: "success",
|
||||
WARNING: "warning",
|
||||
DANGER: "danger",
|
||||
INFO: "info",
|
||||
} as const;
|
||||
type ToneVariant = (typeof ToneVariantDefine)[keyof typeof ToneVariantDefine];
|
||||
|
||||
const BadgeVariantDefine = {
|
||||
DEFAULT: "default",
|
||||
OUTLINE: "outline",
|
||||
CLEAR: "clear",
|
||||
} as const;
|
||||
type BadgeVariant =
|
||||
(typeof BadgeVariantDefine)[keyof typeof BadgeVariantDefine];
|
||||
|
||||
interface Props {
|
||||
tone?: ToneVariant;
|
||||
variant?: BadgeVariant;
|
||||
check?: boolean;
|
||||
label?: string;
|
||||
}
|
||||
|
||||
let {
|
||||
tone = ToneVariantDefine.DEFAULT,
|
||||
variant = BadgeVariantDefine.DEFAULT,
|
||||
check = false,
|
||||
label = "",
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<span class="badge badge-tone--{tone} badge-variant--{variant}">
|
||||
{#if check}<Check size={12} />{/if}
|
||||
{label}
|
||||
</span>
|
||||
|
||||
<style>
|
||||
.badge {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-s);
|
||||
line-height: normal;
|
||||
font-family: var(--font-mono);
|
||||
font-size: var(--font-size-s);
|
||||
font-weight: bold;
|
||||
border-width: var(--size-border-thick);
|
||||
padding: var(--space-s) var(--space-m);
|
||||
}
|
||||
|
||||
.badge-tone--default {
|
||||
--color-badge-main: var(--color-main);
|
||||
--color-badge-tint: var(--color-main-tint);
|
||||
}
|
||||
.badge-tone--accent {
|
||||
--color-badge-main: var(--color-accent);
|
||||
--color-badge-tint: var(--color-accent-tint);
|
||||
}
|
||||
.badge-tone--success {
|
||||
--color-badge-main: var(--color-success);
|
||||
--color-badge-tint: var(--color-success-tint);
|
||||
}
|
||||
.badge-tone--danger {
|
||||
--color-badge-main: var(--color-danger);
|
||||
--color-badge-tint: var(--color-danger-tint);
|
||||
}
|
||||
.badge-tone--warning {
|
||||
--color-badge-main: var(--color-warning);
|
||||
--color-badge-tint: var(--color-warning-tint);
|
||||
}
|
||||
.badge-tone--info {
|
||||
--color-badge-main: var(--color-info);
|
||||
--color-badge-tint: var(--color-info-tint);
|
||||
}
|
||||
|
||||
.badge-variant--default {
|
||||
background-color: var(--color-badge-main);
|
||||
border-color: var(--color-badge-main);
|
||||
color: var(--color-background);
|
||||
}
|
||||
|
||||
.badge-variant--outline {
|
||||
background-color: transparent;
|
||||
border-color: var(--color-badge-tint);
|
||||
color: var(--color-badge-tint);
|
||||
}
|
||||
|
||||
.badge-variant--clear {
|
||||
background-color: transparent;
|
||||
border-color: transparent;
|
||||
color: var(--color-badge-tint);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import type { Component } from "svelte";
|
||||
import { ButtonVariantDefine, type ButtonVariant } from "../define";
|
||||
import Icon from "./Icon.svelte";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
ariaLabel?: string;
|
||||
onclick?: () => void;
|
||||
variant?: ButtonVariant;
|
||||
icon?: Component<{ size?: number; class?: string }>;
|
||||
disabled?: boolean;
|
||||
}
|
||||
let {
|
||||
label,
|
||||
ariaLabel = label,
|
||||
onclick,
|
||||
variant = ButtonVariantDefine.PRIMARY,
|
||||
icon,
|
||||
disabled = false,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
class="btn btn--{variant}"
|
||||
{disabled}
|
||||
aria-label={ariaLabel}
|
||||
onclick={() => onclick?.()}
|
||||
>
|
||||
{#if icon}
|
||||
<Icon {icon} size={14} />
|
||||
{/if}
|
||||
{#if label}
|
||||
<span class="btn-label">{label}</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: var(--space-m);
|
||||
padding: var(--space-m) var(--space-xl);
|
||||
border-color: var(--color-main);
|
||||
border-width: var(--size-border-thick);
|
||||
border-radius: var(--radius-s);
|
||||
font-size: var(--font-size-l);
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
background: var(--color-main);
|
||||
color: var(--color-background);
|
||||
}
|
||||
|
||||
.btn--outline {
|
||||
background: transparent;
|
||||
color: var(--color-main-tint);
|
||||
border-color: var(--color-main-tint);
|
||||
}
|
||||
|
||||
.btn--accent {
|
||||
background: var(--color-accent);
|
||||
color: var(--color-background);
|
||||
border-color: var(--color-accent);
|
||||
}
|
||||
|
||||
.btn--danger {
|
||||
background: var(--color-danger);
|
||||
color: var(--color-background);
|
||||
border-color: var(--color-danger);
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { Download } from "@lucide/svelte";
|
||||
import Button from "./Button.svelte";
|
||||
|
||||
interface Props {
|
||||
label: string;
|
||||
onclick?: () => void;
|
||||
}
|
||||
let { label, onclick }: Props = $props();
|
||||
</script>
|
||||
|
||||
<Button icon={Download} {label} {onclick} />
|
||||
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import type { Component } from "svelte";
|
||||
|
||||
interface Props {
|
||||
icon: Component<{ size?: number; class?: string }>;
|
||||
size?: number;
|
||||
}
|
||||
let { icon: IconComp, size = 16 }: Props = $props();
|
||||
</script>
|
||||
|
||||
<IconComp {size} />
|
||||
@@ -0,0 +1,23 @@
|
||||
<script lang="ts">
|
||||
import type { Component } from "svelte";
|
||||
import { ButtonVariantDefine, type ButtonVariant } from "../define";
|
||||
import Button from "./Button.svelte";
|
||||
|
||||
interface Props {
|
||||
icon: Component<{ size?: number; class?: string }>;
|
||||
label: string;
|
||||
onclick?: () => void;
|
||||
variant?: ButtonVariant;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
let {
|
||||
icon,
|
||||
label,
|
||||
onclick,
|
||||
variant = ButtonVariantDefine.PRIMARY,
|
||||
disabled = false,
|
||||
}: Props = $props();
|
||||
</script>
|
||||
|
||||
<Button label="" {onclick} {variant} {disabled} {icon} ariaLabel={label} />
|
||||
@@ -0,0 +1,46 @@
|
||||
<script lang="ts">
|
||||
let lang = $state("RU");
|
||||
|
||||
// TODO: change to sectioned dual buttons
|
||||
</script>
|
||||
|
||||
<div class="lang" role="group" aria-label="Language">
|
||||
<button
|
||||
type="button"
|
||||
class="lang-btn"
|
||||
class:active={lang === "RU"}
|
||||
onclick={() => (lang = "RU")}
|
||||
>
|
||||
RU
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="lang-btn"
|
||||
class:active={lang === "EN"}
|
||||
onclick={() => (lang = "EN")}>EN</button
|
||||
>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.lang {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: var(--size-border) solid var(--color-border);
|
||||
}
|
||||
.lang-btn {
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--color-text-muted);
|
||||
font: var(--font-size-s) var(--font-mono);
|
||||
padding: var(--space-s) var(--space-m);
|
||||
cursor: pointer;
|
||||
}
|
||||
.lang-div {
|
||||
color: var(--color-text);
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
.lang-btn.active {
|
||||
background: var(--color-text);
|
||||
color: var(--color-background);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,65 @@
|
||||
<script lang="ts">
|
||||
interface Option {
|
||||
value: string;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
options: Option[];
|
||||
value?: string;
|
||||
wide?: boolean;
|
||||
onchange?: (value: string) => void;
|
||||
}
|
||||
let {
|
||||
options,
|
||||
wide = false,
|
||||
value = $bindable(),
|
||||
onchange,
|
||||
}: Props = $props();
|
||||
|
||||
function select(v: string) {
|
||||
value = v;
|
||||
onchange?.(v);
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="segmented" class:wide role="group">
|
||||
{#each options as opt (opt.value)}
|
||||
<button
|
||||
type="button"
|
||||
class="segment"
|
||||
class:selected={value === opt.value}
|
||||
aria-pressed={value === opt.value}
|
||||
onclick={() => select(opt.value)}
|
||||
>
|
||||
{opt.label}
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.segmented {
|
||||
display: inline-flex;
|
||||
border: var(--size-border) solid var(--color-border);
|
||||
cursor: pointer;
|
||||
&.wide {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.segment {
|
||||
border: 0;
|
||||
border-right: var(--size-border) solid var(--color-border);
|
||||
color: var(--color-text-muted);
|
||||
font: var(--font-size-s) var(--font-mono);
|
||||
background: 0 0;
|
||||
padding: var(--space-m);
|
||||
flex: 1;
|
||||
}
|
||||
.segment:last-child {
|
||||
border-right: 0px;
|
||||
}
|
||||
.segment.selected {
|
||||
background: var(--color-main);
|
||||
color: var(--color-background);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import { Moon, Sun } from "@lucide/svelte";
|
||||
import IconButton from "../ui/IconButton.svelte";
|
||||
|
||||
interface Props {
|
||||
theme: "light" | "dark";
|
||||
ontoggle: () => void;
|
||||
}
|
||||
|
||||
let { theme, ontoggle }: Props = $props();
|
||||
|
||||
// TODO: change icon animations - custom button instead of IconButton
|
||||
</script>
|
||||
|
||||
<IconButton
|
||||
icon={theme === "light" ? Moon : Sun}
|
||||
label="Toggle theme"
|
||||
variant="clear"
|
||||
onclick={ontoggle}
|
||||
/>
|
||||
@@ -0,0 +1,45 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
checked: boolean;
|
||||
label?: string;
|
||||
onchange?: (checked: boolean) => void;
|
||||
}
|
||||
let { checked = $bindable(), label, onchange }: Props = $props();
|
||||
|
||||
function handle() {
|
||||
checked = !checked;
|
||||
onchange?.(checked);
|
||||
}
|
||||
</script>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="toggle"
|
||||
class:on={checked}
|
||||
role="switch"
|
||||
aria-checked={checked}
|
||||
aria-label={label}
|
||||
onclick={handle}
|
||||
>
|
||||
<i class="toggle-knob"></i>
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.toggle {
|
||||
position: relative;
|
||||
width: var(--space-xxxl);
|
||||
height: var(--space-xl);
|
||||
border: var(--size-border) solid var(--color-border);
|
||||
border-radius: 0;
|
||||
background: var(--color-background);
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
}
|
||||
.toggle.on {
|
||||
background: var(--color-main);
|
||||
border-color: var(--color-main);
|
||||
}
|
||||
.toggle-knob {
|
||||
transition: transform var(--duration-s) ease;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { resolve } from "$app/paths";
|
||||
</script>
|
||||
|
||||
<nav class="nav">
|
||||
<a href={resolve("/")}>Home page</a>
|
||||
<a href={resolve("/list-tools")}>Catalog</a>
|
||||
<a href={resolve("/kit")}> UI Kit </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>
|
||||
Reference in New Issue
Block a user