feat(PBI-49): add BEM sub-element data-debug-id to components/ideas/*

This commit is contained in:
Scrum4Me Agent 2026-05-09 21:54:25 +02:00
parent 82c0341ff3
commit 0b9f8708ab
8 changed files with 35 additions and 23 deletions

View file

@ -144,7 +144,7 @@ export function IdeaDetailLayout({
</Link>
{/* Header */}
<header className="flex flex-wrap items-start justify-between gap-4">
<header className="flex flex-wrap items-start justify-between gap-4" data-debug-id="idea-detail-layout__header">
<div className="space-y-1">
<p className="font-mono text-xs text-muted-foreground">{idea.code}</p>
<h1 className="text-2xl font-medium text-foreground">{idea.title}</h1>
@ -184,7 +184,7 @@ export function IdeaDetailLayout({
<IdeaPbiLinkCard idea={idea} isDemo={isDemo} />
{/* Tab-switcher */}
<nav className="border-b border-input flex gap-1">
<nav className="border-b border-input flex gap-1" data-debug-id="idea-detail-layout__main">
{([
{ key: 'idee' as TabKey, label: 'Idee', disabled: false, hasContent: true },
{ key: 'grill' as TabKey, label: 'Grill', disabled: !grill_md, hasContent: !!grill_md },

View file

@ -261,7 +261,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
return (
<div className="space-y-4" {...debugProps('idea-list', 'IdeaList', 'components/ideas/idea-list.tsx')}>
{/* Top-bar: search + nieuw-knop */}
<div className="flex flex-wrap items-center gap-3">
<div className="flex flex-wrap items-center gap-3" data-debug-id="idea-list__toolbar">
<Input
value={search}
onChange={(e) => setSearch(e.target.value)}
@ -403,7 +403,7 @@ export function IdeaList({ ideas, products, isDemo }: IdeaListProps) {
: 'Geen ideeën die aan de filters voldoen.'}
</p>
) : (
<Table>
<Table data-debug-id="idea-list__items">
<TableHeader>
<TableRow>
<TableHead className="w-24"><SortHeader col="code" label="Code" sortKey={sortKey} sortDir={sortDir} onSort={handleSort} /></TableHead>

View file

@ -139,6 +139,7 @@ export function IdeaMdEditor({ ideaId, kind, initialValue, onCancel }: Props) {
onKeyDown={onKeyDown}
rows={24}
className="font-mono text-sm leading-relaxed"
data-debug-id="idea-md-editor__textarea"
placeholder={
kind === 'grill'
? '# Idee — ...\n## Scope\n...'
@ -160,6 +161,7 @@ export function IdeaMdEditor({ ideaId, kind, initialValue, onCancel }: Props) {
size="sm"
onClick={save}
disabled={!dirty || submitting || (errors.length > 0 && kind === 'plan')}
data-debug-id="idea-md-editor__save"
>
<Save className="size-3.5 mr-1" />
Opslaan

View file

@ -30,7 +30,7 @@ export function IdeaPbiLinkCard({ idea, isDemo }: Props) {
return (
<div className="rounded-md border border-status-done/30 bg-status-done/10 p-4 flex items-center gap-3" {...debugProps('idea-pbi-link-card', 'IdeaPbiLinkCard', 'components/ideas/idea-pbi-link-card.tsx')}>
<div className="flex-1">
<p className="text-xs uppercase tracking-wide text-status-done font-medium">
<p className="text-xs uppercase tracking-wide text-status-done font-medium" data-debug-id="idea-pbi-link-card__title">
Gepland
</p>
<p className="text-sm">
@ -38,6 +38,7 @@ export function IdeaPbiLinkCard({ idea, isDemo }: Props) {
<Link
href={`/products/${idea.product_id}`}
className="font-medium text-status-done hover:underline inline-flex items-center gap-1"
data-debug-id="idea-pbi-link-card__link"
>
{idea.pbi.code} {idea.pbi.title}
<ExternalLink className="size-3" />

View file

@ -149,24 +149,28 @@ export function IdeaRowActions({ idea, isDemo, onArchive }: IdeaRowActionsProps)
)}
{/* Grill Me */}
<ActionButton
label="Grill"
icon={<Flame className="size-3.5" />}
enabled={grillEnabled}
blockedReason={grillBlockedReason}
isDemo={isDemo}
onClick={() => runStart(startGrillJobAction)}
/>
<span data-debug-id="idea-row-actions__grill">
<ActionButton
label="Grill"
icon={<Flame className="size-3.5" />}
enabled={grillEnabled}
blockedReason={grillBlockedReason}
isDemo={isDemo}
onClick={() => runStart(startGrillJobAction)}
/>
</span>
{/* Make Plan */}
<ActionButton
label="Plan"
icon={<Sparkles className="size-3.5" />}
enabled={makePlanEnabled}
blockedReason={makePlanBlockedReason}
isDemo={isDemo}
onClick={() => runStart(startMakePlanJobAction)}
/>
<span data-debug-id="idea-row-actions__plan">
<ActionButton
label="Plan"
icon={<Sparkles className="size-3.5" />}
enabled={makePlanEnabled}
blockedReason={makePlanBlockedReason}
isDemo={isDemo}
onClick={() => runStart(startMakePlanJobAction)}
/>
</span>
{/* Materialiseer */}
<ActionButton
@ -218,6 +222,7 @@ export function IdeaRowActions({ idea, isDemo, onArchive }: IdeaRowActionsProps)
disabled={isDemo || pending}
aria-label="Archiveer idee"
title="Archiveer"
data-debug-id="idea-row-actions__delete"
>
<Archive className="size-4" />
</Button>

View file

@ -91,7 +91,7 @@ export function IdeaSyncTab({ data }: Props) {
return (
<div className="space-y-4" {...debugProps('idea-sync-tab', 'IdeaSyncTab', 'components/ideas/idea-sync-tab.tsx')}>
{/* Header: PBI-link + PR-status */}
<div className="flex flex-wrap items-center gap-3 rounded-md border border-border bg-surface-container p-3">
<div className="flex flex-wrap items-center gap-3 rounded-md border border-border bg-surface-container p-3" data-debug-id="idea-sync-tab__header">
<a
href={`/backlog/${pbi.id}`}
className="font-mono text-sm text-primary hover:underline"
@ -119,6 +119,7 @@ export function IdeaSyncTab({ data }: Props) {
</div>
{/* Stories */}
<div data-debug-id="idea-sync-tab__items">
{pbi.stories.length === 0 && (
<p className="text-sm text-muted-foreground italic">
Deze PBI heeft nog geen stories.
@ -229,6 +230,7 @@ export function IdeaSyncTab({ data }: Props) {
</div>
</details>
))}
</div>
</div>
)
}

View file

@ -131,7 +131,7 @@ export function IdeaTimeline({
Nog geen activiteit op dit idee.
</p>
) : (
<ol className="border-l-2 border-input pl-4 space-y-3 ml-2">
<ol className="border-l-2 border-input pl-4 space-y-3 ml-2" data-debug-id="idea-timeline__items">
{merged.map((entry, i) => {
// Expliciete locale + format om SSR/CSR hydration-mismatch te voorkomen
// (server-locale verschilde van browser-locale).

View file

@ -59,12 +59,14 @@ export function UserChatInput({ ideaId, isDemo = false }: Props) {
rows={3}
placeholder="Bijv. Waarom is gekozen voor X in plaats van Y?"
disabled={pending}
data-debug-id="user-chat-input__textarea"
/>
<div className="flex justify-end">
<Button
size="sm"
disabled={pending || !text.trim()}
onClick={submit}
data-debug-id="user-chat-input__submit"
>
<Send className="size-4" />
{pending ? 'Bezig…' : 'Verzend'}