Section Board
An ordered set of sections, each generated by a prompt, a model and a few settings. View mode shows the content; edit mode reorders by drag or keyboard and edits each section in a dialog.
Code
const [sections, setSections] = useState<BoardSection[]>(initial);const [editing, setEditing] = useState(false);<SectionBoard sections={sections} editing={editing} models={[{ value: "fast", label: "Fast" }, { value: "deep", label: "Deep reasoning" }]} columns={2} onChange={(next) => { setSections(next); void api.saveSections(next); }} onAdd={() => setSections((s) => [...s, { id: crypto.randomUUID(), title: "New section" }])} renderContent={(s) => <Markdown>{generated[s.id]}</Markdown>}/>;AI Agents · beta
Live examples and controls: Section Board in the lab.
Install
npx shadcn@latest add https://docs.nasaqui.com/r/section-board.jsonA page made of sections that an AI writes: a daily briefing, a report, a generated landing page. Each section has a
prompt, a model and a few free settings. Readers see only the content. Editors switch on editing to reorder the
sections, change how each is generated, or remove one.
When to use
- Pages whose parts are generated from prompts and which the owner tunes over time.
When not to use
- A grid of widgets with sizes and typed settings: use
DashboardBoard. - Reordering form rows: use
Repeater.
Import
import { SectionBoard, type BoardSection } from "@fadymondy/nasaq";Quick start
const [sections, setSections] = useState<BoardSection[]>(initial);
const [editing, setEditing] = useState(false);
<SectionBoard
sections={sections}
editing={editing}
models={[{ value: "fast", label: "Fast" }, { value: "deep", label: "Deep reasoning" }]}
columns={2}
onChange={(next) => {
setSections(next);
void api.saveSections(next);
}}
onAdd={() => setSections((s) => [...s, { id: crypto.randomUUID(), title: "New section" }])}
renderContent={(s) => <Markdown>{generated[s.id]}</Markdown>}
/>;Anatomy
data-slot="section-board"(data-editingin edit mode), anolnamed "Sections".section-board-section(li,data-section,data-dragging): drag handle, title (your heading level), tag, Edit and Remove.section-board-content: the content,inertwhile editing so it cannot be tabbed into as cards move.section-board-prompt: in edit mode, the model and the first line of the prompt.- The editor dialog: title, tag, prompt, model (with a "Default model" choice), and key/value settings rows
(
section-board-setting). - An empty state when there are no sections.
API
| Prop | Type | Notes |
|---|---|---|
sections | BoardSection[] | { id, title, badge?, prompt?, model?, settings?, content? }. |
onChange | (sections) => void | The whole list after a reorder, edit or removal. Without it the board is read only. |
editing | boolean | Edit mode. Default false. |
models | { value, label? }[] | The models offered. An unset model means your default. |
columns | 1 | 2 | Two columns from sm. Default 1. |
onAdd | () => void | Shows Add section in edit mode. |
renderContent | (section) => ReactNode | What a section shows. Default section.content. |
headingAs | ElementType | Section title level. Default h3. |
labels | Partial<SectionBoardLabels> | Text overrides. |
Helpers
From section-board-logic.ts, pure: sectionSettingRows(settings) and sectionSettingsFromRows(rows) convert
between the settings object and editable rows (keys trimmed, empty keys dropped, a repeated key keeps its last
value); duplicateSectionSettingKeys(rows) finds keys used twice; boardSectionChanged(a, b) compares the
editable parts. Types BoardSection, BoardSectionModel, BoardSettingRow.
Accessibility
- Each section is a list item named by its title. Reorder by dragging the handle, or focus it and press the arrow keys, Home or End; the new position is announced ("News is now at position 2 of 4"), as are saves and removals.
- Icon buttons have names that include the section ("Edit News", "Remove News") and tooltips.
- The editor is a dialog with labelled fields. A missing title and repeated setting keys are reported in words with
role="alert"; Save stays off until something changed.
RTL & i18n
English and Arabic strings are built in. Titles, prompts and content use dir="auto"; setting keys stay left to
right. The layout uses logical sides, so it mirrors in Arabic. Positions use the locale's digits.
Styling & tokens
Sections are bg-card with border-border and rounded-card; a dragged section gets border-nq-focus and
shadow-floating. The prompt line uses font-mono and text-muted-foreground.
Do / Don't
- Do keep
ids stable; they key the content you generate. - Do save in
onChange, or collect changes and save when the person leaves edit mode. - Don't put interactive content in a section and expect it to work in edit mode; it is inert there.
Related
dashboard-board, repeater, ai-model-picker, copilot-chat.
Lab
AI Agents › Section Board: Default, Two columns, Read only, Empty, Arabic.
ResearchRun
A research run with an ask box, live stage progress, an answer whose sentences cite numbered evidence, the evidence list, sources, confidence and failed or cancelled states with retry.
AI Citations and Provenance
Show where an AI answer came from. Inline numbered markers that open a quote, source chips, evidence cards with the quoted passage, and a provenance line with model, latency, grounding and confidence.