mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-16 15:08:46 +00:00
Button 및 Input 컴포넌트를 atoms 디렉터리로 이동 및 리팩토링
This commit is contained in:
35
src/lib/components/atoms/buttons/Button.svelte
Normal file
35
src/lib/components/atoms/buttons/Button.svelte
Normal file
@@ -0,0 +1,35 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
import type { ClassValue } from "svelte/elements";
|
||||
|
||||
interface Props {
|
||||
children?: Snippet;
|
||||
class?: ClassValue;
|
||||
color?: "primary" | "gray";
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
let { children, color = "primary", onclick, ...props }: Props = $props();
|
||||
|
||||
let bgColor = $derived(
|
||||
{
|
||||
primary: "bg-primary-600 active:bg-primary-500",
|
||||
gray: "bg-gray-300 active:bg-gray-400",
|
||||
}[color],
|
||||
);
|
||||
let textColor = $derived(
|
||||
{
|
||||
primary: "text-white",
|
||||
gray: "text-gray-800",
|
||||
}[color],
|
||||
);
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={onclick && (() => setTimeout(onclick, 100))}
|
||||
class={["h-12 min-w-fit rounded-xl font-medium", bgColor, textColor, props.class]}
|
||||
>
|
||||
<div class="h-full p-3 transition active:scale-95">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</button>
|
||||
28
src/lib/components/atoms/buttons/EntryButton.svelte
Normal file
28
src/lib/components/atoms/buttons/EntryButton.svelte
Normal file
@@ -0,0 +1,28 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
import type { ClassValue } from "svelte/elements";
|
||||
|
||||
import IconChevronRight from "~icons/material-symbols/chevron-right";
|
||||
|
||||
interface Props {
|
||||
children?: Snippet;
|
||||
class?: ClassValue;
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
let { children, onclick, ...props }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={onclick && (() => setTimeout(onclick, 100))}
|
||||
class={["rounded-xl active:bg-gray-100", props.class]}
|
||||
>
|
||||
<div class="flex h-full p-2 transition active:scale-95">
|
||||
<div class="flex-grow">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<div class="flex flex-shrink-0 items-center">
|
||||
<IconChevronRight class="text-xl text-gray-800" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
@@ -1,30 +1,24 @@
|
||||
<script lang="ts">
|
||||
import type { Component } from "svelte";
|
||||
import type { SvelteHTMLElements } from "svelte/elements";
|
||||
import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
|
||||
import { AdaptiveDiv } from "$lib/components/divs";
|
||||
|
||||
interface Props {
|
||||
icon: Component<SvelteHTMLElements["svg"]>;
|
||||
offset?: string;
|
||||
offset?: ClassValue;
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
let { icon: Icon, offset = "bottom-20", onclick }: Props = $props();
|
||||
|
||||
const click = () => {
|
||||
setTimeout(() => {
|
||||
onclick?.();
|
||||
}, 100);
|
||||
};
|
||||
</script>
|
||||
|
||||
<div class="pointer-events-none fixed inset-0">
|
||||
<div class="absolute w-full {offset}">
|
||||
<div class={["absolute w-full", offset]}>
|
||||
<AdaptiveDiv>
|
||||
<div class="relative">
|
||||
<div class="absolute bottom-4 right-4">
|
||||
<button
|
||||
onclick={click}
|
||||
onclick={onclick && (() => setTimeout(onclick, 100))}
|
||||
class="pointer-events-auto flex h-14 w-14 items-center justify-center rounded-full bg-gray-300 shadow-lg transition active:scale-95 active:bg-gray-400"
|
||||
>
|
||||
<Icon class="text-xl" />
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
children?: Snippet;
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
@@ -10,14 +10,10 @@
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => {
|
||||
setTimeout(() => {
|
||||
onclick?.();
|
||||
}, 100);
|
||||
}}
|
||||
onclick={onclick && (() => setTimeout(onclick, 100))}
|
||||
class="text-sm font-medium text-gray-800 underline underline-offset-2 active:rounded-xl active:bg-gray-100"
|
||||
>
|
||||
<div class="h-full w-full p-1 transition active:scale-95">
|
||||
<div class="h-full p-1 transition active:scale-95">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</button>
|
||||
2
src/lib/components/atoms/index.ts
Normal file
2
src/lib/components/atoms/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./buttons";
|
||||
export * from "./inputs";
|
||||
@@ -5,16 +5,18 @@
|
||||
import IconCheckCircleOutline from "~icons/material-symbols/check-circle-outline";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
checked?: boolean;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { children, checked = $bindable(false) }: Props = $props();
|
||||
let { checked = $bindable(false), children }: Props = $props();
|
||||
</script>
|
||||
|
||||
<label class="flex items-center gap-x-1">
|
||||
<input bind:checked type="checkbox" class="hidden" />
|
||||
{@render children?.()}
|
||||
<div>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
{#if checked}
|
||||
<IconCheckCircle class="text-primary-600" />
|
||||
{:else}
|
||||
@@ -17,7 +17,7 @@
|
||||
/>
|
||||
<!-- svelte-ignore a11y_label_has_associated_control -->
|
||||
<label
|
||||
class="absolute left-0 top-1/2 -translate-y-1/2 transform text-xl text-gray-400 transition-all duration-300 ease-in-out"
|
||||
class="pointer-events-none absolute left-0 top-1/2 -translate-y-1/2 transform text-xl text-gray-400 transition-all duration-300 ease-in-out"
|
||||
>
|
||||
{placeholder}
|
||||
</label>
|
||||
@@ -1,37 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
color?: "primary" | "gray";
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
let { children, color = "primary", onclick }: Props = $props();
|
||||
|
||||
const bgColorStyle = $derived(
|
||||
{
|
||||
primary: "bg-primary-600 active:bg-primary-500",
|
||||
gray: "bg-gray-300 active:bg-gray-400",
|
||||
}[color],
|
||||
);
|
||||
const fontColorStyle = $derived(
|
||||
{
|
||||
primary: "text-white",
|
||||
gray: "text-gray-800",
|
||||
}[color],
|
||||
);
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => {
|
||||
setTimeout(() => {
|
||||
onclick?.();
|
||||
}, 100);
|
||||
}}
|
||||
class="{bgColorStyle} {fontColorStyle} h-12 w-full min-w-fit rounded-xl font-medium"
|
||||
>
|
||||
<div class="h-full w-full p-3 transition active:scale-95">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</button>
|
||||
@@ -1,30 +0,0 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from "svelte";
|
||||
|
||||
import IconChevronRight from "~icons/material-symbols/chevron-right";
|
||||
|
||||
interface Props {
|
||||
children: Snippet;
|
||||
onclick?: () => void;
|
||||
}
|
||||
|
||||
let { children, onclick }: Props = $props();
|
||||
</script>
|
||||
|
||||
<button
|
||||
onclick={() => {
|
||||
setTimeout(() => {
|
||||
onclick?.();
|
||||
}, 100);
|
||||
}}
|
||||
class="w-full rounded-xl active:bg-gray-100"
|
||||
>
|
||||
<div class="flex w-full justify-between p-2 transition active:scale-95">
|
||||
<div>
|
||||
{@render children?.()}
|
||||
</div>
|
||||
<div class="flex items-center justify-center">
|
||||
<IconChevronRight class="text-xl text-gray-800" />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
@@ -2,7 +2,7 @@
|
||||
import type { Component } from "svelte";
|
||||
import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
|
||||
import type { Writable } from "svelte/store";
|
||||
import { EntryButton } from "$lib/components/buttons";
|
||||
import { EntryButton } from "$lib/components/atoms";
|
||||
import { getCategoryInfo, type CategoryInfo } from "$lib/modules/filesystem";
|
||||
import Categories, { type SelectedCategory } from "$lib/molecules/Categories";
|
||||
import { masterKeyStore } from "$lib/stores";
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<div class={["space-y-1", props.class]}>
|
||||
{#snippet subCategoryCreate()}
|
||||
<EntryButton onclick={onSubCategoryCreateClick}>
|
||||
<EntryButton onclick={onSubCategoryCreateClick} class="w-full">
|
||||
<div class="flex h-8 items-center gap-x-4">
|
||||
<IconAddCircle class="text-lg text-gray-600" />
|
||||
<p class="font-medium text-gray-700">카테고리 추가하기</p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { untrack } from "svelte";
|
||||
import { get, type Writable } from "svelte/store";
|
||||
import { CheckBox } from "$lib/components/inputs";
|
||||
import { CheckBox } from "$lib/components/atoms";
|
||||
import { getFileInfo, type FileInfo, type CategoryInfo } from "$lib/modules/filesystem";
|
||||
import { SortBy, sortEntries } from "$lib/modules/util";
|
||||
import type { SelectedCategory } from "$lib/molecules/Categories";
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Modal } from "$lib/components";
|
||||
import { Button } from "$lib/components/buttons";
|
||||
import { TextInput } from "$lib/components/inputs";
|
||||
import { Button, TextInput } from "$lib/components/atoms";
|
||||
|
||||
interface Props {
|
||||
onCreateClick: (name: string) => void;
|
||||
@@ -23,8 +22,8 @@
|
||||
<div class="mt-2 flex w-full">
|
||||
<TextInput bind:value={name} placeholder="카테고리 이름" />
|
||||
</div>
|
||||
<div class="mt-7 flex gap-2">
|
||||
<Button color="gray" onclick={closeModal}>닫기</Button>
|
||||
<Button onclick={() => onCreateClick(name)}>만들기</Button>
|
||||
<div class="mt-7 flex gap-x-2">
|
||||
<Button color="gray" onclick={closeModal} class="flex-1">닫기</Button>
|
||||
<Button onclick={() => onCreateClick(name)} class="flex-1">만들기</Button>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
Reference in New Issue
Block a user