T-98EU-md-ui-toolbar-insert-frontmatter
State: closed/done · Impact: high · Complexity: medium
The engine now has one typed command list, but no product has a toolbar, an insert menu, a
frontmatter panel or a palette entry over it. This task adds the command-driven chrome to the
markdown-ui layer: MdToolbar, MdInsertMenu, MdFrontmatterPanel, useMarkdownCommands,
the chord and icon utilities, and the ⌘K palette projection.
| Location | Role today |
|---|---|
packages/ts/ui/app/components/DToolbar.vue | Toolbar container primitive |
packages/ts/ui/app/components/DIconButton.vue | Icon button primitive the toolbar buttons use |
packages/ts/ui/app/components/DKbd.vue | Keyboard hint chip for tooltips and menu rows |
packages/ts/ui/app/components/DMenu.vue | Menu body used inside UPopover — the sanctioned dropdown idiom |
packages/ts/app-frame/app/composables/useContributions.ts#CommandContribution | Palette entry shape the projection matches structurally; the layer never imports app-frame |
packages/ts/app-frame/app/utils/chords.ts | Portable chord grammar; T-6OI8-ui-extract-anchored-position-and-chords moves it to @determined/ui |
solutions/determined/experiences/notes/app/components/NotesPropertiesPanel.vue#inferKind | Kind inference (with dateParts) the frontmatter panel generalises |
The layer, MdSurface, MdModeToggle and the plugin registry come from
T-A0HT-md-ui-layer-skeleton; commands, commandStates, runCommand and chordLabel from
the engine (T-EXQ7-md-engine-command-catalogue).
Proposed
Section titled “Proposed”| Piece | Design |
|---|---|
MdToolbar | Fixed bar driven by the catalogue and commandStates: groups of DIconButton (size="xs", ghost intent) with aria-pressed from active, disabled from enabled, UTooltip label plus DKbd chord hint; dropdowns (heading level, MdInsertMenu, more actions) as UPopover + DMenu; a ResizeObserver collapses overflowing groups into a trailing DMenu; MdModeToggle renders in #trailing. Layout is MD_TOOLBAR_DEFAULT_LAYOUT, an ordered list of command ids per group, overridable by prop and extended by MarkdownPlugin.toolbar entries |
MdInsertMenu | Grouped menu from commands.filter(group === 'insert') — the same subset the engine’s slash source lists, so the two cannot drift; an “Attachment…” item opens a hidden file input and calls insertAttachments, hidden when provider.saveAttachment is absent |
MdFrontmatterPanel | Collapsible “Properties (n)” over the raw YAML string: read-only rows typed by inferKind/dateParts, which move to app/utils/mdFrontmatter.ts; the default slot lets a host substitute its own panel (notes keeps NotesPropertiesPanel) |
useMarkdownCommands(view, extra?) | { commands, states, run } — the engine catalogue merged with MarkdownPlugin.commands from the registry |
projectMarkdownCommands(commands, run, { titlePrefix: 'Markdown: ' }) | Structurally a CommandContribution[] for the ⌘K palette; a shell or product plugin registers it and routes run to useActiveMarkdownSurface() — no layer dependency on app-frame |
app/utils/mdChords.ts | Chord labels for DKbd hints over the chord utilities @determined/ui gains in T-6OI8-ui-extract-anchored-position-and-chords |
app/utils/mdIcons.ts | Literal map of Lucide icon classes per command id (literal so Tailwind scans them) and a renderIcon(name) factory MdSurface hands to the engine’s autocomplete icon hook |
MdSurface gains the toolbar: boolean | 'fixed' | 'floating' and frontmatter-panel props,
the #toolbar-leading / #toolbar-trailing / #frontmatter slots, and run(id) on its exposed
API.
Approach
Section titled “Approach”- Write
packages/ts/markdown-ui/tests/useMarkdownCommands.test.tsfirst: merge order (plugin commands after catalogue, id collision throws),statesrecompute,rundispatches on the view. - Write
packages/ts/markdown-ui/tests/mdFrontmatter.test.tsby porting theinferKind/datePartscases from the notes panel; writemdFrontmatter.ts. - Write
packages/ts/markdown-ui/tests/mdToolbar.test.ts(happy-dom): buttons render perMD_TOOLBAR_DEFAULT_LAYOUT;aria-pressedmirrors a stubbedstates; a click callsrunwith the command id; every id in the layout resolves in the catalogue. - Implement
mdToolbarLayout.ts,mdIcons.ts,mdChords.ts,useMarkdownCommands.ts,projectMarkdownCommands(with a type-level test against a local copy of theCommandContributioninterface). - Implement
MdToolbar.vue,MdInsertMenu.vue,MdFrontmatterPanel.vuewith stories; wire theMdSurfaceprops and slots. - Add a
toolbarplayground page;moon run markdown-ui:check markdown-ui:test;bun run storybook:build;just ci-guards.
Files to touch
Section titled “Files to touch”| Location | Kind | Change |
|---|---|---|
packages/ts/markdown-ui/app/components/MdToolbar.vue | new | Catalogue-driven toolbar with overflow |
packages/ts/markdown-ui/app/components/MdToolbar.stories.ts | new | Fixed and floating stories |
packages/ts/markdown-ui/app/components/MdInsertMenu.vue | new | Insert group menu with attachment input |
packages/ts/markdown-ui/app/components/MdInsertMenu.stories.ts | new | Story |
packages/ts/markdown-ui/app/components/MdFrontmatterPanel.vue | new | Read-only properties panel |
packages/ts/markdown-ui/app/components/MdFrontmatterPanel.stories.ts | new | Story |
packages/ts/markdown-ui/app/components/MdSurface.vue | new | Created by T-A0HT-md-ui-layer-skeleton; gains toolbar and frontmatter wiring |
packages/ts/markdown-ui/app/composables/useMarkdownCommands.ts | new | Merge, states, run |
packages/ts/markdown-ui/app/utils/mdChords.ts | new | Chord labels for hints |
packages/ts/markdown-ui/app/utils/mdIcons.ts | new | Literal icon map, renderIcon factory |
packages/ts/markdown-ui/app/utils/mdFrontmatter.ts | new | inferKind, dateParts |
packages/ts/markdown-ui/app/utils/mdToolbarLayout.ts | new | MD_TOOLBAR_DEFAULT_LAYOUT, projectMarkdownCommands |
packages/ts/markdown-ui/tests/mdToolbar.test.ts | new | Toolbar tests |
packages/ts/markdown-ui/tests/useMarkdownCommands.test.ts | new | Merge and run tests |
packages/ts/markdown-ui/tests/mdFrontmatter.test.ts | new | Ported kind-inference tests |
packages/ts/markdown-ui/playground/app/pages/toolbar.vue | new | Toolbar over the fixture vault |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1:
moon run markdown-ui:check markdown-ui:testpasses with the three new suites. - AC-2:
projectMarkdownCommands(...)is assignable toCommandContribution[](type-level test over a local copy of the app-frame interface). - AC-3: every id in
MD_TOOLBAR_DEFAULT_LAYOUTresolves to a command in the engine catalogue (asserted by iterating the exported layout in the toolbar test). - AC-4: the insert menu’s option ids equal the ids the engine slash source lists for the same compiled commands (both computed in the test from one command list).
- AC-5: the “Attachment…” item is absent when the provider lacks
saveAttachmentand present with it. - AC-6:
aria-pressedon the bold button followsstates['format.bold'].activeacross a stubbed state flip. - AC-7:
MdFrontmatterPanelrenders “Properties (3)” and three typed rows for a three-key YAML fixture; the portedinferKind/datePartscases pass. - AC-8:
just ci-guardspasses (icon classes literal, colors--d-*only) andbun run storybook:buildsucceeds with the three new stories.
Out of scope
Section titled “Out of scope”- Selection-anchored overlays (T-8ZHI-md-ui-overlays-bubble-link-table).
- Rewiring
NotesPropertiesPanelovermdFrontmatter.tsand the notes/shellregisterModulebridge call (T-3DFJ-notes-adopts-markdown-ui). - Toolbar e2e and perf coverage (T-I630-md-ui-playground-e2e-perf).
Dependencies
Section titled “Dependencies”- T-EXQ7-md-engine-command-catalogue for the catalogue,
commandStates,runCommandandchordLabel. - T-A0HT-md-ui-layer-skeleton for the layer,
MdSurfaceand the plugin registry; T-6OI8-ui-extract-anchored-position-and-chords for the chord utilities in@determined/ui; T-0BFS-md-engine-attachments forinsertAttachmentsbehind the attachment item. - S-0010 / D-DLNG: no
@nuxt/uior Tailwind import; the guard ring from T-A0HT-md-ui-layer-skeleton already enforces it.
Discovery context
Section titled “Discovery context”Member of milestone M-931L; chrome step C5 of decision D-K3EM-markdown-editor-chrome-and-plugin-environment.
Depends on
Section titled “Depends on”T-EXQ7-md-engine-command-catalogue