Files
school_compare/nextjs-app/components/Navigation.module.css
T
Tudor Sitaru 2a8ff29ccd
Build and Push Docker Images / Build Backend (FastAPI) (push) Successful in 49s
Build and Push Docker Images / Build Frontend (Next.js) (push) Successful in 56s
Build and Push Docker Images / Build Pipeline (Meltano + dbt + Airflow) (push) Successful in 2m6s
Build and Push Docker Images / Trigger Portainer Update (push) Successful in 0s
feat(nav): mobile bottom tab bar and ≥44px logo tap target
MOB-01: At ≤640px the top inline nav is hidden and replaced by a
fixed bottom tab bar (Search / Compare / Rankings / Admissions) with
icon + label, 56px tap targets, env(safe-area-inset-bottom) padding,
and the Compare count rendered as a badge on the icon. Eliminates
horizontal page overflow on every route (docW was 401–429 at vw 390;
now docW === vw).

MOB-02: Logo link gains a padded hit area so the touch target is
≥44×44 (was 36×36), without resizing the visual mark.

ComparisonToast lifted above the new bottom bar on mobile so the two
do not stack on top of each other. body gets a bottom padding equal
to the bar height + safe-area inset so page content is never hidden.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 15:26:01 +01:00

238 lines
4.4 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
.header {
position: sticky;
top: 0;
z-index: 1000;
background: var(--bg-card, white);
border-bottom: 1px solid var(--border-color, #e5dfd5);
box-shadow: 0 2px 8px rgba(26, 22, 18, 0.06);
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 0 1.5rem;
display: flex;
justify-content: space-between;
align-items: center;
height: 64px;
}
.logo {
display: flex;
align-items: center;
gap: 0.75rem;
/* Padded hit area so the logo link is ≥44×44 on touch */
margin: -0.375rem -0.5rem;
padding: 0.375rem 0.5rem;
text-decoration: none;
color: var(--text-primary, #1a1612);
font-size: 1.25rem;
font-weight: 700;
transition: color 0.2s ease;
-webkit-tap-highlight-color: transparent;
}
.logo:hover {
color: var(--accent-coral, #e07256);
}
.logoIcon {
display: inline-flex;
width: 36px;
height: 36px;
color: var(--accent-coral, #e07256);
}
.logoIcon svg {
width: 100%;
height: 100%;
}
.logoText {
font-family: var(--font-playfair), 'Playfair Display', serif;
font-weight: 700;
letter-spacing: -0.01em;
}
.nav {
display: flex;
gap: 0.5rem;
}
.navLink {
position: relative;
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.625rem 1rem;
font-size: 0.9375rem;
font-weight: 500;
color: var(--text-secondary, #5c564d);
text-decoration: none;
border-radius: 6px;
transition: all 0.2s ease;
}
/* Sliding underline effect */
.navLink::after {
content: '';
position: absolute;
bottom: 4px;
left: 1rem;
right: 1rem;
height: 2px;
background: var(--accent-coral, #e07256);
transform: scaleX(0);
transform-origin: left;
transition: transform 0.25s ease;
border-radius: 1px;
}
.navLink:hover {
color: var(--text-primary, #1a1612);
background: var(--bg-secondary, #f3ede4);
}
.navLink:hover::after {
transform: scaleX(1);
}
.navLink.active {
color: var(--accent-coral, #e07256);
background: var(--accent-coral-bg);
}
.navLink.active::after {
transform: scaleX(1);
}
.badge {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1.25rem;
height: 1.25rem;
padding: 0 0.375rem;
font-size: 0.75rem;
font-weight: 600;
color: white;
background: var(--accent-coral, #e07256);
border-radius: 9999px;
animation: badgePop 0.3s ease-out;
box-shadow: 0 2px 6px rgba(224, 114, 86, 0.4);
}
@keyframes badgePop {
0% {
transform: scale(0.6);
opacity: 0;
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
opacity: 1;
}
}
/* ─── Bottom tab bar (mobile only) ──────────────────────────────── */
.bottomBar {
display: none;
}
.tab {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.2rem;
flex: 1;
min-height: 56px;
padding: 0.375rem 0.25rem;
color: var(--text-secondary, #5c564d);
text-decoration: none;
font-size: 0.6875rem;
font-weight: 500;
letter-spacing: 0.01em;
transition: color 0.15s ease, background-color 0.15s ease;
-webkit-tap-highlight-color: transparent;
}
.tab:active {
background: var(--bg-secondary, #f3ede4);
}
.tabActive {
color: var(--accent-coral, #e07256);
}
.tabIconWrap {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
}
.tabIcon {
width: 22px;
height: 22px;
}
.tabLabel {
line-height: 1;
}
.tabBadge {
position: absolute;
top: -6px;
right: -10px;
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 18px;
height: 18px;
padding: 0 5px;
font-size: 0.6875rem;
font-weight: 700;
color: white;
background: var(--accent-coral, #e07256);
border: 2px solid var(--bg-card, white);
border-radius: 9999px;
animation: badgePop 0.3s ease-out;
}
@media (max-width: 640px) {
.container {
padding: 0 1rem;
height: 56px;
}
/* Hide the top text nav; the bottom bar takes over */
.nav {
display: none;
}
.logoIcon {
width: 32px;
height: 32px;
}
.bottomBar {
display: flex;
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 1000;
background: var(--bg-card, white);
border-top: 1px solid var(--border-color, #e5dfd5);
box-shadow: 0 -2px 12px rgba(26, 22, 18, 0.06);
/* Respect iPhone home-indicator inset */
padding-bottom: env(safe-area-inset-bottom, 0);
}
}