feat: enhance typography and accessibility in design system

- Added new UI heading utility with specific styles in typography.css.
- Updated typography tests to include new UI heading role and ensure proper size and styling.
- Documented design system audit findings, focusing on accessibility improvements and component consistency.
- Introduced CalendarExamples component to demonstrate calendar functionality with habit tracking.
- Created a shared Field component for consistent labeling and hinting of form controls.
- Implemented comprehensive accessibility tests for calendar and editor components, ensuring proper focus management and keyboard navigation.
- Added structure tests for Field and Card components to verify correct ID generation and heading levels.
This commit is contained in:
syntaxbullet
2026-09-04 13:44:31 +02:00
parent bfa54851c2
commit dde5e77317
19 changed files with 1077 additions and 681 deletions

View File

@@ -45,6 +45,26 @@ export function visibleCalendarDays(
return days.filter((day) => day.date >= range.from && day.date <= range.to);
}
/** One uninterrupted Sunday-first timeline, including partial boundary weeks. */
export function calendarTimeline(days: CalendarDay[]) {
const first = days[0];
if (!first) return { weeks: 0, entries: [], months: [] };
const start = new Date(`${first.date}T00:00:00Z`);
const origin = start.getTime() - start.getUTCDay() * 86_400_000;
const entries = days.map((day, index) => {
const offset = Math.round((Date.parse(`${day.date}T00:00:00Z`) - origin) / 86_400_000);
return { day, index, column: Math.floor(offset / 7) + 1, row: offset % 7 + 1 };
});
const weeks = entries.at(-1)!.column;
const months = entries.filter(({ day }, index) =>
index === 0 || day.date.slice(0, 7) !== entries[index - 1]!.day.date.slice(0, 7),
).map(({ day, column }) => ({ month: day.date.slice(0, 7), column }))
// A short custom range can cross a month boundary inside a single week.
// The exact date-range caption names both; avoid overlapping axis labels.
.filter((month, index, labels) => index === 0 || month.column !== labels[index - 1]!.column);
return { weeks, entries, months };
}
export const HABIT_COLORS = {
water: "#426582",
reading: "#977344",