IconEntryButton 컴포넌트 추가

This commit is contained in:
static
2025-01-26 22:04:53 +09:00
parent c709a79266
commit 32ecf46341
13 changed files with 186 additions and 93 deletions

View File

@@ -17,8 +17,8 @@
onclick={onclick && (() => setTimeout(onclick, 100))} onclick={onclick && (() => setTimeout(onclick, 100))}
class={["rounded-xl active:bg-gray-100", props.class]} class={["rounded-xl active:bg-gray-100", props.class]}
> >
<div class="flex h-full p-2 transition active:scale-95"> <div class="flex h-full gap-x-4 p-2 transition active:scale-95">
<div class="flex-grow"> <div class="h-full flex-grow">
{@render children?.()} {@render children?.()}
</div> </div>
<div class="flex flex-shrink-0 items-center"> <div class="flex flex-shrink-0 items-center">

View File

@@ -0,0 +1,23 @@
<script lang="ts">
import type { Component, Snippet } from "svelte";
import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
import { EntryButton } from "$lib/components/atoms";
import { IconLabel } from "$lib/components/molecules";
interface Props {
children?: Snippet;
class?: ClassValue;
icon: Component<SvelteHTMLElements["svg"]>;
iconClass?: ClassValue;
onclick?: () => void;
textClass?: ClassValue;
}
let { children, icon, onclick, ...props }: Props = $props();
</script>
<EntryButton {onclick} class={props.class}>
<IconLabel {icon} class="h-full" iconClass={props.iconClass} textClass={props.textClass}>
{@render children?.()}
</IconLabel>
</EntryButton>

View File

@@ -1,3 +1,5 @@
export * from "./ActionModal.svelte"; export * from "./ActionModal.svelte";
export { default as ActionModal } from "./ActionModal.svelte"; export { default as ActionModal } from "./ActionModal.svelte";
export { default as IconEntryButton } from "./IconEntryButton.svelte";
export * from "./labels";
export { default as TopBar } from "./TopBar.svelte"; export { default as TopBar } from "./TopBar.svelte";

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import type { ClassValue } from "svelte/elements";
import { IconLabel } from "$lib/components/molecules";
import IconCategory from "~icons/material-symbols/category";
interface Props {
class?: ClassValue;
name: string;
subtext?: string;
textClass?: ClassValue;
}
let { name, subtext, ...props }: Props = $props();
</script>
{#snippet subtextSnippet()}
{subtext}
{/snippet}
<IconLabel
icon={IconCategory}
subtext={subtext ? subtextSnippet : undefined}
class={props.class}
textClass={props.textClass}
>
{name}
</IconLabel>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import type { ClassValue } from "svelte/elements";
import { IconLabel } from "$lib/components/molecules";
import IconFolder from "~icons/material-symbols/folder";
import IconDraft from "~icons/material-symbols/draft";
interface Props {
class?: ClassValue;
name: string;
subtext?: string;
textClass?: ClassValue;
type: "directory" | "file";
}
let { name, subtext, type, ...props }: Props = $props();
</script>
{#snippet subtextSnippet()}
{subtext}
{/snippet}
<IconLabel
icon={type === "directory" ? IconFolder : IconDraft}
iconClass={type === "file" ? "text-blue-400" : undefined}
subtext={subtext ? subtextSnippet : undefined}
class={props.class}
textClass={props.textClass}
>
{name}
</IconLabel>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import type { Component, Snippet } from "svelte";
import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
interface Props {
children?: Snippet;
class?: ClassValue;
icon: Component<SvelteHTMLElements["svg"]>;
iconClass?: ClassValue;
subtext?: Snippet;
textClass?: ClassValue;
}
let { children, icon: Icon, subtext, ...props }: Props = $props();
</script>
<div class={["flex items-center gap-x-4", props.class]}>
<div class={["flex-shrink-0 text-lg", props.iconClass]}>
<Icon />
</div>
<div class="flex flex-grow flex-col gap-y-1 truncate text-left">
<p class={["font-medium", props.textClass]}>
{@render children?.()}
</p>
{#if subtext}
<p class="text-xs text-gray-800">
{@render subtext()}
</p>
{/if}
</div>
</div>

View File

@@ -0,0 +1,3 @@
export { default as CategoryLabel } from "./CategoryLabel.svelte";
export { default as DirectoryEntryLabel } from "./DirectoryEntryLabel.svelte";
export { default as IconLabel } from "./IconLabel.svelte";

View File

@@ -2,7 +2,7 @@
import type { Component } from "svelte"; import type { Component } from "svelte";
import type { ClassValue, SvelteHTMLElements } from "svelte/elements"; import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
import type { Writable } from "svelte/store"; import type { Writable } from "svelte/store";
import { EntryButton } from "$lib/components/atoms"; import { IconEntryButton } from "$lib/components/molecules";
import { getCategoryInfo, type CategoryInfo } from "$lib/modules/filesystem"; import { getCategoryInfo, type CategoryInfo } from "$lib/modules/filesystem";
import Categories, { type SelectedCategory } from "$lib/molecules/Categories"; import Categories, { type SelectedCategory } from "$lib/molecules/Categories";
import { masterKeyStore } from "$lib/stores"; import { masterKeyStore } from "$lib/stores";
@@ -40,12 +40,15 @@
<div class={["space-y-1", props.class]}> <div class={["space-y-1", props.class]}>
{#snippet subCategoryCreate()} {#snippet subCategoryCreate()}
<EntryButton onclick={onSubCategoryCreateClick} class="w-full"> <IconEntryButton
<div class="flex h-8 items-center gap-x-4"> icon={IconAddCircle}
<IconAddCircle class="text-lg text-gray-600" /> onclick={onSubCategoryCreateClick}
<p class="font-medium text-gray-700">카테고리 추가하기</p> class="h-12 w-full"
</div> iconClass="text-gray-600"
</EntryButton> textClass="text-gray-700"
>
카테고리 추가하기
</IconEntryButton>
{/snippet} {/snippet}
{#if subCategoryCreatePosition === "top"} {#if subCategoryCreatePosition === "top"}

View File

@@ -3,8 +3,8 @@
import { untrack } from "svelte"; import { untrack } from "svelte";
import { get, type Writable } from "svelte/store"; import { get, type Writable } from "svelte/store";
import { goto } from "$app/navigation"; import { goto } from "$app/navigation";
import { EntryButton, FullscreenDiv } from "$lib/components/atoms"; import { FullscreenDiv } from "$lib/components/atoms";
import { TopBar } from "$lib/components/molecules"; import { IconEntryButton, TopBar } from "$lib/components/molecules";
import { import {
getFileInfo, getFileInfo,
getCategoryInfo, getCategoryInfo,
@@ -151,12 +151,15 @@
onCategoryClick={({ id }) => goto(`/category/${id}`)} onCategoryClick={({ id }) => goto(`/category/${id}`)}
onCategoryMenuClick={({ id }) => removeFromCategory(id)} onCategoryMenuClick={({ id }) => removeFromCategory(id)}
/> />
<EntryButton onclick={() => (isAddToCategoryBottomSheetOpen = true)} class="w-full"> <IconEntryButton
<div class="flex h-8 items-center gap-x-4"> icon={IconAddCircle}
<IconAddCircle class="text-lg text-gray-600" /> onclick={() => (isAddToCategoryBottomSheetOpen = true)}
<p class="font-medium text-gray-700">카테고리에 추가하기</p> class="h-12 w-full"
</div> iconClass="text-gray-600"
</EntryButton> textClass="text-gray-700"
>
카테고리에 추가하기
</IconEntryButton>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,9 +1,8 @@
<script lang="ts"> <script lang="ts">
import { BottomSheet } from "$lib/components"; import { BottomSheet } from "$lib/components";
import { EntryButton } from "$lib/components/atoms"; import { CategoryLabel, IconEntryButton } from "$lib/components/molecules";
import { useContext } from "./service.svelte"; import { useContext } from "./service.svelte";
import IconCategory from "~icons/material-symbols/category";
import IconEdit from "~icons/material-symbols/edit"; import IconEdit from "~icons/material-symbols/edit";
import IconDelete from "~icons/material-symbols/delete"; import IconDelete from "~icons/material-symbols/delete";
@@ -21,27 +20,14 @@
{@const { name } = context.selectedCategory} {@const { name } = context.selectedCategory}
<BottomSheet bind:isOpen> <BottomSheet bind:isOpen>
<div class="w-full py-4"> <div class="w-full py-4">
<div class="flex h-12 items-center gap-x-4 p-2"> <CategoryLabel {name} class="h-12 p-2" textClass="!font-semibold" />
<div class="flex-shrink-0 text-lg">
<IconCategory />
</div>
<p title={name} class="flex-grow truncate font-semibold">
{name}
</p>
</div>
<div class="my-2 h-px w-full bg-gray-200"></div> <div class="my-2 h-px w-full bg-gray-200"></div>
<EntryButton onclick={onRenameClick} class="w-full"> <IconEntryButton icon={IconEdit} onclick={onRenameClick} class="h-12 w-full">
<div class="flex h-8 items-center gap-x-4"> 이름 바꾸기
<IconEdit class="text-lg" /> </IconEntryButton>
<p class="font-medium">이름 바꾸기</p> <IconEntryButton icon={IconDelete} onclick={onDeleteClick} class="h-12 w-full text-red-500">
</div> 삭제하기
</EntryButton> </IconEntryButton>
<EntryButton onclick={onDeleteClick} class="w-full">
<div class="flex h-8 items-center gap-x-4 text-red-500">
<IconDelete class="text-lg" />
<p class="font-medium">삭제하기</p>
</div>
</EntryButton>
</div> </div>
</BottomSheet> </BottomSheet>
{/if} {/if}

View File

@@ -1,6 +1,6 @@
<script lang="ts"> <script lang="ts">
import { BottomSheet } from "$lib/components"; import { BottomSheet } from "$lib/components";
import { EntryButton } from "$lib/components/atoms"; import { IconEntryButton } from "$lib/components/molecules";
import IconCreateNewFolder from "~icons/material-symbols/create-new-folder"; import IconCreateNewFolder from "~icons/material-symbols/create-new-folder";
import IconUploadFile from "~icons/material-symbols/upload-file"; import IconUploadFile from "~icons/material-symbols/upload-file";
@@ -16,17 +16,21 @@
<BottomSheet bind:isOpen> <BottomSheet bind:isOpen>
<div class="w-full py-4"> <div class="w-full py-4">
<EntryButton onclick={onDirectoryCreateClick} class="w-full"> <IconEntryButton
<div class="flex h-12 items-center gap-x-4"> icon={IconCreateNewFolder}
<IconCreateNewFolder class="text-2xl text-yellow-500" /> onclick={onDirectoryCreateClick}
<p class="font-medium">폴더 만들기</p> class="h-16 w-full"
</div> iconClass="!text-2xl text-yellow-500"
</EntryButton> >
<EntryButton onclick={onFileUploadClick} class="w-full"> 폴더 만들기
<div class="flex h-12 items-center gap-x-4"> </IconEntryButton>
<IconUploadFile class="text-2xl text-blue-400" /> <IconEntryButton
<p class="font-medium">파일 업로드</p> icon={IconUploadFile}
</div> onclick={onFileUploadClick}
</EntryButton> class="h-16 w-full"
iconClass="!text-2xl text-blue-400"
>
파일 업로드
</IconEntryButton>
</div> </div>
</BottomSheet> </BottomSheet>

View File

@@ -1,10 +1,8 @@
<script lang="ts"> <script lang="ts">
import { BottomSheet } from "$lib/components"; import { BottomSheet } from "$lib/components";
import { EntryButton } from "$lib/components/atoms"; import { DirectoryEntryLabel, IconEntryButton } from "$lib/components/molecules";
import { useContext } from "./service.svelte"; import { useContext } from "./service.svelte";
import IconFolder from "~icons/material-symbols/folder";
import IconDraft from "~icons/material-symbols/draft";
import IconEdit from "~icons/material-symbols/edit"; import IconEdit from "~icons/material-symbols/edit";
import IconDelete from "~icons/material-symbols/delete"; import IconDelete from "~icons/material-symbols/delete";
@@ -22,31 +20,14 @@
{@const { name, type } = context.selectedEntry} {@const { name, type } = context.selectedEntry}
<BottomSheet bind:isOpen> <BottomSheet bind:isOpen>
<div class="w-full py-4"> <div class="w-full py-4">
<div class="flex h-12 items-center gap-x-4 p-2"> <DirectoryEntryLabel {type} {name} class="h-12 p-2" textClass="!font-semibold" />
<div class="flex-shrink-0 text-lg">
{#if type === "directory"}
<IconFolder />
{:else}
<IconDraft class="text-blue-400" />
{/if}
</div>
<p title={name} class="flex-grow truncate font-semibold">
{name}
</p>
</div>
<div class="my-2 h-px w-full bg-gray-200"></div> <div class="my-2 h-px w-full bg-gray-200"></div>
<EntryButton onclick={onRenameClick} class="w-full"> <IconEntryButton icon={IconEdit} onclick={onRenameClick} class="h-12 w-full">
<div class="flex h-8 items-center gap-x-4"> 이름 바꾸기
<IconEdit class="text-lg" /> </IconEntryButton>
<p class="font-medium">이름 바꾸기</p> <IconEntryButton icon={IconDelete} onclick={onDeleteClick} class="h-12 w-full text-red-500">
</div> 삭제하기
</EntryButton> </IconEntryButton>
<EntryButton onclick={onDeleteClick} class="w-full">
<div class="flex h-8 items-center gap-x-4 text-red-500">
<IconDelete class="text-lg" />
<p class="font-medium">삭제하기</p>
</div>
</EntryButton>
</div> </div>
</BottomSheet> </BottomSheet>
{/if} {/if}

View File

@@ -1,25 +1,23 @@
<script lang="ts"> <script lang="ts">
import type { Component, Snippet } from "svelte"; import type { Component, Snippet } from "svelte";
import type { SvelteHTMLElements } from "svelte/elements"; import type { ClassValue, SvelteHTMLElements } from "svelte/elements";
import { EntryButton } from "$lib/components/atoms"; import { IconEntryButton } from "$lib/components/molecules";
interface Props { interface Props {
children: Snippet; children: Snippet;
icon: Component<SvelteHTMLElements["svg"]>; icon: Component<SvelteHTMLElements["svg"]>;
iconColor: string; iconColor: ClassValue;
onclick: () => void; onclick: () => void;
} }
let { children, icon: Icon, iconColor, onclick }: Props = $props(); let { children, icon, iconColor, onclick }: Props = $props();
</script> </script>
<EntryButton {onclick} class="w-full"> <IconEntryButton
<div class="flex items-center gap-x-4"> {icon}
<div class="rounded-lg bg-gray-200 p-1 {iconColor}"> {onclick}
<Icon /> class="w-full"
</div> iconClass={["rounded-lg bg-gray-200 p-1 !text-base", iconColor]}
<p class="font-medium"> >
{@render children?.()} {@render children?.()}
</p> </IconEntryButton>
</div>
</EntryButton>