feat: UI improvements — scrollbar, multi-filters, pricing fix, routing, modals

- Global page scrollbar styled with gold theme
- Schedule: multi-select for class types and status tags
- Pricing: fix tab switch blink (display toggle vs conditional render)
- OpenDay: trainer name more prominent, section divider added
- Team: browser back button closes trainer bio (history API)
- Modals: block scroll + compensate scrollbar width to prevent layout shift
- Header: remove booking button from desktop nav
This commit is contained in:
2026-03-26 13:23:03 +03:00
parent 228e547e10
commit 8088b99a43
17 changed files with 275 additions and 229 deletions
+11 -11
View File
@@ -8,8 +8,8 @@ interface DayCardProps {
showLocation?: boolean;
filterTrainer: string | null;
setFilterTrainer: (trainer: string | null) => void;
filterType: string | null;
setFilterType: (type: string | null) => void;
filterTypes: Set<string>;
toggleFilterType: (type: string) => void;
}
function ClassRow({
@@ -17,15 +17,15 @@ function ClassRow({
typeDots,
filterTrainer,
setFilterTrainer,
filterType,
setFilterType,
filterTypes,
toggleFilterType,
}: {
cls: ScheduleClassWithLocation;
typeDots: Record<string, string>;
filterTrainer: string | null;
setFilterTrainer: (trainer: string | null) => void;
filterType: string | null;
setFilterType: (type: string | null) => void;
filterTypes: Set<string>;
toggleFilterType: (type: string) => void;
}) {
return (
<div className={`px-5 py-3.5 ${cls.hasSlots ? "bg-emerald-500/5" : cls.recruiting ? "bg-sky-500/5" : ""}`}>
@@ -58,12 +58,12 @@ function ClassRow({
</button>
<div className="mt-2 flex items-center gap-2 flex-wrap">
<button
onClick={() => setFilterType(filterType === cls.type ? null : cls.type)}
onClick={() => toggleFilterType(cls.type)}
className="flex items-center gap-2 cursor-pointer active:opacity-60"
>
<span className={`h-2 w-2 shrink-0 rounded-full ${typeDots[cls.type] ?? "bg-white/30"}`} />
<span className={`text-xs ${
filterType === cls.type
filterTypes.has(cls.type)
? "text-gold underline underline-offset-2"
: "text-neutral-500 dark:text-white/40"
}`}>{cls.type}</span>
@@ -78,7 +78,7 @@ function ClassRow({
);
}
export function DayCard({ day, typeDots, showLocation, filterTrainer, setFilterTrainer, filterType, setFilterType }: DayCardProps) {
export function DayCard({ day, typeDots, showLocation, filterTrainer, setFilterTrainer, filterTypes, toggleFilterType }: DayCardProps) {
// Group classes by location when showLocation is true
const locationGroups = showLocation
? Array.from(
@@ -123,7 +123,7 @@ export function DayCard({ day, typeDots, showLocation, filterTrainer, setFilterT
</div>
<div className="divide-y divide-neutral-100 dark:divide-white/[0.04]">
{classes.map((cls, i) => (
<ClassRow key={i} cls={cls} typeDots={typeDots} filterTrainer={filterTrainer} setFilterTrainer={setFilterTrainer} filterType={filterType} setFilterType={setFilterType} />
<ClassRow key={i} cls={cls} typeDots={typeDots} filterTrainer={filterTrainer} setFilterTrainer={setFilterTrainer} filterTypes={filterTypes} toggleFilterType={toggleFilterType} />
))}
</div>
</div>
@@ -133,7 +133,7 @@ export function DayCard({ day, typeDots, showLocation, filterTrainer, setFilterT
// Single location — no sub-headers
<div className="divide-y divide-neutral-100 dark:divide-white/[0.04]">
{day.classes.map((cls, i) => (
<ClassRow key={i} cls={cls} typeDots={typeDots} filterTrainer={filterTrainer} setFilterTrainer={setFilterTrainer} filterType={filterType} setFilterType={setFilterType} />
<ClassRow key={i} cls={cls} typeDots={typeDots} filterTrainer={filterTrainer} setFilterTrainer={setFilterTrainer} filterTypes={filterTypes} toggleFilterType={toggleFilterType} />
))}
</div>
)}