You've already forked AstralRinth
forked from didirus/AstralRinth
Add Modal
This commit is contained in:
@@ -78,11 +78,11 @@
|
||||
border-radius: var(--rounded);
|
||||
transition: opacity 0.5s ease-in-out, filter 0.2s ease-in-out, transform 0.05s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
&:hover:not(&--color-transparent) {
|
||||
filter: brightness(0.85);
|
||||
}
|
||||
|
||||
&:active {
|
||||
&:active:not(&--color-transparent) {
|
||||
transform: scale(0.95);
|
||||
filter: brightness(0.8);
|
||||
}
|
||||
@@ -114,6 +114,15 @@
|
||||
&-transparent {
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
filter: brightness(1) !important;
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.2) 0 0);
|
||||
}
|
||||
}
|
||||
|
||||
&-danger {
|
||||
@@ -122,8 +131,8 @@
|
||||
}
|
||||
|
||||
&-danger-light {
|
||||
background-color: var(--color-popup-danger-bg);
|
||||
color: var(--color-popup-danger-text);
|
||||
background-color: var(--color-danger-bg);
|
||||
color: var(--color-danger-text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
135
src/package/components/Modal.svelte
Normal file
135
src/package/components/Modal.svelte
Normal file
@@ -0,0 +1,135 @@
|
||||
<script lang="ts">
|
||||
import { fade, fly } from 'svelte/transition'
|
||||
import Button from './Button.svelte'
|
||||
import { classCombine } from '../utils/classCombine'
|
||||
import IconX from 'virtual:icons/heroicons-outline/x'
|
||||
import { t } from 'svelte-intl-precompile'
|
||||
|
||||
export let open = false
|
||||
|
||||
/** Set the width of the modal */
|
||||
export let size: 'md' | 'lg' = 'md'
|
||||
|
||||
export let title = ''
|
||||
|
||||
/** If enabled, clicking outside the modal with close it */
|
||||
export let dismissable = true
|
||||
|
||||
function close() {
|
||||
open = false
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if open}
|
||||
<div
|
||||
class="modal-background"
|
||||
transition:fade={{ duration: 300 }}
|
||||
on:click={() => {
|
||||
if (dismissable) close()
|
||||
}} />
|
||||
|
||||
<div
|
||||
class={classCombine(['modal', `modal--size-${size}`, 'card'])}
|
||||
transition:fly={{ y: 400, duration: 250 }}>
|
||||
<div class="modal__top">
|
||||
<h2 class="title-secondary">{title}</h2>
|
||||
<Button title="Close" color="transparent" on:click={close}>
|
||||
<IconX width={20} />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
|
||||
<div class="modal__buttons">
|
||||
<Button on:click={close}><IconX /> Cancel</Button>
|
||||
<slot name="button" />
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<style lang="postcss">
|
||||
:global(.base.theme-dark > .modal, .base.theme-oled > .modal) {
|
||||
border: 1px solid var(--color-divider);
|
||||
}
|
||||
|
||||
.modal-background {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: hsla(0, 0%, 0%, 0.5);
|
||||
backdrop-filter: blur(3px);
|
||||
z-index: 20;
|
||||
}
|
||||
|
||||
.modal {
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
|
||||
width: 80%;
|
||||
z-index: 21;
|
||||
max-height: calc(100% - 2rem);
|
||||
overflow-y: auto;
|
||||
|
||||
&--size {
|
||||
&-md {
|
||||
max-width: 600px;
|
||||
}
|
||||
&-lg {
|
||||
max-width: 750px;
|
||||
}
|
||||
}
|
||||
|
||||
&__top {
|
||||
background-color: var(--color-bg);
|
||||
margin: -1rem -1rem 0.5rem -1rem;
|
||||
padding: 1rem 1rem 1rem 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&__danger {
|
||||
margin: -1.5rem -1rem 0.5rem;
|
||||
background-color: var(--color-danger-bg);
|
||||
padding: 1rem 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
color: var(--color-danger-text);
|
||||
border-color: var(--color-danger-text);
|
||||
border-width: 0.15rem 0;
|
||||
border-style: solid;
|
||||
|
||||
:global(.icon) {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
:global(p),
|
||||
:global(ul),
|
||||
:global(ol) {
|
||||
line-height: 1.5;
|
||||
margin: 0;
|
||||
|
||||
:global(a) {
|
||||
color: var(--color-link);
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__buttons {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 1rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
61
src/package/components/ModalDeletion.svelte
Normal file
61
src/package/components/ModalDeletion.svelte
Normal file
@@ -0,0 +1,61 @@
|
||||
<script lang="ts">
|
||||
import Modal from './Modal.svelte'
|
||||
import Button from './Button.svelte'
|
||||
import TextInput from './TextInput.svelte'
|
||||
import { t } from 'svelte-intl-precompile'
|
||||
import IconExclamation from 'virtual:icons/heroicons-outline/exclamation'
|
||||
import IconTrash from 'virtual:icons/heroicons-outline/trash'
|
||||
import { markdown } from '../utils'
|
||||
|
||||
export let key: string
|
||||
export let type: 'project' | 'version' | 'account' | 'image'
|
||||
|
||||
export let open = false
|
||||
|
||||
let keyInput = ''
|
||||
</script>
|
||||
|
||||
<Modal title={$t(`modal.deletion.${type}.title`)} bind:open>
|
||||
{#if type === 'account' || 'project'}
|
||||
<div class="important-banner">
|
||||
<IconExclamation /><span>{$t('modal.deletion.generic.important')}</span>
|
||||
</div>
|
||||
{/if}
|
||||
{@html markdown($t(`modal.deletion.${type}.description`))}
|
||||
<span class="verify-label">{@html $t('modal.deletion.generic.verify', { values: { key } })}</span>
|
||||
<TextInput
|
||||
placeholder={$t('modal.deletion.generic.placeholder', { values: { key } })}
|
||||
bind:value={keyInput} />
|
||||
<Button color="danger" slot="button" disabled={key !== keyInput}>
|
||||
<IconTrash />
|
||||
{$t(`modal.deletion.${type}.action`)}
|
||||
</Button>
|
||||
</Modal>
|
||||
|
||||
<style lang="postcss">
|
||||
.important-banner {
|
||||
margin: -1.5rem -1rem 0.5rem;
|
||||
background-color: var(--color-danger-bg);
|
||||
padding: 1rem 1.25rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
color: var(--color-danger-text);
|
||||
border-color: var(--color-danger-text);
|
||||
border-width: 0.15rem 0;
|
||||
border-style: solid;
|
||||
|
||||
:global(.icon) {
|
||||
height: 1.5rem;
|
||||
width: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.verify-label {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
:global(i) {
|
||||
font-weight: var(--font-weight-normal);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user