From d7f9ae8841850e065d9d4f1fae75b06e798d17f9 Mon Sep 17 00:00:00 2001 From: Mireya Cueto Garrido Date: Tue, 2 Jun 2026 12:56:30 +0200 Subject: [PATCH] Improve responsive UX/UI consistency across all frontend screens. This polish pass unifies mobile navigation, spacing, typography hierarchy, and CTA behavior so all core exam workflows remain clear and fully usable on both mobile and desktop. --- frontend/src/components/layout/Navbar.jsx | 57 ++- frontend/src/index.css | 368 +++++++++++++++++-- frontend/src/pages/CreateTemplatePage.jsx | 8 +- frontend/src/pages/DashboardPage.jsx | 4 +- frontend/src/pages/TemplateDetailPage.jsx | 18 + frontend/src/pages/template/ExportTab.jsx | 4 +- frontend/src/pages/template/GenerateTab.jsx | 9 +- frontend/src/pages/template/ImagesTab.jsx | 4 +- frontend/src/pages/template/MaterialsTab.jsx | 6 +- frontend/src/pages/template/OverviewTab.jsx | 9 +- frontend/src/pages/template/QuestionsTab.jsx | 4 +- 11 files changed, 428 insertions(+), 63 deletions(-) diff --git a/frontend/src/components/layout/Navbar.jsx b/frontend/src/components/layout/Navbar.jsx index 7e64384..41752f3 100644 --- a/frontend/src/components/layout/Navbar.jsx +++ b/frontend/src/components/layout/Navbar.jsx @@ -10,37 +10,60 @@ export default function Navbar() { const { user, logout } = useAuth(); const navigate = useNavigate(); const [confirmOut, setConfirmOut] = useState(false); + const [mobileOpen, setMobileOpen] = useState(false); const doLogout = () => { logout(); navigate("/login"); }; + const closeMobileMenu = () => setMobileOpen(false); + return (
- + - GenExámenes IA + GenExámenes IA - - -
-
- {initials(user?.full_name || user?.email)} + + + +
+ + +
+
+ {initials(user?.full_name || user?.email)} +
+
-
diff --git a/frontend/src/index.css b/frontend/src/index.css index 1c5e016..7923361 100644 --- a/frontend/src/index.css +++ b/frontend/src/index.css @@ -31,6 +31,10 @@ --font: "Inter", "Segoe UI", system-ui, -apple-system, sans-serif; --maxw: 1180px; + --h1: 30px; + --h2: 24px; + --h3: 19px; + --h4: 16px; } * { @@ -48,7 +52,7 @@ body { background: var(--c-bg); color: var(--c-text); font-size: 15px; - line-height: 1.55; + line-height: 1.6; -webkit-font-smoothing: antialiased; } @@ -64,10 +68,22 @@ h1, h2, h3, h4 { - margin: 0 0 0.4em; + margin: 0 0 0.45em; line-height: 1.25; font-weight: 700; - letter-spacing: -0.01em; + letter-spacing: -0.012em; +} +h1 { + font-size: var(--h1); +} +h2 { + font-size: var(--h2); +} +h3 { + font-size: var(--h3); +} +h4 { + font-size: var(--h4); } button { @@ -82,6 +98,12 @@ button { .icon-inline { margin-right: 6px; } +.card-head .icon, +.tab .icon, +.btn .icon, +.badge .icon { + stroke-width: 1.9; +} .icon-lg { width: 40px; height: 40px; @@ -181,7 +203,7 @@ button { .nav-link { padding: 8px 14px; border-radius: var(--radius-sm); - color: var(--c-text-soft); + color: #4e566c; font-weight: 500; font-size: 14px; } @@ -228,16 +250,16 @@ button { display: flex; align-items: flex-start; gap: 16px; - margin-bottom: 24px; + margin-bottom: 26px; flex-wrap: wrap; } .page-header h1 { - font-size: 26px; + font-size: clamp(24px, 3vw, 30px); margin: 0; } .page-header p { - margin: 4px 0 0; - color: var(--c-text-soft); + margin: 7px 0 0; + color: #5a6277; } .page-header-actions { margin-left: auto; @@ -245,6 +267,23 @@ button { gap: 10px; } +.page-lead { + max-width: 68ch; +} + +.section-title { + font-size: 15px; + font-weight: 700; + color: var(--c-text); + margin: 0 0 8px; +} + +.section-subtle { + font-size: 13px; + color: var(--c-text-faint); + margin: 0; +} + /* ---------- Cards ---------- */ .card { background: var(--c-surface); @@ -253,10 +292,10 @@ button { box-shadow: var(--shadow-sm); } .card-pad { - padding: 22px; + padding: 20px; } .card-head { - padding: 18px 22px; + padding: 16px 20px; border-bottom: 1px solid var(--c-border); display: flex; align-items: center; @@ -265,9 +304,10 @@ button { .card-head h3 { margin: 0; font-size: 16px; + letter-spacing: -0.01em; } .card-body { - padding: 22px; + padding: 20px; } .grid { @@ -365,12 +405,12 @@ button { display: block; font-size: 13px; font-weight: 600; - color: var(--c-text); + color: #2a3143; margin-bottom: 7px; } .field-hint { font-size: 12.5px; - color: var(--c-text-faint); + color: #78809a; margin-top: 6px; } .field-error { @@ -440,12 +480,12 @@ button { display: inline-flex; align-items: center; gap: 5px; - padding: 3px 10px; + padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 600; background: var(--c-surface-2); - color: var(--c-text-soft); + color: #505a74; } .badge-primary { background: var(--c-primary-soft); @@ -477,10 +517,10 @@ button { overflow-x: auto; } .tab { - padding: 11px 16px; + padding: 11px 15px; border: none; background: none; - color: var(--c-text-soft); + color: #556079; font-weight: 600; font-size: 14px; cursor: pointer; @@ -492,7 +532,7 @@ button { gap: 7px; } .tab:hover { - color: var(--c-text); + color: #252c3f; } .tab.active { color: var(--c-primary); @@ -627,7 +667,7 @@ button { display: flex; gap: 16px; flex-wrap: wrap; - color: var(--c-text-soft); + color: #586178; font-size: 13px; } .meta-row span { @@ -668,13 +708,17 @@ button { } .list-item-sub { font-size: 13px; - color: var(--c-text-faint); + color: #7a839c; } .empty-state { text-align: center; padding: 56px 24px; - color: var(--c-text-soft); + color: #5c657a; +} +.empty-state p { + margin: 6px auto 0; + max-width: 56ch; } .empty-state-icon { margin: 0 auto 12px; @@ -813,15 +857,15 @@ button { } .toast-content { flex: 1; - font-size: 14px; + font-size: 13.5px; } .toast-title { font-weight: 600; margin-bottom: 2px; } .toast-msg { - color: var(--c-text-soft); - font-size: 13px; + color: #5b6378; + font-size: 12.5px; } .toast-close { background: none; @@ -863,14 +907,17 @@ button { .mt-lg { margin-top: 26px; } +.mb-sm { + margin-bottom: 10px; +} .mb { margin-bottom: 16px; } .text-soft { - color: var(--c-text-soft); + color: #5a6379; } .text-faint { - color: var(--c-text-faint); + color: #7b849c; } .text-sm { font-size: 13px; @@ -933,3 +980,272 @@ button { border: 1px solid var(--c-border); background: var(--c-surface-2); } + +.layout-split { + grid-template-columns: minmax(0, 1fr) 320px; +} + +.layout-split-wide { + grid-template-columns: minmax(0, 1.4fr) minmax(260px, 1fr); +} + +.tabs-select-wrap { + display: none; + margin-bottom: 14px; +} + +/* ---------- Responsive ---------- */ +@media (max-width: 1080px) { + .navbar-inner { + padding: 0 16px; + gap: 12px; + } + + .page { + padding: 24px 16px 42px; + } +} + +@media (max-width: 900px) { + .list-item { + flex-wrap: wrap; + align-items: flex-start; + } + + .list-item-actions { + width: 100%; + justify-content: flex-end; + } + + .layout-split, + .layout-split-wide { + grid-template-columns: 1fr; + } +} + +@media (max-width: 760px) { + :root { + --radius: 10px; + --radius-lg: 14px; + --h1: 26px; + --h2: 22px; + --h3: 18px; + --h4: 15px; + } + + .navbar-inner { + height: auto; + min-height: 64px; + flex-wrap: wrap; + align-items: center; + padding-top: 10px; + padding-bottom: 10px; + } + + .brand { + min-width: 0; + flex: 1; + } + + .brand-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .nav-mobile-toggle { + display: inline-flex; + } + + .nav-collapse { + width: 100%; + display: none; + flex-direction: column; + gap: 10px; + padding: 8px 0 2px; + border-top: 1px solid var(--c-border); + } + + .nav-collapse.open { + display: flex; + } + + .nav-links { + margin-left: 0; + width: 100%; + flex-direction: column; + gap: 6px; + } + + .nav-link { + width: 100%; + min-height: 42px; + display: inline-flex; + align-items: center; + padding: 10px 12px; + } + + .nav-spacer { + display: none; + } + + .nav-user { + width: 100%; + justify-content: space-between; + border-top: 1px solid var(--c-border); + padding-top: 10px; + } + + .page-header h1 { + font-size: 25px; + } + + .page-header p, + .page-lead { + font-size: 14px; + } + + .page-header-actions { + margin-left: 0; + width: 100%; + } + + .page-header-actions .btn { + width: 100%; + } + + .card-head, + .card-body, + .card-pad { + padding: 15px; + } + + .card-head { + flex-wrap: wrap; + } + + .card-head > .btn { + width: 100%; + } + + .card-head h3 { + font-size: 15px; + } + + .tabs { + gap: 6px; + margin-left: -4px; + margin-right: -4px; + padding: 0 4px; + scrollbar-width: thin; + } + + .tabs-select-wrap { + display: block; + } + + .tab { + min-height: 44px; + padding: 10px 13px; + } + + .btn { + min-height: 42px; + } + + .btn.btn-sm { + min-height: 38px; + } + + .btn.btn-lg { + min-height: 46px; + } + + .mobile-stack { + flex-direction: column; + align-items: stretch; + } + + .mobile-stack > .btn { + width: 100%; + } + + .modal-overlay { + padding: 12px; + align-items: flex-end; + } + + .modal { + max-height: 94vh; + border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + } + + .modal-head, + .modal-body, + .modal-foot { + padding-left: 16px; + padding-right: 16px; + } + + .modal-foot { + flex-wrap: wrap; + } + + .modal-foot .btn { + flex: 1; + min-width: 130px; + } + + .toast-stack { + top: auto; + bottom: 12px; + right: 12px; + left: 12px; + max-width: none; + } + + .spinner-center { + padding: 36px 0; + } + + .empty-state { + padding: 34px 16px; + } + + .empty-state h3 { + font-size: 18px; + margin-bottom: 6px; + } + + .empty-state .btn { + width: 100%; + } + + .code-block { + max-height: 320px; + font-size: 12px; + padding: 12px; + } + + .progress { + height: 9px; + } + + .list-item-sub { + margin-top: 2px; + } +} + +@media (min-width: 761px) { + .nav-mobile-toggle { + display: none; + } + + .nav-collapse { + display: flex; + flex: 1; + align-items: center; + gap: 12px; + } +} diff --git a/frontend/src/pages/CreateTemplatePage.jsx b/frontend/src/pages/CreateTemplatePage.jsx index 198e53a..ff4c17b 100644 --- a/frontend/src/pages/CreateTemplatePage.jsx +++ b/frontend/src/pages/CreateTemplatePage.jsx @@ -122,7 +122,7 @@ export default function CreateTemplatePage() {

Nuevo examen

-

Define la estructura. Después podrás subir material y generar preguntas.

+

Define la estructura. Después podrás subir material y generar preguntas.

@@ -192,7 +192,7 @@ export default function CreateTemplatePage() { className="card" style={{ padding: 16, marginBottom: 14, background: "var(--c-surface-2)" }} > -
+
Bloque {idx + 1} {types.length > 1 && ( diff --git a/frontend/src/pages/DashboardPage.jsx b/frontend/src/pages/DashboardPage.jsx index 303f118..d298447 100644 --- a/frontend/src/pages/DashboardPage.jsx +++ b/frontend/src/pages/DashboardPage.jsx @@ -32,10 +32,10 @@ export default function DashboardPage() {

Mis exámenes

-

Gestiona tus plantillas de examen y genera preguntas con IA.

+

Gestiona tus plantillas de examen y genera preguntas con IA.

- diff --git a/frontend/src/pages/TemplateDetailPage.jsx b/frontend/src/pages/TemplateDetailPage.jsx index c0d992a..6ccb2d1 100644 --- a/frontend/src/pages/TemplateDetailPage.jsx +++ b/frontend/src/pages/TemplateDetailPage.jsx @@ -154,6 +154,24 @@ export default function TemplateDetailPage() {
+
+ + +
+
{TABS.map((t) => (