feat(ui): add reduced-motion floor and tasteful hover micro-interactions
CI and Deploy / test (push) Successful in 2m12s
CI and Deploy / deploy (push) Successful in 20s

Global @media (prefers-reduced-motion: reduce) rule in MuiCssBaseline
collapses every animation/transition duration to near-zero at once --
covers MUI's own Dialog/Menu/Collapse/ripple transitions and every
hover-lift added below, so accessibility doesn't need re-checking
per-component as more motion gets added later.

Dashboard stat tiles and Kanban cards get a subtle hover lift (shadow
deepens, translateY(-2px)/-1px), matching the hover pattern the
landing page's feature cards already had -- these are the two places
a small lift reads as an affordance rather than noise: stat tiles are
dashboard-customization-adjacent, and kanban cards are literally
draggable, so the lift reinforces the existing grab-cursor signal
instead of competing with it. Left everything else alone -- most
cards on this app hold passive content, not something to invite a
hover response.
This commit is contained in:
cesnimda
2026-07-13 15:07:11 +02:00
parent 093f303cdd
commit dab39bd570
3 changed files with 22 additions and 1 deletions
@@ -359,7 +359,13 @@ export default function DashboardView() {
{!summaryResource.loading && !summaryResource.error && prefs.cards ? (
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(2, 1fr)", xl: "repeat(4, 1fr)" }, gap: 2, mt: 2 }}>
{metricCards.map((card) => (
<SectionCard key={card.label}>
<SectionCard
key={card.label}
sx={{
transition: "box-shadow .2s, transform .2s",
"&:hover": { boxShadow: 6, transform: "translateY(-2px)" },
}}
>
<Typography variant="overline" sx={{ color: "text.secondary" }}>{card.label}</Typography>
<Typography variant="h3" sx={{ mt: 0.5 }}>{card.value}</Typography>
{card.trend || card.caption ? (
@@ -199,6 +199,9 @@ export default function KanbanBoard() {
cursor: "grab",
borderRadius: 2.5,
borderLeft: `4px solid ${c}`,
transition: "box-shadow .15s, transform .15s",
"&:hover": { boxShadow: 4, transform: "translateY(-1px)" },
"&:active": { cursor: "grabbing" },
}}
>
<CardContent sx={{ p: 1.25, "&:last-child": { pb: 1.25 } }}>
+12
View File
@@ -254,6 +254,18 @@ export const getTheme = (_mode: "light" | "dark") => {
WebkitFontSmoothing: "antialiased",
MozOsxFontSmoothing: "grayscale",
},
// A global floor under every animation added this session (card hover-lift,
// MUI's own Dialog/Menu/Collapse transitions, ripple) -- users who set this OS/
// browser preference get near-instant, non-animated interactions everywhere at
// once, rather than each component needing its own reduced-motion check.
"@media (prefers-reduced-motion: reduce)": {
"*, *::before, *::after": {
animationDuration: "0.01ms !important",
animationIterationCount: "1 !important",
transitionDuration: "0.01ms !important",
scrollBehavior: "auto !important",
},
},
},
},
MuiPaper: {