migrate dialog consumers to ModalHeader/Body/Footer pattern

This commit is contained in:
Justin Edmund 2025-12-13 14:55:46 -08:00
parent a3c5676c4c
commit 789494e773
4 changed files with 277 additions and 213 deletions

View file

@ -12,6 +12,9 @@
useAddSummonsToCollection useAddSummonsToCollection
} from '$lib/api/mutations/collection.mutations' } from '$lib/api/mutations/collection.mutations'
import Dialog from '$lib/components/ui/Dialog.svelte' import Dialog from '$lib/components/ui/Dialog.svelte'
import ModalHeader from '$lib/components/ui/ModalHeader.svelte'
import ModalBody from '$lib/components/ui/ModalBody.svelte'
import ModalFooter from '$lib/components/ui/ModalFooter.svelte'
import Button from '$lib/components/ui/Button.svelte' import Button from '$lib/components/ui/Button.svelte'
import Icon from '$lib/components/Icon.svelte' import Icon from '$lib/components/Icon.svelte'
import CollectionFilters, { import CollectionFilters, {
@ -316,8 +319,9 @@
}) })
</script> </script>
<Dialog bind:open {onOpenChange} title={dialogTitle} size="large"> <Dialog bind:open {onOpenChange} size="large">
{#snippet children()} {#snippet children()}
<ModalHeader title={dialogTitle} />
<div class="modal-content"> <div class="modal-content">
<!-- Search input --> <!-- Search input -->
<div class="search-bar"> <div class="search-bar">
@ -441,9 +445,8 @@
{/if} {/if}
</div> </div>
</div> </div>
{/snippet} <ModalFooter>
{#snippet children()}
{#snippet footer()}
<div class="modal-footer"> <div class="modal-footer">
<div class="footer-left"> <div class="footer-left">
{#if selectedCount > 0} {#if selectedCount > 0}
@ -476,6 +479,8 @@
</div> </div>
</div> </div>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
<style lang="scss"> <style lang="scss">

View file

@ -18,6 +18,9 @@
--> -->
<script lang="ts"> <script lang="ts">
import Dialog from '$lib/components/ui/Dialog.svelte' import Dialog from '$lib/components/ui/Dialog.svelte'
import ModalHeader from '$lib/components/ui/ModalHeader.svelte'
import ModalBody from '$lib/components/ui/ModalBody.svelte'
import ModalFooter from '$lib/components/ui/ModalFooter.svelte'
import Button from '$lib/components/ui/Button.svelte' import Button from '$lib/components/ui/Button.svelte'
import type { ConflictData } from '$lib/types/api/conflict' import type { ConflictData } from '$lib/types/api/conflict'
import type { GridCharacter, GridWeapon } from '$lib/types/api/party' import type { GridCharacter, GridWeapon } from '$lib/types/api/party'
@ -167,7 +170,11 @@
} }
</script> </script>
<Dialog bind:open onOpenChange={handleOpenChange} title={m.conflict_title()}> <Dialog bind:open onOpenChange={handleOpenChange}>
{#snippet children()}
<ModalHeader title={m.conflict_title()} />
<ModalBody>
{#snippet children()}
{#if conflict} {#if conflict}
<div class={styles.content}> <div class={styles.content}>
<p class={styles.message}>{conflictMessage}</p> <p class={styles.message}>{conflictMessage}</p>
@ -224,8 +231,10 @@
</div> </div>
</div> </div>
{/if} {/if}
{/snippet}
{#snippet footer()} </ModalBody>
<ModalFooter>
{#snippet children()}
<Button variant="ghost" onclick={handleCancel} disabled={isLoading}> <Button variant="ghost" onclick={handleCancel} disabled={isLoading}>
{m.conflict_cancel()} {m.conflict_cancel()}
</Button> </Button>
@ -233,4 +242,6 @@
{m.conflict_confirm()} {m.conflict_confirm()}
</Button> </Button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>

View file

@ -46,6 +46,9 @@
import type { AddItemResult } from '$lib/types/api/search' import type { AddItemResult } from '$lib/types/api/search'
import { GridType } from '$lib/types/enums' import { GridType } from '$lib/types/enums'
import Dialog from '$lib/components/ui/Dialog.svelte' import Dialog from '$lib/components/ui/Dialog.svelte'
import ModalHeader from '$lib/components/ui/ModalHeader.svelte'
import ModalBody from '$lib/components/ui/ModalBody.svelte'
import ModalFooter from '$lib/components/ui/ModalFooter.svelte'
import Button from '$lib/components/ui/Button.svelte' import Button from '$lib/components/ui/Button.svelte'
import Icon from '$lib/components/Icon.svelte' import Icon from '$lib/components/Icon.svelte'
import DescriptionRenderer from '$lib/components/DescriptionRenderer.svelte' import DescriptionRenderer from '$lib/components/DescriptionRenderer.svelte'
@ -1003,8 +1006,10 @@
</div> </div>
<!-- Edit Dialog --> <!-- Edit Dialog -->
<Dialog bind:open={editDialogOpen} title="Edit Party Details"> <Dialog bind:open={editDialogOpen}>
{#snippet children()} {#snippet children()}
<ModalHeader title="Edit Party Details" />
<ModalBody>
<div class="edit-form"> <div class="edit-form">
<label for="party-title">Party Title</label> <label for="party-title">Party Title</label>
<input <input
@ -1015,9 +1020,9 @@
disabled={loading} disabled={loading}
/> />
</div> </div>
{/snippet} </ModalBody>
<ModalFooter>
{#snippet footer()} {#snippet children()}
<button class="btn-secondary" onclick={() => (editDialogOpen = false)} disabled={loading}> <button class="btn-secondary" onclick={() => (editDialogOpen = false)} disabled={loading}>
Cancel Cancel
</button> </button>
@ -1025,19 +1030,23 @@
{loading ? 'Saving...' : 'Save'} {loading ? 'Saving...' : 'Save'}
</button> </button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
<!-- Delete Confirmation Dialog --> <!-- Delete Confirmation Dialog -->
<Dialog bind:open={deleteDialogOpen} title="Delete Party"> <Dialog bind:open={deleteDialogOpen}>
{#snippet children()} {#snippet children()}
<ModalHeader title="Delete Party" />
<ModalBody>
<div class="delete-confirmation"> <div class="delete-confirmation">
<p>Are you sure you want to delete this party?</p> <p>Are you sure you want to delete this party?</p>
<p><strong>{party.name || 'Unnamed Party'}</strong></p> <p><strong>{party.name || 'Unnamed Party'}</strong></p>
<p class="warning">⚠️ This action cannot be undone.</p> <p class="warning">⚠️ This action cannot be undone.</p>
</div> </div>
{/snippet} </ModalBody>
<ModalFooter>
{#snippet footer()} {#snippet children()}
<button class="btn-secondary" onclick={() => (deleteDialogOpen = false)} disabled={deleting}> <button class="btn-secondary" onclick={() => (deleteDialogOpen = false)} disabled={deleting}>
Cancel Cancel
</button> </button>
@ -1045,6 +1054,8 @@
{deleting ? 'Deleting...' : 'Delete Party'} {deleting ? 'Deleting...' : 'Delete Party'}
</button> </button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
<!-- Conflict Resolution Dialog --> <!-- Conflict Resolution Dialog -->

View file

@ -1,6 +1,9 @@
<script module> <script module>
import { defineMeta } from '@storybook/addon-svelte-csf' import { defineMeta } from '@storybook/addon-svelte-csf'
import Dialog from '$lib/components/ui/Dialog.svelte' import Dialog from '$lib/components/ui/Dialog.svelte'
import ModalHeader from '$lib/components/ui/ModalHeader.svelte'
import ModalBody from '$lib/components/ui/ModalBody.svelte'
import ModalFooter from '$lib/components/ui/ModalFooter.svelte'
import Button from '$lib/components/ui/Button.svelte' import Button from '$lib/components/ui/Button.svelte'
const { Story } = defineMeta({ const { Story } = defineMeta({
@ -22,10 +25,15 @@
<Story name="Default"> <Story name="Default">
<div> <div>
<Button onclick={() => (defaultOpen = true)}>Open Dialog</Button> <Button onclick={() => (defaultOpen = true)}>Open Dialog</Button>
<Dialog bind:open={defaultOpen} title="Dialog Title"> <Dialog bind:open={defaultOpen}>
{#snippet children()}
<ModalHeader title="Dialog Title" />
<ModalBody>
{#snippet children()} {#snippet children()}
<p>This is the dialog content. You can put any content here.</p> <p>This is the dialog content. You can put any content here.</p>
{/snippet} {/snippet}
</ModalBody>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>
@ -34,14 +42,15 @@
<Story name="With Description"> <Story name="With Description">
<div> <div>
<Button onclick={() => (withDescOpen = true)}>Open Dialog</Button> <Button onclick={() => (withDescOpen = true)}>Open Dialog</Button>
<Dialog <Dialog bind:open={withDescOpen}>
bind:open={withDescOpen} {#snippet children()}
title="Account Settings" <ModalHeader title="Account Settings" description="Make changes to your account settings here." />
description="Make changes to your account settings here." <ModalBody>
>
{#snippet children()} {#snippet children()}
<p>Your account settings form would go here.</p> <p>Your account settings form would go here.</p>
{/snippet} {/snippet}
</ModalBody>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>
@ -50,14 +59,21 @@
<Story name="With Footer"> <Story name="With Footer">
<div> <div>
<Button onclick={() => (withFooterOpen = true)}>Open Dialog</Button> <Button onclick={() => (withFooterOpen = true)}>Open Dialog</Button>
<Dialog bind:open={withFooterOpen} title="Confirm Action"> <Dialog bind:open={withFooterOpen}>
{#snippet children()}
<ModalHeader title="Confirm Action" />
<ModalBody>
{#snippet children()} {#snippet children()}
<p>Are you sure you want to proceed with this action?</p> <p>Are you sure you want to proceed with this action?</p>
{/snippet} {/snippet}
{#snippet footer()} </ModalBody>
<ModalFooter>
{#snippet children()}
<Button variant="secondary" onclick={() => (withFooterOpen = false)}>Cancel</Button> <Button variant="secondary" onclick={() => (withFooterOpen = false)}>Cancel</Button>
<Button variant="primary" onclick={() => (withFooterOpen = false)}>Confirm</Button> <Button variant="primary" onclick={() => (withFooterOpen = false)}>Confirm</Button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>
@ -66,7 +82,10 @@
<Story name="Long Content"> <Story name="Long Content">
<div> <div>
<Button onclick={() => (longContentOpen = true)}>Open Long Dialog</Button> <Button onclick={() => (longContentOpen = true)}>Open Long Dialog</Button>
<Dialog bind:open={longContentOpen} title="Terms and Conditions"> <Dialog bind:open={longContentOpen}>
{#snippet children()}
<ModalHeader title="Terms and Conditions" />
<ModalBody>
{#snippet children()} {#snippet children()}
<div style="display: flex; flex-direction: column; gap: 16px;"> <div style="display: flex; flex-direction: column; gap: 16px;">
<p> <p>
@ -92,10 +111,14 @@
</p> </p>
</div> </div>
{/snippet} {/snippet}
{#snippet footer()} </ModalBody>
<ModalFooter>
{#snippet children()}
<Button variant="secondary" onclick={() => (longContentOpen = false)}>Decline</Button> <Button variant="secondary" onclick={() => (longContentOpen = false)}>Decline</Button>
<Button variant="primary" onclick={() => (longContentOpen = false)}>Accept</Button> <Button variant="primary" onclick={() => (longContentOpen = false)}>Accept</Button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>
@ -104,7 +127,10 @@
<Story name="Form Dialog"> <Story name="Form Dialog">
<div> <div>
<Button onclick={() => (formOpen = true)}>Edit Profile</Button> <Button onclick={() => (formOpen = true)}>Edit Profile</Button>
<Dialog bind:open={formOpen} title="Edit Profile" description="Update your profile information."> <Dialog bind:open={formOpen}>
{#snippet children()}
<ModalHeader title="Edit Profile" description="Update your profile information." />
<ModalBody>
{#snippet children()} {#snippet children()}
<div style="display: flex; flex-direction: column; gap: 16px;"> <div style="display: flex; flex-direction: column; gap: 16px;">
<div> <div>
@ -133,10 +159,14 @@
</div> </div>
</div> </div>
{/snippet} {/snippet}
{#snippet footer()} </ModalBody>
<ModalFooter>
{#snippet children()}
<Button variant="secondary" onclick={() => (formOpen = false)}>Cancel</Button> <Button variant="secondary" onclick={() => (formOpen = false)}>Cancel</Button>
<Button variant="primary" onclick={() => (formOpen = false)}>Save Changes</Button> <Button variant="primary" onclick={() => (formOpen = false)}>Save Changes</Button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>
@ -145,17 +175,24 @@
<Story name="Confirmation Dialog"> <Story name="Confirmation Dialog">
<div> <div>
<Button variant="destructive" onclick={() => (confirmOpen = true)}>Delete Item</Button> <Button variant="destructive" onclick={() => (confirmOpen = true)}>Delete Item</Button>
<Dialog bind:open={confirmOpen} title="Delete Item"> <Dialog bind:open={confirmOpen}>
{#snippet children()}
<ModalHeader title="Delete Item" />
<ModalBody>
{#snippet children()} {#snippet children()}
<p> <p>
Are you sure you want to delete this item? This action cannot be undone and all associated Are you sure you want to delete this item? This action cannot be undone and all associated
data will be permanently removed. data will be permanently removed.
</p> </p>
{/snippet} {/snippet}
{#snippet footer()} </ModalBody>
<ModalFooter>
{#snippet children()}
<Button variant="secondary" onclick={() => (confirmOpen = false)}>Cancel</Button> <Button variant="secondary" onclick={() => (confirmOpen = false)}>Cancel</Button>
<Button variant="destructive" onclick={() => (confirmOpen = false)}>Delete</Button> <Button variant="destructive" onclick={() => (confirmOpen = false)}>Delete</Button>
{/snippet} {/snippet}
</ModalFooter>
{/snippet}
</Dialog> </Dialog>
</div> </div>
</Story> </Story>