refactor: align files tab with content tab design (#5621)

* fix: files.vue bugs before styling changes

* feat: move files tab to shared layout structure

* fix: qa

* fix: qa

* fix: bugs

* fix: lint

* fix: admonition cleanup with progress + actions

* fix: cleanup

* fix: modals

* fix: admon title

* fix: i18n standard

* fix: lint + i18n pass

* fix: remove transition

* fix: type errors

* feat: files tab in app

* fix: qa

* fix: backup item minmax

* fix: use ContentPageHeader for server panel

* fix: lint

* fix: lint

* fix: lint

* feat: page leave safety

* fix: lint

* fix: cargo fmt fix

* fix: blank in prod

* fix: content card table stuff

* Revert "fix: blank in prod"

This reverts commit 74758fe185cf85a4a20355857f889cb091b97ace.

* fix: import

* feat: browse worlds/servers flow

* fix: worlds tab parity with content tab

* fix: perf bug + shader filter pill copy

* feat: singleplayer filter

* fix: ordering

* fix: breadcrumbs

* fix: lint

* fix: qa

* feat: store server proj id when adding to a non-linked instance

* fix: lint

* fix: i18n + qa

* fix: conflict

* qa: already installed modal + placeholders not server-specific

* fix: qa

* fix: add + edit server modals

* fix: qa

* fix: security

* fix: devin flags

* fix: lint

* chore: change file to break build cache

* fix: admon

* fix: import path stuff

* feat: qa

* fix: fmt fmt idiot

---------

Signed-off-by: Calum H. <calum@modrinth.com>
This commit is contained in:
Calum H.
2026-03-26 18:55:15 +00:00
committed by GitHub
parent 706eb800cb
commit 381ea51cce
170 changed files with 8052 additions and 4571 deletions
@@ -0,0 +1,106 @@
<template>
<NewModal ref="modal" :header="localizeIfPossible(title)" fade="warning" max-width="500px">
<div class="flex flex-col gap-6">
<Admonition :type="admonitionType" :header="localizeIfPossible(header)">
{{ localizeIfPossible(body) }}
</Admonition>
</div>
<template #actions>
<div class="flex justify-end gap-2">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="cancel">
<XIcon />
{{ localizeIfPossible(stayLabel) }}
</button>
</ButtonStyled>
<ButtonStyled color="red">
<button @click="leave">
<RightArrowIcon />
{{ localizeIfPossible(leaveLabel) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import { RightArrowIcon, XIcon } from '@modrinth/assets'
import { ref } from 'vue'
import Admonition from '#ui/components/base/Admonition.vue'
import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import { defineMessage, type MessageDescriptor, useVIntl } from '#ui/composables/i18n'
import NewModal from './NewModal.vue'
const { formatMessage } = useVIntl()
withDefaults(
defineProps<{
title?: MessageDescriptor | string
header?: MessageDescriptor | string
body?: MessageDescriptor | string
stayLabel?: MessageDescriptor | string
leaveLabel?: MessageDescriptor | string
admonitionType?: 'warning' | 'critical' | 'info'
}>(),
{
title: () =>
defineMessage({
id: 'ui.confirm-leave-modal.title',
defaultMessage: 'Leave page?',
}),
header: () =>
defineMessage({
id: 'ui.confirm-leave-modal.header',
defaultMessage: 'You have unsaved changes',
}),
body: () =>
defineMessage({
id: 'ui.confirm-leave-modal.body',
defaultMessage: 'You have unsaved changes that will be lost if you leave this page.',
}),
stayLabel: () =>
defineMessage({
id: 'ui.confirm-leave-modal.stay',
defaultMessage: 'Stay on page',
}),
leaveLabel: () =>
defineMessage({
id: 'ui.confirm-leave-modal.leave',
defaultMessage: 'Leave page',
}),
admonitionType: 'critical',
},
)
function localizeIfPossible(message: MessageDescriptor | string) {
return typeof message === 'string' ? message : formatMessage(message)
}
const modal = ref<InstanceType<typeof NewModal>>()
let resolvePromise: ((value: boolean) => void) | null = null
function prompt(): Promise<boolean> {
return new Promise((resolve) => {
resolvePromise = resolve
modal.value?.show()
})
}
function leave() {
modal.value?.hide()
resolvePromise?.(true)
resolvePromise = null
}
function cancel() {
modal.value?.hide()
resolvePromise?.(false)
resolvePromise = null
}
defineExpose({ prompt })
</script>
@@ -1,3 +1,4 @@
export { default as ConfirmLeaveModal } from './ConfirmLeaveModal.vue'
export { default as ConfirmModal } from './ConfirmModal.vue'
export { default as InstallToPlayModal } from './InstallToPlayModal.vue'
export { default as Modal } from './Modal.vue'