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 74758fe185.

* 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,89 @@
<template>
<NewModal ref="modal" fade="warning" :header="formatMessage(messages.header)" max-width="500px">
<p class="m-0 text-secondary">
{{ formatMessage(messages.body) }}
</p>
<template #actions>
<div class="flex justify-end gap-2">
<ButtonStyled type="outlined">
<button class="!border !border-surface-4" @click="handleCancel">
<XIcon />
{{ formatMessage(commonMessages.cancelButton) }}
</button>
</ButtonStyled>
<ButtonStyled color="red">
<button @click="handleDiscard">
<TrashIcon />
{{ formatMessage(messages.discard) }}
</button>
</ButtonStyled>
<ButtonStyled color="green">
<button @click="handleSave">
<SaveIcon />
{{ formatMessage(commonMessages.saveButton) }}
</button>
</ButtonStyled>
</div>
</template>
</NewModal>
</template>
<script setup lang="ts">
import { SaveIcon, TrashIcon, XIcon } from '@modrinth/assets'
import { ref } from 'vue'
import ButtonStyled from '#ui/components/base/ButtonStyled.vue'
import NewModal from '#ui/components/modal/NewModal.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
import { commonMessages } from '#ui/utils/common-messages'
const { formatMessage } = useVIntl()
const messages = defineMessages({
header: {
id: 'files.unsaved-changes-modal.header',
defaultMessage: 'Unsaved changes',
},
body: {
id: 'files.unsaved-changes-modal.body',
defaultMessage:
'You have unsaved changes that will be lost if you leave. Would you like to save before leaving?',
},
discard: {
id: 'files.unsaved-changes-modal.discard',
defaultMessage: 'Discard',
},
})
export type UnsavedChangesResult = 'cancel' | 'discard' | 'save'
const modal = ref<InstanceType<typeof NewModal>>()
let resolvePromise: ((value: UnsavedChangesResult) => void) | null = null
function prompt(): Promise<UnsavedChangesResult> {
return new Promise((resolve) => {
resolvePromise = resolve
modal.value?.show()
})
}
function resolve(result: UnsavedChangesResult) {
modal.value?.hide()
resolvePromise?.(result)
resolvePromise = null
}
function handleCancel() {
resolve('cancel')
}
function handleDiscard() {
resolve('discard')
}
function handleSave() {
resolve('save')
}
defineExpose({ prompt })
</script>