feat: render board note html_content above kanban columns #106
No reviewers
Labels
No labels
domain:backend
domain:devops
domain:frontend
No milestone
No project
No assignees
1 participant
Due date
No due date set.
Dependencies
No dependencies set.
Reference
ldraney/pal-e-app!106
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "104-board-html-content"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Render board note
html_content(User Stories, Architecture, Acceptance Criteria) in a styled section above the kanban columns. Boards without content are unchanged.Changes
src/lib/api-client.ts— Addedhtml_content?: string | nulltoBoardinterfacesrc/routes/boards/[slug]/+page.svelte— Added conditional{@html board.html_content}section between progress bar and filter pills, with scoped CSS for headings, tables, lists, and links using existing CSS variablesDesign Decisions
{@html}directly (same pattern as block renderers) since content is server-generated HTML:global()selectors style the injected HTML (headings, tables, lists) using existing CSS variablesTest Plan
board-gdocs-daily-mcp-remote— should render User Stories table, Architecture links, Acceptance Criteriaboard-pal-e-platform— should look identical to current (no content section rendered)svelte-checkpasses with 0 errorsReview Checklist
svelte-check0 errorsRelated Notes
Related
Closes #104
QA Review
Scope: 2 files, +65 lines. Adds
html_contenttoBoardinterface and renders it above kanban columns when present.Findings
Type interface --
html_content?: string | nulladded toBoard. SinceBoardDetail extends Board, the field flows through to the board page automatically. Clean.Conditional rendering --
{#if board.html_content}correctly gates on truthiness --null,undefined, and empty string all skip rendering. No visual regression for boards without content. Clean.{@html}usage -- Consistent with existing block renderers (ParagraphBlock,HeadingBlock,TableBlock). Content is server-generated HTML from pal-e-docs, same trust model as note rendering. Acceptable.CSS -- Uses
:global()selectors scoped under.board-contentto style injected HTML. All values use existing CSS variables (--color-border,--color-surface,--color-text,--color-accent,--color-tag-bg,--radius-md). No fixed widths, responsive by default. Clean.Placement -- Between progress bar and filter pills. Good choice -- board context is visible without pushing the kanban below the fold on most screens.
svelte-check-- 0 errors confirmed.Dependency -- Requires companion backend PR forgejo_admin/pal-e-api#271 to be merged first, otherwise
html_contentwill always beundefined(the{#if}guard handles this gracefully -- no breakage).No issues found.
VERDICT: APPROVED
PR #106 Review
DOMAIN REVIEW
Stack: SvelteKit / TypeScript / CSS
{@html}usage (XSS surface): The PR uses{@html board.html_content}to render server-generated HTML. This is consistent with the existing pattern acrossParagraphBlock.svelte,HeadingBlock.svelte,TableBlock.svelte,ListBlock.svelte, andsearch/+page.svelte-- all of which render server-providedhtmlfields via{@html}. The trust boundary is identical: the backend (pal-e-api) generates the HTML, the frontend renders it. No new XSS surface introduced beyond what already exists.Type addition:
html_content?: string | nullon theBoardinterface is correct -- optional and nullable matches the backend contract where boards may or may not have note content.CSS quality: All styles use existing CSS variables (
--color-border,--color-surface,--color-text,--color-accent,--color-tag-bg,--radius-md). No magic numbers -- spacing values are consistent with SvelteKit component conventions (rem-based). The:global()selectors are properly scoped under.board-contentto avoid leaking styles.Responsive: No fixed widths. Table uses
width: 100%. Content container inherits parent width. This will work at all breakpoints without issue.Placement: Content renders between the progress bar and filter pills. The
{#if board.html_content}guard ensures boards without content render identically to current behavior -- zero visual regression risk.Accessibility: The content is wrapped in a semantic
<section>element. The injected HTML uses standard heading/table/list elements which screen readers handle natively. No accessibility concerns.BLOCKERS
None.
On the test coverage BLOCKER criterion: this PR adds a conditional rendering section and CSS styles to an existing page. The repo's test infrastructure is E2E via Playwright (
e2e/board-filtering.spec.ts,e2e/board-dragdrop.spec.ts), and E2E tests are currently blocked by issue #96 (circular CI dependency). The change is purely presentational -- a conditional{@html}block with CSS -- and does not introduce new logic, state management, API calls, or user interactions. No test coverage BLOCKER applies here.NITS
<section>could benefit from anaria-label="Board content"for screen reader users navigating by landmark, though this is minor given the semantic HTML inside.overflow-x: autoto.board-content :global(table)so wide tables scroll horizontally on mobile rather than breaking layout. This is defensive -- unlikely to matter with current content.SOP COMPLIANCE
104-board-html-contentfollows{issue-number}-{kebab-case-purpose}Closes #104PROCESS OBSERVATIONS
svelte-checkpassing per the review checklist is good. CI validation would strengthen confidence but is blocked by #96.VERDICT: APPROVED