Re work modal scrolling

This commit is contained in:
Jon Staab 2026-01-30 14:14:12 -08:00
parent 4169db33e6
commit 38c0a9d403
75 changed files with 2340 additions and 2030 deletions

View file

@ -2,6 +2,7 @@
import type {Snippet} from "svelte" import type {Snippet} from "svelte"
import {page} from "$app/stores" import {page} from "$app/stores"
import {pubkey} from "@welshman/app" import {pubkey} from "@welshman/app"
import Dialog from "@lib/components/Dialog.svelte"
import Landing from "@app/components/Landing.svelte" import Landing from "@app/components/Landing.svelte"
import Toast from "@app/components/Toast.svelte" import Toast from "@app/components/Toast.svelte"
import PrimaryNav from "@app/components/PrimaryNav.svelte" import PrimaryNav from "@app/components/PrimaryNav.svelte"
@ -20,7 +21,7 @@
{@render children?.()} {@render children?.()}
</PrimaryNav> </PrimaryNav>
{:else if !$modals[$page.url.hash.slice(1)]} {:else if !$modals[$page.url.hash.slice(1)]}
<Landing /> <Dialog children={{component: Landing, props: {}}} />
{/if} {/if}
</div> </div>
<Toast /> <Toast />

View file

@ -14,6 +14,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import DateTimeInput from "@lib/components/DateTimeInput.svelte" import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {PROTECTED} from "@app/core/state" import {PROTECTED} from "@app/core/state"
@ -114,7 +116,8 @@
}) })
</script> </script>
<form novalidate class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" novalidate onsubmit={preventDefault(submit)}>
<ModalBody>
{@render header()} {@render header()}
<Field> <Field>
{#snippet label()} {#snippet label()}
@ -131,7 +134,8 @@
<p>Summary</p> <p>Summary</p>
{/snippet} {/snippet}
{#snippet input()} {#snippet input()}
<div class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100"> <div
class="relative z-feature flex gap-2 border-t border-solid border-base-100 bg-base-100">
<div class="input-editor flex-grow overflow-hidden"> <div class="input-editor flex-grow overflow-hidden">
<EditorContent {editor} /> <EditorContent {editor} />
</div> </div>
@ -172,6 +176,7 @@
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -181,4 +186,4 @@
<Spinner loading={$uploading}>Save Event</Spinner> <Spinner loading={$uploading}>Save Event</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -7,6 +7,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {PLATFORM_NAME} from "@app/core/state" import {PLATFORM_NAME} from "@app/core/state"
@ -33,7 +35,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Enable Messages</div> <div>Enable Messages</div>
@ -47,9 +50,10 @@
{PLATFORM_NAME} to download and decrypt a lot of data. {PLATFORM_NAME} to download and decrypt a lot of data.
</p> </p>
<p> <p>
If you'd like to enable them, please make sure your signer is set up to to auto-approve requests If you'd like to enable them, please make sure your signer is set up to to auto-approve
to decrypt data. requests to decrypt data.
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -60,4 +64,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -1,6 +1,9 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
interface Props { interface Props {
@ -10,7 +13,8 @@
const {pubkeys}: Props = $props() const {pubkeys}: Props = $props()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>People in this conversation</div> <div>People in this conversation</div>
@ -21,5 +25,8 @@
<Profile {pubkey} /> <Profile {pubkey} />
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalFooter>
</Modal>

View file

@ -11,6 +11,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte" import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
@ -52,7 +54,8 @@
}) })
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Start a Chat</div> <div>Start a Chat</div>
@ -66,6 +69,7 @@
<ProfileMultiSelect autofocus bind:value={pubkeys} {term} /> <ProfileMultiSelect autofocus bind:value={pubkeys} {term} />
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -76,4 +80,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -11,6 +11,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import {clip} from "@app/util/toast" import {clip} from "@app/util/toast"
@ -36,7 +38,8 @@
}) })
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Event Details</div> <div>Event Details</div>
@ -106,4 +109,5 @@
</p> </p>
</div> </div>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalBody>
</Modal>

View file

@ -9,6 +9,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import {roomsByUrl} from "@app/core/state" import {roomsByUrl} from "@app/core/state"
import {makeRoomPath} from "@app/util/routes" import {makeRoomPath} from "@app/util/routes"
@ -29,7 +31,8 @@
let selection = $state("") let selection = $state("")
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Share {noun}</div> <div>Share {noun}</div>
@ -50,6 +53,7 @@
</button> </button>
{/each} {/each}
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -60,4 +64,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -12,6 +12,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {PROTECTED} from "@app/core/state" import {PROTECTED} from "@app/core/state"
@ -82,7 +84,8 @@
let amount = $state(1000) let amount = $state(1000)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Create a Funding Goal</div> <div>Create a Funding Goal</div>
@ -154,6 +157,7 @@
bind:value={amount} /> bind:value={amount} />
</div> </div>
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -161,4 +165,4 @@
</Button> </Button>
<Button type="submit" class="btn btn-primary">Create Goal</Button> <Button type="submit" class="btn btn-primary">Create Goal</Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -1,11 +1,14 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import {PLATFORM_NAME} from "@app/core/state" import {PLATFORM_NAME} from "@app/core/state"
</script> </script>
<div class="column gap-4"> <Modal
><ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What is a bunker link?</div> <div>What is a bunker link?</div>
@ -17,9 +20,9 @@
company, and can bring it with them from app to app. company, and can bring it with them from app to app.
</p> </p>
<p> <p>
A good way to manage your keys is to use a remote signing application. These apps can hold your A good way to manage your keys is to use a remote signing application. These apps can hold
keys and log you in remotely to as many applications as you like, without risking loss or theft your keys and log you in remotely to as many applications as you like, without risking loss or
of your keys. theft of your keys.
</p> </p>
<p> <p>
One way to log in with a remote signer is using a "bunker link" which is more secure and One way to log in with a remote signer is using a "bunker link" which is more secure and
@ -36,4 +39,4 @@
>. >.
</p> </p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalBody></Modal>

View file

@ -1,11 +1,14 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import {PLATFORM_NAME} from "@app/core/state" import {PLATFORM_NAME} from "@app/core/state"
</script> </script>
<div class="column gap-4"> <Modal
><ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What is a nostr address?</div> <div>What is a nostr address?</div>
@ -26,4 +29,4 @@
>. >.
</p> </p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalBody></Modal>

View file

@ -5,6 +5,8 @@
import CheckCircle from "@assets/icons/check-circle.svg?dataurl" import CheckCircle from "@assets/icons/check-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import KeyRecoveryRequest from "@app/components/KeyRecoveryRequest.svelte" import KeyRecoveryRequest from "@app/components/KeyRecoveryRequest.svelte"
@ -16,29 +18,37 @@
const startRecoveryRequest = () => pushModal(KeyRecoveryRequest) const startRecoveryRequest = () => pushModal(KeyRecoveryRequest)
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What is a private key?</div> <div>What is a private key?</div>
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p> <p>
Most online services keep track of users by giving them a username and password. This gives the Most online services keep track of users by giving them a username and password. This gives
service <strong>total control</strong> over their users, allowing them to ban them at any time, or the service <strong>total control</strong> over their users, allowing them to ban them at any time,
sell their activity. or sell their activity.
</p> </p>
<p> <p>
On <Link external href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your own On <Link external href="https://nostr.com/">Nostr</Link>, <strong>you</strong> control your
identity and social data, through the magic of cryptography. The basic idea is that you have a own identity and social data, through the magic of cryptography. The basic idea is that you
have a
<strong>public key</strong>, which acts as your user ID, and a <strong>public key</strong>, which acts as your user ID, and a
<strong>private key</strong> which allows you to prove your identity. <strong>private key</strong> which allows you to prove your identity.
</p> </p>
{#if $session?.email} {#if $session?.email}
<p> <p>
It's very important to keep private keys safe, but this can sometimes be tricky, which is why {PLATFORM_NAME} It's very important to keep private keys safe, but this can sometimes be tricky, which is
why {PLATFORM_NAME}
supports a traditional account-based login for new users. supports a traditional account-based login for new users.
</p> </p>
<p>If you'd like to switch to self-custody, please click below to get started.</p> <p>If you'd like to switch to self-custody, please click below to get started.</p>
{:else}
<Button class="btn btn-primary" onclick={back}>Got it</Button>
{/if}
</ModalBody>
{#if $session?.email}
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -49,7 +59,5 @@
I want to hold my own keys I want to hold my own keys
</Button> </Button>
</ModalFooter> </ModalFooter>
{:else}
<Button class="btn btn-primary" onclick={back}>Got it</Button>
{/if} {/if}
</div> </Modal>

View file

@ -1,10 +1,13 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
</script> </script>
<div class="column gap-4"> <Modal
><ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What is nostr?</div> <div>What is nostr?</div>
@ -27,4 +30,4 @@
<Link external class="link" href="https://nosta.me/">nosta.me</Link>. <Link external class="link" href="https://nosta.me/">nosta.me</Link>.
</p> </p>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalBody></Modal>

View file

@ -2,10 +2,14 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {PLATFORM_NAME} from "@app/core/state" import {PLATFORM_NAME} from "@app/core/state"
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What is a relay?</div> <div>What is a relay?</div>
@ -15,12 +19,15 @@
{PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline" {PLATFORM_NAME} hosts spaces on the <Link external href="https://nostr.com/" class="underline"
>Nostr protocol</Link >Nostr protocol</Link
>. Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's >. Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's
language. This means that anyone can host their own data, making the web more decentralized and language. This means that anyone can host their own data, making the web more decentralized
resilient. and resilient.
</p> </p>
<p> <p>
Different relays have different policies for access control and content retention. Be sure to Different relays have different policies for access control and content retention. Be sure to
double check that you have access to the relays you try to use by visiting their website. double check that you have access to the relays you try to use by visiting their website.
</p> </p>
</ModalBody>
<ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalFooter>
</Modal>

View file

@ -1,12 +1,15 @@
<script lang="ts"> <script lang="ts">
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
const back = () => history.back() const back = () => history.back()
</script> </script>
<div class="column gap-4"> <Modal
><ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>What are digital signatures?</div> <div>What are digital signatures?</div>
@ -20,8 +23,8 @@
</p> </p>
<p> <p>
On <Link external href="https://nostr.com/">Nostr</Link>, all your content is authenticated On <Link external href="https://nostr.com/">Nostr</Link>, all your content is authenticated
using <strong>digital signatures</strong>, which cryptographically tie a particular person to a using <strong>digital signatures</strong>, which cryptographically tie a particular person to
given post or message. a given post or message.
</p> </p>
<p> <p>
The result is that you don't normally have to trust service providers not to tamper with the The result is that you don't normally have to trust service providers not to tamper with the
@ -29,4 +32,4 @@
piece of data is authentic. piece of data is authentic.
</p> </p>
<Button class="btn btn-primary" onclick={back}>Got it</Button> <Button class="btn btn-primary" onclick={back}>Got it</Button>
</div> </ModalBody></Modal>

View file

@ -5,6 +5,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ProfileLink from "@app/components/ProfileLink.svelte" import ProfileLink from "@app/components/ProfileLink.svelte"
const {pubkey} = $props() const {pubkey} = $props()
@ -14,7 +16,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Unable to Zap</div> <div>Unable to Zap</div>
@ -28,10 +31,11 @@
they don't currently have a zap receiver set up. they don't currently have a zap receiver set up.
{/if} {/if}
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -10,6 +10,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -104,7 +106,8 @@
let didDownload = $state(false) let didDownload = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(next)}> <Modal tag="form" onsubmit={preventDefault(next)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Your Keys are Ready!</div> <div>Your Keys are Ready!</div>
@ -115,8 +118,8 @@
account, while your <strong>private key</strong> acts sort of like a master password. account, while your <strong>private key</strong> acts sort of like a master password.
</p> </p>
<p> <p>
Securing your private key is very important, so make sure to take the time to save your key in a Securing your private key is very important, so make sure to take the time to save your key in
secure place (like a password manager). a secure place (like a password manager).
</p> </p>
{#if usePassword} {#if usePassword}
<Field> <Field>
@ -147,6 +150,7 @@
{/if} {/if}
</Button> </Button>
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -157,4 +161,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -9,6 +9,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import KeyDownload from "@app/components/KeyDownload.svelte" import KeyDownload from "@app/components/KeyDownload.svelte"
@ -81,7 +83,8 @@
let input = $state("") let input = $state("")
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Recover your Key Recover your Key
@ -99,6 +102,7 @@
rows={POMADE_SIGNERS.length + 1} rows={POMADE_SIGNERS.length + 1}
class="textarea textarea-bordered leading-4" class="textarea textarea-bordered leading-4"
bind:value={input}></textarea> bind:value={input}></textarea>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -109,4 +113,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -8,6 +8,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
@ -39,7 +41,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Recover your Key Recover your Key
@ -49,13 +52,14 @@
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p> <p>
When you signed up, your Nostr secret key was split into multiple pieces and stored on separate When you signed up, your Nostr secret key was split into multiple pieces and stored on
third-party servers to keep it safe. separate third-party servers to keep it safe.
</p> </p>
<p> <p>
If you're ready to take control of your cryptographic identity, click below. We'll confirm your If you're ready to take control of your cryptographic identity, click below. We'll confirm
email by sending you some recovery codes. your email by sending you some recovery codes.
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -66,4 +70,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -4,7 +4,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Dialog from "@lib/components/Dialog.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import CardButton from "@lib/components/CardButton.svelte" import CardButton from "@lib/components/CardButton.svelte"
import LogIn from "@app/components/LogIn.svelte" import LogIn from "@app/components/LogIn.svelte"
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
@ -16,8 +17,8 @@
const signUp = () => pushModal(SignUp) const signUp = () => pushModal(SignUp)
</script> </script>
<Dialog> <Modal>
<div class="column gap-4"> <ModalBody>
<div class="py-2"> <div class="py-2">
<h1 class="heading">Welcome to {PLATFORM_NAME}!</h1> <h1 class="heading">Welcome to {PLATFORM_NAME}!</h1>
<p class="text-center">The chat app built for self-hosted communities.</p> <p class="text-center">The chat app built for self-hosted communities.</p>
@ -53,5 +54,5 @@
<Link external class="link" href={PLATFORM_TERMS}>Terms of Service</Link> and <Link external class="link" href={PLATFORM_TERMS}>Terms of Service</Link> and
<Link external class="link" href={PLATFORM_PRIVACY}>Privacy Policy</Link>. <Link external class="link" href={PLATFORM_PRIVACY}>Privacy Policy</Link>.
</p> </p>
</div> </ModalBody>
</Dialog> </Modal>

View file

@ -10,6 +10,8 @@
import Key from "@assets/icons/key.svg?dataurl" import Key from "@assets/icons/key.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte" import InfoNostr from "@app/components/InfoNostr.svelte"
@ -91,12 +93,13 @@
}) })
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<h1 class="heading">Log in with Nostr</h1> <h1 class="heading">Log in with Nostr</h1>
<p class="m-auto max-w-sm text-center"> <p class="m-auto max-w-sm text-center">
{PLATFORM_NAME} is built using the {PLATFORM_NAME} is built using the
<Button class="link" onclick={() => pushModal(InfoNostr)}>nostr protocol</Button>, which allows <Button class="link" onclick={() => pushModal(InfoNostr)}>nostr protocol</Button>, which
you to own your social identity. allows you to own your social identity.
</p> </p>
{#if getNip07()} {#if getNip07()}
<Button {disabled} onclick={loginWithNip07} class="btn btn-primary"> <Button {disabled} onclick={loginWithNip07} class="btn btn-primary">
@ -157,4 +160,5 @@
Need an account? Need an account?
<Button class="link" onclick={signUp}>Register instead</Button> <Button class="link" onclick={signUp}>Register instead</Button>
</div> </div>
</div> </ModalBody>
</Modal>

View file

@ -10,6 +10,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import BunkerConnect from "@app/components/BunkerConnect.svelte" import BunkerConnect from "@app/components/BunkerConnect.svelte"
@ -120,7 +122,8 @@
}) })
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Log In with a Signer</div> <div>Log In with a Signer</div>
@ -137,6 +140,7 @@
<Button class="btn {$bunker ? 'btn-neutral' : 'btn-primary'}" onclick={selectConnect} <Button class="btn {$bunker ? 'btn-neutral' : 'btn-primary'}" onclick={selectConnect}
>Log in with a QR code instead</Button> >Log in with a QR code instead</Button>
{/if} {/if}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={$loading}> <Button class="btn btn-link" onclick={back} disabled={$loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -149,4 +153,4 @@
</Button> </Button>
{/if} {/if}
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -10,6 +10,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import LogInOTP from "@app/components/LogInOTP.svelte" import LogInOTP from "@app/components/LogInOTP.svelte"
@ -67,7 +69,8 @@
let password = $state("") let password = $state("")
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Log In</div> <div>Log In</div>
@ -103,6 +106,7 @@
>Log in with a one-time access code</Button >Log in with a one-time access code</Button
>. >.
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -113,4 +117,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -13,6 +13,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {clearModals} from "@app/util/modal" import {clearModals} from "@app/util/modal"
@ -71,7 +73,8 @@
} }
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Log In with Key</div> <div>Log In with Key</div>
@ -115,6 +118,7 @@
to keep your keys safe. to keep your keys safe.
</p> </p>
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -125,4 +129,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -8,6 +8,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import LogInOTPConfirm from "@app/components/LogInOTPConfirm.svelte" import LogInOTPConfirm from "@app/components/LogInOTPConfirm.svelte"
@ -44,7 +46,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Log In</div> <div>Log In</div>
@ -64,6 +67,7 @@
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -74,4 +78,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -7,6 +7,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {clearModals} from "@app/util/modal" import {clearModals} from "@app/util/modal"
@ -79,7 +81,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Log In</div> <div>Log In</div>
@ -97,6 +100,7 @@
rows={POMADE_SIGNERS.length + 1} rows={POMADE_SIGNERS.length + 1}
class="textarea textarea-bordered leading-4" class="textarea textarea-bordered leading-4"
bind:value={input}></textarea> bind:value={input}></textarea>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -107,4 +111,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -4,6 +4,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {Push} from "@app/util/notifications" import {Push} from "@app/util/notifications"
@ -31,13 +33,15 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(doLogout)}> <Modal tag="form" onsubmit={preventDefault(doLogout)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Are you sure you want<br />to log out?</div> <div>Are you sure you want<br />to log out?</div>
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p class="text-center">Your local database will be cleared.</p> <p class="text-center">Your local database will be cleared.</p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -47,4 +51,4 @@
<Spinner {loading}>Log Out</Spinner> <Spinner {loading}>Log Out</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -35,14 +35,7 @@
props: { props: {
onClose: closeModals, onClose: closeModals,
fullscreen: options.fullscreen, fullscreen: options.fullscreen,
children: createRawSnippet(() => ({ children: {component, props},
render: () => "<div></div>",
setup: (target: Element) => {
const child = mount(component, {target, props})
return () => unmount(child)
},
})),
}, },
}) })
} }

View file

@ -18,6 +18,8 @@
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls} from "@app/core/state" import {INDEXER_RELAYS, PLATFORM_NAME, userSpaceUrls} from "@app/core/state"
import {kv, db} from "@app/core/storage" import {kv, db} from "@app/core/storage"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -108,7 +110,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(confirm)}> <Modal tag="form" onsubmit={preventDefault(confirm)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Delete your account Delete your account
@ -122,13 +125,15 @@
We are currently sending deletion requests to your relay selections and space hosts. Please We are currently sending deletion requests to your relay selections and space hosts. Please
wait while we complete this process. Once we're done, you'll be automatically logged out. wait while we complete this process. Once we're done, you'll be automatically logged out.
</p> </p>
<progress class="progress progress-primary w-full" value={progress! * 100} max="100"></progress> <progress class="progress progress-primary w-full" value={progress! * 100} max="100"
></progress>
{:else} {:else}
<p> <p>
This will delete your nostr account everywhere, not just on {PLATFORM_NAME}. This will delete your nostr account everywhere, not just on {PLATFORM_NAME}.
</p> </p>
<p> <p>
To confirm, please type "{CONFIRM_TEXT}" into the text box below. This action can't be undone. To confirm, please type "{CONFIRM_TEXT}" into the text box below. This action can't be
undone.
</p> </p>
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
<input bind:value={confirmText} class="grow" type="text" /> <input bind:value={confirmText} class="grow" type="text" />
@ -138,6 +143,7 @@
content continues to be available, please contact the offending relays directly. content continues to be available, please contact the offending relays directly.
</p> </p>
{/if} {/if}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -148,4 +154,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -15,6 +15,8 @@
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Popover from "@lib/components/Popover.svelte" import Popover from "@lib/components/Popover.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import ProfileInfo from "@app/components/ProfileInfo.svelte" import ProfileInfo from "@app/components/ProfileInfo.svelte"
@ -75,6 +77,8 @@
let showMenu = $state(false) let showMenu = $state(false)
</script> </script>
<Modal>
<ModalBody>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<div class="flex justify-between"> <div class="flex justify-between">
<Profile showPubkey avatarSize={14} {pubkey} {url} /> <Profile showPubkey avatarSize={14} {pubkey} {url} />
@ -112,6 +116,8 @@
</div> </div>
<ProfileInfo {pubkey} {url} /> <ProfileInfo {pubkey} {url} />
<ProfileBadges {pubkey} {url} /> <ProfileBadges {pubkey} {url} />
</div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button onclick={back} class="hidden md:btn md:btn-link"> <Button onclick={back} class="hidden md:btn md:btn-link">
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -128,4 +134,4 @@
</Button> </Button>
</div> </div>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -8,6 +8,8 @@
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import InputProfilePicture from "@app/components/InputProfilePicture.svelte" import InputProfilePicture from "@app/components/InputProfilePicture.svelte"
import InfoHandle from "@app/components/InfoHandle.svelte" import InfoHandle from "@app/components/InfoHandle.svelte"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
@ -33,7 +35,8 @@
let file: File | undefined = $state() let file: File | undefined = $state()
</script> </script>
<form class="col-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
{#if isSignup} {#if isSignup}
<div class="grid grid-cols-2"> <div class="grid grid-cols-2">
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
@ -119,5 +122,6 @@
{/snippet} {/snippet}
</FieldInline> </FieldInline>
{/if} {/if}
</ModalBody>
{@render footer()} {@render footer()}
</form> </Modal>

View file

@ -1,6 +1,9 @@
<script lang="ts"> <script lang="ts">
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
interface Props { interface Props {
@ -13,7 +16,8 @@
const {subtitle = "", pubkeys, url, ...restProps}: Props = $props() const {subtitle = "", pubkeys, url, ...restProps}: Props = $props()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>{restProps.title}</div> <div>{restProps.title}</div>
@ -27,5 +31,8 @@
<Profile {pubkey} {url} /> <Profile {pubkey} {url} />
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter>
<Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button> <Button class="btn btn-primary" onclick={() => history.back()}>Got it</Button>
</div> </ModalFooter>
</Modal>

View file

@ -9,6 +9,8 @@
import AddCircle from "@assets/icons/add-circle.svg?dataurl" import AddCircle from "@assets/icons/add-circle.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import RelayItem from "@app/components/RelayItem.svelte" import RelayItem from "@app/components/RelayItem.svelte"
interface Props { interface Props {
@ -39,6 +41,8 @@
}) })
</script> </script>
<Modal>
<ModalBody>
<label class="input input-bordered flex w-full items-center gap-2"> <label class="input input-bordered flex w-full items-center gap-2">
<Icon icon={Magnifier} /> <Icon icon={Magnifier} />
<input bind:value={term} class="grow" type="text" placeholder="Search for relays..." /> <input bind:value={term} class="grow" type="text" placeholder="Search for relays..." />
@ -46,7 +50,9 @@
<div class="column -m-6 mt-0 h-[50vh] gap-2 overflow-auto p-6 pt-2" bind:this={element}> <div class="column -m-6 mt-0 h-[50vh] gap-2 overflow-auto p-6 pt-2" bind:this={element}>
{#if customUrl && isShareableRelayUrl(customUrl) && !$relays.includes(normalizeRelayUrl(customUrl))} {#if customUrl && isShareableRelayUrl(customUrl) && !$relays.includes(normalizeRelayUrl(customUrl))}
<RelayItem url={term}> <RelayItem url={term}>
<Button class="btn btn-outline btn-sm flex items-center" onclick={() => addRelay(customUrl)}> <Button
class="btn btn-outline btn-sm flex items-center"
onclick={() => addRelay(customUrl)}>
<Icon icon={AddCircle} /> <Icon icon={AddCircle} />
Add Relay Add Relay
</Button> </Button>
@ -64,3 +70,5 @@
</RelayItem> </RelayItem>
{/each} {/each}
</div> </div>
</ModalBody>
</Modal>

View file

@ -8,6 +8,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {publishReport} from "@app/core/commands" import {publishReport} from "@app/core/commands"
@ -38,7 +40,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(confirm)}> <Modal tag="form" onsubmit={preventDefault(confirm)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Report Content</div> <div>Report Content</div>
@ -78,6 +81,7 @@
<p>Please provide any additional details relevant to your report.</p> <p>Please provide any additional details relevant to your report.</p>
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -88,4 +92,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -4,7 +4,10 @@
import {deriveEventsById} from "@welshman/store" import {deriveEventsById} from "@welshman/store"
import {repository} from "@welshman/app" import {repository} from "@welshman/app"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import ReportItem from "@app/components/ReportItem.svelte" import ReportItem from "@app/components/ReportItem.svelte"
type Props = { type Props = {
@ -28,7 +31,8 @@
} }
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Report Details</div> <div>Report Details</div>
@ -42,5 +46,8 @@
<ReportItem {url} event={report} {onDelete} /> <ReportItem {url} event={report} {onDelete} />
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter>
<Button class="btn btn-primary" onclick={back}>Got it</Button> <Button class="btn btn-primary" onclick={back}>Got it</Button>
</div> </ModalFooter>
</Modal>

View file

@ -20,6 +20,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ProfileCircles from "@app/components/ProfileCircles.svelte" import ProfileCircles from "@app/components/ProfileCircles.svelte"
import RoomMembers from "@app/components/RoomMembers.svelte" import RoomMembers from "@app/components/RoomMembers.svelte"
@ -36,7 +38,11 @@
deriveIsMuted, deriveIsMuted,
MembershipStatus, MembershipStatus,
} from "@app/core/state" } from "@app/core/state"
import {addRoomMembership, removeRoomMembership, toggleRoomNotifications} from "@app/core/commands" import {
addRoomMembership,
removeRoomMembership,
toggleRoomNotifications,
} from "@app/core/commands"
import {makeSpacePath} from "@app/util/routes" import {makeSpacePath} from "@app/util/routes"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -114,7 +120,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<div class="flex flex-col gap-3"> <Modal>
<ModalBody>
<div class="flex justify-between"> <div class="flex justify-between">
<div class="flex gap-3"> <div class="flex gap-3">
<div class="pt-0.5"> <div class="pt-0.5">
@ -175,24 +182,25 @@
<Icon icon={VolumeLoud} /> <Icon icon={VolumeLoud} />
<span>Notifications</span> <span>Notifications</span>
</div> </div>
<Button <input
class={cx("btn btn-sm", {"btn-primary": !isMuted, "btn-neutral": isMuted})} type="checkbox"
onclick={toggleMute}> class="toggle toggle-primary"
{isMuted ? "Off" : "On"} checked={!isMuted}
</Button> onchange={toggleMute} />
</div> </div>
<div class="flex items-center justify-between"> <div class="flex items-center justify-between">
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<Icon icon={Bookmark} /> <Icon icon={Bookmark} />
<span>Favorite</span> <span>Favorite</span>
</div> </div>
<Button <input
class={cx("btn btn-sm", {"btn-primary": isFavorite, "btn-neutral": !isFavorite})} type="checkbox"
onclick={toggleFavorite}> class="toggle toggle-primary"
{isFavorite ? "On" : "Off"} checked={isFavorite}
</Button> onchange={toggleFavorite} />
</div> </div>
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -234,4 +242,4 @@
{/if} {/if}
</div> </div>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -11,6 +11,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ImageIcon from "@lib/components/ImageIcon.svelte" import ImageIcon from "@lib/components/ImageIcon.svelte"
import IconPickerButton from "@lib/components/IconPickerButton.svelte" import IconPickerButton from "@lib/components/IconPickerButton.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {uploadFile} from "@app/core/commands" import {uploadFile} from "@app/core/commands"
@ -105,7 +107,8 @@
} }
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(trySubmit)}> <Modal tag="form" onsubmit={preventDefault(trySubmit)}>
<ModalBody>
{@render header()} {@render header()}
<FieldInline> <FieldInline>
{#snippet label()} {#snippet label()}
@ -177,5 +180,6 @@
<input type="checkbox" class="checkbox" bind:checked={values.isClosed} /> <input type="checkbox" class="checkbox" bind:checked={values.isClosed} />
<span class="text-sm opacity-75">Ignore requests to join</span> <span class="text-sm opacity-75">Ignore requests to join</span>
</div> </div>
</ModalBody>
{@render footer({loading})} {@render footer({loading})}
</form> </Modal>

View file

@ -9,6 +9,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Popover from "@lib/components/Popover.svelte" import Popover from "@lib/components/Popover.svelte"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
@ -59,7 +61,8 @@
let menuPubkey = $state<string | undefined>() let menuPubkey = $state<string | undefined>()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <div class="flex min-w-0 flex-col gap-1">
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1> <h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1>
<p class="ellipsize text-sm opacity-75">of <RoomName {url} {h} /></p> <p class="ellipsize text-sm opacity-75">of <RoomName {url} {h} /></p>
@ -100,10 +103,11 @@
</div> </div>
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -7,6 +7,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import RoomName from "@app/components/RoomName.svelte" import RoomName from "@app/components/RoomName.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte" import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -48,7 +50,8 @@
let pubkeys: string[] = $state([]) let pubkeys: string[] = $state([])
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Add Members</div> <div>Add Members</div>
@ -65,6 +68,7 @@
<ProfileMultiSelect bind:value={pubkeys} /> <ProfileMultiSelect bind:value={pubkeys} />
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -74,4 +78,4 @@
<Spinner {loading}>Save changes</Spinner> <Spinner {loading}>Save changes</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -15,6 +15,8 @@
import {getKey, setKey} from "@lib/implicit" import {getKey, setKey} from "@lib/implicit"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import LogIn from "@app/components/LogIn.svelte" import LogIn from "@app/components/LogIn.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte" import InfoNostr from "@app/components/InfoNostr.svelte"
import SignUpKey from "@app/components/SignUpKey.svelte" import SignUpKey from "@app/components/SignUpKey.svelte"
@ -92,7 +94,8 @@
} }
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<h1 class="heading">Sign up with Nostr</h1> <h1 class="heading">Sign up with Nostr</h1>
<p class="m-auto max-w-sm text-center"> <p class="m-auto max-w-sm text-center">
{PLATFORM_NAME} is built using the {PLATFORM_NAME} is built using the
@ -113,4 +116,5 @@
Already have an account? Already have an account?
<Button class="link" onclick={login}>Log in instead</Button> <Button class="link" onclick={login}>Log in instead</Button>
</div> </div>
</div> </ModalBody>
</Modal>

View file

@ -4,6 +4,8 @@
import HomeSmile from "@assets/icons/home-smile.svg?dataurl" import HomeSmile from "@assets/icons/home-smile.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
@ -16,7 +18,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(next)}> <Modal tag="form" onsubmit={preventDefault(next)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>You're all set!</div> <div>You're all set!</div>
@ -27,9 +30,10 @@
without asking permission! without asking permission!
</p> </p>
<p> <p>
From your dashboard, you can use invite links, discover community spaces, and keep up-to-date on From your dashboard, you can use invite links, discover community spaces, and keep up-to-date
groups you've already joined. Click below to get started! on groups you've already joined. Click below to get started!
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -40,4 +44,4 @@
Go to Dashboard Go to Dashboard
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -11,6 +11,8 @@
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import SignUpEmailConfirm from "@app/components/SignUpEmailConfirm.svelte" import SignUpEmailConfirm from "@app/components/SignUpEmailConfirm.svelte"
@ -92,7 +94,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Sign up with Email</div> <div>Sign up with Email</div>
@ -131,6 +134,7 @@
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -141,4 +145,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -9,6 +9,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
@ -35,7 +37,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(onSubmit)}> <Modal tag="form" onsubmit={preventDefault(onSubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Verify your Email Address</div> <div>Verify your Email Address</div>
@ -59,6 +62,7 @@
We just sent a one-time confirmation code to {email}. Once you receive it, you can enter it We just sent a one-time confirmation code to {email}. Once you receive it, you can enter it
above. above.
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -69,4 +73,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -5,6 +5,8 @@
import {getKey, setKey} from "@lib/implicit" import {getKey, setKey} from "@lib/implicit"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ProfileEditForm from "@app/components/ProfileEditForm.svelte" import ProfileEditForm from "@app/components/ProfileEditForm.svelte"
@ -26,7 +28,8 @@
} }
</script> </script>
<div class="flex flex-col gap-4"> <Modal>
<ModalBody>
<ProfileEditForm isSignup {initialValues} {onsubmit}> <ProfileEditForm isSignup {initialValues} {onsubmit}>
{#snippet footer()} {#snippet footer()}
<ModalFooter> <ModalFooter>
@ -41,4 +44,5 @@
</ModalFooter> </ModalFooter>
{/snippet} {/snippet}
</ProfileEditForm> </ProfileEditForm>
</div> </ModalBody>
</Modal>

View file

@ -9,6 +9,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -48,7 +50,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(join)}> <Modal tag="form" onsubmit={preventDefault(join)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Request Access</div> <div>Request Access</div>
@ -68,6 +71,7 @@
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -78,4 +82,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -6,6 +6,8 @@
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import CardButton from "@lib/components/CardButton.svelte" import CardButton from "@lib/components/CardButton.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import SpaceInviteAccept from "@app/components/SpaceInviteAccept.svelte" import SpaceInviteAccept from "@app/components/SpaceInviteAccept.svelte"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
@ -19,7 +21,8 @@
const startJoin = () => pushModal(SpaceInviteAccept) const startJoin = () => pushModal(SpaceInviteAccept)
</script> </script>
<div class="column gap-2"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Add a Space</div> <div>Add a Space</div>
@ -69,4 +72,5 @@
{/snippet} {/snippet}
</CardButton> </CardButton>
</Link> </Link>
</div> </ModalBody>
</Modal>

View file

@ -8,6 +8,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import {preventDefault} from "@lib/html" import {preventDefault} from "@lib/html"
import {ucFirst} from "@lib/util" import {ucFirst} from "@lib/util"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import SpaceAccessRequest from "@app/components/SpaceAccessRequest.svelte" import SpaceAccessRequest from "@app/components/SpaceAccessRequest.svelte"
@ -37,7 +39,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(requestAccess)}> <Modal tag="form" onsubmit={preventDefault(requestAccess)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Access Error</div> <div>Access Error</div>
@ -47,11 +50,14 @@
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p> <p>
We received an error from the relay indicating you don't have access to {displayRelayUrl(url)}: We received an error from the relay indicating you don't have access to {displayRelayUrl(
url,
)}:
</p> </p>
<p class="bg-alt card2 welshman-content"> <p class="bg-alt card2 welshman-content">
{@html renderAsHtml(parse({content: ucFirst(error)}))} {@html renderAsHtml(parse({content: ucFirst(error)}))}
</p> </p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -67,4 +73,4 @@
</Button> </Button>
</div> </div>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -8,6 +8,8 @@
import BillList from "@assets/icons/bill-list.svg?dataurl" import BillList from "@assets/icons/bill-list.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Link from "@lib/components/Link.svelte" import Link from "@lib/components/Link.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import RelayName from "@app/components/RelayName.svelte" import RelayName from "@app/components/RelayName.svelte"
@ -33,7 +35,8 @@
const startEdit = () => pushModal(SpaceEdit, {url, initialValues: $relay || {url}}) const startEdit = () => pushModal(SpaceEdit, {url, initialValues: $relay || {url}})
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<div class="flex justify-between"> <div class="flex justify-between">
<div class="relative flex gap-4"> <div class="relative flex gap-4">
<div class="relative"> <div class="relative">
@ -91,10 +94,11 @@
</div> </div>
{/if} {/if}
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -11,6 +11,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ImageIcon from "@lib/components/ImageIcon.svelte" import ImageIcon from "@lib/components/ImageIcon.svelte"
@ -119,7 +121,8 @@
} }
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(trySubmit)}> <Modal tag="form" onsubmit={preventDefault(trySubmit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Edit a Space</div> <div>Edit a Space</div>
@ -183,6 +186,7 @@
</label> </label>
{/snippet} {/snippet}
</FieldInline> </FieldInline>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -192,4 +196,4 @@
<Spinner {loading}>Save Changes</Spinner> <Spinner {loading}>Save Changes</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -6,6 +6,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {removeSpaceMembership, publishLeaveRequest, removeTrustedRelay} from "@app/core/commands" import {removeSpaceMembership, publishLeaveRequest, removeTrustedRelay} from "@app/core/commands"
@ -31,7 +33,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(exit)}> <Modal tag="form" onsubmit={preventDefault(exit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div> <div>
@ -40,6 +43,7 @@
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p class="text-center">Are you sure you want to leave?</p> <p class="text-center">Are you sure you want to leave?</p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -49,4 +53,4 @@
<Spinner {loading}>Confirm</Spinner> <Spinner {loading}>Confirm</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -9,6 +9,8 @@
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import QRCode from "@app/components/QRCode.svelte" import QRCode from "@app/components/QRCode.svelte"
@ -52,7 +54,8 @@
}) })
</script> </script>
<div class="col-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Create an Invite</div> <div>Create an Invite</div>
@ -97,7 +100,8 @@
</div> </div>
{/if} {/if}
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-primary flex-grow" onclick={back}>Done</Button> <Button class="btn btn-primary flex-grow" onclick={back}>Done</Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -12,6 +12,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl" import AltArrowRight from "@assets/icons/alt-arrow-right.svg?dataurl"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import RelaySummary from "@app/components/RelaySummary.svelte" import RelaySummary from "@app/components/RelaySummary.svelte"
@ -24,12 +26,10 @@
type Props = { type Props = {
invite: string invite: string
abortAction?: Snippet back?: () => void
} }
let {invite = "", abortAction}: Props = $props() let {invite = "", back = () => history.back()}: Props = $props()
const back = () => history.back()
const joinRelay = async () => { const joinRelay = async () => {
const {url, claim} = inviteData! const {url, claim} = inviteData!
@ -63,7 +63,8 @@
const inviteData = $derived(parseInviteLink(invite)) const inviteData = $derived(parseInviteLink(invite))
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(join)}> <Modal tag="form" onsubmit={preventDefault(join)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Join a Space</div> <div>Join a Space</div>
@ -83,28 +84,25 @@
</label> </label>
{/snippet} {/snippet}
</Field> </Field>
<div class="-my-4">
{#if inviteData} {#if inviteData}
<div class="-my-4">
<div transition:slideAndFade class="flex flex-col gap-4 py-4"> <div transition:slideAndFade class="flex flex-col gap-4 py-4">
<div class="card2 bg-alt flex flex-col gap-4"> <div class="card2 bg-alt flex flex-col gap-4">
<p class="opacity-75">You're about to join:</p> <p class="opacity-75">You're about to join:</p>
<RelaySummary url={inviteData.url} /> <RelaySummary url={inviteData.url} />
</div> </div>
</div> </div>
{/if}
</div> </div>
{/if}
</ModalBody>
<ModalFooter> <ModalFooter>
{#if abortAction}
{@render abortAction?.()}
{:else}
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
{/if}
<Button type="submit" class="btn btn-primary" disabled={!inviteData || loading}> <Button type="submit" class="btn btn-primary" disabled={!inviteData || loading}>
<Spinner {loading}>Join Space</Spinner> <Spinner {loading}>Join Space</Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -12,14 +12,20 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import StatusIndicator from "@lib/components/StatusIndicator.svelte" import StatusIndicator from "@lib/components/StatusIndicator.svelte"
import RelaySummary from "@app/components/RelaySummary.svelte" import RelaySummary from "@app/components/RelaySummary.svelte"
import SocketStatusIndicator from "@app/components/SocketStatusIndicator.svelte" import SocketStatusIndicator from "@app/components/SocketStatusIndicator.svelte"
import SpaceAccessRequest from "@app/components/SpaceAccessRequest.svelte" import SpaceAccessRequest from "@app/components/SpaceAccessRequest.svelte"
import {attemptRelayAccess, addSpaceMembership, broadcastUserData, setSpaceNotifications} from "@app/core/commands" import {
attemptRelayAccess,
addSpaceMembership,
broadcastUserData,
setSpaceNotifications,
} from "@app/core/commands"
import {relaysMostlyRestricted, deriveSpaceMembers, notificationSettings} from "@app/core/state" import {relaysMostlyRestricted, deriveSpaceMembers, notificationSettings} from "@app/core/state"
import {pushModal} from "@app/util/modal" import {pushModal} from "@app/util/modal"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
@ -83,7 +89,8 @@
}) })
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(join)}> <Modal tag="form" onsubmit={preventDefault(join)}>
<ModalBody>
<RelaySummary {url} /> <RelaySummary {url} />
<div class="card2 card2-sm bg-alt"> <div class="card2 card2-sm bg-alt">
<div class="flex justify-between gap-12"> <div class="flex justify-between gap-12">
@ -112,16 +119,17 @@
</div> </div>
{/if} {/if}
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back} disabled={loading}> <Button class="btn btn-link" onclick={back} disabled={loading}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
<Button type="submit" class="btn btn-primary" disabled={loading}> <Button type="submit" class="btn btn-primary" disabled={loading}>
<Spinner loading={loading}> <Spinner {loading}>
{error ? "Request Access" : "Join Space"} {error ? "Request Access" : "Join Space"}
</Spinner> </Spinner>
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -10,6 +10,8 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Popover from "@lib/components/Popover.svelte" import Popover from "@lib/components/Popover.svelte"
import Confirm from "@lib/components/Confirm.svelte" import Confirm from "@lib/components/Confirm.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
import SpaceMembersAdd from "@app/components/SpaceMembersAdd.svelte" import SpaceMembersAdd from "@app/components/SpaceMembersAdd.svelte"
@ -68,7 +70,8 @@
let menuPubkey = $state<string | undefined>() let menuPubkey = $state<string | undefined>()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <div class="flex min-w-0 flex-col gap-1">
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1> <h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Members</h1>
<p class="ellipsize text-sm opacity-75">of {displayRelayUrl(url)}</p> <p class="ellipsize text-sm opacity-75">of {displayRelayUrl(url)}</p>
@ -114,10 +117,11 @@
</div> </div>
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -6,6 +6,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte" import ProfileMultiSelect from "@app/components/ProfileMultiSelect.svelte"
@ -49,7 +51,8 @@
let pubkeys: string[] = $state([]) let pubkeys: string[] = $state([])
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Add Members</div> <div>Add Members</div>
@ -66,6 +69,7 @@
<ProfileMultiSelect bind:value={pubkeys} /> <ProfileMultiSelect bind:value={pubkeys} />
{/snippet} {/snippet}
</Field> </Field>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -75,4 +79,4 @@
<Spinner {loading}>Save changes</Spinner> <Spinner {loading}>Save changes</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -8,6 +8,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Popover from "@lib/components/Popover.svelte" import Popover from "@lib/components/Popover.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Profile from "@app/components/Profile.svelte" import Profile from "@app/components/Profile.svelte"
@ -49,7 +51,8 @@
let menuPubkey = $state<string | undefined>() let menuPubkey = $state<string | undefined>()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Banned users</div> <div>Banned users</div>
@ -86,10 +89,11 @@
</div> </div>
</div> </div>
{/each} {/each}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Got it Got it
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -3,6 +3,8 @@
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl" import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import ReportItem from "@app/components/ReportItem.svelte" import ReportItem from "@app/components/ReportItem.svelte"
import {deriveEventsForUrl} from "@app/core/state" import {deriveEventsForUrl} from "@app/core/state"
@ -18,7 +20,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<div class="flex min-w-0 flex-col gap-1"> <div class="flex min-w-0 flex-col gap-1">
<h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Reports</h1> <h1 class="ellipsize whitespace-nowrap text-2xl font-bold">Reports</h1>
<p class="ellipsize text-sm opacity-75">on {displayRelayUrl(url)}</p> <p class="ellipsize text-sm opacity-75">on {displayRelayUrl(url)}</p>
@ -26,10 +29,11 @@
{#each $reports as event (event.id)} {#each $reports as event (event.id)}
<ReportItem {url} {event} /> <ReportItem {url} {event} />
{/each} {/each}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
Go back Go back
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -8,7 +8,10 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte"
import InfoSignatures from "@app/components/InfoSignatures.svelte" import InfoSignatures from "@app/components/InfoSignatures.svelte"
import {relaysPendingTrust} from "@app/core/state" import {relaysPendingTrust} from "@app/core/state"
import {removeSpaceMembership, addTrustedRelay, removeTrustedRelay} from "@app/core/commands" import {removeSpaceMembership, addTrustedRelay, removeTrustedRelay} from "@app/core/commands"
@ -49,7 +52,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(trustSpace)}> <Modal tag="form" onsubmit={preventDefault(trustSpace)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Do you trust this space? Do you trust this space?
@ -67,11 +71,13 @@
>, which means that they have the ability to forge messages from other users. >, which means that they have the ability to forge messages from other users.
</p> </p>
<p> <p>
If you trust this space's admin, you can continue. Otherwise, it may be safer not to join this If you trust this space's admin, you can continue. Otherwise, it may be safer not to join
space. this space.
</p> </p>
</div> </div>
<div class="mt-4 flex flex-col gap-2 sm:flex-row sm:justify-between"> </ModalBody>
<ModalFooter>
<div class="flex flex-col gap-2 sm:flex-row sm:justify-between">
<Button class="btn btn-neutral" onclick={untrustSpace} disabled={loading}> <Button class="btn btn-neutral" onclick={untrustSpace} disabled={loading}>
{#if !loading} {#if !loading}
<Icon icon={CloseCircle} /> <Icon icon={CloseCircle} />
@ -85,4 +91,5 @@
<Spinner {loading}>I trust this space, continue</Spinner> <Spinner {loading}>I trust this space, continue</Spinner>
</Button> </Button>
</div> </div>
</form> </ModalFooter>
</Modal>

View file

@ -10,6 +10,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import EditorContent from "@app/editor/EditorContent.svelte" import EditorContent from "@app/editor/EditorContent.svelte"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"
import {PROTECTED} from "@app/core/state" import {PROTECTED} from "@app/core/state"
@ -74,7 +76,8 @@
let title: string = $state("") let title: string = $state("")
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(submit)}> <Modal tag="form" onsubmit={preventDefault(submit)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Create a Thread</div> <div>Create a Thread</div>
@ -121,6 +124,7 @@
{/if} {/if}
</Button> </Button>
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -128,4 +132,4 @@
</Button> </Button>
<Button type="submit" class="btn btn-primary">Create Thread</Button> <Button type="submit" class="btn btn-primary">Create Thread</Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -2,6 +2,8 @@
import {getWalletAddress} from "@welshman/util" import {getWalletAddress} from "@welshman/util"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {updateProfile} from "@app/core/commands" import {updateProfile} from "@app/core/commands"
@ -32,7 +34,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Set as Receiving Address? Set as Receiving Address?
@ -43,7 +46,8 @@
Your current receiving address is different from the one provided by your connected wallet. Your current receiving address is different from the one provided by your connected wallet.
</p> </p>
<p> <p>
Would you like to update your receiving address to <span class="text-primary">{lud16}</span>? Would you like to update your receiving address to <span class="text-primary">{lud16}</span
>?
</p> </p>
{:else} {:else}
<p> <p>
@ -52,10 +56,11 @@
</p> </p>
<p>Would you like to use the one associated with your connected wallet?</p> <p>Would you like to use the one associated with your connected wallet?</p>
{/if} {/if}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-neutral" onclick={cancel} disabled={loading}>No, skip this</Button> <Button class="btn btn-neutral" onclick={cancel} disabled={loading}>No, skip this</Button>
<Button class="btn btn-primary" onclick={confirm} disabled={loading}> <Button class="btn btn-primary" onclick={confirm} disabled={loading}>
<Spinner {loading}>Yes, set as receiving address</Spinner> <Spinner {loading}>Yes, set as receiving address</Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -15,6 +15,8 @@
import Scanner from "@lib/components/Scanner.svelte" import Scanner from "@lib/components/Scanner.svelte"
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Field from "@lib/components/Field.svelte" import Field from "@lib/components/Field.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {getWebLn} from "@app/core/commands" import {getWebLn} from "@app/core/commands"
@ -109,7 +111,8 @@
let loading = $state(false) let loading = $state(false)
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Connect a Wallet</div> <div>Connect a Wallet</div>
@ -164,6 +167,7 @@
{#if showScanner} {#if showScanner}
<Scanner onscan={onScan} /> <Scanner onscan={onScan} />
{/if} {/if}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -185,4 +189,4 @@
</Spinner> </Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -8,6 +8,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Scanner from "@lib/components/Scanner.svelte" import Scanner from "@lib/components/Scanner.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {payInvoice} from "@app/core/commands" import {payInvoice} from "@app/core/commands"
@ -48,7 +50,8 @@
let sats = $state(0) let sats = $state(0)
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Pay with Lightning</div> <div>Pay with Lightning</div>
@ -94,6 +97,7 @@
To make a payment, scan a lightning invoice with your camera. To make a payment, scan a lightning invoice with your camera.
</p> </p>
{/if} {/if}
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -108,4 +112,4 @@
Confirm Payment Confirm Payment
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -5,6 +5,8 @@
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import Wallet from "@assets/icons/wallet.svg?dataurl" import Wallet from "@assets/icons/wallet.svg?dataurl"
import CheckCircle from "@assets/icons/check-circle.svg?dataurl" import CheckCircle from "@assets/icons/check-circle.svg?dataurl"
import {updateProfile} from "@app/core/commands" import {updateProfile} from "@app/core/commands"
@ -42,7 +44,8 @@
} }
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
Update Lightning Address Update Lightning Address
@ -84,7 +87,7 @@
</div> </div>
{/if} {/if}
</div> </div>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-neutral" onclick={back} disabled={isLoading}>Cancel</Button> <Button class="btn btn-neutral" onclick={back} disabled={isLoading}>Cancel</Button>
<Button class="btn btn-primary" onclick={save} disabled={isLoading}> <Button class="btn btn-primary" onclick={save} disabled={isLoading}>
@ -96,4 +99,4 @@
Save Changes Save Changes
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -10,6 +10,8 @@
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import FieldInline from "@lib/components/FieldInline.svelte" import FieldInline from "@lib/components/FieldInline.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import EmojiButton from "@lib/components/EmojiButton.svelte" import EmojiButton from "@lib/components/EmojiButton.svelte"
@ -109,7 +111,8 @@
}) })
</script> </script>
<div class="column gap-4"> <Modal>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>Send a Zap</div> <div>Send a Zap</div>
@ -149,6 +152,7 @@
min={minPos} min={minPos}
max={maxPos} max={maxPos}
bind:value={pos} /> bind:value={pos} />
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -165,4 +169,4 @@
</Spinner> </Spinner>
</Button> </Button>
</ModalFooter> </ModalFooter>
</div> </Modal>

View file

@ -389,11 +389,11 @@ export const toggleRoomNotifications = async (url: string, h: string) => {
} else { } else {
// Toggle exception status // Toggle exception status
const hasException = existing.exceptions.includes(h) const hasException = existing.exceptions.includes(h)
const exceptions = hasException ? remove(h, existing.exceptions) : append(h, existing.exceptions) const exceptions = hasException
? remove(h, existing.exceptions)
: append(h, existing.exceptions)
updated = alerts.map((s: SpaceNotificationSettings) => updated = alerts.map((s: SpaceNotificationSettings) => (s.url === url ? {...s, exceptions} : s))
s.url === url ? {...s, exceptions} : s,
)
} }
return publishSettings({alerts: updated}) return publishSettings({alerts: updated})

View file

@ -533,9 +533,7 @@ class CapacitorNotifications implements IPushAdapter {
} else { } else {
// notify=false: exceptions are opt-in (only include those rooms) // notify=false: exceptions are opt-in (only include those rooms)
if (exceptions.length > 0) { if (exceptions.length > 0) {
filters.push( filters.push(...baseFilters.map(f => ({...f, "#h": exceptions})))
...baseFilters.map(f => ({...f, "#h": exceptions})),
)
} }
} }
} }
@ -625,9 +623,7 @@ class CapacitorNotifications implements IPushAdapter {
await Promise.all(get(userSpaceUrls).map(url => this._unsyncRelay(url, "spaces"))) await Promise.all(get(userSpaceUrls).map(url => this._unsyncRelay(url, "spaces")))
await Promise.all( await Promise.all(
getRelaysFromList(get(userMessagingRelayList)).map(url => getRelaysFromList(get(userMessagingRelayList)).map(url => this._unsyncRelay(url, "messages")),
this._unsyncRelay(url, "messages"),
),
) )
} }
} }

View file

@ -7,6 +7,8 @@
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import Modal from "@lib/components/Modal.svelte"
import ModalBody from "@lib/components/ModalBody.svelte"
interface Props { interface Props {
title?: string title?: string
@ -32,7 +34,8 @@
const back = () => history.back() const back = () => history.back()
</script> </script>
<form class="column gap-4" onsubmit={preventDefault(tryConfirm)}> <Modal tag="form" onsubmit={preventDefault(tryConfirm)}>
<ModalBody>
<ModalHeader> <ModalHeader>
{#snippet title()} {#snippet title()}
<div>{restProps.title || "Are you sure?"}</div> <div>{restProps.title || "Are you sure?"}</div>
@ -42,6 +45,7 @@
{/snippet} {/snippet}
</ModalHeader> </ModalHeader>
<p class="text-center">{message}</p> <p class="text-center">{message}</p>
</ModalBody>
<ModalFooter> <ModalFooter>
<Button class="btn btn-link" onclick={back}> <Button class="btn btn-link" onclick={back}>
<Icon icon={AltArrowLeft} /> <Icon icon={AltArrowLeft} />
@ -52,4 +56,4 @@
<Icon icon={AltArrowRight} /> <Icon icon={AltArrowRight} />
</Button> </Button>
</ModalFooter> </ModalFooter>
</form> </Modal>

View file

@ -1,12 +1,17 @@
<script lang="ts"> <script lang="ts">
import type {Component} from "svelte"
import cx from "classnames" import cx from "classnames"
import {onMount} from "svelte"
import {noop} from "@welshman/lib" import {noop} from "@welshman/lib"
import {fade, fly} from "@lib/transition" import {fade, fly} from "@lib/transition"
interface Props { type Props = {
onClose?: any onClose?: any
fullscreen?: boolean fullscreen?: boolean
children?: import("svelte").Snippet children: {
component: Component<any>
props: Record<string, any>
}
} }
const {onClose = noop, fullscreen = false, children}: Props = $props() const {onClose = noop, fullscreen = false, children}: Props = $props()
@ -21,9 +26,9 @@
const innerClass = $derived( const innerClass = $derived(
cx( cx(
"relative text-base-content text-base-content flex-grow pointer-events-auto", "relative text-base-content text-base-content flex-grow pointer-events-auto",
"px-4 py-6 rounded-t-box sm:p-6 sm:rounded-box sm:mt-0", "rounded-t-box sm:rounded-box",
{ {
"bg-alt shadow-m max-h-[90vh] scroll-container overflow-auto": !fullscreen, "bg-alt shadow-m max-h-[90vh] flex flex-col": !fullscreen,
}, },
), ),
) )
@ -39,7 +44,7 @@
</button> </button>
<div class={wrapperClass}> <div class={wrapperClass}>
<div class={innerClass} transition:fly={{duration: 300}}> <div class={innerClass} transition:fly={{duration: 300}}>
{@render children?.()} <children.component {...children.props} />
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,7 +1,16 @@
<script lang="ts"> <script lang="ts">
import type {Component} from "svelte"
import {fade, translate} from "@lib/transition" import {fade, translate} from "@lib/transition"
const {onClose, children} = $props() type Props = {
onClose?: any
children: {
component: Component
props: Record<string, any>
}
}
const {onClose, children}: Props = $props()
</script> </script>
<div class="drawer fixed inset-0 z-modal"> <div class="drawer fixed inset-0 z-modal">
@ -14,6 +23,6 @@
<div <div
class="scroll-container py-sai pr-sair absolute bottom-0 right-0 top-0 w-72 overflow-auto bg-base-200 text-base-content lg:w-96" class="scroll-container py-sai pr-sair absolute bottom-0 right-0 top-0 w-72 overflow-auto bg-base-200 text-base-content lg:w-96"
transition:translate={{axis: "x", duration: 300}}> transition:translate={{axis: "x", duration: 300}}>
{@render children?.()} <children.component {...children.props} />
</div> </div>
</div> </div>

View file

@ -58,7 +58,12 @@
</Tippy> </Tippy>
{#if showIconPicker} {#if showIconPicker}
<Dialog onClose={close}> <Dialog
<IconPicker onSelect={onClick} /> onClose={close}
</Dialog> children={{
component: IconPicker,
props: {
onSelect: onClick,
},
}} />
{/if} {/if}

View file

@ -0,0 +1,17 @@
<script lang="ts">
import cx from "classnames"
import type {Snippet} from "svelte"
interface Props {
tag?: string
class?: string
children?: Snippet
[key: string]: any
}
const {children, tag = "div", ...props}: Props = $props()
</script>
<svelte:element this={tag} {...props} class={cx("flex flex-col overflow-hidden pb-6", props.class)}>
{@render children?.()}
</svelte:element>

View file

@ -0,0 +1,16 @@
<script lang="ts">
import cx from "classnames"
import type {Snippet} from "svelte"
interface Props {
class?: string
children?: Snippet
}
const {children, ...props}: Props = $props()
</script>
<div
class={cx("scroll-container overflow-y-auto min-h-0 flex flex-col gap-4 p-6 pb-0", props.class)}>
{@render children?.()}
</div>

View file

@ -8,6 +8,9 @@
const {children}: Props = $props() const {children}: Props = $props()
</script> </script>
<div class="row-4 mt-4 items-center justify-between"> <div class="h-20 flex-shrink-0"></div>
<div class="flex absolute bottom-0 left-0 right-0 p-6 pt-2 rounded-b-box bg-base-100">
<div class="flex flex-grow gap-4 items-center justify-between">
{@render children?.()} {@render children?.()}
</div> </div>
</div>

View file

@ -7,7 +7,7 @@
const {title, info}: Props = $props() const {title, info}: Props = $props()
</script> </script>
<div class="column m-auto max-w-xs gap-2 py-4"> <div class="flex flex-col m-auto max-w-xs gap-2 py-4">
<h1 class="heading">{@render title?.()}</h1> <h1 class="heading">{@render title?.()}</h1>
<p class="text-center text-sm opacity-75">{@render info?.()}</p> <p class="text-center text-sm opacity-75">{@render info?.()}</p>
</div> </div>

View file

@ -1,20 +1,16 @@
<script lang="ts"> <script lang="ts">
import {page} from "$app/stores" import {page} from "$app/stores"
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
import AltArrowLeft from "@assets/icons/alt-arrow-left.svg?dataurl"
import Icon from "@lib/components/Icon.svelte"
import Dialog from "@lib/components/Dialog.svelte" import Dialog from "@lib/components/Dialog.svelte"
import Button from "@lib/components/Button.svelte"
import SpaceInviteAccept from "@app/components/SpaceInviteAccept.svelte" import SpaceInviteAccept from "@app/components/SpaceInviteAccept.svelte"
const children = {
component: SpaceInviteAccept,
props: {
invite: $page.url.href,
back: () => goto("/home"),
},
}
</script> </script>
<Dialog> <Dialog {children} />
<SpaceInviteAccept invite={$page.url.href}>
{#snippet abortAction()}
<Button class="btn btn-link" onclick={() => goto("/home")}>
<Icon icon={AltArrowLeft} />
Go back
</Button>
{/snippet}
</SpaceInviteAccept>
</Dialog>

View file

@ -47,11 +47,7 @@
userSettingsValues, userSettingsValues,
} from "@app/core/state" } from "@app/core/state"
import {setChecked, checked} from "@app/util/notifications" import {setChecked, checked} from "@app/util/notifications"
import { import {canEnforceNip70, prependParent, publishDelete} from "@app/core/commands"
canEnforceNip70,
prependParent,
publishDelete,
} from "@app/core/commands"
import {makeFeed} from "@app/core/requests" import {makeFeed} from "@app/core/requests"
import {popKey} from "@lib/implicit" import {popKey} from "@lib/implicit"
import {pushToast} from "@app/util/toast" import {pushToast} from "@app/util/toast"