fix: pin Writing toolbar and Entities header, fix Entities form alignment and red hint text, and make Settings category bar horizontal

This commit is contained in:
Schwitzz
2026-10-30 15:49:24 -05:00
parent 723fafdef8
commit 65d06e1681
8 changed files with 621 additions and 513 deletions
+132 -126
View File
@@ -127,138 +127,144 @@ export function EntitiesView() {
};
return (
<div className="ps-entities-view" style={{ padding: "20px 24px", overflowY: "auto" }}>
<div className="ps-entity-toolbar">
<div className="ps-entity-tabs">
{TABS.map((t) => (
<div key={t.id} className={"ps-entity-tab-wrap" + (t.id === tab ? " active" : "")}>
<button
type="button"
className={"ps-entity-tab" + (t.id === tab ? " active" : "")}
onClick={() => setTab(t.id)}
>
{t.label}
</button>
{t.createKind && (
<div className="ps-entities-view">
<div className="ps-entities-pinned-header">
<div className="ps-entity-toolbar">
<div className="ps-entity-tabs">
{TABS.map((t) => (
<div key={t.id} className={"ps-entity-tab-wrap" + (t.id === tab ? " active" : "")}>
<button
type="button"
className="ps-entity-tab-add"
title={t.createLabel ?? `Add to ${t.label}`}
aria-label={t.createLabel ?? `Add to ${t.label}`}
onClick={(e) => {
e.stopPropagation();
void handleCreateKind(t.createKind!, t.id);
}}
className={"ps-entity-tab" + (t.id === tab ? " active" : "")}
onClick={() => setTab(t.id)}
>
+
{t.label}
</button>
)}
</div>
))}
</div>
<div className="ps-entity-new-group">
{activeTabDef.createKind ? (
<Button
variant="primary"
size="sm"
onClick={() => void handleCreateKind(activeTabDef.createKind!)}
>
{activeTabDef.createLabel}
</Button>
) : tab === "all" ? (
<>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("character", "people")}
>
+ Person
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("world", "places")}
>
+ World Item
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("note", "notes")}
>
+ Note
</Button>
</>
) : null}
</div>
</div>
<div className="ps-entity-search">
<Input
className="ps-entity-search-input"
placeholder="Search people, places, world items, and notes…"
value={query}
onChange={(ev) => setQuery(ev.target.value)}
/>
</div>
{tab === "consistency" ? (
<ConsistencyPanel
issues={issues}
onOpenEntity={(id) => {
const e = entities.find((x) => x.id === id);
if (e) {
setDraft(e);
setOpen(true);
}
}}
/>
) : visible.length === 0 ? (
<div className="ps-emptystate">
<div className="ps-emptystate-title">No entities in this view yet</div>
<p className="ps-muted">
{activeTabDef.createKind
? `Click "${activeTabDef.createLabel}" or the + button on the tab to create one.`
: "Use the + buttons on the People, Places & World, or Notes tabs to add story entities."}
</p>
</div>
) : (
<div className="ps-entity-grid">
{visible.map((e) => (
<button
key={e.id}
type="button"
className="ps-entity-card"
onClick={() => openEntity(e)}
>
<div className="ps-entity-card-top">
<span className="ps-entity-type-badge">{badgeFor(e)}</span>
{t.createKind && (
<button
type="button"
className="ps-entity-tab-add"
title={t.createLabel ?? `Add to ${t.label}`}
aria-label={t.createLabel ?? `Add to ${t.label}`}
onClick={(e) => {
e.stopPropagation();
void handleCreateKind(t.createKind!, t.id);
}}
>
+
</button>
)}
</div>
<div className="ps-entity-card-name">{entityLabel(e)}</div>
<div className="ps-entity-card-sub">{subFor(e)}</div>
{tagsFor(e).length > 0 && (
<div className="ps-entity-card-tags">
{tagsFor(e).slice(0, 4).map((t) => (
<span key={t} className="ps-entity-tag">
{t}
</span>
))}
</div>
)}
</button>
))}
</div>
)}
))}
</div>
<EntityEditor
entity={draft}
entities={entities}
open={open}
onClose={() => setOpen(false)}
onSave={save}
onDelete={remove}
/>
<div className="ps-entity-new-group">
{activeTabDef.createKind ? (
<Button
variant="primary"
size="sm"
onClick={() => void handleCreateKind(activeTabDef.createKind!)}
>
{activeTabDef.createLabel}
</Button>
) : tab === "all" ? (
<>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("character", "people")}
>
+ Person
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("world", "places")}
>
+ World Item
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => void handleCreateKind("note", "notes")}
>
+ Note
</Button>
</>
) : null}
</div>
</div>
<div className="ps-entity-search">
<Input
className="ps-entity-search-input"
placeholder="Search people, places, world items, and notes…"
value={query}
onChange={(ev) => setQuery(ev.target.value)}
/>
</div>
</div>
<div className="ps-entities-body">
<div className="ps-entities-main">
{tab === "consistency" ? (
<ConsistencyPanel
issues={issues}
onOpenEntity={(id) => {
const e = entities.find((x) => x.id === id);
if (e) {
setDraft(e);
setOpen(true);
}
}}
/>
) : visible.length === 0 ? (
<div className="ps-emptystate">
<div className="ps-emptystate-title">No entities in this view yet</div>
<p className="ps-muted">
{activeTabDef.createKind
? `Click "${activeTabDef.createLabel}" or the + button on the tab to create one.`
: "Use the + buttons on the People, Places & World, or Notes tabs to add story entities."}
</p>
</div>
) : (
<div className="ps-entity-grid">
{visible.map((e) => (
<button
key={e.id}
type="button"
className={`ps-entity-card${open && draft?.id === e.id ? " is-selected" : ""}`}
onClick={() => openEntity(e)}
>
<div className="ps-entity-card-top">
<span className="ps-entity-type-badge">{badgeFor(e)}</span>
</div>
<div className="ps-entity-card-name">{entityLabel(e)}</div>
<div className="ps-entity-card-sub">{subFor(e)}</div>
{tagsFor(e).length > 0 && (
<div className="ps-entity-card-tags">
{tagsFor(e).slice(0, 4).map((t) => (
<span key={t} className="ps-entity-tag">
{t}
</span>
))}
</div>
)}
</button>
))}
</div>
)}
</div>
<EntityEditor
entity={draft}
entities={entities}
open={open}
onClose={() => setOpen(false)}
onSave={save}
onDelete={remove}
/>
</div>
</div>
);
}