Skip to content

Commit 1ac27f2

Browse files
committed
Updated the frontend design
1 parent 2de59cf commit 1ac27f2

9 files changed

Lines changed: 994 additions & 216 deletions

package-lock.json

Lines changed: 125 additions & 118 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/MitigationCard.jsx

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ import styles from "./MitigationCard.module.css";
44

55
export default function MitigationCard({ group, active, accent, t }) {
66
const [open, setOpen] = useState(false);
7+
78
return (
89
<div
910
className={`${styles.card} ${active ? "" : styles.cardInactive}`}
1011
style={{
11-
border: `2px solid ${active ? accent : "var(--border-subtle)"}`,
12-
background: active ? `${accent}10` : "var(--bg-main)",
12+
border: `1px solid ${active ? accent : "var(--border-subtle)"}`,
13+
background: active ? `${accent}10` : "transparent",
1314
}}
1415
>
1516
<div
@@ -18,34 +19,48 @@ export default function MitigationCard({ group, active, accent, t }) {
1819
style={{ cursor: active ? "pointer" : "default" }}
1920
>
2021
<div className={styles.headerInfo}>
21-
<span className={styles.icon}>{group.icon}</span>
22+
<span className={styles.icon} style={{ opacity: active ? 1 : 0.35 }}>
23+
{active ? group.icon : "🔒"}
24+
</span>
2225
<div>
23-
<div className={styles.title} style={{ color: active ? "var(--text-heading)" : "var(--text-secondary)" }}>
26+
<div
27+
className={styles.title}
28+
style={{
29+
color: active ? "var(--text-heading)" : "var(--text-secondary)",
30+
opacity: active ? 1 : 0.5,
31+
}}
32+
>
2433
{group.title}
2534
</div>
26-
<div className={styles.subtitle}>
27-
{group.measures.length} {group.measures.length !== 1 ? t.measures : t.measure}
35+
<div className={styles.subtitle} style={{ opacity: active ? 1 : 0.4 }}>
36+
{active
37+
? `${group.measures.length} ${group.measures.length !== 1 ? t.measures : t.measure}`
38+
: `Unlocks at Tier ${group.tier}`}
2839
</div>
2940
</div>
3041
</div>
3142
{active && <span className={`${styles.chevron} ${open ? styles.chevronOpen : ""}`}></span>}
3243
</div>
33-
{active && open && (
34-
<div className={styles.measures}>
35-
{group.measures.map((m, i) => {
36-
const tc = TYPE_COLORS[m.type];
37-
return (
38-
<div key={i} className={styles.measure} style={{ borderLeft: `3px solid ${tc.color}` }}>
39-
<div className={styles.measureHeader}>
40-
<span className={styles.measureName}>{m.name}</span>
41-
<span className={styles.typeBadge} style={{ color: tc.color, background: tc.bg }}>
42-
{t.typeBadges[m.type]}
43-
</span>
44+
45+
{/* Always rendered — grid-template-rows animates open/close smoothly */}
46+
{active && (
47+
<div className={`${styles.measuresWrapper} ${open ? styles.measuresWrapperOpen : ""}`}>
48+
<div className={styles.measures}>
49+
{group.measures.map((m, i) => {
50+
const tc = TYPE_COLORS[m.type];
51+
return (
52+
<div key={i} className={styles.measure} style={{ borderLeft: `3px solid ${tc.color}` }}>
53+
<div className={styles.measureHeader}>
54+
<span className={styles.measureName}>{m.name}</span>
55+
<span className={styles.typeBadge} style={{ color: tc.color, background: tc.bg }}>
56+
{t.typeBadges[m.type]}
57+
</span>
58+
</div>
59+
<div className={styles.measureDesc}>{m.desc}</div>
4460
</div>
45-
<div className={styles.measureDesc}>{m.desc}</div>
46-
</div>
47-
);
48-
})}
61+
);
62+
})}
63+
</div>
4964
</div>
5065
)}
5166
</div>

src/components/MitigationCard.module.css

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
.card {
2-
border-radius: 12px;
3-
padding: 12px 14px;
4-
transition: all 0.3s;
2+
border-radius: 10px;
3+
padding: 10px 14px;
4+
transition:
5+
border-color 0.25s ease,
6+
background 0.25s ease,
7+
box-shadow 0.25s ease,
8+
transform 0.25s cubic-bezier(0.34, 1.2, 0.64, 1);
9+
}
10+
11+
.card:not(.cardInactive):hover {
12+
transform: translateY(-2px) scale(1.01);
13+
box-shadow: 0 6px 24px -4px rgba(0, 0, 0, 0.25);
14+
border-width: 2px !important;
15+
filter: brightness(1.08);
516
}
617

718
.cardInactive {
8-
opacity: 0.5;
19+
padding: 7px 14px;
20+
border-radius: 8px;
921
}
1022

1123
.header {
@@ -21,40 +33,75 @@
2133
}
2234

2335
.icon {
24-
font-size: 24px;
36+
font-size: 20px;
37+
transition: opacity 0.3s ease;
2538
}
2639

2740
.title {
28-
font-weight: 700;
29-
font-size: 18px;
41+
font-weight: 600;
42+
font-size: 16px;
43+
transition:
44+
color 0.3s ease,
45+
opacity 0.3s ease;
3046
}
3147

3248
.subtitle {
33-
font-size: 13px;
49+
font-size: 12px;
3450
color: var(--text-secondary);
51+
transition: opacity 0.3s ease;
3552
}
3653

3754
.chevron {
38-
font-size: 22px;
55+
font-size: 20px;
3956
color: var(--text-secondary);
40-
transition: transform 0.2s;
57+
transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
4158
}
4259

4360
.chevronOpen {
4461
transform: rotate(180deg);
4562
}
4663

64+
/* ── Smooth expand/collapse ──────────────────────────────────────────────── */
65+
/*
66+
grid-template-rows trick: animating from 0fr → 1fr smoothly collapses
67+
and expands content of any height without needing to know it in advance.
68+
The inner div needs overflow:hidden to clip during animation.
69+
*/
70+
71+
.measuresWrapper {
72+
max-height: 0;
73+
overflow: hidden;
74+
transition: max-height 0.6s cubic-bezier(0.4, 0, 0.2, 1);
75+
}
76+
77+
.measuresWrapperOpen {
78+
max-height: 600px;
79+
transition: max-height 0.8s cubic-bezier(0.4, 0, 0.2, 1);
80+
}
81+
4782
.measures {
4883
margin-top: 10px;
4984
display: flex;
5085
flex-direction: column;
5186
gap: 6px;
87+
padding-bottom: 10px;
5288
}
5389

5490
.measure {
5591
background: var(--bg-card);
5692
border-radius: 8px;
5793
padding: 8px 10px;
94+
transition:
95+
box-shadow 0.2s ease,
96+
transform 0.2s cubic-bezier(0.34, 1.2, 0.64, 1),
97+
background 0.2s ease;
98+
}
99+
100+
.measure:hover {
101+
transform: translateX(3px);
102+
box-shadow: 0 2px 12px -2px rgba(0, 0, 0, 0.2);
103+
background: var(--bg-sidebar);
104+
filter: brightness(1.1);
58105
}
59106

60107
.measureHeader {
@@ -67,7 +114,7 @@
67114

68115
.measureName {
69116
font-weight: 600;
70-
font-size: 16px;
117+
font-size: 15px;
71118
color: var(--text-primary);
72119
}
73120

@@ -81,7 +128,7 @@
81128
}
82129

83130
.measureDesc {
84-
font-size: 15px;
131+
font-size: 14px;
85132
color: var(--text-secondary);
86133
margin-top: 3px;
87134
line-height: 1.4;

0 commit comments

Comments
 (0)