feat(ui): weekend/vacation/checkbox colors follow accent theme
- Unify Saturday+Sunday into single isWeekend flag (header + grid lines) - Replace hardcoded amber vacation bar/tooltip colors with brand-* classes - Add global accent-color for checkboxes and radio buttons via CSS variable - Update VACATION_TIMELINE_COLORS/BORDER to use brand palette (SICK stays red) - Vacation-only tooltip uses neutral dark surface with brand accent border Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -146,6 +146,11 @@
|
|||||||
linear-gradient(180deg, rgb(10 10 12 / 0.35), transparent 28rem);
|
linear-gradient(180deg, rgb(10 10 12 / 0.35), transparent 28rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
accent-color: rgb(var(--accent-500));
|
||||||
|
}
|
||||||
|
|
||||||
h1,
|
h1,
|
||||||
h2,
|
h2,
|
||||||
h3,
|
h3,
|
||||||
|
|||||||
@@ -62,9 +62,9 @@ export function TimelineHeader({
|
|||||||
<div className="flex">
|
<div className="flex">
|
||||||
{dates.map((date, i) => {
|
{dates.map((date, i) => {
|
||||||
const isToday = date.toDateString() === today.toDateString();
|
const isToday = date.toDateString() === today.toDateString();
|
||||||
const isMonday = date.getDay() === 1;
|
const dow = date.getDay();
|
||||||
const isSaturday = date.getDay() === 6;
|
const isMonday = dow === 1;
|
||||||
const isSunday = date.getDay() === 0;
|
const isWeekend = dow === 0 || dow === 6;
|
||||||
// Week zoom: show label only on Mondays to avoid overcrowding
|
// Week zoom: show label only on Mondays to avoid overcrowding
|
||||||
const showLabel = zoom === "day" || isMonday;
|
const showLabel = zoom === "day" || isMonday;
|
||||||
return (
|
return (
|
||||||
@@ -73,8 +73,7 @@ export function TimelineHeader({
|
|||||||
className={clsx(
|
className={clsx(
|
||||||
"flex-shrink-0 border-r flex flex-col items-center justify-center text-xs overflow-hidden",
|
"flex-shrink-0 border-r flex flex-col items-center justify-center text-xs overflow-hidden",
|
||||||
isToday ? "bg-brand-50 dark:bg-brand-950/40 border-brand-200 dark:border-brand-800" :
|
isToday ? "bg-brand-50 dark:bg-brand-950/40 border-brand-200 dark:border-brand-800" :
|
||||||
isSaturday ? "bg-amber-50/60 dark:bg-amber-950/30 border-amber-200 dark:border-amber-800" :
|
isWeekend ? "bg-brand-50/60 dark:bg-brand-950/30 border-brand-200 dark:border-brand-800" :
|
||||||
isSunday ? "bg-gray-100/80 dark:bg-gray-800/50 border-gray-200 dark:border-gray-700" :
|
|
||||||
isMonday ? "border-gray-200 dark:border-gray-700" : "border-gray-100 dark:border-gray-800",
|
isMonday ? "border-gray-200 dark:border-gray-700" : "border-gray-100 dark:border-gray-800",
|
||||||
)}
|
)}
|
||||||
style={{ width: CELL_WIDTH, height: HEADER_DAY_HEIGHT }}
|
style={{ width: CELL_WIDTH, height: HEADER_DAY_HEIGHT }}
|
||||||
@@ -83,7 +82,7 @@ export function TimelineHeader({
|
|||||||
<>
|
<>
|
||||||
<span className={clsx(
|
<span className={clsx(
|
||||||
"font-medium leading-none",
|
"font-medium leading-none",
|
||||||
isToday ? "text-brand-600" : isSaturday ? "text-amber-600 dark:text-amber-400" : "text-gray-600 dark:text-gray-300",
|
isToday ? "text-brand-600" : isWeekend ? "text-brand-600 dark:text-brand-400" : "text-gray-600 dark:text-gray-300",
|
||||||
)}>
|
)}>
|
||||||
{zoom === "week"
|
{zoom === "week"
|
||||||
? `${date.getDate()} ${MONTHS_SHORT[date.getMonth()]}`
|
? `${date.getDate()} ${MONTHS_SHORT[date.getMonth()]}`
|
||||||
@@ -92,9 +91,9 @@ export function TimelineHeader({
|
|||||||
{zoom === "day" && (
|
{zoom === "day" && (
|
||||||
<span className={clsx(
|
<span className={clsx(
|
||||||
"text-[9px] leading-none mt-0.5",
|
"text-[9px] leading-none mt-0.5",
|
||||||
isSaturday ? "text-amber-400 dark:text-amber-500" : "text-gray-300 dark:text-gray-600",
|
isWeekend ? "text-brand-400 dark:text-brand-500" : "text-gray-300 dark:text-gray-600",
|
||||||
)}>
|
)}>
|
||||||
{["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"][date.getDay()]}
|
{["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"][dow]}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
|
|||||||
@@ -242,25 +242,25 @@ function VacationSummary({
|
|||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
<div className="flex items-center gap-1.5">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="inline-block h-2 w-2 flex-shrink-0 rounded-full bg-amber-500" />
|
<span className="inline-block h-2 w-2 flex-shrink-0 rounded-full bg-brand-500" />
|
||||||
<span className="font-semibold text-amber-300">{title}</span>
|
<span className="font-semibold text-brand-300">{title}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-0.5 text-[11px] text-amber-200/80">
|
<div className="mt-0.5 text-[11px] text-brand-200/80">
|
||||||
{formatDateLong(vacation.startDate)} to {formatDateLong(vacation.endDate)}
|
{formatDateLong(vacation.startDate)} to {formatDateLong(vacation.endDate)}
|
||||||
</div>
|
</div>
|
||||||
{holidayMeta ? (
|
{holidayMeta ? (
|
||||||
<div className="mt-1 text-[11px] text-amber-100/75">{holidayMeta}</div>
|
<div className="mt-1 text-[11px] text-brand-100/75">{holidayMeta}</div>
|
||||||
) : null}
|
) : null}
|
||||||
{holidayLocationBasis ? (
|
{holidayLocationBasis ? (
|
||||||
<div className="mt-1 text-[11px] text-amber-100/85">{holidayLocationBasis}</div>
|
<div className="mt-1 text-[11px] text-brand-100/85">{holidayLocationBasis}</div>
|
||||||
) : null}
|
) : null}
|
||||||
{isPublicHoliday && vacation.calendarName ? (
|
{isPublicHoliday && vacation.calendarName ? (
|
||||||
<div className="mt-1 text-[11px] text-amber-200/60">
|
<div className="mt-1 text-[11px] text-brand-200/60">
|
||||||
Calendar: {vacation.calendarName}
|
Calendar: {vacation.calendarName}
|
||||||
</div>
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
{vacation.note && !isPublicHoliday ? (
|
{vacation.note && !isPublicHoliday ? (
|
||||||
<div className="mt-1 text-[11px] text-amber-200/60">{vacation.note}</div>
|
<div className="mt-1 text-[11px] text-brand-200/60">{vacation.note}</div>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -376,7 +376,7 @@ export function TimelineTooltip({
|
|||||||
<VacationSummary
|
<VacationSummary
|
||||||
vacation={vacationHover}
|
vacation={vacationHover}
|
||||||
title={vacationTitle ?? "Vacation"}
|
title={vacationTitle ?? "Vacation"}
|
||||||
className="mt-2 border-t border-amber-700/40 pt-2"
|
className="mt-2 border-t border-brand-700/40 pt-2"
|
||||||
/>
|
/>
|
||||||
</TooltipSurface>,
|
</TooltipSurface>,
|
||||||
);
|
);
|
||||||
@@ -410,8 +410,8 @@ export function TimelineTooltip({
|
|||||||
<TooltipSurface
|
<TooltipSurface
|
||||||
tooltipRef={vacationTooltipRef}
|
tooltipRef={vacationTooltipRef}
|
||||||
position={vacationTooltipPos}
|
position={vacationTooltipPos}
|
||||||
backgroundColor="rgba(120, 53, 15, 0.95)"
|
backgroundColor="rgba(10, 10, 10, 0.96)"
|
||||||
className="fixed z-40 max-w-xs pointer-events-none rounded-xl border border-amber-700/50 bg-amber-950/95 px-3 py-2 text-xs text-amber-50 shadow-2xl"
|
className="fixed z-40 max-w-xs pointer-events-none rounded-xl border border-brand-700/50 bg-gray-950/96 px-3 py-2 text-xs text-gray-50 shadow-2xl"
|
||||||
>
|
>
|
||||||
<VacationSummary vacation={vacationHover} title={vacationTitle ?? "Vacation"} />
|
<VacationSummary vacation={vacationHover} title={vacationTitle ?? "Vacation"} />
|
||||||
</TooltipSurface>,
|
</TooltipSurface>,
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ export function renderVacationBlocks(blocks: VacationBlockInfo[], rowHeight: num
|
|||||||
if (blocks.length === 0) return null;
|
if (blocks.length === 0) return null;
|
||||||
|
|
||||||
return blocks.map(({ vacation: v, left, width }) => {
|
return blocks.map(({ vacation: v, left, width }) => {
|
||||||
const colorClass = VACATION_TIMELINE_COLORS[v.type] ?? "bg-orange-400/40";
|
const colorClass = VACATION_TIMELINE_COLORS[v.type] ?? "bg-brand-400/40";
|
||||||
const borderClass = VACATION_TIMELINE_BORDER[v.type] ?? "border-orange-500";
|
const borderClass = VACATION_TIMELINE_BORDER[v.type] ?? "border-brand-500";
|
||||||
const label = VACATION_TYPE_LABELS_SHORT[v.type] ?? v.type;
|
const label = VACATION_TYPE_LABELS_SHORT[v.type] ?? v.type;
|
||||||
const isPending = v.status === "PENDING";
|
const isPending = v.status === "PENDING";
|
||||||
|
|
||||||
|
|||||||
@@ -37,16 +37,15 @@ export function useTimelineLayout(
|
|||||||
// Grid lines — memoized; identical for every row
|
// Grid lines — memoized; identical for every row
|
||||||
const gridLines = useMemo(() => dates.map((date, i) => {
|
const gridLines = useMemo(() => dates.map((date, i) => {
|
||||||
const isToday = date.toDateString() === today.toDateString();
|
const isToday = date.toDateString() === today.toDateString();
|
||||||
const isSaturday = date.getDay() === 6;
|
const dow = date.getDay();
|
||||||
const isSunday = date.getDay() === 0;
|
const isWeekend = dow === 0 || dow === 6;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={i}
|
key={i}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"absolute top-0 bottom-0 border-r",
|
"absolute top-0 bottom-0 border-r",
|
||||||
isToday ? "border-brand-300 dark:border-brand-700 border-r-2" :
|
isToday ? "border-brand-300 dark:border-brand-700 border-r-2" :
|
||||||
isSaturday ? "border-amber-200 dark:border-amber-800 bg-amber-50/40 dark:bg-amber-950/20" :
|
isWeekend ? "border-brand-200 dark:border-brand-800 bg-brand-50/40 dark:bg-brand-950/20" :
|
||||||
isSunday ? "border-gray-200 dark:border-gray-700 bg-gray-100/60 dark:bg-gray-800/40" :
|
|
||||||
"border-gray-100 dark:border-gray-800",
|
"border-gray-100 dark:border-gray-800",
|
||||||
)}
|
)}
|
||||||
style={{ left: i * CELL_WIDTH, width: CELL_WIDTH }}
|
style={{ left: i * CELL_WIDTH, width: CELL_WIDTH }}
|
||||||
|
|||||||
@@ -49,17 +49,17 @@ export const ORDER_TYPE_BADGE: Record<string, string> = {
|
|||||||
|
|
||||||
/** Vacation overlay colors for timeline bars */
|
/** Vacation overlay colors for timeline bars */
|
||||||
export const VACATION_TIMELINE_COLORS: Record<string, string> = {
|
export const VACATION_TIMELINE_COLORS: Record<string, string> = {
|
||||||
ANNUAL: "bg-orange-400/40",
|
ANNUAL: "bg-brand-400/40",
|
||||||
SICK: "bg-red-500/40",
|
SICK: "bg-red-500/40",
|
||||||
PUBLIC_HOLIDAY: "bg-violet-400/40",
|
PUBLIC_HOLIDAY: "bg-brand-300/35",
|
||||||
OTHER: "bg-amber-400/40",
|
OTHER: "bg-brand-400/30",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VACATION_TIMELINE_BORDER: Record<string, string> = {
|
export const VACATION_TIMELINE_BORDER: Record<string, string> = {
|
||||||
ANNUAL: "border-orange-500",
|
ANNUAL: "border-brand-500",
|
||||||
SICK: "border-red-600",
|
SICK: "border-red-600",
|
||||||
PUBLIC_HOLIDAY: "border-violet-500",
|
PUBLIC_HOLIDAY: "border-brand-400",
|
||||||
OTHER: "border-amber-500",
|
OTHER: "border-brand-500",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VACATION_TYPE_LABELS_SHORT: Record<string, string> = {
|
export const VACATION_TYPE_LABELS_SHORT: Record<string, string> = {
|
||||||
|
|||||||
Reference in New Issue
Block a user