feat(ui): improve ui for test, drills and htm screens

This commit is contained in:
shafin-r
2026-02-21 02:04:50 +06:00
parent 76d2108aec
commit 65dbe99647
10 changed files with 3325 additions and 1464 deletions

View File

@ -1,4 +1,126 @@
import { Badge } from "./ui/badge";
const STYLES = `
@import url('https://fonts.googleapis.com/css2?family=Nunito:wght@700;800;900&family=Nunito+Sans:wght@600;700&display=swap');
.cc-btn {
width: 100%;
background: white;
border: 2.5px solid #f3f4f6;
border-radius: 18px;
padding: 0.85rem 1rem;
text-align: left;
cursor: pointer;
display: flex;
flex-direction: column;
gap: 0.2rem;
box-shadow: 0 3px 10px rgba(0,0,0,0.04);
transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease;
font-family: 'Nunito', sans-serif;
position: relative;
overflow: hidden;
-webkit-tap-highlight-color: transparent;
}
.cc-btn:hover:not(.cc-selected) {
transform: translateY(-2px);
box-shadow: 0 8px 20px rgba(0,0,0,0.07);
border-color: #e5e7eb;
}
.cc-btn:active {
transform: translateY(1px);
box-shadow: 0 2px 6px rgba(0,0,0,0.05);
}
/* Selected state */
.cc-btn.cc-selected {
border-color: #c4b5fd;
background: #fdf4ff;
box-shadow: 0 6px 0 #e9d5ff, 0 8px 20px rgba(168,85,247,0.1);
}
/* Selected shimmer bar on left edge */
.cc-btn.cc-selected::before {
content: '';
position: absolute;
left: 0; top: 0; bottom: 0;
width: 4px;
background: linear-gradient(180deg, #a855f7, #7c3aed);
border-radius: 0 2px 2px 0;
}
/* Top row */
.cc-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
}
.cc-label {
font-size: 0.9rem;
font-weight: 900;
color: #1e1b4b;
line-height: 1.2;
flex: 1;
transition: color 0.15s ease;
}
.cc-btn.cc-selected .cc-label { color: #7c3aed; }
/* Section badge */
.cc-section-badge {
font-size: 0.6rem;
font-weight: 800;
letter-spacing: 0.1em;
text-transform: uppercase;
border-radius: 100px;
padding: 0.2rem 0.6rem;
flex-shrink: 0;
border: 2px solid transparent;
}
.cc-section-badge.ebrw {
background: #eff6ff;
border-color: #bfdbfe;
color: #2563eb;
}
.cc-section-badge.math {
background: #fff1f2;
border-color: #fecdd3;
color: #e11d48;
}
/* Sub label */
.cc-sublabel {
font-family: 'Nunito Sans', sans-serif;
font-size: 0.75rem;
font-weight: 600;
color: #9ca3af;
line-height: 1.3;
padding-left: 0.05rem;
transition: color 0.15s ease;
}
.cc-btn.cc-selected .cc-sublabel { color: #a855f7; }
/* Checkmark */
.cc-check {
position: absolute;
top: 0.65rem;
right: 0.75rem;
width: 20px; height: 20px;
border-radius: 50%;
border: 2px solid #e5e7eb;
display: flex; align-items: center; justify-content: center;
flex-shrink: 0;
transition: all 0.2s cubic-bezier(0.34,1.56,0.64,1);
background: white;
}
.cc-btn.cc-selected .cc-check {
background: #a855f7;
border-color: #a855f7;
transform: scale(1.1);
}
`;
let stylesInjected = false;
export const ChoiceCard = ({
label,
@ -12,23 +134,51 @@ export const ChoiceCard = ({
subLabel?: string;
section?: string;
onClick: () => void;
}) => (
<button
onClick={onClick}
className={`rounded-2xl border p-4 text-left transition flex flex-col
${selected ? "border-indigo-600 bg-indigo-50" : "hover:border-gray-300"}`}
>
<div className="flex justify-between">
<span className="font-satoshi-bold text-lg">{label}</span>
{section && (
<Badge
variant={"secondary"}
className={`font-satoshi text-sm ${section === "EBRW" ? "bg-blue-400 text-blue-100" : "bg-red-400 text-red-100"}`}
>
{section}
</Badge>
)}
</div>
{subLabel && <span className="font-satoshi text-md">{subLabel}</span>}
</button>
);
}) => {
if (!stylesInjected) {
const tag = document.createElement("style");
tag.textContent = STYLES;
document.head.appendChild(tag);
stylesInjected = true;
}
const sectionClass =
section === "EBRW"
? "ebrw"
: section === "Math" || section === "MATH"
? "math"
: "";
return (
<button
onClick={onClick}
className={`cc-btn${selected ? " cc-selected" : ""}`}
>
{/* Checkmark */}
<div className="cc-check">
{selected && (
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
<path
d="M1.5 5L4 7.5L8.5 2.5"
stroke="white"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)}
</div>
{/* Top row: label + section badge */}
<div className="cc-top" style={{ paddingRight: "1.75rem" }}>
<span className="cc-label">{label}</span>
{section && (
<span className={`cc-section-badge ${sectionClass}`}>{section}</span>
)}
</div>
{/* Sub label */}
{subLabel && <span className="cc-sublabel">{subLabel}</span>}
</button>
);
};