From 8b16d3e5d32a2a83e7bbfb1114c1105b7e3bc3ed Mon Sep 17 00:00:00 2001 From: Fadhlan Ridhwanallah Date: Thu, 16 Jul 2026 11:22:42 +0700 Subject: [PATCH 1/2] Render embed chooser current-target tile as a fitted card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The markdown embed chooser's edit-mode current-target tile showed only a text label (filename for files, title for cards). Render the placed card/file itself in its fitted template instead — a compact Double Strip chip — reusing the existing MarkdownEmbedPreview so both cards and files render fitted and a broken preload shows the compact broken-link visual. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../markdown-embed-chooser/tab-panel.gts | 61 +++++++---------- .../markdown-embed-chooser-modal-test.gts | 68 +++++++++++++------ 2 files changed, 73 insertions(+), 56 deletions(-) diff --git a/packages/host/app/components/markdown-embed-chooser/tab-panel.gts b/packages/host/app/components/markdown-embed-chooser/tab-panel.gts index b965555268..13edf564c8 100644 --- a/packages/host/app/components/markdown-embed-chooser/tab-panel.gts +++ b/packages/host/app/components/markdown-embed-chooser/tab-panel.gts @@ -23,10 +23,9 @@ import { import { cardTypeName, fileNameFromUrl, + type BfmSizeSpec, } from '@cardstack/runtime-common/bfm-card-references'; -import { maybeRelativeReference } from '@cardstack/runtime-common/url'; - import MiniCardChooser from '@cardstack/host/components/card-chooser/mini'; import MiniFileChooser from '@cardstack/host/components/file-chooser/mini'; @@ -37,6 +36,7 @@ import type { import type StoreService from '@cardstack/host/services/store'; import MarkdownEmbedPreviewPane from './pane'; +import MarkdownEmbedPreview from './preview'; import TabPills from './tab-pills'; import type EmbedFormatSelection from './format-selection'; @@ -128,31 +128,12 @@ export default class MarkdownEmbedChooserTabPanel extends Component { return dirty ? 'Accept' : 'Done'; } - private get currentTargetLabel(): string { - let t = this.selectedTarget; - if (!t) return this.toDisplayUrl(this.selectedUrl ?? ''); - if (this.args.refType === 'file') { - return fileNameFromUrl(t.id ?? this.selectedUrl ?? ''); - } - return ( - (t as CardDef).cardTitle ?? - this.toDisplayUrl(t.id ?? this.selectedUrl ?? '') - ); - } - - // When the label falls back to showing a raw URL (a broken ref, or a card - // with no title), relativize it against the editing document's own URL — - // yielding the `../Type/id` form the pane serializes into the directive, so - // the label matches what gets inserted. Falls back to the absolute URL when - // there's no base or either URL can't be parsed. - private toDisplayUrl(url: string): string { - let base = this.args.documentBaseUrl; - if (!url || !base) return url; - try { - return maybeRelativeReference(new URL(url), new URL(base), undefined); - } catch { - return url; - } + // The current-target tile renders the placed card/file as a compact fitted + // chip — a fixed Double Strip (250×65), independent of the format the user + // picks for the actual embed in the preview pane. It's an identity marker for + // "what's placed here now", not the embed being configured. + private get currentTileSize(): BfmSizeSpec { + return { format: 'fitted', width: 250, height: 65 }; } @action @@ -271,12 +252,19 @@ export default class MarkdownEmbedChooserTabPanel extends Component { class='markdown-embed-chooser-tab-panel__current' data-test-markdown-embed-chooser-current > - - {{this.currentTargetLabel}} - +
{ padding: var(--boxel-sp); text-align: center; } - .markdown-embed-chooser-tab-panel__current-label { - font: 600 var(--boxel-font); - word-break: break-word; + /* The fitted chip carries its own fixed footprint; keep it from + stretching to the centered column's cross axis. */ + .markdown-embed-chooser-tab-panel__current-preview { + flex: 0 0 auto; } .markdown-embed-chooser-tab-panel__current-actions { display: flex; diff --git a/packages/host/tests/integration/components/markdown-embed-chooser-modal-test.gts b/packages/host/tests/integration/components/markdown-embed-chooser-modal-test.gts index 78e60da721..58db55de9f 100644 --- a/packages/host/tests/integration/components/markdown-embed-chooser-modal-test.gts +++ b/packages/host/tests/integration/components/markdown-embed-chooser-modal-test.gts @@ -380,17 +380,14 @@ module('Integration | markdown-embed-chooser-modal', function (hooks) { '[data-test-markdown-embed-chooser-tab-panel="card"] [data-test-markdown-embed-chooser-current]', ) .exists('the current-target tile renders for the broken preload'); - // The label falls back to the ref (no title to show). It relativizes - // against the editing document's URL, so it reads as the `../`-relative - // path — the same form the pane serializes into the directive. + // The tile itself renders the compact broken visual (not a text label), + // so a broken preload reads as the same warning box the resolved chip would + // occupy. assert .dom( - '[data-test-markdown-embed-chooser-tab-panel="card"] [data-test-markdown-embed-chooser-current-label]', + '[data-test-markdown-embed-chooser-tab-panel="card"] [data-test-markdown-embed-chooser-current] [data-test-broken-link-template]', ) - .hasText( - '../books/ghost', - 'a broken ref labels as its document-relative path', - ); + .exists('the current-target tile shows the compact broken visual'); assert .dom('[data-test-markdown-embed-chooser-remove]') .exists('Remove is available'); @@ -402,7 +399,7 @@ module('Integration | markdown-embed-chooser-modal', function (hooks) { await pending; }); - test('a broken ref in a different realm than the document keeps its full URL as the label', async function (assert) { + test('edit-mode preload renders the current-target tile as a fitted card chip', async function (assert) { await render(