mirror of
https://github.com/kmc7468/arkvault.git
synced 2025-12-15 06:18:48 +00:00
IconEntryButton 컴포넌트 추가
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
23
src/lib/components/molecules/IconEntryButton.svelte
Normal file
23
src/lib/components/molecules/IconEntryButton.svelte
Normal 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>
|
||||||
@@ -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";
|
||||||
|
|||||||
28
src/lib/components/molecules/labels/CategoryLabel.svelte
Normal file
28
src/lib/components/molecules/labels/CategoryLabel.svelte
Normal 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>
|
||||||
@@ -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>
|
||||||
31
src/lib/components/molecules/labels/IconLabel.svelte
Normal file
31
src/lib/components/molecules/labels/IconLabel.svelte
Normal 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>
|
||||||
3
src/lib/components/molecules/labels/index.ts
Normal file
3
src/lib/components/molecules/labels/index.ts
Normal 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";
|
||||||
@@ -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"}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user