11import type { DevframeDockEntry } from '@devframes/hub'
2+ import type { DocksContext } from '@devframes/hub/client'
23import type { Meta , StoryObj } from '@storybook/vue3-vite'
34import { h } from 'vue'
45import { categorizedEntries } from '../../stories/fixtures'
@@ -13,6 +14,61 @@ const blankEntries: DevframeDockEntry[] = [
1314 { id : 'assets' , type : 'iframe' , url : 'about:blank' , title : 'Assets' , icon : 'ph:images-duotone' } ,
1415] as DevframeDockEntry [ ]
1516
17+ const dashboardUrl = '/iframe.html?id=dock-shell-embedded--dashboard-fixture&viewMode=story'
18+
19+ function dashboardEntries ( seamless : boolean ) : DevframeDockEntry [ ] {
20+ return [ {
21+ id : 'dashboard' ,
22+ type : 'iframe' ,
23+ url : dashboardUrl ,
24+ title : 'Dashboard' ,
25+ icon : 'ph:gauge-duotone' ,
26+ ...( seamless ? { presentation : 'seamless' as const } : { } ) ,
27+ } ] as DevframeDockEntry [ ]
28+ }
29+
30+ function dashboardStage ( context : DocksContext ) {
31+ return h ( 'div' , {
32+ style : {
33+ background : 'radial-gradient(circle at 25% 15%, #4338ca 0, #172033 38%, #090e19 100%)' ,
34+ color : '#f8fafc' ,
35+ minHeight : '100vh' ,
36+ padding : '32px' ,
37+ } ,
38+ } , [
39+ h ( 'h1' , { style : { font : '600 24px system-ui, sans-serif' , margin : 0 } } , 'Host application' ) ,
40+ h ( 'p' , { style : { font : '14px system-ui, sans-serif' , opacity : 0.65 } } , 'An embedded dashboard over the host surface' ) ,
41+ h ( DockEmbedded , { context } ) ,
42+ ] )
43+ }
44+
45+ function dashboardContent ( ) {
46+ const card = ( title : string , value : string ) => h ( 'article' , {
47+ style : {
48+ background : '#111827cc' ,
49+ border : '1px solid #ffffff24' ,
50+ borderRadius : '12px' ,
51+ padding : '20px' ,
52+ } ,
53+ } , [
54+ h ( 'h2' , { style : { fontSize : '13px' , fontWeight : 500 , margin : '0 0 10px' , opacity : 0.65 } } , title ) ,
55+ h ( 'strong' , { style : { fontSize : '28px' } } , value ) ,
56+ ] )
57+
58+ return h ( 'main' , {
59+ style : {
60+ background : 'linear-gradient(135deg, #312e81, #111827 65%)' ,
61+ color : '#f8fafc' ,
62+ display : 'grid' ,
63+ font : '14px system-ui, sans-serif' ,
64+ gap : '16px' ,
65+ gridTemplateColumns : 'repeat(2, minmax(0, 1fr))' ,
66+ minHeight : '100vh' ,
67+ padding : '24px' ,
68+ } ,
69+ } , [ card ( 'Requests' , '12.4k' ) , card ( 'Success rate' , '99.98%' ) ] )
70+ }
71+
1672const meta = {
1773 title : 'Dock/Shell/Embedded' ,
1874 component : DockEmbedded ,
@@ -31,6 +87,13 @@ const meta = {
3187export default meta
3288type Story = StoryObj
3389
90+ /** Same-origin content used by the iframe presentation examples below. */
91+ export const DashboardFixture : Story = {
92+ render : ( ) => ( {
93+ setup : ( ) => dashboardContent ,
94+ } ) ,
95+ }
96+
3497/** Float mode, panel closed — just the resting dock bar. */
3598export const FloatClosed : Story = {
3699 render : ( ) => ( {
@@ -51,6 +114,26 @@ export const FloatOpen: Story = {
51114 } ) ,
52115}
53116
117+ /** Float mode embedding a dashboard with the default viewer chrome. */
118+ export const FloatOpenDashboard : Story = {
119+ render : ( ) => ( {
120+ setup : ( ) => mountWithContext (
121+ { entries : dashboardEntries ( false ) , selectedId : 'dashboard' , panel : { mode : 'float' , position : 'bottom' , left : 50 , top : 100 , inactiveTimeout : - 1 , width : 60 , height : 60 } } ,
122+ dashboardStage ,
123+ ) ,
124+ } ) ,
125+ }
126+
127+ /** Float mode embedding the same dashboard without the viewer's own chrome. */
128+ export const FloatOpenDashboardSeamless : Story = {
129+ render : ( ) => ( {
130+ setup : ( ) => mountWithContext (
131+ { entries : dashboardEntries ( true ) , selectedId : 'dashboard' , panel : { mode : 'float' , position : 'bottom' , left : 50 , top : 100 , inactiveTimeout : - 1 , width : 60 , height : 60 } } ,
132+ dashboardStage ,
133+ ) ,
134+ } ) ,
135+ }
136+
54137/**
55138 * `panelOverlapFactor: 0.2` — the panel slides clear of the dock bar, leaving
56139 * most of the bar hanging past the panel edge so the iframe underneath stays
0 commit comments