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
|
||||
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
|
||||
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
|
||||
|
||||
@@ -93,11 +93,10 @@ export function HabitForm({
|
||||
}
|
||||
|
||||
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}>
|
||||
<fieldset className="ds-task-editor-fieldset" disabled={busy}>
|
||||
<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">
|
||||
{STARTERS.map((starter) => (
|
||||
<Button key={starter.label} variant="secondary" onClick={() => applyStarter(starter)}>{starter.label}</Button>
|
||||
|
||||
@@ -40,7 +40,6 @@ export function isHabitColor(value: string) {
|
||||
export function HabitColorPicker({
|
||||
value,
|
||||
onChange,
|
||||
mode = "demo",
|
||||
compact = false,
|
||||
}: {
|
||||
value: string;
|
||||
@@ -55,8 +54,8 @@ export function HabitColorPicker({
|
||||
return (
|
||||
<fieldset className="ds-color-picker" aria-describedby={`${id}-hint`}>
|
||||
<legend>Habit color</legend>
|
||||
<p id={`${id}-hint`} className="ds-footnote">
|
||||
{showDetails ? "Choose a suggested shade or enter a custom color for this habit’s calendar." : "Choose a color for your habit."}
|
||||
<p id={`${id}-hint`} className={showDetails ? "ds-footnote" : "ds-visually-hidden"}>
|
||||
Custom colors use six-digit hex values, such as #426582.
|
||||
</p>
|
||||
{compact && (
|
||||
<>
|
||||
@@ -156,13 +155,6 @@ export function HabitColorPicker({
|
||||
<span className="ds-muted">0 → complete</span>
|
||||
</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 && (
|
||||
<p id={`${id}-error`} role="alert" className="ds-form-feedback">
|
||||
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={() => {}} />));
|
||||
const input = container.querySelector('input[type="text"]')!;
|
||||
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");
|
||||
});
|
||||
|
||||
|
||||
@@ -540,24 +540,24 @@ function SavedHabit({
|
||||
habit.requirements?.method === "tasks" ? (
|
||||
<>
|
||||
<ul className="ds-routine-items">
|
||||
{habit.requirements.tasks.map((config) => {
|
||||
const occurrence = habit.tasks.find((task) => task.taskId === config.id);
|
||||
return (
|
||||
<SavedTask
|
||||
key={config.id}
|
||||
task={{ taskId: config.id, name: config.name, done: occurrence?.done ?? false }}
|
||||
disabled={disabled}
|
||||
blocked={blocked || !occurrence}
|
||||
scheduled={!!occurrence}
|
||||
schedule={config.schedule}
|
||||
habitSchedule={habit.requirements!.schedule}
|
||||
date={date}
|
||||
onCheck={(done) => void onUpdate(habit, { done }, config.id)}
|
||||
onSave={(patch) => onManage(habit, patch, config.id)}
|
||||
onDelete={() => onManage(habit, null, config.id)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
{habit.requirements.tasks.map((config) => {
|
||||
const occurrence = habit.tasks.find((task) => task.taskId === config.id);
|
||||
return (
|
||||
<SavedTask
|
||||
key={config.id}
|
||||
task={{ taskId: config.id, name: config.name, done: occurrence?.done ?? false }}
|
||||
disabled={disabled}
|
||||
blocked={blocked || !occurrence}
|
||||
scheduled={!!occurrence}
|
||||
schedule={config.schedule}
|
||||
habitSchedule={habit.requirements!.schedule}
|
||||
date={date}
|
||||
onCheck={(done) => void onUpdate(habit, { done }, config.id)}
|
||||
onSave={(patch) => onManage(habit, patch, config.id)}
|
||||
onDelete={() => onManage(habit, null, config.id)}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
{addingTask && (
|
||||
<InlineTaskEditor
|
||||
|
||||
Reference in New Issue
Block a user