feat(ux): per-view subtitles, correspondence cross-links, mobile kanban, a11y
Continuing the product/UX review's deferred items: - Every top-level view now gets a one-line subtitle under its title (Dashboard/Jobs/Kanban/Reminders/Correspondence/Gmail review) stating what that specific view is for, instead of navigation being the only signal of what each page does. - Correspondence inbox and Gmail review queue cross-link to each other instead of being two unexplained flat sidebar items -- kept both nav entries (renaming/nesting risked breaking muscle memory) but made the relationship between them explicit in the UI itself. - Kanban board switches to a horizontal scroll-snap row on phone-width viewports instead of stacking all 5 columns vertically, which meant a lot of scrolling to see anything past "Applied". - Match-score ring gets an aria-label with the actual percentage -- it was two nested decorative CircularProgress elements with no accessible text. (Keyboard-accessible status changes on kanban cards were already covered by the existing "..." menu -- no gap there.)
This commit is contained in:
@@ -1231,13 +1231,14 @@ function MatchScoreCard({ score, loading }: { score: MatchScore | null; loading:
|
||||
<Box sx={{ p: 1.75, mb: 2, borderRadius: 3, border: "1px solid", borderColor: "divider", backgroundColor: "background.default" }}>
|
||||
<Box sx={{ display: "flex", gap: 2.5, alignItems: "center", flexWrap: "wrap", mb: 1.5 }}>
|
||||
{score.hasEnoughSignal ? (
|
||||
<Box sx={{ position: "relative", width: 92, height: 92, flexShrink: 0 }}>
|
||||
<CircularProgress variant="determinate" value={100} size={92} thickness={4} sx={{ color: "divider", position: "absolute" }} />
|
||||
<Box role="img" aria-label={`${t("matchScoreTitle")}: ${score.score}%`} sx={{ position: "relative", width: 92, height: 92, flexShrink: 0 }}>
|
||||
<CircularProgress variant="determinate" value={100} size={92} thickness={4} aria-hidden="true" sx={{ color: "divider", position: "absolute" }} />
|
||||
<CircularProgress
|
||||
variant="determinate"
|
||||
value={score.score}
|
||||
size={92}
|
||||
thickness={4}
|
||||
aria-hidden="true"
|
||||
color={color === "inherit" ? "primary" : color}
|
||||
sx={{ position: "absolute", "& .MuiCircularProgress-circle": { strokeLinecap: "round" } }}
|
||||
/>
|
||||
|
||||
@@ -101,7 +101,18 @@ export default function KanbanBoard() {
|
||||
/>
|
||||
|
||||
{!jobsResource.loading && !jobsResource.error ? (
|
||||
<Box sx={{ display: "grid", gridTemplateColumns: { xs: "1fr", md: "repeat(3, 1fr)", xl: "repeat(6, 1fr)" }, gap: 2, alignItems: "start" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: { xs: "flex", md: "grid" },
|
||||
gridTemplateColumns: { md: "repeat(3, 1fr)", xl: "repeat(6, 1fr)" },
|
||||
gap: 2,
|
||||
alignItems: "start",
|
||||
overflowX: { xs: "auto", md: "visible" },
|
||||
scrollSnapType: { xs: "x mandatory", md: "none" },
|
||||
pb: { xs: 1, md: 0 },
|
||||
"-webkit-overflow-scrolling": "touch",
|
||||
}}
|
||||
>
|
||||
{STATUSES.map((status) => {
|
||||
const c = toneColor(theme, status);
|
||||
const list = groups.get(status) ?? [];
|
||||
@@ -114,6 +125,8 @@ export default function KanbanBoard() {
|
||||
p: 1.5,
|
||||
borderRadius: 3,
|
||||
minHeight: 220,
|
||||
flex: { xs: "0 0 85vw", md: "none" },
|
||||
scrollSnapAlign: { xs: "start", md: "none" },
|
||||
border: "1px solid",
|
||||
borderColor: "divider",
|
||||
background: theme.palette.mode === "dark" ? alpha(theme.palette.common.white, 0.02) : alpha(theme.palette.text.primary, 0.015),
|
||||
|
||||
Reference in New Issue
Block a user