Details dialog
Edits the name, description, folder and tags of a library component or template, which is what the agent reads to choose it.
import { DetailsDialog } from "@/pages/library/parts";
import "@/pages/library/library.css";DetailsDialog is the form behind "Edit details, folder and tags" on a workspace card and behind "Save as template" in the page builder. Its fields are not only labels for people: the agent reads the name, description, folder and tags when it decides which component or template to build a page from. The hint under the fields says so.
It is a medium Dialog (650px) inside the library's scrim, with its own state for each field. It closes on Escape, on a click outside, on the close icon and on Cancel.
Editing a component
Everything can change. The folder buttons under the fields set the folder in one click, and the one that matches the folder field turns blue.
{editing && (
<DetailsDialog
title="Component details"
item={editing}
folders={folders}
onClose={() => setEditing(null)}
onSave={(details) => { updateDetails(editing.uid, details); toast.success("Saved."); }}
/>
)}onSave gets { name, description, folder, tags }. Text is trimmed, and tags are split on commas, trimmed, lowercased and de-duplicated by parseTags in src/mocks/library.js. The dialog then calls onClose itself, so onSave does not have to close it.
A template from the library
With fixed, the name and description are hidden. A template taken from the library keeps the library's wording, so only its folder and tags are the workspace's to change. onSave then gets only { folder, tags }.
<DetailsDialog
title="Template details"
noun="template"
item={template}
folders={folders}
fixed={!template.saved}
onClose={close}
onSave={(details) => updateTemplate(template.id, details)}
/>Saving a page as a template
The page builder reuses the dialog with its own confirm label and hint, and a name worked out from the page's name.
<DetailsDialog
title="Save as template"
noun="template"
confirmLabel="Save template"
item={{ name: `${page.name.replace(/ page$/i, "")} template`, description: "", folder: "", tags: [] }}
folders={folders}
hint="The page is saved as it is now. Describe when to use it: the agent reads the name, description, folder and tags to pick a template."
onClose={() => setSaving(false)}
onSave={(details) => library.saveTemplate(details, page.sections)}
/>States
| State | What happens |
|---|---|
| Name empty | The Name field shows its error, "Give the component a name." (or "template"), as soon as it is empty. Save does nothing until a name is typed. |
fixed | Name and description are hidden. Save always works. |
| No folders yet | With an empty folders list, the "Your folders" row is hidden. |
| Folder picked | The folder button that matches the Folder field, after trimming, gets .lib-tag--on. |
The error shows the moment the field is empty, before anyone has tried to save, and the Save button stays enabled and silently does nothing. The Dialog panel has no way to disable Confirm in its default state, which is why the check lives in onConfirm.
Layout
| Part | Style |
|---|---|
| Panel | Dialog at md, 650px, with .lib-dialog .lib-dialog--form: body fields stretch to full width with a 16px gap. |
| Name, Description | A TextInput and a three-row TextArea. Placeholders follow noun: "Component name", "When should this component be used?". |
| Folder and Tags | Two TextInputs side by side in .lib-dialog__row, a two-column grid with a 16px gap. Tags placeholder: "demo, webinar". |
| Your folders | .lib-card__filing with a 12px label and one .lib-tag button per folder. |
| Hint | .lib-dialog__hint, 12px in --color-grey-500. |
| Footer | Cancel and Save, both 32px tall. .lib-dialog .dialog__footer .btn brings them down from the Dialog's usual 36px at this size. |
| Scrim | .lib-dialog__scrim: fixed, z-index: 80, 16px padding, rgba(31, 33, 46, 0.45). |
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
title | string | The dialog title and its accessible name. | |
noun | string | "component" | Used in placeholders, the error and the default hint. |
item | { name?, description?, folder?, tags? } | Required. The starting values. Read once, when the dialog mounts. | |
folders | string[] | [] | Folder shortcuts. Hidden when empty. |
fixed | boolean | false | Hides name and description. |
confirmLabel | string | "Save" | |
hint | string | Replaces the default line about what the agent reads. | |
onSave | (details) => void | Required. Gets { name, description, folder, tags }, or { folder, tags } when fixed. | |
onClose | () => void | Required. Escape, scrim click, close icon, Cancel and after a save. |
Accessibility
- The wrapper has
role="dialog",aria-modal="true"andaria-labelset totitle. - The Name field has
autoFocus, so focus lands there when the dialog opens. Withfixednothing is focused, and focus stays on the button that opened it, behind the scrim. - The name error is linked to the field with
aria-describedbyand announced withrole="alert". - Escape closes it through a
keydownlistener onwindow. - Focus is not kept inside the dialog and is not returned to the trigger on close. See Dialog for the wrapper that does both.
Do and don't
- Do write the description as when to use the component ("Use when the only goal is a booked demo"). That sentence is what the agent follows.
- Do pass
foldersso people reuse folder names instead of typing near-duplicates. - Do use
fixedfor anything whose wording belongs to the library. - Don't use this dialog for page settings or publishing. Those have their own dialogs: Page settings and Publish.
When to use it
Use it for any library item the agent chooses from by description. For a plain rename or a single field elsewhere, use a small Dialog from @/ui with one TextInput.
Where it is used
| File | Title | Notes |
|---|---|---|
src/pages/library/LibraryPage.jsx, WorkspaceComponents | "Component details" | Saves through updateDetails in useLibraryStore.js. |
src/pages/library/LibraryPage.jsx, Templates | "Template details" | fixed for library templates, editable for templates saved from a page. |
src/pages/library/PageBuilderPage.jsx | "Save as template" | Custom confirmLabel and hint. Saves through saveTemplate. |