Remove redundant habit copy and document goal layouts
This commit is contained in:
@@ -88,6 +88,11 @@ routines on days off; creating a habit or editing one out of today’s schedule
|
|||||||
it reachable in All habits. Saved calendars expand through **View history**, with
|
it reachable in All habits. Saved calendars expand through **View history**, with
|
||||||
historical corrections available inside the expanded view.
|
historical corrections available inside the expanded view.
|
||||||
|
|
||||||
|
Each saved habit uses its own action layout: count goals have a prominent counter
|
||||||
|
and unit, simple check-ins place the checkbox beside the clickable heading, and
|
||||||
|
routines show their task list without an accordion. Daily schedule labels and
|
||||||
|
duplicate progress copy are omitted; days off stay explicit.
|
||||||
|
|
||||||
Count totals can be typed directly and saved with **Save** or Enter. Escape restores
|
Count totals can be typed directly and saved with **Save** or Enter. Escape restores
|
||||||
the recorded total; plus and minus remain available. Counts may exceed the target.
|
the recorded total; plus and minus remain available. Counts may exceed the target.
|
||||||
New habits offer editable Reading, Get outside, and Evening routine starters, with
|
New habits offer editable Reading, Get outside, and Evening routine starters, with
|
||||||
|
|||||||
@@ -93,11 +93,10 @@ export function HabitForm({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal id="new-habit" eyebrow="A NEW HABIT" title={<>Make it <em>yours.</em></>} description="Choose what counts as complete. Your schedule follows your account’s timezone." onClose={onCancel} closeLabel="Close new habit" busy={busy} size="compact" initialFocus="input" returnFocus={() => document.getElementById("add-habit")}>
|
<Modal id="new-habit" eyebrow="A NEW HABIT" title={<>Make it <em>yours.</em></>} description="Schedules follow your account’s timezone." onClose={onCancel} closeLabel="Close new habit" busy={busy} size="compact" initialFocus="input" returnFocus={() => document.getElementById("add-habit")}>
|
||||||
<form ref={form} className="ds-edit-content" onSubmit={submit}>
|
<form ref={form} className="ds-edit-content" onSubmit={submit}>
|
||||||
<fieldset className="ds-task-editor-fieldset" disabled={busy}>
|
<fieldset className="ds-task-editor-fieldset" disabled={busy}>
|
||||||
<div className="ds-habit-starters" role="group" aria-label="Start with an idea">
|
<div className="ds-habit-starters" role="group" aria-label="Start with an idea">
|
||||||
<p className="ds-footnote">Start with an idea, then make it your own.</p>
|
|
||||||
<div className="ds-habit-starter-options">
|
<div className="ds-habit-starter-options">
|
||||||
{STARTERS.map((starter) => (
|
{STARTERS.map((starter) => (
|
||||||
<Button key={starter.label} variant="secondary" onClick={() => applyStarter(starter)}>{starter.label}</Button>
|
<Button key={starter.label} variant="secondary" onClick={() => applyStarter(starter)}>{starter.label}</Button>
|
||||||
|
|||||||
@@ -40,7 +40,6 @@ export function isHabitColor(value: string) {
|
|||||||
export function HabitColorPicker({
|
export function HabitColorPicker({
|
||||||
value,
|
value,
|
||||||
onChange,
|
onChange,
|
||||||
mode = "demo",
|
|
||||||
compact = false,
|
compact = false,
|
||||||
}: {
|
}: {
|
||||||
value: string;
|
value: string;
|
||||||
@@ -55,8 +54,8 @@ export function HabitColorPicker({
|
|||||||
return (
|
return (
|
||||||
<fieldset className="ds-color-picker" aria-describedby={`${id}-hint`}>
|
<fieldset className="ds-color-picker" aria-describedby={`${id}-hint`}>
|
||||||
<legend>Habit color</legend>
|
<legend>Habit color</legend>
|
||||||
<p id={`${id}-hint`} className="ds-footnote">
|
<p id={`${id}-hint`} className={showDetails ? "ds-footnote" : "ds-visually-hidden"}>
|
||||||
{showDetails ? "Choose a suggested shade or enter a custom color for this habit’s calendar." : "Choose a color for your habit."}
|
Custom colors use six-digit hex values, such as #426582.
|
||||||
</p>
|
</p>
|
||||||
{compact && (
|
{compact && (
|
||||||
<>
|
<>
|
||||||
@@ -156,13 +155,6 @@ export function HabitColorPicker({
|
|||||||
<span className="ds-muted">0 → complete</span>
|
<span className="ds-muted">0 → complete</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<p className="ds-footnote">
|
|
||||||
{mode === "create"
|
|
||||||
? "Saved with your habit."
|
|
||||||
: mode === "edit"
|
|
||||||
? "Save to apply this color; Cancel restores the saved color."
|
|
||||||
: "Charts preview changes immediately. Save keeps the demo color; Cancel reverts it."}
|
|
||||||
</p>
|
|
||||||
{!valid && (
|
{!valid && (
|
||||||
<p id={`${id}-error`} role="alert" className="ds-form-feedback">
|
<p id={`${id}-error`} role="alert" className="ds-form-feedback">
|
||||||
Use a six-digit hex color, such as #426582.
|
Use a six-digit hex color, such as #426582.
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ test("invalid custom colors associate both guidance and corrective feedback", as
|
|||||||
await act(async () => root.render(<HabitColorPicker value="#bad" onChange={() => {}} />));
|
await act(async () => root.render(<HabitColorPicker value="#bad" onChange={() => {}} />));
|
||||||
const input = container.querySelector('input[type="text"]')!;
|
const input = container.querySelector('input[type="text"]')!;
|
||||||
expect(input.getAttribute("aria-invalid")).toBe("true");
|
expect(input.getAttribute("aria-invalid")).toBe("true");
|
||||||
expect(description(input)).toContain("Choose a suggested shade");
|
expect(description(input)).toContain("Custom colors use six-digit hex values");
|
||||||
expect(description(input)).toContain("Use a six-digit hex color");
|
expect(description(input)).toContain("Use a six-digit hex color");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -540,24 +540,24 @@ function SavedHabit({
|
|||||||
habit.requirements?.method === "tasks" ? (
|
habit.requirements?.method === "tasks" ? (
|
||||||
<>
|
<>
|
||||||
<ul className="ds-routine-items">
|
<ul className="ds-routine-items">
|
||||||
{habit.requirements.tasks.map((config) => {
|
{habit.requirements.tasks.map((config) => {
|
||||||
const occurrence = habit.tasks.find((task) => task.taskId === config.id);
|
const occurrence = habit.tasks.find((task) => task.taskId === config.id);
|
||||||
return (
|
return (
|
||||||
<SavedTask
|
<SavedTask
|
||||||
key={config.id}
|
key={config.id}
|
||||||
task={{ taskId: config.id, name: config.name, done: occurrence?.done ?? false }}
|
task={{ taskId: config.id, name: config.name, done: occurrence?.done ?? false }}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
blocked={blocked || !occurrence}
|
blocked={blocked || !occurrence}
|
||||||
scheduled={!!occurrence}
|
scheduled={!!occurrence}
|
||||||
schedule={config.schedule}
|
schedule={config.schedule}
|
||||||
habitSchedule={habit.requirements!.schedule}
|
habitSchedule={habit.requirements!.schedule}
|
||||||
date={date}
|
date={date}
|
||||||
onCheck={(done) => void onUpdate(habit, { done }, config.id)}
|
onCheck={(done) => void onUpdate(habit, { done }, config.id)}
|
||||||
onSave={(patch) => onManage(habit, patch, config.id)}
|
onSave={(patch) => onManage(habit, patch, config.id)}
|
||||||
onDelete={() => onManage(habit, null, config.id)}
|
onDelete={() => onManage(habit, null, config.id)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</ul>
|
</ul>
|
||||||
{addingTask && (
|
{addingTask && (
|
||||||
<InlineTaskEditor
|
<InlineTaskEditor
|
||||||
|
|||||||
Reference in New Issue
Block a user