Skip to content

Commit 3133852

Browse files
antfubotdvcolomban
andauthored
feat(hub-ui): render message actions as buttons on toast notifications (#215)
Co-authored-by: dvcolomban <90617742+dvcolomban@users.noreply.github.com>
1 parent 3bfcd2a commit 3133852

2 files changed

Lines changed: 44 additions & 0 deletions

File tree

packages/hub-ui/src/client/components/display/ToastOverlay.stories.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Meta, StoryObj } from '@storybook/vue3-vite'
22
import { h, onMounted } from 'vue'
3+
import { MESSAGES_DOCK_ID } from '../../constants'
34
import { addToast } from '../../state/toasts'
45
import { message } from '../../stories/fixtures'
56
import ToastOverlay from './ToastOverlay.vue'
@@ -36,3 +37,23 @@ export const Stack: Story = {
3637
},
3738
}),
3839
}
40+
41+
/** A toast whose message carries an `activate` action, rendered alongside the dismiss control. */
42+
export const WithAction: Story = {
43+
render: () => ({
44+
setup() {
45+
onMounted(() => {
46+
addToast(message({
47+
level: 'warn',
48+
message: 'New a11y violation detected',
49+
notify: true,
50+
autoDismiss: 10 ** 7,
51+
actions: [
52+
{ id: 'view', label: 'View', kind: 'activate', activate: { dockId: MESSAGES_DOCK_ID } },
53+
],
54+
}))
55+
})
56+
return () => h(ToastOverlay)
57+
},
58+
}),
59+
}

packages/hub-ui/src/client/components/display/ToastOverlay.vue

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import type { DevframeMessageAction } from '@devframes/hub'
23
import type { DocksContext } from '@devframes/hub/client'
34
import { MESSAGES_DOCK_ID } from '../../constants'
45
import { selectMessage, useMessages } from '../../state/messages'
@@ -23,6 +24,20 @@ function openMessages(toastId: string) {
2324
// (its dock id is the plugin's devframe id).
2425
props.context?.docks.switchEntry(MESSAGES_DOCK_ID)
2526
}
27+
28+
/**
29+
* Mirrors `@devframes/plugin-messages`'s own `onActivate` dispatch (its
30+
* `App.vue`) — the toast's own `entry.actions` buttons behave identically to
31+
* the ones in the messages panel's detail view, without waiting for that
32+
* panel to be open. `context.docks`/`context.commands` reach the hub
33+
* directly here, whereas the plugin (an iframe) goes through RPC.
34+
*/
35+
function dispatchAction(action: DevframeMessageAction) {
36+
if (action.kind === 'activate')
37+
props.context?.docks.switchEntry(action.activate.dockId)
38+
else if (action.kind === 'command')
39+
props.context?.commands.execute(action.command.id, ...(action.command.params ?? []))
40+
}
2641
</script>
2742

2843
<template>
@@ -44,6 +59,14 @@ function openMessages(toastId: string) {
4459
>
4560
<MessageItem :entry="toast.entry" compact class="px-3 py-2.5">
4661
<template #actions>
62+
<button
63+
v-for="action of toast.entry.actions"
64+
:key="action.id"
65+
class="flex-none text-xs px-1.5 py-0.5 rounded border border-base op70 hover:op100 hover:bg-active transition"
66+
@click.stop="dispatchAction(action)"
67+
>
68+
{{ action.label }}
69+
</button>
4770
<button
4871
class="flex-none op30 hover:op100 p-0.5 rounded hover:bg-active transition"
4972
@click.stop="dismissToast(toast.id)"

0 commit comments

Comments
 (0)