greatly improve handling of modals
This commit is contained in:
parent
dc8414c050
commit
72c9650f71
11 changed files with 262 additions and 297 deletions
|
@ -1,8 +1,22 @@
|
||||||
import { fade, fly, scale } from "svelte/transition";
|
import { fade, fly, scale } from "svelte/transition";
|
||||||
import { cubicInOut } from "svelte/easing";
|
import { cubicInOut, linear } from "svelte/easing";
|
||||||
import { getItem } from "./storage";
|
import { getItem } from "./storage";
|
||||||
import { smallViewport } from "./stores";
|
import { smallViewport } from "./stores";
|
||||||
|
|
||||||
|
|
||||||
|
// Function specific for the Login and CreateAccount modals, where the transition duration is relied upon
|
||||||
|
export function maybeModalFadeIf(...e) {
|
||||||
|
if (e[1] && e[1]._condition)
|
||||||
|
return maybeModalFade(e[0]);
|
||||||
|
else
|
||||||
|
return {
|
||||||
|
delay: 0,
|
||||||
|
duration: e[1].duration,
|
||||||
|
easing: e[1].easing,
|
||||||
|
css: (_t) => ""
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function maybeModalFade(node) {
|
export function maybeModalFade(node) {
|
||||||
return maybeFade(node, { duration: 175, easing: cubicInOut });
|
return maybeFade(node, { duration: 175, easing: cubicInOut });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { overlayStore } from "../../stores";
|
import { overlayStore } from "../../stores";
|
||||||
import { methods, remoteSignal } from "../../request";
|
import { methods, remoteSignal } from "../../request";
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
let communityName = "";
|
let communityName = "";
|
||||||
let createButtonEnabled = true;
|
let createButtonEnabled = true;
|
||||||
|
@ -15,36 +15,20 @@
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await create();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<Modal {close} enter={create}>
|
||||||
.full-width {
|
<span class="h4" slot="header">Create Community</span>
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ close }" on:keydown="{ onKeydown }">
|
<svelte:fragment slot="content">
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation>
|
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Create Community</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Community Name
|
Community Name
|
||||||
<input class="input full-width" minlength="1" maxlength="32" bind:value={ communityName } />
|
<input class="input full-width" minlength="1" maxlength="32" bind:value={ communityName } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !createButtonEnabled }">Create</button>
|
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !createButtonEnabled }">Create</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { overlayStore, OverlayType } from "../../stores";
|
import { overlayStore, OverlayType } from "../../stores";
|
||||||
import { methods, remoteCall } from "../../request";
|
import { methods, remoteCall } from "../../request";
|
||||||
import { maybeModalScale } from "../../animations";
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
let username = "";
|
let username = "";
|
||||||
let password = "";
|
let password = "";
|
||||||
|
@ -30,31 +30,18 @@
|
||||||
overlayStore.push(OverlayType.Login);
|
overlayStore.push(OverlayType.Login);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await create();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
margin-bottom: var(--space-md);
|
margin-bottom: var(--space-md);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="modal-backdrop modal-backdrop-opaque" on:keydown="{ onKeydown }">
|
<Modal opaque close={loginInstead} {outroEnd} enter={create}>
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation on:outroend="{ outroEnd }">
|
<span class="h4" slot="header">Create an Account</span>
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Create an Account</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Username
|
Username
|
||||||
<input class="input full-width" minlength="1" maxlength="32" bind:value={ username } />
|
<input class="input full-width" minlength="1" maxlength="32" bind:value={ username } />
|
||||||
|
@ -66,11 +53,10 @@
|
||||||
Password
|
Password
|
||||||
<input class="input full-width" minlength="8" type="password" bind:value={ password } />
|
<input class="input full-width" minlength="8" type="password" bind:value={ password } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ loginInstead }">Log in instead</button>
|
<button class="button modal-secondary-action" on:click="{ loginInstead }">Log in instead</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !buttonsEnabled }">Create</button>
|
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !buttonsEnabled }">Create</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { overlayStore } from "../../stores";
|
import { overlayStore } from "../../stores";
|
||||||
import { methods, remoteCall, remoteSignal } from "../../request";
|
import { methods, remoteSignal } from "../../request";
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
let channelName = "";
|
let channelName = "";
|
||||||
let createButtonEnabled = true;
|
let createButtonEnabled = true;
|
||||||
|
@ -16,39 +16,25 @@
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await create();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<Modal {close} enter={create}>
|
||||||
.full-width {
|
<svelte:fragment slot="header">
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ close }" on:keydown="{ onKeydown }">
|
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation>
|
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Create Channel</span>
|
<span class="h4">Create Channel</span>
|
||||||
{#if community.id !== -1}
|
{#if community.id !== -1}
|
||||||
<span class="text-fg-3 text-small">in <span class="text-fg-2">{ community.name }</span></span>
|
<span class="text-fg-3 text-small">in <span class="text-fg-2">{ community.name }</span></span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Channel Name
|
Channel Name
|
||||||
<input class="input full-width" minlength="1" maxlength="32" bind:value={ channelName } />
|
<input class="input full-width" minlength="1" maxlength="32" bind:value={ channelName } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !createButtonEnabled }">Create</button>
|
<button class="button button-accent modal-primary-action" on:click="{ create }" disabled="{ !createButtonEnabled }">Create</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
|
||||||
import { overlayStore } from "../../stores";
|
import { overlayStore } from "../../stores";
|
||||||
import { methods, remoteCall, remoteSignal } from "../../request";
|
import { methods, remoteSignal } from "../../request";
|
||||||
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
export let channel;
|
export let channel;
|
||||||
|
|
||||||
|
@ -25,41 +25,27 @@
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await save();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-button {
|
.delete-button {
|
||||||
color: var(--red-2);
|
color: var(--red-2);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ close }" on:keydown="{ onKeydown }">
|
<Modal {close} enter={save}>
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation>
|
<span class="h4" slot="header">Edit Channel</span>
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Edit Channel</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Channel Name
|
Channel Name
|
||||||
<input class="input full-width" minlength="1" maxlength="32" bind:value={ channelName } />
|
<input class="input full-width" minlength="1" maxlength="32" bind:value={ channelName } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
||||||
<button class="button modal-secondary-action delete-button" on:click="{ deleteChannel }" disabled="{ !buttonsEnabled }">Delete</button>
|
<button class="button modal-secondary-action delete-button" on:click="{ deleteChannel }" disabled="{ !buttonsEnabled }">Delete</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Save</button>
|
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Save</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { overlayStore } from "../../stores";
|
import { overlayStore } from "../../stores";
|
||||||
import { methods, remoteCall, remoteSignal } from "../../request";
|
import { methods, remoteSignal } from "../../request";
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
export let message;
|
export let message;
|
||||||
|
|
||||||
|
@ -25,41 +25,27 @@
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await save();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.delete-button {
|
.delete-button {
|
||||||
color: var(--red-2);
|
color: var(--red-2);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ close }" on:keydown="{ onKeydown }">
|
<Modal {close} enter={save}>
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation>
|
<span class="h4" slot="header">Edit Message</span>
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Edit Message</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Content
|
Content
|
||||||
<input class="input full-width" minlength="1" bind:value={ messageContent } />
|
<input class="input full-width" minlength="1" bind:value={ messageContent } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
<button class="button modal-secondary-action" on:click="{ close }">Cancel</button>
|
||||||
<button class="button modal-secondary-action delete-button" on:click="{ deleteMessage }" disabled="{ !buttonsEnabled }">Delete</button>
|
<button class="button modal-secondary-action delete-button" on:click="{ deleteMessage }" disabled="{ !buttonsEnabled }">Delete</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Save</button>
|
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Save</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
import { overlayStore, OverlayType } from "../../stores";
|
import { overlayStore, OverlayType } from "../../stores";
|
||||||
import { remoteCall } from "../../request";
|
import { remoteCall } from "../../request";
|
||||||
import { authWithToken } from "../../auth";
|
import { authWithToken } from "../../auth";
|
||||||
import { maybeModalScale } from "../../animations";
|
|
||||||
import { methods } from "../../request";
|
import { methods } from "../../request";
|
||||||
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
let username = "";
|
let username = "";
|
||||||
let password = "";
|
let password = "";
|
||||||
|
@ -35,31 +35,18 @@
|
||||||
overlayStore.push(OverlayType.CreateAccount);
|
overlayStore.push(OverlayType.CreateAccount);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await login();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
margin-bottom: var(--space-md);
|
margin-bottom: var(--space-md);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<div class="modal-backdrop modal-backdrop-opaque" on:keydown="{ onKeydown }">
|
<Modal opaque close={createAccountInstead} {outroEnd} enter={login}>
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation on:outroend="{ outroEnd }">
|
<span class="h4" slot="header">Welcome back!</span>
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Welcome back!</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<label class="input-label">
|
<label class="input-label">
|
||||||
Username
|
Username
|
||||||
<input class="input full-width" minlength="1" maxlength="32" bind:value={ username } />
|
<input class="input full-width" minlength="1" maxlength="32" bind:value={ username } />
|
||||||
|
@ -71,11 +58,10 @@
|
||||||
Password
|
Password
|
||||||
<input class="input full-width" minlength="8" type="password" bind:value={ password } />
|
<input class="input full-width" minlength="8" type="password" bind:value={ password } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ createAccountInstead }">Create an account instead</button>
|
<button class="button modal-secondary-action" on:click="{ createAccountInstead }">Create an account instead</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ login }" disabled="{ !buttonsEnabled }">Log In</button>
|
<button class="button button-accent modal-primary-action" on:click="{ login }" disabled="{ !buttonsEnabled }">Log In</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
57
frontend/src/components/overlays/Modal.svelte
Normal file
57
frontend/src/components/overlays/Modal.svelte
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { maybeModalFade, maybeModalFadeIf, maybeModalScale } from "../../animations";
|
||||||
|
|
||||||
|
export let close = () => {};
|
||||||
|
export let enter = () => {};
|
||||||
|
export let outroEnd = () => {};
|
||||||
|
export let className = "";
|
||||||
|
export let opaque = false;
|
||||||
|
let modal;
|
||||||
|
let blur = false;
|
||||||
|
|
||||||
|
const onKeydown = ({ code }) => {
|
||||||
|
if (code === "Enter") {
|
||||||
|
enter();
|
||||||
|
} else if (code === "Escape") {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const backdropIntroEnd = () => {
|
||||||
|
blur = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const backdropOutroStart = () => {
|
||||||
|
blur = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
modal.focus();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||||
|
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||||
|
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||||
|
<div class="modal-backdrop" class:modal-backdrop-opaque={opaque} class:blur={blur} transition:maybeModalFadeIf="{{ _condition: !opaque }}" on:click="{ close }" on:keydown="{ onKeydown }" on:introend={backdropIntroEnd} on:outrostart={backdropOutroStart}>
|
||||||
|
<div bind:this={modal} role="alertdialog" tabindex="-1" aria-modal="true" class={className + " modal"} transition:maybeModalScale on:click|stopPropagation on:outroend={outroEnd}>
|
||||||
|
{#if $$slots.header}
|
||||||
|
<div class="modal-header">
|
||||||
|
<slot name="header" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $$slots.content}
|
||||||
|
<div class="modal-content">
|
||||||
|
<slot name="content" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if $$slots.footer}
|
||||||
|
<div class="modal-footer">
|
||||||
|
<slot name="footer" />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
export let onSubmit = async () => {};
|
export let onSubmit = async () => {};
|
||||||
export let onClose = async () => {};
|
export let onClose = async () => {};
|
||||||
|
@ -19,36 +19,18 @@
|
||||||
await onSubmit(userInput);
|
await onSubmit(userInput);
|
||||||
closePrompt();
|
closePrompt();
|
||||||
};
|
};
|
||||||
const onKeydown = async (e) => {
|
|
||||||
if (e.code !== "Enter")
|
|
||||||
return;
|
|
||||||
|
|
||||||
await save();
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<Modal {closePrompt} enter={save}>
|
||||||
.full-width {
|
<span class="h4" slot="header">{ heading }</span>
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ closePrompt }" on:keydown="{ onKeydown }">
|
<label class="input-label" slot="content">
|
||||||
<div class="modal" transition:maybeModalScale on:click|stopPropagation>
|
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">{ heading }</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
|
||||||
<label class="input-label">
|
|
||||||
{ valueName }
|
{ valueName }
|
||||||
<input class="input full-width" bind:value={ userInput } />
|
<input class="input full-width" bind:value={ userInput } />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-footer">
|
<svelte:fragment slot="footer">
|
||||||
<button class="button modal-secondary-action" on:click="{ closePrompt }">Cancel</button>
|
<button class="button modal-secondary-action" on:click="{ closePrompt }">Cancel</button>
|
||||||
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Submit</button>
|
<button class="button button-accent modal-primary-action" on:click="{ save }" disabled="{ !buttonsEnabled }">Submit</button>
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
import { overlayStore, userInfoStore, smallViewport, theme, doAnimations, OverlayType, sendTypingUpdatesItemStore } from "../../stores";
|
import { overlayStore, userInfoStore, smallViewport, theme, doAnimations, OverlayType, sendTypingUpdatesItemStore } from "../../stores";
|
||||||
import { logOut } from "../../auth";
|
import { logOut } from "../../auth";
|
||||||
import { maybeModalFade, maybeModalScale } from "../../animations";
|
import { maybeModalFade, maybeModalScale } from "../../animations";
|
||||||
import request, { methods, remoteBlobUpload, remoteCall } from "../../request";
|
import request, { methods, remoteBlobUpload } from "../../request";
|
||||||
import { apiRoute, getItem } from "../../storage";
|
import { apiRoute, getItem } from "../../storage";
|
||||||
import UserView from "../UserView.svelte";
|
import UserView from "../UserView.svelte";
|
||||||
import ChipBar from "../ChipBar.svelte";
|
import ChipBar from "../ChipBar.svelte";
|
||||||
import Switch from "../Switch.svelte";
|
|
||||||
import StoredSwitch from "../StoredSwitch.svelte";
|
import StoredSwitch from "../StoredSwitch.svelte";
|
||||||
|
import Modal from "./Modal.svelte";
|
||||||
|
|
||||||
export let close = () => {};
|
export let close = () => {};
|
||||||
let avatarFileInput;
|
let avatarFileInput;
|
||||||
|
@ -76,12 +76,7 @@
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
|
||||||
<style>
|
<style>
|
||||||
.full-width {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
margin-bottom: var(--space-sm);
|
margin-bottom: var(--space-sm);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +123,7 @@
|
||||||
grid-template-columns: repeat(2, 1fr);
|
grid-template-columns: repeat(2, 1fr);
|
||||||
}
|
}
|
||||||
|
|
||||||
.large-settings {
|
:global(.large-settings) {
|
||||||
width: 600px;
|
width: 600px;
|
||||||
min-height: 425px;
|
min-height: 425px;
|
||||||
padding-bottom: var(--space-xs);
|
padding-bottom: var(--space-xs);
|
||||||
|
@ -138,23 +133,19 @@
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-modal {
|
:global(.settings-modal) {
|
||||||
background-color: var(--background-color-1);
|
background-color: var(--background-color-1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.settings-modal .modal-header {
|
:global(.settings-modal .modal-header) {
|
||||||
padding-bottom: var(--space-xxs);
|
padding-bottom: var(--space-xxs);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
<Modal {close} className={`settings-modal ${$smallViewport ? "" : "large-settings"}`}>
|
||||||
<div class="modal-backdrop" transition:maybeModalFade on:click="{ close }">
|
<span class="h4" slot="header">Settings</span>
|
||||||
<div class="modal settings-modal" class:large-settings="{ !$smallViewport }" transition:maybeModalScale on:click|stopPropagation>
|
|
||||||
<div class="modal-header">
|
|
||||||
<span class="h4">Settings</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="modal-content">
|
<svelte:fragment slot="content">
|
||||||
<ChipBar selectedOptionId="ACCOUNT" onSelect={ (tab) => selectedTab = tab } options={[
|
<ChipBar selectedOptionId="ACCOUNT" onSelect={ (tab) => selectedTab = tab } options={[
|
||||||
{ id: "ACCOUNT", text: "Account", icon: "person" },
|
{ id: "ACCOUNT", text: "Account", icon: "person" },
|
||||||
{ id: "PRIVACY", text: "Privacy", icon: "lock" },
|
{ id: "PRIVACY", text: "Privacy", icon: "lock" },
|
||||||
|
@ -209,6 +200,5 @@
|
||||||
{:else}
|
{:else}
|
||||||
<span>Page not found: { selectedTab }</span>
|
<span>Page not found: { selectedTab }</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</svelte:fragment>
|
||||||
</div>
|
</Modal>
|
||||||
</div>
|
|
||||||
|
|
|
@ -222,10 +222,13 @@ body {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 15;
|
z-index: 15;
|
||||||
background-color: rgba(0, 0, 0, 0.4);
|
background-color: rgba(0, 0, 0, 0.4);
|
||||||
backdrop-filter: blur(1.5px);
|
|
||||||
contain: strict;
|
contain: strict;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal-backdrop.blur {
|
||||||
|
backdrop-filter: blur(1.5px);
|
||||||
|
}
|
||||||
|
|
||||||
.modal-backdrop-opaque {
|
.modal-backdrop-opaque {
|
||||||
background-color: var(--background-color-1);
|
background-color: var(--background-color-1);
|
||||||
backdrop-filter: unset;
|
backdrop-filter: unset;
|
||||||
|
@ -284,7 +287,6 @@ body {
|
||||||
.modal-backdrop {
|
.modal-backdrop {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
backdrop-filter: unset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-backdrop-opaque {
|
.modal-backdrop-opaque {
|
||||||
|
@ -327,8 +329,10 @@ body {
|
||||||
background: none;
|
background: none;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0.7em;
|
padding: 0.85em;
|
||||||
border-radius: 1em;
|
padding-top: 0.65em;
|
||||||
|
padding-bottom: 0.65em;
|
||||||
|
border-radius: 9999px;
|
||||||
font: inherit;
|
font: inherit;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
font-weight: 550;
|
font-weight: 550;
|
||||||
|
@ -588,6 +592,10 @@ body {
|
||||||
border-bottom-left-radius: var(--radius-mdplus);
|
border-bottom-left-radius: var(--radius-mdplus);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.full-width {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! the tweaks below are heavily based on modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
|
/*! the tweaks below are heavily based on modern-normalize v1.1.0 | MIT License | https://github.com/sindresorhus/modern-normalize */
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue