feat: add unknown .mrpack install warning modal (#5942)

* Update modpack button copy

* Change outlined button style for standard buttons

* add unknown pack warning modal

* implementation

* Redo download toasts

* prepr

* improve hit area of window controls

* implement "don't show again"

* prepr

* duplicate modal ref declarations

* increase spacing of progress items

* address truman review
This commit is contained in:
Prospector
2026-04-29 09:53:10 -07:00
committed by GitHub
parent a80cc7e47b
commit dfb6814095
24 changed files with 1208 additions and 587 deletions

View File

@@ -204,9 +204,6 @@ const colorVariables = computed(() => {
if (props.type === 'outlined' || props.type === 'transparent') {
colors.bg = 'transparent'
if (props.hoverColorFill === 'none') {
hoverColors.bg = 'transparent'
}
colors = setColorFill(colors, props.colorFill === 'auto' ? 'text' : props.colorFill)
hoverColors = setColorFill(
hoverColors,
@@ -245,7 +242,7 @@ const fontSize = computed(() => {
<div
class="btn-wrapper"
:class="[{ outline: type === 'outlined', chip: type === 'chip' }, fontSize]"
:style="`${colorVariables}--_height:${height};--_width:${width};--_radius: ${radius};--_padding-x:${paddingX};--_padding-y:${paddingY};--_gap:${gap};--_font-weight:${fontWeight};--_icon-size:${iconSize};`"
:style="`${colorVariables}--_height:${height};--_width:${width};--_radius: ${radius};--_padding-x:${paddingX};--_padding-y:${paddingY};--_gap:${gap};--_font-weight:${fontWeight};--_icon-size:${iconSize};--_outline-color:${color === 'standard' && type === 'outlined' ? 'var(--surface-5)' : 'currentColor'}`"
>
<slot />
</div>
@@ -266,10 +263,8 @@ const fontSize = computed(() => {
> *:first-child
> *:first-child
> :is(button, a, .button-like):first-child {
@apply flex cursor-pointer flex-row items-center justify-center border-solid border border-transparent bg-[--_bg] text-[--_text] h-[--_height] min-w-[--_width] rounded-[--_radius] px-[--_padding-x] py-[--_padding-y] gap-[--_gap] font-[--_font-weight] whitespace-nowrap;
@apply flex cursor-pointer flex-row items-center justify-center border-solid border-2 border-transparent bg-[--_bg] text-[--_text] h-[--_height] min-w-[--_width] rounded-[--_radius] px-[--_padding-x] py-[--_padding-y] gap-[--_gap] font-[--_font-weight] whitespace-nowrap;
box-shadow: var(--_box-shadow, inset 0 0 0 transparent);
-webkit-font-smoothing: antialiased;
will-change: filter;
transition:
scale 0.125s ease-in-out,
background-color 0.25s ease-in-out,
@@ -328,7 +323,7 @@ const fontSize = computed(() => {
> *:first-child
> *:first-child
> :is(button, a, .button-like):first-child {
@apply border-current;
@apply border-[--_outline-color,currentColor];
}
/*noinspection CssUnresolvedCustomProperty*/

View File

@@ -95,11 +95,11 @@ const messages = defineMessages({
},
modpackBaseTitle: {
id: 'creation-flow.modal.setup-type.option.modpack-base.title',
defaultMessage: 'Modpack base',
defaultMessage: 'Install modpack',
},
modpackBaseDescription: {
id: 'creation-flow.modal.setup-type.option.modpack-base.description',
defaultMessage: 'Use a popular modpack or upload one as your starting point.',
defaultMessage: 'Browse modpacks on Modrinth or import one from a file.',
},
importInstanceTitle: {
id: 'creation-flow.modal.setup-type.option.import-instance.title',

View File

@@ -24,11 +24,15 @@
:class="{
'text-red': item.type === 'error',
'text-orange': item.type === 'warning',
'text-green': item.type === 'download',
'text-contrast': item.type === 'success',
'text-blue': !item.type || !['error', 'warning', 'success'].includes(item.type),
'text-blue':
!item.type ||
!['error', 'warning', 'success', 'download'].includes(item.type),
}"
>
<IssuesIcon v-if="item.type === 'warning'" class="h-5 w-5" />
<DownloadIcon v-else-if="item.type === 'download'" class="h-5 w-5" />
<CheckCircleIcon v-else-if="item.type === 'success'" class="h-5 w-5" />
<XCircleIcon v-else-if="item.type === 'error'" class="h-5 w-5" />
<InfoIcon v-else class="h-5 w-5" />
@@ -47,6 +51,37 @@
{{ item.text }}
</span>
</div>
<div v-if="item.progressItems?.length" class="flex flex-col gap-3">
<div
v-for="progressItem in item.progressItems"
:key="progressItem.id"
class="flex flex-col gap-2"
>
<div class="text-contrast truncate">
{{ progressItem.title }}
</div>
<ProgressBar
:progress="progressItem.progress"
:max="1"
:waiting="progressItem.waiting"
:color="progressColorForType(item.type)"
:gradient-border="false"
full-width
/>
<div v-if="progressItem.text" class="text-sm text-secondary truncate">
{{ progressItem.text }}
</div>
</div>
</div>
<ProgressBar
v-else-if="item.progress != null || item.waiting"
:progress="item.progress ?? 0"
:max="1"
:waiting="item.waiting ?? false"
:color="progressColorForType(item.type)"
:gradient-border="false"
full-width
/>
<div v-if="item.buttons?.length" class="flex gap-1.5">
<ButtonStyled
v-for="(btn, idx) in item.buttons"
@@ -65,7 +100,14 @@
</template>
<script setup lang="ts">
import { CheckCircleIcon, InfoIcon, IssuesIcon, XCircleIcon, XIcon } from '@modrinth/assets'
import {
CheckCircleIcon,
DownloadIcon,
InfoIcon,
IssuesIcon,
XCircleIcon,
XIcon,
} from '@modrinth/assets'
import { computed } from 'vue'
import {
@@ -74,6 +116,7 @@ import {
type PopupNotificationButton,
} from '../../providers'
import ButtonStyled from '../base/ButtonStyled.vue'
import ProgressBar from '../base/ProgressBar.vue'
const popupNotificationManager = injectPopupNotificationManager()
const notifications = computed<PopupNotification[]>(() =>
@@ -90,6 +133,21 @@ function handleButtonClick(id: string | number, btn: PopupNotificationButton) {
popupNotificationManager.removeNotification(id)
}
function progressColorForType(type: PopupNotification['type']) {
if (type === 'error') {
return 'red'
} else if (type === 'warning') {
return 'orange'
} else if (type === 'download') {
return 'green'
} else if (type === 'success') {
return 'green'
} else if (type === 'info') {
return 'blue'
}
return 'green'
}
withDefaults(
defineProps<{
hasSidebar?: boolean

View File

@@ -720,10 +720,10 @@
"defaultMessage": "Import instance"
},
"creation-flow.modal.setup-type.option.modpack-base.description": {
"defaultMessage": "Use a popular modpack or upload one as your starting point."
"defaultMessage": "Browse modpacks on Modrinth or import one from a file."
},
"creation-flow.modal.setup-type.option.modpack-base.title": {
"defaultMessage": "Modpack base"
"defaultMessage": "Install modpack"
},
"creation-flow.modal.setup-type.option.vanilla-minecraft.description": {
"defaultMessage": "Classic Minecraft with no mods or plugins."

View File

@@ -6,11 +6,22 @@ export interface PopupNotificationButton {
color?: 'brand' | 'red' | 'orange' | 'green' | 'blue' | 'standard'
}
export interface PopupNotificationProgressItem {
id: string
title: string
text?: string
progress: number
waiting: boolean
}
export interface PopupNotification {
id: string | number
title: string
text?: string
type?: 'error' | 'warning' | 'success' | 'info'
type?: 'error' | 'warning' | 'success' | 'info' | 'download'
progress?: number
waiting?: boolean
progressItems?: PopupNotificationProgressItem[]
buttons?: PopupNotificationButton[]
autoCloseMs?: number | null
timer?: NodeJS.Timeout

View File

@@ -107,6 +107,57 @@ export const Default: StoryObj = {
})
}
const showWaitingProgress = () => {
popupManager.addPopupNotification({
title: 'Installing modpack...',
text: 'example-pack-1.0.0.mrpack',
type: 'info',
autoCloseMs: null,
waiting: true,
})
}
const showDeterminateProgress = () => {
popupManager.addPopupNotification({
title: 'Downloading update',
text: 'Downloading files...',
type: 'success',
autoCloseMs: null,
progress: 0.62,
})
}
const showGroupedDownloads = () => {
popupManager.addPopupNotification({
title: 'Downloads',
type: 'download',
autoCloseMs: null,
progressItems: [
{
id: 'java-21',
title: 'Downloading Java 21',
text: '42% Downloading runtime',
progress: 0.42,
waiting: false,
},
{
id: 'pack-nebula',
title: 'Nebula Pack',
text: '8% Resolving files',
progress: 0.08,
waiting: false,
},
{
id: 'assets',
title: 'Assets',
text: 'Preparing...',
progress: 0,
waiting: true,
},
],
})
}
const clearAll = () => {
popupManager.clearAllNotifications()
}
@@ -118,6 +169,9 @@ export const Default: StoryObj = {
showInfo,
showNoButtons,
showPermanent,
showWaitingProgress,
showDeterminateProgress,
showGroupedDownloads,
clearAll,
}
},
@@ -142,6 +196,15 @@ export const Default: StoryObj = {
<ButtonStyled>
<button @click="showPermanent">Permanent</button>
</ButtonStyled>
<ButtonStyled>
<button @click="showWaitingProgress">Waiting Progress</button>
</ButtonStyled>
<ButtonStyled>
<button @click="showDeterminateProgress">Determinate Progress</button>
</ButtonStyled>
<ButtonStyled>
<button @click="showGroupedDownloads">Grouped Downloads</button>
</ButtonStyled>
<ButtonStyled>
<button @click="clearAll">Clear All</button>
</ButtonStyled>