feat: create reusable CloseButton icon component
- Create CloseButton.svelte with configurable size, color, strokeWidth props - Replace inline close button SVGs in 7 components - Update Modal, Lightbox, MediaDetailsModal, MediaInput, GalleryManager, AlbumSelectorModal, UnifiedMediaModal 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5370ae020d
commit
df3dd1abd9
8 changed files with 47 additions and 101 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte'
|
import { onMount } from 'svelte'
|
||||||
import { fade, scale } from 'svelte/transition'
|
import { fade, scale } from 'svelte/transition'
|
||||||
|
import CloseButton from '$components/icons/CloseButton.svelte'
|
||||||
|
|
||||||
// Convert CSS transition durations to milliseconds for Svelte transitions
|
// Convert CSS transition durations to milliseconds for Svelte transitions
|
||||||
const TRANSITION_NORMAL_MS = 200 // $transition-normal: 0.2s
|
const TRANSITION_NORMAL_MS = 200 // $transition-normal: 0.2s
|
||||||
|
|
@ -111,20 +112,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="lightbox-close" onclick={close} aria-label="Close lightbox">
|
<button class="lightbox-close" onclick={close} aria-label="Close lightbox">
|
||||||
<svg
|
<CloseButton />
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M18 6L6 18M6 6l12 12"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
import Modal from './Modal.svelte'
|
import Modal from './Modal.svelte'
|
||||||
import AlbumSelector from './AlbumSelector.svelte'
|
import AlbumSelector from './AlbumSelector.svelte'
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
|
import CloseButton from '../icons/CloseButton.svelte'
|
||||||
import LoadingSpinner from './LoadingSpinner.svelte'
|
import LoadingSpinner from './LoadingSpinner.svelte'
|
||||||
import type { Album } from '@prisma/client'
|
import type { Album } from '@prisma/client'
|
||||||
|
|
||||||
|
|
@ -86,20 +87,7 @@
|
||||||
<div class="header-top">
|
<div class="header-top">
|
||||||
<h2>Add to Album</h2>
|
<h2>Add to Album</h2>
|
||||||
<button class="close-button" onclick={handleClose} aria-label="Close modal">
|
<button class="close-button" onclick={handleClose} aria-label="Close modal">
|
||||||
<svg
|
<CloseButton size={20} />
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p class="modal-subtitle">
|
<p class="modal-subtitle">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
|
import CloseButton from '../icons/CloseButton.svelte'
|
||||||
import UnifiedMediaModal from './UnifiedMediaModal.svelte'
|
import UnifiedMediaModal from './UnifiedMediaModal.svelte'
|
||||||
import type { Media } from '@prisma/client'
|
import type { Media } from '@prisma/client'
|
||||||
|
|
||||||
|
|
@ -221,20 +222,7 @@
|
||||||
onclick={() => removeImage(index)}
|
onclick={() => removeImage(index)}
|
||||||
aria-label="Remove image"
|
aria-label="Remove image"
|
||||||
>
|
>
|
||||||
<svg
|
<CloseButton size={14} color="currentColor" />
|
||||||
width="14"
|
|
||||||
height="14"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<!-- Order Indicator -->
|
<!-- Order Indicator -->
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
import SmartImage from '../SmartImage.svelte'
|
import SmartImage from '../SmartImage.svelte'
|
||||||
import AlbumSelector from './AlbumSelector.svelte'
|
import AlbumSelector from './AlbumSelector.svelte'
|
||||||
import AlbumIcon from '$icons/album.svg?component'
|
import AlbumIcon from '$icons/album.svg?component'
|
||||||
|
import CloseButton from '$components/icons/CloseButton.svelte'
|
||||||
import { authenticatedFetch } from '$lib/admin-auth'
|
import { authenticatedFetch } from '$lib/admin-auth'
|
||||||
import { toast } from '$lib/stores/toast'
|
import { toast } from '$lib/stores/toast'
|
||||||
import type { Media } from '@prisma/client'
|
import type { Media } from '@prisma/client'
|
||||||
|
|
@ -296,21 +297,7 @@
|
||||||
</svg>
|
</svg>
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant="ghost" onclick={handleClose} iconOnly aria-label="Close modal">
|
<Button variant="ghost" onclick={handleClose} iconOnly aria-label="Close modal">
|
||||||
<svg
|
<CloseButton slot="icon" />
|
||||||
slot="icon"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
|
import CloseButton from '../icons/CloseButton.svelte'
|
||||||
import UnifiedMediaModal from './UnifiedMediaModal.svelte'
|
import UnifiedMediaModal from './UnifiedMediaModal.svelte'
|
||||||
import type { Media } from '@prisma/client'
|
import type { Media } from '@prisma/client'
|
||||||
|
|
||||||
|
|
@ -209,21 +210,7 @@
|
||||||
<Button variant="ghost" onclick={openModal}>Browse</Button>
|
<Button variant="ghost" onclick={openModal}>Browse</Button>
|
||||||
{#if hasValue}
|
{#if hasValue}
|
||||||
<Button variant="ghost" onclick={handleClear} aria-label="Clear selection">
|
<Button variant="ghost" onclick={handleClear} aria-label="Clear selection">
|
||||||
<svg
|
<CloseButton slot="icon" size={16} />
|
||||||
slot="icon"
|
|
||||||
width="16"
|
|
||||||
height="16"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import BaseModal from './BaseModal.svelte'
|
import BaseModal from './BaseModal.svelte'
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
|
import CloseButton from '$components/icons/CloseButton.svelte'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
|
|
@ -41,21 +42,7 @@
|
||||||
aria-label="Close modal"
|
aria-label="Close modal"
|
||||||
class="close-button"
|
class="close-button"
|
||||||
>
|
>
|
||||||
<svg
|
<CloseButton slot="icon" />
|
||||||
slot="icon"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</Button>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
import Select from './Select.svelte'
|
import Select from './Select.svelte'
|
||||||
import Input from './Input.svelte'
|
import Input from './Input.svelte'
|
||||||
import Button from './Button.svelte'
|
import Button from './Button.svelte'
|
||||||
|
import CloseButton from '../icons/CloseButton.svelte'
|
||||||
import LoadingSpinner from './LoadingSpinner.svelte'
|
import LoadingSpinner from './LoadingSpinner.svelte'
|
||||||
import SmartImage from '../SmartImage.svelte'
|
import SmartImage from '../SmartImage.svelte'
|
||||||
import { InfiniteLoader, LoaderState } from 'svelte-infinite'
|
import { InfiniteLoader, LoaderState } from 'svelte-infinite'
|
||||||
|
|
@ -307,20 +308,7 @@
|
||||||
<div class="header-top">
|
<div class="header-top">
|
||||||
<h2>{computedTitle}</h2>
|
<h2>{computedTitle}</h2>
|
||||||
<button class="close-button" onclick={handleClose} aria-label="Close modal">
|
<button class="close-button" onclick={handleClose} aria-label="Close modal">
|
||||||
<svg
|
<CloseButton size={20} />
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M6 6L18 18M6 18L18 6"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
stroke-linecap="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
33
src/lib/components/icons/CloseButton.svelte
Normal file
33
src/lib/components/icons/CloseButton.svelte
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
<script lang="ts">
|
||||||
|
interface Props {
|
||||||
|
size?: number | string
|
||||||
|
color?: string
|
||||||
|
strokeWidth?: number
|
||||||
|
class?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
size = 24,
|
||||||
|
color = 'currentColor',
|
||||||
|
strokeWidth = 2,
|
||||||
|
class: className = ''
|
||||||
|
}: Props = $props()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
width={size}
|
||||||
|
height={size}
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class={className}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M18 6L6 18M6 6l12 12"
|
||||||
|
stroke={color}
|
||||||
|
stroke-width={strokeWidth}
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
Loading…
Reference in a new issue