feat: install flow improvements (#6669)

* feat: better error handling + copy details btn for info

* refactor: clean up error handling into diagnostics

* feat: extra info for failure states + queuing properly

* fix: cleanup

* fix: lint

* fix: fmt

* fix: cleanup

* fix: cleanup

* fix: lint

* feat: use bon builder
This commit is contained in:
Calum H.
2026-07-10 11:54:56 +00:00
committed by GitHub
parent 57a977f7f3
commit c07727aa49
44 changed files with 2572 additions and 480 deletions
@@ -50,10 +50,9 @@
:progress-type="progressItem.progressType"
:progress-current="progressItem.progressCurrent"
:progress-total="progressItem.progressTotal"
:action-label="progressItem.buttons?.[0]?.label"
:action-icon="progressItem.buttons?.[0]?.icon"
:actions="progressItem.buttons"
@dismiss="handleProgressItemDismiss(item, progressItem)"
@action="handleProgressItemAction(progressItem)"
@action="(index) => handleProgressItemAction(progressItem, index)"
/>
</div>
</div>
@@ -233,8 +232,11 @@ async function handleProgressItemDismiss(
dismiss(item.id)
}
async function handleProgressItemAction(progressItem: PopupNotificationProgressItem) {
const button = progressItem.buttons?.[0]
async function handleProgressItemAction(
progressItem: PopupNotificationProgressItem,
index: number,
) {
const button = progressItem.buttons?.[index]
if (button) {
await handleProgressItemButtonClick(progressItem, button)
}
@@ -250,8 +252,8 @@ async function handleProgressItemButtonClick(
}
}
function handleButtonClick(id: string | number, btn: PopupNotificationButton) {
btn.action()
async function handleButtonClick(id: string | number, btn: PopupNotificationButton) {
await btn.action()
if (!btn.keepOpen) {
popupNotificationManager.removeNotification(id)
}
@@ -138,13 +138,17 @@
</div>
</div>
<div
v-if="type === 'instance-download' && actionLabel"
class="col-start-1 row-start-3 mt-2 flex min-w-0 items-center gap-2"
v-if="type === 'instance-download' && actions?.length"
class="col-start-1 col-end-3 row-start-3 mt-2 flex min-w-0 flex-wrap items-center gap-2"
>
<ButtonStyled color="brand">
<button @click="$emit('action')">
<component :is="actionIcon" v-if="actionIcon" />
{{ actionLabel }}
<ButtonStyled
v-for="(action, index) in actions"
:key="index"
:color="action.color || (index === 0 ? 'brand' : undefined)"
>
<button class="!shadow-none" @click="$emit('action', index)">
<component :is="action.icon" v-if="action.icon" />
{{ action.label }}
</button>
</ButtonStyled>
</div>
@@ -172,10 +176,10 @@
<script setup lang="ts">
import { XIcon } from '@modrinth/assets'
import { type Component, computed, ref } from 'vue'
import { computed, ref } from 'vue'
import { useFormatBytes, useFormatNumber } from '../../composables'
import type { PopupNotificationProgressType } from '../../providers'
import type { PopupNotificationButton, PopupNotificationProgressType } from '../../providers'
import { truncatedTooltip } from '../../utils/truncate'
import Avatar from '../base/Avatar.vue'
import ButtonStyled from '../base/ButtonStyled.vue'
@@ -202,8 +206,7 @@ const props = withDefaults(
progressType?: PopupNotificationProgressType
progressCurrent?: number
progressTotal?: number
actionLabel?: string
actionIcon?: Component
actions?: PopupNotificationButton[]
}>(),
{
actorName: null,
@@ -221,7 +224,7 @@ defineEmits<{
accept: []
decline: []
dismiss: []
action: []
action: [index: number]
launch: []
'open-actor': []
'open-instance': []
@@ -4,7 +4,7 @@ import { createContext } from '.'
export interface PopupNotificationButton {
label: string
action: () => void
action: () => void | Promise<void>
icon?: Component
color?: 'brand' | 'red' | 'orange' | 'green' | 'blue' | 'standard'
keepOpen?: boolean
@@ -1,7 +1,8 @@
import { MinecraftServerIcon } from '@modrinth/assets'
import { CopyIcon, MinecraftServerIcon, UpdatedIcon } from '@modrinth/assets'
import type { Meta, StoryObj } from '@storybook/vue3-vite'
import { NotificationToast } from '../../components/notifications'
import type { PopupNotificationButton } from '../../providers'
const avatarUrl =
'https://cdn.modrinth.com/user/6Qo4A5QT/9d81be1a9fb1afd163b7f2f05a791955e7693c90.png'
@@ -205,3 +206,43 @@ export const DownloadProgressLabels: Story = {
`,
}),
}
export const FailedDownloadActions: Story = {
render: () => ({
components: { NotificationToast },
setup() {
return {
instanceIconUrl: MinecraftServerIcon,
actions: [
{
label: 'Retry',
icon: UpdatedIcon,
color: 'brand',
action: noop,
},
{
label: 'Copy details',
icon: CopyIcon,
color: 'standard',
action: noop,
},
] satisfies PopupNotificationButton[],
noop,
}
},
template: /* html */ `
<NotificationToast
type="instance-download"
entity-name="Cobblemon Official Modpack"
:entity-icon-url="instanceIconUrl"
status-text="Failed while downloading content."
:progress="0"
:show-progress="false"
wrap-text
:actions="actions"
@action="(index) => actions[index].action()"
@dismiss="noop"
/>
`,
}),
}