Replace final usage of legacy modal

This commit is contained in:
Prospector
2026-07-28 21:18:40 -07:00
parent 20235b7d32
commit ee60b1adbc
5 changed files with 38 additions and 383 deletions
-156
View File
@@ -1,156 +0,0 @@
<template>
<div v-if="shown">
<div
:class="{
shown: actuallyShown,
noblur: !$orElse(cosmetics.advancedRendering, true),
}"
class="modal-overlay"
@click="hide"
/>
<div class="modal-container" :class="{ shown: actuallyShown }">
<div class="modal-body">
<div v-if="header" class="header">
<strong>{{ header }}</strong>
<ButtonStyled circular type="transparent">
<button @click="hide">
<XIcon />
</button>
</ButtonStyled>
</div>
<div class="content">
<slot />
</div>
</div>
</div>
</div>
<div v-else />
</template>
<script>
import { XIcon } from '@modrinth/assets'
import { ButtonStyled } from '@modrinth/ui'
export default {
components: {
ButtonStyled,
XIcon,
},
props: {
header: {
type: String,
default: null,
},
},
setup() {
const cosmetics = useCosmetics()
return { cosmetics }
},
data() {
return {
shown: false,
actuallyShown: false,
}
},
methods: {
show() {
this.shown = true
setTimeout(() => {
this.actuallyShown = true
}, 50)
},
hide() {
this.actuallyShown = false
setTimeout(() => {
this.shown = false
}, 300)
},
},
}
</script>
<style lang="scss" scoped>
.modal-overlay {
visibility: hidden;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 20;
transition: all 0.3s ease-in-out;
&.shown {
opacity: 1;
visibility: visible;
background: hsla(0, 0%, 0%, 0.5);
backdrop-filter: blur(3px);
}
&.noblur {
backdrop-filter: none;
}
}
.modal-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 21;
visibility: hidden;
pointer-events: none;
&.shown {
visibility: visible;
.modal-body {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
}
.modal-body {
position: fixed;
box-shadow: var(--shadow-raised), var(--shadow-inset);
border-radius: var(--size-rounded-lg);
max-height: calc(100% - 2 * var(--spacing-card-bg));
overflow-y: auto;
width: 600px;
pointer-events: auto;
outline: 3px solid transparent;
.header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: var(--color-bg);
padding: var(--spacing-card-md) var(--spacing-card-lg);
strong {
font-size: 1.25rem;
margin: 0.67em 0;
}
}
.content {
background-color: var(--color-raised-bg);
}
transform: translateY(50vh);
visibility: hidden;
opacity: 0;
transition: all 0.25s ease-in-out;
@media screen and (max-width: 650px) {
width: calc(100% - 2 * var(--spacing-card-bg));
}
}
}
</style>
@@ -7,10 +7,10 @@
:proceed-label="formatMessage(messages.deleteConfirmButton)"
@proceed="removeApp(editingId)"
/>
<Modal ref="appModal" :header="formatMessage(messages.modalHeader)">
<div class="universal-modal">
<label for="app-name"
><span class="label__title">{{ formatMessage(messages.nameLabel) }}</span>
<NewModal ref="appModal" :header="formatMessage(messages.modalHeader)" width="40rem" scrollable>
<div class="flex flex-col">
<label for="app-name" class="m-0 mb-2 text-lg font-semibold text-contrast">
{{ formatMessage(messages.nameLabel) }}
</label>
<StyledInput
id="app-name"
@@ -19,8 +19,12 @@
autocomplete="off"
:placeholder="formatMessage(messages.namePlaceholder)"
/>
<label v-if="editingId" for="app-icon"
><span class="label__title">{{ formatMessage(messages.iconLabel) }}</span>
<label
v-if="editingId"
for="app-icon"
class="mb-2 mt-4 text-lg font-semibold text-contrast"
>
{{ formatMessage(messages.iconLabel) }}
</label>
<div v-if="editingId" class="icon-submission">
<Avatar size="md" :src="icon" />
@@ -36,8 +40,8 @@
</FileInput>
</ButtonStyled>
</div>
<label v-if="editingId" for="app-url">
<span class="label__title">{{ formatMessage(messages.urlLabel) }}</span>
<label v-if="editingId" for="app-url" class="mb-2 mt-4 text-lg font-semibold text-contrast">
{{ formatMessage(messages.urlLabel) }}
</label>
<StyledInput
v-if="editingId"
@@ -48,8 +52,12 @@
autocomplete="off"
:placeholder="formatMessage(messages.urlPlaceholder)"
/>
<label v-if="editingId" for="app-description">
<span class="label__title">{{ formatMessage(messages.descriptionLabel) }}</span>
<label
v-if="editingId"
for="app-description"
class="mb-2 mt-4 text-lg font-semibold text-contrast"
>
{{ formatMessage(messages.descriptionLabel) }}
</label>
<StyledInput
v-if="editingId"
@@ -61,15 +69,12 @@
:placeholder="formatMessage(messages.descriptionPlaceholder)"
input-class="h-24 resize-y"
/>
<label for="app-scopes"
><span class="label__title">{{ formatMessage(messages.scopesLabel) }}</span>
<label for="app-scopes" class="mb-2 mt-4 text-lg font-semibold text-contrast">
{{ formatMessage(messages.scopesLabel) }}
</label>
<div
id="app-scopes"
class="scope-items mt-2 grid grid-cols-1 gap-x-6 gap-y-4 min-[600px]:grid-cols-2"
>
<div id="app-scopes" class="scope-items grid grid-cols-1 gap-6 min-[600px]:grid-cols-2">
<div v-for="category in scopeCategories" :key="category.name" class="flex flex-col gap-2">
<h4 class="m-0 border-b border-divider pb-1 text-base font-bold text-contrast">
<h4 class="m-0 text-base font-medium text-primary">
{{ category.name }}
</h4>
<div class="flex flex-col gap-2">
@@ -83,8 +88,8 @@
</div>
</div>
</div>
<label for="app-redirect-uris" class="mt-4"
><span class="label__title">{{ formatMessage(messages.redirectUrisLabel) }}</span>
<label for="app-redirect-uris" class="mb-2 mt-4 text-lg font-semibold text-contrast">
{{ formatMessage(messages.redirectUrisLabel) }}
</label>
<div class="uri-input-list">
<div v-for="(_, index) in redirectUris" :key="index">
@@ -93,6 +98,7 @@
v-model="redirectUris[index]"
:maxlength="2048"
type="url"
class="w-80"
autocomplete="off"
:placeholder="formatMessage(messages.redirectUriPlaceholder)"
/>
@@ -116,18 +122,20 @@
</ButtonStyled>
</div>
</div>
</div>
<div class="submit-row input-group push-right">
<template #actions>
<div class="flex justify-end gap-2 p-2">
<ButtonStyled>
<button @click="$refs.appModal.hide()">
<XIcon />
{{ formatMessage(messages.cancel) }}
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled v-if="editingId" color="brand">
<button :disabled="!canSubmit" @click="editApp">
<SaveIcon />
{{ formatMessage(messages.saveChanges) }}
{{ formatMessage(commonMessages.saveChangesButton) }}
</button>
</ButtonStyled>
<ButtonStyled v-else color="brand">
@@ -137,8 +145,8 @@
</button>
</ButtonStyled>
</div>
</div>
</Modal>
</template>
</NewModal>
<div class="header__row">
<div class="header__title">
@@ -220,7 +228,7 @@
"
>
<EditIcon />
{{ formatMessage(messages.edit) }}
{{ formatMessage(commonMessages.editButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="red">
@@ -255,6 +263,7 @@ import {
injectModrinthClient,
injectNotificationManager,
IntlFormatted,
NewModal,
normalizeChildren,
StyledInput,
useFormatDateTime,
@@ -262,7 +271,6 @@ import {
} from '@modrinth/ui'
import { useQuery } from '@tanstack/vue-query'
import Modal from '~/components/ui/Modal.vue'
import {
getScopeValue,
hasScope,
@@ -355,14 +363,6 @@ const messages = defineMessages({
id: 'settings.applications.button.add-redirect-uri',
defaultMessage: 'Add a redirect URI',
},
cancel: {
id: 'settings.applications.button.cancel',
defaultMessage: 'Cancel',
},
saveChanges: {
id: 'settings.applications.button.save-changes',
defaultMessage: 'Save changes',
},
createApp: {
id: 'settings.applications.button.create',
defaultMessage: 'Create app',
@@ -396,10 +396,6 @@ const messages = defineMessages({
id: 'settings.applications.created-on',
defaultMessage: 'Created on {date}',
},
edit: {
id: 'settings.applications.button.edit',
defaultMessage: 'Edit',
},
delete: {
id: 'settings.applications.button.delete',
defaultMessage: 'Delete',