fix(web): label interactive controls
This commit is contained in:
parent
16dddcb728
commit
01c2d31514
@ -100,8 +100,8 @@ export default function SettingsPage() {
|
|||||||
{error && <div style={{ color: "var(--nl-danger)", fontSize: "var(--nl-fs-sm)" }}>{error}</div>}
|
{error && <div style={{ color: "var(--nl-danger)", fontSize: "var(--nl-fs-sm)" }}>{error}</div>}
|
||||||
{success && <div style={{ color: "var(--nl-status-success)", fontSize: "var(--nl-fs-sm)" }}>{success}</div>}
|
{success && <div style={{ color: "var(--nl-status-success)", fontSize: "var(--nl-fs-sm)" }}>{success}</div>}
|
||||||
<form onSubmit={handleChangePassword} style={{ display: "grid", gap: "var(--nl-space-3)" }}>
|
<form onSubmit={handleChangePassword} style={{ display: "grid", gap: "var(--nl-space-3)" }}>
|
||||||
<input className="input-shell" type="password" placeholder="Current password" value={currentPassword} onChange={(e) => setCurrentPassword(e.target.value)} required />
|
<input className="input-shell" type="password" placeholder="Current password" aria-label="Current password" value={currentPassword} onChange={(e) => setCurrentPassword(e.target.value)} required />
|
||||||
<input className="input-shell" type="password" placeholder="New password" minLength={8} value={newPassword} onChange={(e) => setNewPassword(e.target.value)} required />
|
<input className="input-shell" type="password" placeholder="New password" aria-label="New password" minLength={8} value={newPassword} onChange={(e) => setNewPassword(e.target.value)} required />
|
||||||
<button type="submit" disabled={isLoading} style={{ padding: "8px 16px", background: "var(--nl-accent-primary)", color: "var(--nl-on-accent)", border: "none", borderRadius: "var(--nl-radius-sm)", fontWeight: 600, justifySelf: "start" }}>
|
<button type="submit" disabled={isLoading} style={{ padding: "8px 16px", background: "var(--nl-accent-primary)", color: "var(--nl-on-accent)", border: "none", borderRadius: "var(--nl-radius-sm)", fontWeight: 600, justifySelf: "start" }}>
|
||||||
{isLoading ? "Updating…" : "Update password"}
|
{isLoading ? "Updating…" : "Update password"}
|
||||||
</button>
|
</button>
|
||||||
@ -176,15 +176,15 @@ MCP API base: ${MCP_SERVER_URL}
|
|||||||
<section className="surface-card" style={{ padding: "var(--nl-space-5)", display: "grid", gap: "var(--nl-space-3)", marginTop: "var(--nl-space-4)" }}>
|
<section className="surface-card" style={{ padding: "var(--nl-space-5)", display: "grid", gap: "var(--nl-space-3)", marginTop: "var(--nl-space-4)" }}>
|
||||||
<strong>Send feedback</strong>
|
<strong>Send feedback</strong>
|
||||||
<div style={{ display: "grid", gridTemplateColumns: "140px 1fr", gap: "var(--nl-space-3)" }}>
|
<div style={{ display: "grid", gridTemplateColumns: "140px 1fr", gap: "var(--nl-space-3)" }}>
|
||||||
<select className="input-shell" value={feedbackType} onChange={(e) => setFeedbackType(e.target.value as typeof feedbackType)}>
|
<select className="input-shell" value={feedbackType} onChange={(e) => setFeedbackType(e.target.value as typeof feedbackType)} aria-label="Feedback type">
|
||||||
<option value="bug">Bug</option>
|
<option value="bug">Bug</option>
|
||||||
<option value="feature">Feature request</option>
|
<option value="feature">Feature request</option>
|
||||||
<option value="praise">Praise</option>
|
<option value="praise">Praise</option>
|
||||||
<option value="other">Other</option>
|
<option value="other">Other</option>
|
||||||
</select>
|
</select>
|
||||||
<input className="input-shell" placeholder="Title" value={feedbackTitle} onChange={(e) => setFeedbackTitle(e.target.value)} />
|
<input className="input-shell" placeholder="Title" aria-label="Feedback title" value={feedbackTitle} onChange={(e) => setFeedbackTitle(e.target.value)} />
|
||||||
</div>
|
</div>
|
||||||
<textarea className="input-shell" placeholder="Details (optional)" rows={3} value={feedbackBody} onChange={(e) => setFeedbackBody(e.target.value)} style={{ resize: "vertical" }} />
|
<textarea className="input-shell" placeholder="Details (optional)" aria-label="Feedback details" rows={3} value={feedbackBody} onChange={(e) => setFeedbackBody(e.target.value)} style={{ resize: "vertical" }} />
|
||||||
<button
|
<button
|
||||||
onClick={handleSubmitFeedback}
|
onClick={handleSubmitFeedback}
|
||||||
disabled={submittingFeedback || !feedbackTitle.trim()}
|
disabled={submittingFeedback || !feedbackTitle.trim()}
|
||||||
|
|||||||
@ -99,6 +99,7 @@ export function ArtifactPanel({
|
|||||||
value={title}
|
value={title}
|
||||||
onChange={(event) => setTitle(event.target.value)}
|
onChange={(event) => setTitle(event.target.value)}
|
||||||
placeholder="Artifact title"
|
placeholder="Artifact title"
|
||||||
|
aria-label="Artifact title"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: "grid", gridTemplateColumns: "minmax(140px, 180px) minmax(0, 1fr)", gap: "var(--nl-space-3)" }}>
|
<div style={{ display: "grid", gridTemplateColumns: "minmax(140px, 180px) minmax(0, 1fr)", gap: "var(--nl-space-3)" }}>
|
||||||
@ -106,6 +107,7 @@ export function ArtifactPanel({
|
|||||||
className="input-shell"
|
className="input-shell"
|
||||||
value={artifactType}
|
value={artifactType}
|
||||||
onChange={(event) => setArtifactType(event.target.value as "file" | "summary" | "extraction" | "citation" | "export")}
|
onChange={(event) => setArtifactType(event.target.value as "file" | "summary" | "extraction" | "citation" | "export")}
|
||||||
|
aria-label="Artifact type"
|
||||||
>
|
>
|
||||||
<option value="file">file</option>
|
<option value="file">file</option>
|
||||||
<option value="summary">summary</option>
|
<option value="summary">summary</option>
|
||||||
@ -118,6 +120,7 @@ export function ArtifactPanel({
|
|||||||
value={blobPath}
|
value={blobPath}
|
||||||
onChange={(event) => setBlobPath(event.target.value)}
|
onChange={(event) => setBlobPath(event.target.value)}
|
||||||
placeholder="Optional blob path"
|
placeholder="Optional blob path"
|
||||||
|
aria-label="Artifact blob path"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<textarea
|
<textarea
|
||||||
@ -125,6 +128,7 @@ export function ArtifactPanel({
|
|||||||
value={description}
|
value={description}
|
||||||
onChange={(event) => setDescription(event.target.value)}
|
onChange={(event) => setDescription(event.target.value)}
|
||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
|
aria-label="Artifact description"
|
||||||
style={{ minHeight: 96, resize: "vertical" }}
|
style={{ minHeight: 96, resize: "vertical" }}
|
||||||
/>
|
/>
|
||||||
<div style={{ display: "flex", justifyContent: "flex-end", gap: "var(--nl-space-2)" }}>
|
<div style={{ display: "flex", justifyContent: "flex-end", gap: "var(--nl-space-2)" }}>
|
||||||
@ -173,6 +177,7 @@ export function ArtifactPanel({
|
|||||||
void handleOpenArtifact(artifact);
|
void handleOpenArtifact(artifact);
|
||||||
}}
|
}}
|
||||||
disabled={openingId === artifact.id}
|
disabled={openingId === artifact.id}
|
||||||
|
aria-label={`Open artifact: ${artifact.name}`}
|
||||||
>
|
>
|
||||||
{openingId === artifact.id ? "Opening…" : "Open"}
|
{openingId === artifact.id ? "Opening…" : "Open"}
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@ -94,6 +94,7 @@ export function CreateNoteModal({ workspaces, defaultWorkspaceId, onCreated, onC
|
|||||||
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Template</span>
|
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Template</span>
|
||||||
<select
|
<select
|
||||||
className="input"
|
className="input"
|
||||||
|
aria-label="Note template"
|
||||||
value={templateId}
|
value={templateId}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const v = e.target.value;
|
const v = e.target.value;
|
||||||
@ -115,7 +116,7 @@ export function CreateNoteModal({ workspaces, defaultWorkspaceId, onCreated, onC
|
|||||||
|
|
||||||
<label style={{ display: "grid", gap: "var(--nl-space-1)" }}>
|
<label style={{ display: "grid", gap: "var(--nl-space-1)" }}>
|
||||||
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Workspace</span>
|
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Workspace</span>
|
||||||
<select value={workspaceId} onChange={(e) => setWorkspaceId(e.target.value)} className="input">
|
<select value={workspaceId} onChange={(e) => setWorkspaceId(e.target.value)} className="input" aria-label="Workspace">
|
||||||
{workspaces.map((ws) => (
|
{workspaces.map((ws) => (
|
||||||
<option key={ws.id} value={ws.id}>
|
<option key={ws.id} value={ws.id}>
|
||||||
{ws.name}
|
{ws.name}
|
||||||
@ -132,6 +133,7 @@ export function CreateNoteModal({ workspaces, defaultWorkspaceId, onCreated, onC
|
|||||||
value={title}
|
value={title}
|
||||||
onChange={(e) => setTitle(e.target.value)}
|
onChange={(e) => setTitle(e.target.value)}
|
||||||
placeholder="Note title"
|
placeholder="Note title"
|
||||||
|
aria-label="Note title"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
@ -143,6 +145,7 @@ export function CreateNoteModal({ workspaces, defaultWorkspaceId, onCreated, onC
|
|||||||
value={body}
|
value={body}
|
||||||
onChange={(e) => setBody(e.target.value)}
|
onChange={(e) => setBody(e.target.value)}
|
||||||
placeholder="Note content..."
|
placeholder="Note content..."
|
||||||
|
aria-label="Note body"
|
||||||
rows={6}
|
rows={6}
|
||||||
style={{ resize: "vertical" }}
|
style={{ resize: "vertical" }}
|
||||||
/>
|
/>
|
||||||
@ -156,6 +159,7 @@ export function CreateNoteModal({ workspaces, defaultWorkspaceId, onCreated, onC
|
|||||||
value={tags}
|
value={tags}
|
||||||
onChange={(e) => setTags(e.target.value)}
|
onChange={(e) => setTags(e.target.value)}
|
||||||
placeholder="launch, meeting, review"
|
placeholder="launch, meeting, review"
|
||||||
|
aria-label="Note tags"
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
|||||||
@ -51,12 +51,12 @@ export function CreateWorkspaceModal({ onCreated, onClose }: Props) {
|
|||||||
|
|
||||||
<label style={{ display: "grid", gap: 6 }}>
|
<label style={{ display: "grid", gap: 6 }}>
|
||||||
<span style={{ fontWeight: 600, fontSize: "var(--nl-fs-sm)" }}>Name</span>
|
<span style={{ fontWeight: 600, fontSize: "var(--nl-fs-sm)" }}>Name</span>
|
||||||
<input className="input-shell" type="text" required value={name} onChange={(e) => setName(e.target.value)} autoFocus />
|
<input className="input-shell" type="text" required value={name} onChange={(e) => setName(e.target.value)} aria-label="Workspace name" autoFocus />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label style={{ display: "grid", gap: 6 }}>
|
<label style={{ display: "grid", gap: 6 }}>
|
||||||
<span style={{ fontWeight: 600, fontSize: "var(--nl-fs-sm)" }}>Description</span>
|
<span style={{ fontWeight: 600, fontSize: "var(--nl-fs-sm)" }}>Description</span>
|
||||||
<textarea className="input-shell" value={description} onChange={(e) => setDescription(e.target.value)} rows={3} style={{ resize: "vertical" }} />
|
<textarea className="input-shell" value={description} onChange={(e) => setDescription(e.target.value)} rows={3} style={{ resize: "vertical" }} aria-label="Workspace description" />
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div style={{ display: "flex", justifyContent: "flex-end", gap: "var(--nl-space-3)" }}>
|
<div style={{ display: "flex", justifyContent: "flex-end", gap: "var(--nl-space-3)" }}>
|
||||||
|
|||||||
@ -97,6 +97,7 @@ export function LinkNoteModal({ noteId, workspaceId, existingLinkedIds, onLinked
|
|||||||
value={query}
|
value={query}
|
||||||
onChange={(e) => setQuery(e.target.value)}
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
placeholder="Search notes..."
|
placeholder="Search notes..."
|
||||||
|
aria-label="Search notes to link"
|
||||||
style={{ flex: 1 }}
|
style={{ flex: 1 }}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
@ -123,6 +124,7 @@ export function LinkNoteModal({ noteId, workspaceId, existingLinkedIds, onLinked
|
|||||||
border: selectedId === note.id ? "2px solid var(--nl-accent-primary)" : "2px solid transparent",
|
border: selectedId === note.id ? "2px solid var(--nl-accent-primary)" : "2px solid transparent",
|
||||||
}}
|
}}
|
||||||
onClick={() => setSelectedId(note.id)}
|
onClick={() => setSelectedId(note.id)}
|
||||||
|
aria-label={`Select note: ${note.title}`}
|
||||||
>
|
>
|
||||||
<div style={{ fontWeight: 600 }}>{note.title}</div>
|
<div style={{ fontWeight: 600 }}>{note.title}</div>
|
||||||
<div style={{ color: "var(--nl-text-secondary)", fontSize: "0.875rem" }}>{note.excerpt}</div>
|
<div style={{ color: "var(--nl-text-secondary)", fontSize: "0.875rem" }}>{note.excerpt}</div>
|
||||||
@ -134,7 +136,7 @@ export function LinkNoteModal({ noteId, workspaceId, existingLinkedIds, onLinked
|
|||||||
{selectedId && (
|
{selectedId && (
|
||||||
<label style={{ display: "grid", gap: "var(--nl-space-1)" }}>
|
<label style={{ display: "grid", gap: "var(--nl-space-1)" }}>
|
||||||
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Relationship type</span>
|
<span style={{ fontWeight: 600, fontSize: "0.875rem" }}>Relationship type</span>
|
||||||
<select value={relationshipType} onChange={(e) => setRelationshipType(e.target.value)} className="input">
|
<select value={relationshipType} onChange={(e) => setRelationshipType(e.target.value)} className="input" aria-label="Relationship type">
|
||||||
{RELATIONSHIP_TYPES.map((rt) => (
|
{RELATIONSHIP_TYPES.map((rt) => (
|
||||||
<option key={rt} value={rt}>
|
<option key={rt} value={rt}>
|
||||||
{rt.replace("_", " ")}
|
{rt.replace("_", " ")}
|
||||||
|
|||||||
@ -25,9 +25,9 @@ const TOOLBAR_BTN_ACTIVE: React.CSSProperties = {
|
|||||||
color: "var(--nl-text-primary)",
|
color: "var(--nl-text-primary)",
|
||||||
};
|
};
|
||||||
|
|
||||||
function ToolbarButton({ active, onClick, label }: { active: boolean; onClick: () => void; label: string }) {
|
function ToolbarButton({ active, onClick, label, ariaLabel }: { active: boolean; onClick: () => void; label: string; ariaLabel: string }) {
|
||||||
return (
|
return (
|
||||||
<button type="button" style={active ? TOOLBAR_BTN_ACTIVE : TOOLBAR_BTN} onClick={onClick} title={label}>
|
<button type="button" style={active ? TOOLBAR_BTN_ACTIVE : TOOLBAR_BTN} onClick={onClick} title={label} aria-label={ariaLabel}>
|
||||||
{label}
|
{label}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
@ -194,18 +194,18 @@ export function NoteEditor({
|
|||||||
|
|
||||||
{editor && (
|
{editor && (
|
||||||
<div style={{ display: "flex", gap: 4, flexWrap: "wrap", padding: "4px 0" }}>
|
<div style={{ display: "flex", gap: 4, flexWrap: "wrap", padding: "4px 0" }}>
|
||||||
<ToolbarButton active={editor.isActive("bold")} onClick={() => editor.chain().focus().toggleBold().run()} label="B" />
|
<ToolbarButton active={editor.isActive("bold")} onClick={() => editor.chain().focus().toggleBold().run()} label="B" ariaLabel="Bold" />
|
||||||
<ToolbarButton active={editor.isActive("italic")} onClick={() => editor.chain().focus().toggleItalic().run()} label="I" />
|
<ToolbarButton active={editor.isActive("italic")} onClick={() => editor.chain().focus().toggleItalic().run()} label="I" ariaLabel="Italic" />
|
||||||
<ToolbarButton active={editor.isActive("strike")} onClick={() => editor.chain().focus().toggleStrike().run()} label="S" />
|
<ToolbarButton active={editor.isActive("strike")} onClick={() => editor.chain().focus().toggleStrike().run()} label="S" ariaLabel="Strikethrough" />
|
||||||
<span style={{ width: 1, background: "var(--nl-border-default)", margin: "0 4px" }} />
|
<span style={{ width: 1, background: "var(--nl-border-default)", margin: "0 4px" }} />
|
||||||
<ToolbarButton active={editor.isActive("heading", { level: 1 })} onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} label="H1" />
|
<ToolbarButton active={editor.isActive("heading", { level: 1 })} onClick={() => editor.chain().focus().toggleHeading({ level: 1 }).run()} label="H1" ariaLabel="Heading level 1" />
|
||||||
<ToolbarButton active={editor.isActive("heading", { level: 2 })} onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} label="H2" />
|
<ToolbarButton active={editor.isActive("heading", { level: 2 })} onClick={() => editor.chain().focus().toggleHeading({ level: 2 }).run()} label="H2" ariaLabel="Heading level 2" />
|
||||||
<ToolbarButton active={editor.isActive("heading", { level: 3 })} onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} label="H3" />
|
<ToolbarButton active={editor.isActive("heading", { level: 3 })} onClick={() => editor.chain().focus().toggleHeading({ level: 3 }).run()} label="H3" ariaLabel="Heading level 3" />
|
||||||
<span style={{ width: 1, background: "var(--nl-border-default)", margin: "0 4px" }} />
|
<span style={{ width: 1, background: "var(--nl-border-default)", margin: "0 4px" }} />
|
||||||
<ToolbarButton active={editor.isActive("bulletList")} onClick={() => editor.chain().focus().toggleBulletList().run()} label="•" />
|
<ToolbarButton active={editor.isActive("bulletList")} onClick={() => editor.chain().focus().toggleBulletList().run()} label="•" ariaLabel="Bullet list" />
|
||||||
<ToolbarButton active={editor.isActive("orderedList")} onClick={() => editor.chain().focus().toggleOrderedList().run()} label="1." />
|
<ToolbarButton active={editor.isActive("orderedList")} onClick={() => editor.chain().focus().toggleOrderedList().run()} label="1." ariaLabel="Numbered list" />
|
||||||
<ToolbarButton active={editor.isActive("codeBlock")} onClick={() => editor.chain().focus().toggleCodeBlock().run()} label="<>" />
|
<ToolbarButton active={editor.isActive("codeBlock")} onClick={() => editor.chain().focus().toggleCodeBlock().run()} label="<>" ariaLabel="Code block" />
|
||||||
<ToolbarButton active={editor.isActive("blockquote")} onClick={() => editor.chain().focus().toggleBlockquote().run()} label="❝" />
|
<ToolbarButton active={editor.isActive("blockquote")} onClick={() => editor.chain().focus().toggleBlockquote().run()} label="❝" ariaLabel="Block quote" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ export function NoteEditor({
|
|||||||
{explainResult && (
|
{explainResult && (
|
||||||
<div style={{ background: "var(--nl-surface-card)", border: "1px solid var(--nl-border-default)", borderRadius: "var(--nl-radius-md)", padding: "var(--nl-space-3)", fontSize: "var(--nl-fs-sm)", color: "var(--nl-text-secondary)", display: "flex", gap: 8, alignItems: "flex-start" }}>
|
<div style={{ background: "var(--nl-surface-card)", border: "1px solid var(--nl-border-default)", borderRadius: "var(--nl-radius-md)", padding: "var(--nl-space-3)", fontSize: "var(--nl-fs-sm)", color: "var(--nl-text-secondary)", display: "flex", gap: 8, alignItems: "flex-start" }}>
|
||||||
<div style={{ flex: 1 }}>{explainResult}</div>
|
<div style={{ flex: 1 }}>{explainResult}</div>
|
||||||
<button type="button" style={{ ...TOOLBAR_BTN, fontSize: 12 }} onClick={() => setExplainResult(null)}>✕</button>
|
<button type="button" style={{ ...TOOLBAR_BTN, fontSize: 12 }} onClick={() => setExplainResult(null)} aria-label="Dismiss explanation">✕</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export function SurveyBanner() {
|
|||||||
<span><strong>{survey.title}</strong> — Quick survey ({survey.questions.length} questions)</span>
|
<span><strong>{survey.title}</strong> — Quick survey ({survey.questions.length} questions)</span>
|
||||||
<div style={{ display: "flex", gap: "var(--nl-space-3)" }}>
|
<div style={{ display: "flex", gap: "var(--nl-space-3)" }}>
|
||||||
<button onClick={handleStart} style={{ background: "var(--nl-accent-primary)", color: "var(--nl-on-accent)", border: "none", borderRadius: "var(--nl-radius-sm)", padding: "4px 12px", fontWeight: 600, cursor: "pointer" }}>Start</button>
|
<button onClick={handleStart} style={{ background: "var(--nl-accent-primary)", color: "var(--nl-on-accent)", border: "none", borderRadius: "var(--nl-radius-sm)", padding: "4px 12px", fontWeight: 600, cursor: "pointer" }}>Start</button>
|
||||||
<button onClick={dismiss} style={{ background: "none", border: "none", color: "var(--nl-text-secondary)", cursor: "pointer" }}>×</button>
|
<button onClick={dismiss} aria-label="Dismiss survey" style={{ background: "none", border: "none", color: "var(--nl-text-secondary)", cursor: "pointer" }}>×</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -125,6 +125,7 @@ export function SurveyBanner() {
|
|||||||
placeholder="Your answer…"
|
placeholder="Your answer…"
|
||||||
value={getTextValue()}
|
value={getTextValue()}
|
||||||
onChange={(e) => handleAnswer(question, e.target.value)}
|
onChange={(e) => handleAnswer(question, e.target.value)}
|
||||||
|
aria-label="Survey answer"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -134,6 +135,7 @@ export function SurveyBanner() {
|
|||||||
<button
|
<button
|
||||||
key={n}
|
key={n}
|
||||||
onClick={() => handleAnswer(question, String(n))}
|
onClick={() => handleAnswer(question, String(n))}
|
||||||
|
aria-label={`Rate ${n}`}
|
||||||
style={{
|
style={{
|
||||||
width: 36, height: 36,
|
width: 36, height: 36,
|
||||||
borderRadius: "var(--nl-radius-sm)",
|
borderRadius: "var(--nl-radius-sm)",
|
||||||
@ -155,6 +157,7 @@ export function SurveyBanner() {
|
|||||||
<button
|
<button
|
||||||
key={opt.id}
|
key={opt.id}
|
||||||
onClick={() => handleAnswer(question, opt.id)}
|
onClick={() => handleAnswer(question, opt.id)}
|
||||||
|
aria-label={`Choose ${opt.text}`}
|
||||||
style={{
|
style={{
|
||||||
padding: "4px 12px",
|
padding: "4px 12px",
|
||||||
borderRadius: "var(--nl-radius-sm)",
|
borderRadius: "var(--nl-radius-sm)",
|
||||||
|
|||||||
@ -51,6 +51,7 @@ export function TaskReviewPanel({
|
|||||||
value={description}
|
value={description}
|
||||||
onChange={(event) => setDescription(event.target.value)}
|
onChange={(event) => setDescription(event.target.value)}
|
||||||
placeholder="Description"
|
placeholder="Description"
|
||||||
|
aria-label="Task description"
|
||||||
style={{ minHeight: 96, resize: "vertical" }}
|
style={{ minHeight: 96, resize: "vertical" }}
|
||||||
/>
|
/>
|
||||||
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
<div style={{ display: "flex", justifyContent: "flex-end" }}>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user