3d1fe40be6
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
92 lines
4.9 KiB
Markdown
92 lines
4.9 KiB
Markdown
---
|
|
id: 24-8
|
|
title: 24-8 Articles and Legal Pages
|
|
status: Ready for Dev
|
|
date: 2026-10-31
|
|
parent: 24
|
|
---
|
|
|
|
## Description
|
|
|
|
Restyle the articles index, the article page and the legal pages. Behaviour does not change:
|
|
search (`wire:model.live.debounce.300ms="search"`), pagination (`paginate(10)`), result counts,
|
|
empty states, the 404 for unpublished posts, and the CMS content of legal pages. Remove the
|
|
temporary `<div class="wrap py-8">` wrappers added in 24-1.
|
|
|
|
### `/posts` — `resources/views/livewire/pages/posts/index.blade.php`
|
|
|
|
`<section class="sec" style="padding-top:56px"><div class="wrap">`:
|
|
- `<x-site.section-head :label="__('site.hero_eyebrow')" :title="__('site.nav_articles')">`
|
|
(the h2 reads «المقالات» / "Articles"; the existing `posts.posts` key reads "Posts" in English, so
|
|
it is not used here) with,
|
|
in the slot, the search field: a pill input (`.search`: min-height 48px, radius 999px, padding
|
|
12px 20px, `1.5px solid rgba(45,54,36,.18)`, white, width min(360px, 100%); focus gold border
|
|
plus `0 0 0 4px rgba(166,137,102,.2)`), same `wire:model` and placeholder
|
|
`posts.search_placeholder`, with an accessible label (`sr-only` text
|
|
`posts.search_placeholder`).
|
|
- The existing result-count / no-result lines (`posts.search_results`, `posts.no_results`) as a
|
|
muted paragraph, and the existing clear-search action as `btn btn-ghost`.
|
|
- The posts as `<x-site.post-card :post="$post" />` in a `.posts` grid (3 columns; 2 at ≤1100px;
|
|
1 at ≤760px — the grid CSS exists from 24-4; at this page the last card does not span two
|
|
columns: add `body.site .posts-index .post:last-child{grid-column:auto}` and give the grid the
|
|
extra class `posts-index`).
|
|
- Empty states `posts.no_posts` as before.
|
|
- Pagination: `{{ $posts->links() }}` kept; style its links under `body.site .pagination-wrap`
|
|
(wrap the call in `<div class="pagination-wrap">`): 44px pill buttons, `1.5px solid var(--line)`,
|
|
current page `background:var(--forest)` with cream text, disabled at 50% opacity.
|
|
|
|
### `/posts/{post}` — `resources/views/livewire/pages/posts/show.blade.php`
|
|
|
|
`<section class="sec" style="padding-top:56px"><article class="wrap" style="max-width:768px">`
|
|
(720px content + padding):
|
|
- `<span class="meta">` the published date (existing `translatedFormat('l, d F Y')` expression),
|
|
colour `--gold-ink`, .85rem, weight 600.
|
|
- `<h1>` = `$post->getTitle()` — display font, `clamp(2rem,3.4vw,3rem)`, margin 10px 0 28px.
|
|
- Body `<div class="prose prose-lg prose-brand max-w-none site-prose">{!! $post->getBody() !!}</div>`
|
|
(keep the existing output exactly). New CSS: `body.site .site-prose :is(h2,h3,h4){font-family:var(--display)}`,
|
|
`body.site .site-prose a{color:var(--olive)}`, `body.site .site-prose{font-size:1.06rem;line-height:1.85}`.
|
|
- Footer: `<a class="btn btn-ghost" href="{{ route('posts.index') }}" wire:navigate>`
|
|
`posts.back_to_posts`, preceded by a hairline `border-top:1px solid var(--line)` with 48px
|
|
margin-top and 24px padding-top. Remove `flux:heading`.
|
|
|
|
### Legal pages
|
|
|
|
- `resources/views/pages/legal.blade.php` — inside `<x-layouts.public>`:
|
|
`<section class="sec" style="padding-top:56px"><div class="wrap" style="max-width:768px">`,
|
|
`<h1>` `$page->getTitle()` (same h1 style as the article page), the existing
|
|
`prose prose-brand` block with the class `site-prose` added and its card styling replaced by
|
|
white background, radius 16px, `--shadow-1`, padding 40px (24px ≤760px); the existing
|
|
"last updated" line as muted .85rem text. Keep the `clean()` call and the
|
|
`pages.content_coming_soon` fallback unchanged.
|
|
- `resources/views/pages/terms.blade.php` and `resources/views/pages/privacy.blade.php` — the same
|
|
structure with their existing title and placeholder text. (`/terms` and `/privacy` redirect to
|
|
`/page/terms` and `/page/privacy`; these two views are kept in case they are rendered
|
|
directly.)
|
|
|
|
### Language keys
|
|
|
|
None new; `site.hero_eyebrow` (24-4) and `site.nav_articles` (24-2) are reused.
|
|
|
|
### Files
|
|
|
|
- Modify: `resources/views/livewire/pages/posts/index.blade.php`,
|
|
`resources/views/livewire/pages/posts/show.blade.php`, `resources/views/pages/legal.blade.php`,
|
|
`resources/views/pages/terms.blade.php`, `resources/views/pages/privacy.blade.php`,
|
|
`resources/css/public.css`.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] `/posts` shows the section head, a working search (typing filters results after the
|
|
debounce and shows the count line), text-only post cards and styled pagination when there
|
|
are more than 10 published posts.
|
|
- [ ] `/posts/{post}` for a published post shows date, a display-font `<h1>`, the body and a Back
|
|
button to `/posts`; an unpublished post still returns 404.
|
|
- [ ] `/page/terms` and `/page/privacy` show the title, the sanitised CMS content (or the
|
|
coming-soon text) and the last-updated line.
|
|
- [ ] Each of these pages has exactly one `<h1>` and no horizontal scroll at 1440, 768 and 390px.
|
|
- [ ] The admin posts screens (`/admin/posts`) are unchanged (they do not use the public layout).
|
|
|
|
## Sub-tasks
|
|
|
|
None.
|