feat(ui): improve ui for test, drills and htm screens
This commit is contained in:
@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user