Center each habit layout on its completion action

This commit is contained in:
syntaxbullet
2026-09-05 08:06:16 +02:00
parent 3945998fa8
commit b832b5734e
6 changed files with 87 additions and 12 deletions

View File

@@ -21,6 +21,8 @@ export function HabitChart({
due = true,
id,
headingLevel = 4,
trackingMethod,
checkInId,
}: {
name: string;
method: string;
@@ -38,9 +40,33 @@ export function HabitChart({
due?: boolean;
id?: string;
headingLevel?: 3 | 4;
trackingMethod?: "manual" | "count" | "tasks";
checkInId?: string;
}) {
const headingId = useId();
const Heading = `h${headingLevel}` as const;
if (trackingMethod) return (
<section className={`ds-habit-chart ds-goal ds-goal--${trackingMethod}`} id={id} aria-labelledby={headingId} style={{ "--habit-color": color } as CSSProperties}>
<header className="ds-goal-heading">
<div className="ds-goal-title">
{trackingMethod === "manual" && children}
<Heading id={headingId} className="type-title">
{trackingMethod === "manual" ? <label htmlFor={checkInId}>{name}</label> : name}
</Heading>
</div>
{headingActions}
</header>
{(!due || schedule !== "Every day") && <p className="ds-goal-schedule">{due ? schedule : `Not scheduled today · ${schedule}`}</p>}
{editor}
{trackingMethod === "count" && <div className="ds-goal-count">{children}<span className="ds-goal-unit">{unit}</span></div>}
{trackingMethod === "tasks" && <div className="ds-goal-tasks">
{due && target > 0 && <p className="ds-goal-task-progress" role="status">{value} / {target} completed</p>}
{tasks}
</div>}
{calendar}
</section>
);
return (
<section className="ds-habit-chart" id={id} aria-labelledby={headingId} style={{ "--habit-color": color } as CSSProperties}>
<header className="ds-habit-chart-heading">

View File

@@ -56,19 +56,20 @@ export function SectionHeading({
export function Checkbox({
label,
description,
hideLabel = false,
className = "",
...props
}: Omit<InputHTMLAttributes<HTMLInputElement>, "type"> & { label: string; description?: string }) {
}: Omit<InputHTMLAttributes<HTMLInputElement>, "type"> & { label: string; description?: string; hideLabel?: boolean }) {
const descriptionId = useId();
return (
<label className={`ds-checkbox ${className}`}>
<input
type="checkbox"
aria-label={description ? label : undefined}
aria-label={description || hideLabel ? label : undefined}
{...props}
aria-describedby={[props["aria-describedby"], description ? descriptionId : undefined].filter(Boolean).join(" ") || undefined}
/>
<span className="ds-checkbox-copy">
<span className={`ds-checkbox-copy${hideLabel ? " ds-visually-hidden" : ""}`}>
<span className="ds-checkbox-label">{label}</span>
{description && <span id={descriptionId} className="ds-checkbox-description">{description}</span>}
</span>