update archiving, move general project settings to v3 (start redesign there), use project id lookups for stable cache keys, advanced in server search

This commit is contained in:
Prospector
2026-08-06 21:27:44 -07:00
parent f7c5552354
commit d94d6c796e
58 changed files with 912 additions and 510 deletions
+14 -1
View File
@@ -108,7 +108,15 @@ import { getSeverityIcon } from '../../utils'
const props = withDefaults(
defineProps<{
type?: 'info' | 'warning' | 'critical' | 'success' | 'moderation' | 'circle-warning' | 'neutral'
type?:
| 'info'
| 'warning'
| 'critical'
| 'success'
| 'moderation'
| 'circle-warning'
| 'neutral'
| 'grey'
header?: string
body?: string
inlineActions?: boolean
@@ -174,6 +182,7 @@ const typeClasses = {
success: 'border-brand-green bg-bg-green',
moderation: 'border-brand-orange bg-bg-orange',
neutral: 'border-surface-4 bg-surface-3',
grey: 'border-gray-500 bg-gray-950',
}
const iconClasses = {
@@ -184,6 +193,7 @@ const iconClasses = {
success: 'text-brand-green',
moderation: 'text-brand-orange',
neutral: 'text-secondary',
grey: 'text-secondary',
}
const buttonColors = {
@@ -194,6 +204,7 @@ const buttonColors = {
success: 'green',
moderation: 'orange',
neutral: 'standard',
grey: 'standard',
} as const
const progressTrackClasses = {
@@ -204,6 +215,7 @@ const progressTrackClasses = {
success: 'bg-brand-green/20',
moderation: 'bg-brand-orange/20',
neutral: 'bg-surface-4',
grey: 'bg-surface-4',
}
const progressFillClasses = {
@@ -216,6 +228,7 @@ const progressFillClasses = {
green: 'bg-brand-green',
red: 'bg-brand-red',
neutral: 'bg-surface-5',
grey: 'bg-surface-5',
}
</script>
@@ -0,0 +1,32 @@
<script setup lang="ts">
import type { Component } from 'vue'
defineProps<{
title: string
icon?: Component
description?: string
}>()
</script>
<template>
<div
class="grid w-full grid-cols-[1fr_auto] items-center gap-6 p-4 rounded-2xl border border-solid border-surface-4 bg-surface-3"
>
<div>
<h3 class="mb-1 mt-0 flex items-center gap-2 text-base font-semibold text-contrast">
<component :is="icon" v-if="icon" class="size-5 shrink-0 text-primary" aria-hidden="true" />
{{ title }}
</h3>
<div
v-if="description || $slots.default"
class="flex flex-col gap-2 text-sm leading-normal [&>p]:m-0"
>
<p v-if="description">{{ description }}</p>
<slot />
</div>
</div>
<div>
<slot name="actions" />
</div>
</div>
</template>
@@ -5,7 +5,8 @@
v-bind="$attrs"
class="smart-clickable__contents"
:class="{
'pointer-events-none': !!$slots.clickable,
'smart-clickable__contents--disabled': disabled,
'pointer-events-none': !!$slots.clickable && !disabled,
}"
>
<slot />
@@ -14,6 +15,10 @@
</template>
<script setup lang="ts">
defineProps<{
disabled?: boolean
}>()
defineOptions({
inheritAttrs: false,
})
@@ -77,7 +82,7 @@ defineOptions({
}
// When clickable is being clicked, give contents an effect
:first-child:active + .smart-clickable__contents {
:first-child:active + .smart-clickable__contents:not(.smart-clickable__contents--disabled) {
scale: 0.98;
}
}
@@ -20,6 +20,7 @@ function toggle() {
<template>
<SmartClickable
class="flex w-full flex-col overflow-clip rounded-2xl border border-solid border-surface-4 bg-surface-3"
:disabled="disabled"
>
<template #clickable>
<button
+1
View File
@@ -109,6 +109,7 @@ export { default as ScrollablePanel } from './ScrollablePanel.vue'
export { default as ServerNotice } from './ServerNotice.vue'
export { default as SettingsFormGroup } from './SettingsFormGroup.vue'
export { default as SettingsLabel } from './SettingsLabel.vue'
export { default as SettingsOptionCard } from './SettingsOptionCard.vue'
export { default as SettingsToggleCard } from './SettingsToggleCard.vue'
export { default as SimpleBadge } from './SimpleBadge.vue'
export { default as Slider } from './Slider.vue'
@@ -1,10 +1,12 @@
<template>
<NewModal ref="modal" :noblur="noblur" :danger="danger" :on-hide="onHide" max-width="550px">
<template #title>
<slot name="title">
<span class="font-extrabold text-contrast text-lg">{{ title }}</span>
</slot>
</template>
<NewModal
ref="modal"
:noblur="noblur"
:danger="danger"
:on-hide="onHide"
max-width="800px"
:header="title"
>
<div class="flex flex-col gap-4">
<template v-if="description">
<div
@@ -20,7 +22,7 @@
<label v-if="hasToType" for="confirmation">
<span>
To confirm you want to proceed, type
<span class="italic font-bold">{{ confirmationText }}</span> below:
<span class="font-semibold text-contrast">{{ confirmationText }}</span> below:
</span>
</label>
<StyledInput
@@ -66,7 +66,7 @@ const messages = defineMessages({
},
body3: {
id: 'search.photosensitivity-warning-modal.body.3',
defaultMessage: 'Using any content on Modrinth is at your own risk, please stay safe! 💚',
defaultMessage: 'Using any content on Modrinth is at your own risk. Please stay safe! 💚',
},
dontShowAgain: {
id: 'search.photosensitivity-warning-modal.dont-show-again',
@@ -0,0 +1,37 @@
<script setup lang="ts">
import { ArchiveIcon } from '@modrinth/assets'
import { computed } from 'vue'
import Admonition from '#ui/components/base/Admonition.vue'
import { defineMessages, useVIntl } from '#ui/composables/i18n'
const props = defineProps<{
title: string
reason?: string | null
}>()
const { formatMessage } = useVIntl()
const trimmedReason = computed(() => props.reason?.trim() || null)
const messages = defineMessages({
header: {
id: 'project.status.archived.header',
defaultMessage: '{title} has been archived',
},
body: {
id: 'project.status.archived.body',
defaultMessage:
'{title} will not receive any further updates unless the author decides to unarchive the project.',
},
})
</script>
<template>
<Admonition type="grey" :header="formatMessage(messages.header, { title })">
<template #icon="{ iconClass }">
<ArchiveIcon :class="iconClass" />
</template>
<span>{{ trimmedReason ?? formatMessage(messages.body, { title }) }}</span>
</Admonition>
</template>
@@ -9,7 +9,7 @@
</template>
<template v-if="showStatusBadge" #badges>
<ProjectStatusBadge :status="project.status" />
<ProjectStatusBadge :status="projectV3.status" />
</template>
<template #metadata>
@@ -2,6 +2,7 @@ export * from './server'
export * from './settings'
// Other
export { default as ArchivedProjectBanner } from './ArchivedProjectBanner.vue'
export { default as ProjectCard } from './card/ProjectCard.vue'
export { default as ProjectBackgroundGradient } from './ProjectBackgroundGradient.vue'
export { default as ProjectCardList } from './ProjectCardList.vue'