From d37220d010885f5c1f8bcea145119fb22171d495 Mon Sep 17 00:00:00 2001 From: Konrad Kollnig <5175206+kasnder@users.noreply.github.com> Date: Tue, 22 Sep 2026 23:56:51 +0200 Subject: [PATCH] Fix responsive iOS layout and user-facing search copy --- lib/i18n.js | 5 +---- public/css/styles.css | 25 +++++++++++++++++++------ routes/index.js | 6 +++--- test/websiteViews.test.js | 8 ++++++++ views/about.pug | 1 + views/directory.pug | 1 + views/form.pug | 4 ++-- views/layout.pug | 2 +- views/statistics.pug | 6 +++++- 9 files changed, 41 insertions(+), 17 deletions(-) diff --git a/lib/i18n.js b/lib/i18n.js index 409ad6c..988b7b3 100644 --- a/lib/i18n.js +++ b/lib/i18n.js @@ -19,7 +19,6 @@ const da = { 'Statistics': 'Statistik', 'About': 'Om', 'Search apps': 'Søg efter apps', - 'Search apps placeholder': 'Søg efter apps', 'Footer navigation': 'Sidefodsnavigation', 'TrackerControl project': 'TrackerControl-projektet', 'Contact': 'Kontakt', @@ -77,7 +76,6 @@ const da = { 'reports may be out of date, incomplete or incorrect. They describe an analysed app version on the date shown, and automated analysis makes mistakes. ': 'rapporter kan være forældede, ufuldstændige eller forkerte. De beskriver en analyseret appversion på den viste dato, og automatiske analyser kan tage fejl. ', 'Read the full disclaimer': 'Læs hele ansvarsfraskrivelsen', - 'Search apps heading': 'Søg efter apps', 'Search results': 'Søgeresultater', 'Search': 'Søg', 'No apps found for “{{term}}”.': 'Ingen apps fundet for “{{term}}”.', @@ -89,8 +87,6 @@ const da = { 'No matching free app was returned by the UK App Store search. Check the spelling or try a shorter name.': 'Søgningen i den britiske App Store gav ingen matchende gratis app. Kontrollér stavningen, eller prøv et kortere navn.', 'Free apps without a published report open a confirmation page first. A request is queued only after confirmation.': 'Gratis apps uden en udgivet rapport åbner først en bekræftelsesside. En anmodning kommer kun i kø efter bekræftelse.', 'Search again': 'Søg igen', - 'Search app': 'Søg efter app', - 'Search apps title': 'Søg efter apps', 'App report': 'App-rapport', 'Untitled app': 'Unavngiven app', @@ -260,6 +256,7 @@ const da = { '{{count}} entries': '{{count}} poster', 'Tracker directory table': 'Trackerkatalogtabel', 'Company directory table': 'Virksomhedskatalogtabel', + 'Scroll sideways to see all columns.': 'Rul sidelæns for at se alle kolonner.', 'Rank': 'Rang', 'Tracker': 'Tracker', 'Company': 'Virksomhed', diff --git a/public/css/styles.css b/public/css/styles.css index 196012c..d9c7803 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -69,7 +69,7 @@ button { cursor: pointer; } padding-bottom: 1rem; } -.platform-header { border-bottom: 1px solid var(--border); } +.platform-header { background: var(--warm); border-bottom: 1px solid var(--border); } .platform-nav { display: flex; flex-wrap: wrap; gap: .6rem 1.4rem; padding-top: .65rem; padding-bottom: .65rem; font-size: .78rem; } .platform-nav a { color: var(--muted); text-decoration: none; } .platform-nav a:hover { color: var(--brand); text-decoration: underline; } @@ -155,7 +155,7 @@ h3 { font-size: 1.35rem; line-height: 1.2; margin-bottom: 1rem; } text-transform: uppercase; } -.hero { padding: 5rem 0 5.4rem; } +.hero { padding: 3rem 0 5.4rem; } .hero h1 { max-width: 760px; } .hero-intro { color: #4b3d3d; font-size: clamp(1.08rem, 2vw, 1.3rem); line-height: 1.45; margin-bottom: 3.3rem; max-width: 540px; } @@ -217,6 +217,7 @@ input::placeholder { color: #796d6d; } .metrics .section-note { grid-column: 1 / -1; margin-top: .4rem; } .home-section, .stats-section, .about-section, .lookup-apps, .lookup-trackers { border-top: 1px solid var(--border); padding: 3.4rem 0 0; margin-top: 3.4rem; } +.metrics + .home-section { border-top: 0; margin-top: 0; } .section-heading { margin-bottom: 1.7rem; } .section-heading .eyebrow { margin-bottom: .55rem; } .section-heading h2 { margin-bottom: 0; } @@ -225,6 +226,8 @@ input::placeholder { color: #796d6d; } .bar-list { display: grid; gap: 1rem; } .bar-item { min-width: 0; } +.bar-item--tiny { position: relative; } +.bar-item--tiny::after { background: var(--brand); bottom: 0; content: ''; height: 8px; left: 0; pointer-events: none; position: absolute; width: 2px; } .bar-label { align-items: baseline; display: flex; font-size: .84rem; gap: 1rem; justify-content: space-between; margin-bottom: .3rem; } .bar-label span, .bar-label strong { overflow-wrap: anywhere; } .bar-label strong { font-weight: 750; text-align: right; } @@ -280,6 +283,7 @@ progress.bar-track::-moz-progress-bar { background: var(--brand); } .directory-controls input { min-width: 0; } .directory-controls .result-count { align-self: center; } .result-count { color: var(--muted); flex: 0 1 auto; font-size: .8rem; } +.table-scroll-hint { display: none; } .table-scroll { border: 1px solid var(--border); margin-top: 1.3rem; max-width: 100%; overflow-x: auto; } .table-scroll:focus { outline: 3px solid #b71c1c; outline-offset: 3px; } .data-table { border-collapse: collapse; min-width: 660px; width: 100%; } @@ -378,8 +382,9 @@ progress.bar-track::-moz-progress-bar { background: var(--brand); } @media (max-width: 1050px) { .site-header { align-items: flex-start; } - .site-nav { order: 3; width: 100%; } - .nav-search { flex: 1 1 230px; margin-left: auto; } + .language-toggle { order: 1; } + .site-nav { order: 2; width: 100%; } + .nav-search { flex: 1 1 100%; order: 3; } .search-form { grid-template-columns: 1fr; } .metadata { grid-template-columns: repeat(2, 1fr); } .report-summary { grid-template-columns: repeat(3, 1fr); } @@ -391,9 +396,9 @@ progress.bar-track::-moz-progress-bar { background: var(--brand); } .site-header { gap: .8rem 1rem; padding-bottom: 1.2rem; padding-top: 1.2rem; } .nav-search { flex-basis: 100%; margin-left: 0; } .nav-search input { min-height: 44px; } - .site-nav { gap: .5rem .9rem; } + .site-nav { display: grid; gap: .5rem .9rem; grid-template-columns: repeat(3, max-content); justify-content: space-between; } .site-nav a, .site-footer nav a { align-items: center; display: inline-flex; min-height: 44px; } - .hero { padding: 3.5rem 0 4.2rem; } + .hero { padding: 2rem 0 4.2rem; } h1 { font-size: clamp(2.45rem, 13vw, 3.5rem); } .hero-intro { margin-bottom: 2.5rem; } .search-form__controls { align-items: stretch; flex-direction: column; } @@ -409,6 +414,7 @@ progress.bar-track::-moz-progress-bar { background: var(--brand); } .directory-controls, .tracker-controls { align-items: stretch; grid-template-columns: 1fr; } .directory-controls .result-count { align-self: start; } .table-scroll { margin-left: 0; width: 100%; } + .table-scroll-hint { color: var(--muted); display: block; font-size: .8rem; margin: 1rem 0 -.7rem; } .report-page { padding-top: 1.4rem; } .report-header { gap: 1rem; grid-template-columns: 64px minmax(0, 1fr); padding: 2.2rem 0; } .app-icon--large { border-radius: 12px; font-size: 2rem; height: 64px; width: 64px; } @@ -429,3 +435,10 @@ progress.bar-track::-moz-progress-bar { background: var(--brand); } .site-footer__inner { align-items: flex-start; flex-direction: column; gap: .8rem; min-height: 140px; padding-bottom: 1.4rem; padding-top: 1.4rem; } .request-details { grid-template-columns: 110px minmax(0, 1fr); } } + +@media (max-width: 360px) { + .site-header { column-gap: .5rem; } + .site-header .wordmark { font-size: .95rem; } + .site-header .wordmark small { display: none; } + .site-header .wordmark__icon { height: 32px; width: 32px; } +} diff --git a/routes/index.js b/routes/index.js index 1437568..8192329 100644 --- a/routes/index.js +++ b/routes/index.js @@ -456,7 +456,7 @@ router.get('/search', })); res.render('form', { - title: res.locals.t('Search app'), + title: res.locals.t('Search results'), errors: errors.array(), data: req.query, searchResults @@ -464,14 +464,14 @@ router.get('/search', } catch (err) { console.log(err); res.status(502).render('form', { - title: res.locals.t('Search apps title'), + title: res.locals.t('Search apps'), data: req.query, errors: [{ msg: res.locals.t('Error while searching. Try again later.') }], }); } } else { res.render('form', { - title: res.locals.t('Search app'), + title: res.locals.t('Search apps'), errors: errors.array(), data: req.query, }); diff --git a/test/websiteViews.test.js b/test/websiteViews.test.js index 853c176..2b7cadb 100644 --- a/test/websiteViews.test.js +++ b/test/websiteViews.test.js @@ -161,9 +161,17 @@ test('search, directory, lookup, statistics, about, request and error states ren const emptySearch = render('form.pug', { currentPath: '/search', data: { search: 'nothing' }, searchResults: [] }); assertSingleH1(emptySearch, 'empty search'); assert.match(emptySearch, /id="nav-search"/); + assert.match(emptySearch, /placeholder="Search apps"/); assert.match(emptySearch, /No apps found for/); assert.match(emptySearch, /No matching free app/); + const failedSearch = render('form.pug', { + currentPath: '/search', + errors: [{ msg: 'Please enter a search term' }] + }); + assert.match(failedSearch, /