Repository navigation
Design review: Activity and News pages #266
Copy link
Copy link
Closed
Labels
Description
Part of #271 (Phase 2).
#265 splits the site's updates into two streams. News carries announcements people write: new projects, grants, people and workshops. Activity is a new page for library releases and lecture updates, generated by the reporter bot. The Activity page ships with interim styling, and the News page hasn't changed since the #194 redesign, even though it now carries far fewer posts. This issue tracks a design pass over both pages, done with Claude Design and then implemented here.
Gate: the design work starts once John approves the stream definitions in #265, so the design is built on settled rules.
How this issue works
This issue is the home of the design review for both pages.
- Briefs: each round's Claude Design brief is posted as a comment: round 1 and round 2.
- Outputs: each round's results (links to the Claude Design artifacts and screenshots) are posted as comments, along with the discussion.
- Decisions: decisions go in the table below, so the outcome can be read without the thread.
- Implementation: the build is tracked in News and Activity: announcements on News and a self-updating Activity feed #271; this issue closes when the design review is complete.
Decisions
| Decision | Choice | Why | Date |
|---|---|---|---|
| Stream definitions (what goes in News and in Activity) | Pending formal approval. On #265 John is "happy with the arrangement above, as long as something gets posted regularly and we don't have to do much work!" | ||
How Activity appears on /news/ |
Option A: a side rail, with News two-thirds and Activity one-third | It keeps announcements first on every screen size and shows at a glance that the project is active. It's less busy and cheaper than the integrated timeline (Option B), which is parked for team discussion in #268. See the round 1 outcome. | 2026-09-28 |
| Home page "Latest News" | c1: the three news cards plus a compact "Latest activity" strip | It keeps the headlines, and the strip shows the section is current. The activity-chart idea (c3) is parked. | 2026-09-28 |
| Where Activity sits in the navigation | Part of News: no menu item of its own, and the News item is highlighted on /news/ and /activity/. It's reached from the rail and its mobile panel, the home strip and the footer |
The designer's recommendation. Activity is presented as part of News, so it belongs there rather than under Projects. Done in #265 (318ad25). | 2026-09-28 |
| Date format | "Sep 27" in activity rows, week headings and the mobile panel; "Sep 27, 2026" on news cards; ranges "Sep 21–27", "Jul 27 – Aug 2", "Dec 28, 2026 – Jan 3, 2027"; always in a <time> element, never relative |
Short dates inside dated groups, the year where a card stands alone, and a static build can't keep "this week" true. Round 2 handoff. | 2026-09-29 |
| Rail layout | At 1200px and wider, a rail in the right-hand third: the latest 6 rows under Monday–Sunday week headings, filtered by type (All, Releases, Lectures, Translations, and Books since the book type in #284). Below 1200px, a collapsed panel above the news cards |
At 1024px a one-third rail is only 296px wide. Fixed week ranges stay correct in a static build. | 2026-09-29 |
| Rail panel height | The tinted panel runs the full height of the news column, and only its list is sticky (sticking by its bottom edge when it's taller than the screen). A small "Activity" label sits inside the sticky part | The product owner's choice, judged on #291's preview and kept when it merged. The fallback was a transparent column with the tint on the sticky box only. | 2026-09-29, confirmed 2026-09-30 |
| Rail details, from #291's preview | Below 576px the filter's gaps are 10px, so all five buttons fit on one line from 390px. At 1200–1239px the site's back-to-top button can cover the end of "View all activity" while the list is stuck; accepted. While keyboard focus is in the list, the list scrolls with the page instead of sticking. Books stays in the filter while there are no book rows, showing a dashed "No book updates yet" box rather than being hidden | Judged on the preview. The last keeps a focused row from staying off-screen in a stuck list. | 2026-09-30 |
Page head on /news/ |
No intro line under the News h1. Below 1200px, the collapsed Activity panel carries a short second line, e.g. "Library releases and lecture updates, from GitHub" | A cleaner page head (product owner), with the small-screen case still explained. | 2026-09-29 |
| Count line in the rail | None | It would add a second count (entries, not rows) and a date comparison that can break the build (product owner). | 2026-09-29 |
| Home strip form | One compact line at 1200px and wider, with the type label (language, editions, "same day") kept outside the truncated title and items sized to their content; a stacked list below 1200px; "View all activity →" | Keeps the compact look while never cutting a translation's language or a group's label. | 2026-09-29 |
| Row rules | Same-day releases merge into one row, as do same-day editions of a translated series and same-day entries for the same series. Within a day: lecture updates, then translations, then releases, A–Z by project | The rows come out the same whatever order the data files are in. Lecture sites often publish twice a day (10 times across 5 sites since June). | 2026-09-29 |
| Where rows are computed | A Jekyll plugin over _data/activity/*.yml, ported from the handoff's activity-data.js and tested in CI |
The rules need regexes and keyed merges that Liquid can't do reliably. | 2026-09-29 |
| Accessibility fixes | workshop #4a7c3c, books #b83d4b and NEW #d0344f pills; #666 meta text; a #64748b card chevron; a visible news-card focus ring; reduced motion |
Each failed WCAG AA or was invisible. In #269. | 2026-09-29 |
| Activity RSS feed | Yes: a second feed at /activity/feed.xml for Activity entries, linked from the rail. /feed.xml stays News-only |
One subscription covering every library release and lecture update. GitHub only has per-repository release feeds, and nothing friendly for lecture updates. It's built from the same data, so there's nothing to maintain. | 2026-09-29 |
| How often Activity updates | Daily. The reporter opens one PR a day with that day's entries (none on a quiet day), and it merges itself once the data check passes | A fresh feed with no review work. Daily PRs that each needed a human merge would bring back the pile-up of drafts. Needs a branch-protection bypass for the reporter App (QuantEcon/reports-activity#91). | 2026-09-29 |
Plan
- Round 1: layouts. Claude Design produced layout directions for
/activity/,/news/and the home page from the round 1 brief. See the round 1 outcome. - Pick a direction, and record it in the Decisions table: Option A on
/news/, and c1 on the home page. - Round 2: Option A + c1 handoff. A build-ready handoff for the rail and the home strip, including the points listed in the round 1 outcome. It should cover entry variants, hover and focus states, filter states, the empty state and the mobile panel. The brief is in the thread; see the round 2 outcome.
- Sign-off (2026-09-29): design complete; the build is tracked in News and Activity: announcements on News and a self-updating Activity feed #271.
Activity page: questions to settle
| Question | Notes |
|---|---|
| Grouping | By month (the interim page) or by week? Should same-day releases collapse into one row? |
| Filtering | By type (releases, lectures, translations) and by project. Where do the filters sit, and what does an empty result show? This must work with the keyboard and in plain JavaScript. |
| Detail | Should the pull-request links behind a lecture entry be shown, collapsed or hidden? The summary should read first. |
| Scale | About 2–3 entries a week today, expected to reach 6–7 a week once the reporter is fixed, with some lecture entries carrying 10 or more changes. The page must stay usable with hundreds of entries: archive, "show more" or a jump list? |
| Type markers | The interim lectures pill uses the Python-badge blue, and release uses the Julia-badge purple. Pick markers that don't collide, within the single-accent principle below. |
| RSS | Should Activity have its own feed? |
News page: questions to settle
| Question | Notes |
|---|---|
| Format | With about one post a month, do the inline expand/collapse cards and the year accordion still fit, or should the page move to cards that link to full posts? |
| Tag pills | workshop (#6EAC5B, 2.72:1), books (#D25663, 4.00:1) and new (#e94560, 3.83:1) fail WCAG AA with white text. |
| Meta text | Dates and meta use #888 (3.54:1) and #999 (2.85:1), which fail AA at their sizes. Activity already uses #666. |
| Pointer to Activity | #265 adds a one-line pointer at the top of /news/. Is that enough, or does it need a stronger treatment? |
Across both pages
- Navigation: where Activity lives. Decided: part of News, with no menu item of its own (see Decisions).
- Home page: (decided: the c1 strip; see Decisions) should "Latest News" gain a compact "Recent activity" module? The stream definitions in Split updates into News and an Activity feed #265 cover only what each stream contains, so where Activity appears is decided here.
- Date format: one format across the site (decided for these pages; see Decisions). Today there are four:
- "15 Jul 2026" on the home page;
- "Jul 15, 2026" on the News cards;
- "July 15, 2026" on posts;
- "Jul 15" in the archive.
- Accessibility: WCAG AA contrast throughout, visible focus outlines, and real buttons for filters.
- Keep the principles from the About redesign (Redesign About page (Design 1E) in the QuantEcon brand #234):
- the real site chrome;
- at most one multi-colour moment per page;
- a single brand-blue accent otherwise;
- soft blue-tinted surfaces rather than heavy dark blocks.
Related
- Split updates into News and an Activity feed #265: the News/Activity split, the definitions and the interim Activity page.
- NEWS: move to a single weekly news post to reduce noise + only report changes to lectures and major software (QuantEcon.py, mystmd etc.) #225: the original discussion about reducing news noise.
- [news] page design updates #138: earlier News tagging work.
- Redesign and modernise quantecon.org #194: the site redesign that introduced the current News page.
- Redesign About page (Design 1E) in the QuantEcon brand #234: the About page redesign, the source of the design principles above.
- QuantEcon/reports-activity#91: the reporter changes that will feed Activity (private repository).
Reactions are currently unavailable
Activity
mmcky commentedon Sep 28, 2026
Round 1 brief: Activity page layouts
This is the prompt for round 1: three layout directions for
/activity/, each on a desktop and a mobile artboard. It was written against the Activity data in #265 as of 2026-09-28 (40 entries). If Activity has grown by the time the round starts, refresh the data section at the end first.To use it: copy the prompt below into Claude Design and attach two screenshots taken at 1440px wide. The brief refers to them by these filenames:
screenshot-news-1440.pngscreenshot-activity-interim-1440.pngThe round's outputs, the chosen direction and the round 2 brief will follow in this thread.
Claude Design prompt, round 1 (expand, then use the copy button)
mmcky commentedon Sep 28, 2026
One idea I have is to combine the News and Activity Pages.
Make News the hero on the LHS with 2/3 of the page and then Activity stream on the RHS with 1/3 of the page
mmcky commentedon Sep 28, 2026
Round 1 outcome
Decision:
/news/: Option A, a side rail. News keeps the main column (two-thirds of the page), and a sticky Activity rail (one-third) shows the latest entries and links to the full log.Why Option A: it keeps announcements first on every screen size, which is the reason for the News/Activity split. It also shows at a glance that the project is active, which was John's aim in #265. It's less busy than the integrated timeline, cheaper to build, and stays the same size as the log grows.
Claude Design's handoff specified Option B and c1. Before building, the handoff was reviewed against the real data and the repo:
To carry into the Option A handoff and build
Data and grouping:
The data lives in
_data/activity/*.yml, not_data/activity.yml. Merge the files in filename order, then sort whole days rather than entries, as_layouts/activity.htmldoes. Liquid'ssortisn't stable and reorders entries within a day.If anything compares an activity date with a post date, compare
YYYY-MM-DDstrings. One example is a rail header such as "N updates since ". A direct comparison stops the Jekyll build ("comparison of Date with Time failed"). Post dates are local to the site, and activity dates are UTC days.Compute the grouped rows in a small Jekyll plugin (
_plugins/), tested in CI, rather than in Liquid.jekyll build, so plugins work in both.Group by key rather than by adjacency:
With adjacency, a second Jul 26 release reported in a later file would land after that day's lecture entry and not group with the first release.
Drop the "exclude posts tagged
software" rule. Split updates into News and an Activity feed #265 already removes those posts.Add two checks to
.github/scripts/check-activity-data.rbin Split updates into News and an Activity feed #265:translationentry'sprojectmust end in(Language);The rows take the language from the first and print
#Nfrom the second.Page:
section { overflow: hidden }rule prevents it. Useoverflow: clipscoped to the News page, as team: add Translators section and section navigation #264 (still open) does for the Team page's contents column.Accessibility:
.news-card { overflow: hidden }clips the outline. Include the change in the/news/rail PR.workshop(2.72:1) andbooks(4.00:1) pills fail WCAG AA and appear on most visible cards.#4a7c3c(4.95:1) and#b83d4b(5.52:1) pass.#666for meta text instead of#888/#999.Home strip (c1):
Consistency:
/activity/: switch it to the same row design as the rail and the strip, so an entry looks the same everywhere.Navigation: the designer recommends taking Activity out of Projects ▾ and treating
/activity/as part of News./activity/from/news/and the footer.This is still to decide (see the Decisions table). If adopted, it's about a three-line change in
_layouts/default.html, best made in Split updates into News and an Activity feed #265 before it merges.Missing from the handoff: the
future_idea_c3/folder (the parked activity-chart idea) that its README refers to.Next
/activity/switched to it;/news/rail;activity: treat /activity/ as part of News in the nav; tighten data c…
mmcky commentedon Sep 28, 2026
Round 2 brief: Option A and c1 handoff
This is the prompt for round 2: a build-ready handoff for the decisions recorded above.
/news/: Option A, the side rail./activity/: restyled with the same row design.It builds in the corrections from the round 1 outcome and the navigation decision. It also adds acceptance checks and a priority order, in case the round runs short.
It uses the same data as round 1: 40 Activity entries as of 2026-09-28, plus the 8 newest News posts. If Activity has grown by the time the round starts, refresh the data section at the end first.
To use it: copy the prompt below into Claude Design. If you start a fresh Claude Design session rather than continuing round 1, attach the round-1 artboards for Option A and c1 from the round-1 design sheet. The Option A screenshot is also in #268.
The round's outputs, and any decisions they lead to, will follow in this thread.
Claude Design prompt, round 2 (expand, then use the copy button)
mmcky commentedon Sep 28, 2026
Round 2 outcome
Claude Design delivered the round-2 handoff: the Option A rail on
/news/, the c1 strip on the home page, and/activity/restyled. It was reviewed against the real data and the repo in four independent passes:Verdict: build-ready, with the decisions and fixes below.
overflow: clipfix and the phone fold check on the real site.The handoff's
README.mdis the spec. Where the design sheet's notes disagree with it, the README wins. The decisions below amend it. The README is included at the end of this comment for the record.Decisions (also in the table above)
Home strip:
Explaining
/news/below 1200px: the collapsed Activity panel gets a short second line, e.g. "Library releases and lecture updates, from GitHub". The desktop page head stays clean, with no intro line.Full-height rail panel: build it as designed and judge it on the Netlify preview with all 20 cards. If it looks empty, the fallback is a transparent tall column with the tint on the sticky box only. Either way, add a small "Activity" label inside the sticky part, because the heading scrolls away.
Same-day duplicates: lecture sites often publish twice on one day (10 times across 5 sites since June 1). So:
The reporter will also emit one entry per series per day (noted on QuantEcon/reports-activity#91).
NEWbadge: darkened to#d0344f(4.90:1), along with theworkshopandbookspills, in Fix tag-pill contrast and make the news-card focus ring visible #269.Recorded product-owner changes in the handoff:
Activity RSS feed: still open.
Implementation fixes (no design change)
/activity/, so the/activity/restyle ships before them or with them.scroll-padding-topto/news/as well as/activity/. Otherwise keyboard focus can land under the fixed header while the rail is stuck (WCAG 2.2 SC 2.4.11).hidden, or they're unreachable without JavaScript.main.js:sessionStorageaccess, which can throw and stop everything after it;h2before the news list, so screen readers don't file the posts under "Activity";<aside>, lists), not the prototypes'<div>s;outline: none.Build plan
NEWbadge contrast, the news-card meta greys, a visible news-card focus ring, and reduced motion. It doesn't depend on Split updates into News and an Activity feed #265./activity/restyled with the shared rows, filters and day anchors./news/rail and mobile panel.B to F wait for #265 to merge.
Also
activity-data.js) are in the local handoff bundle. The README follows.Round 2 handoff README (the spec as delivered; amended by the decisions above)
Handoff, round 2:
/news/Option A (side rail), home c1 strip, and the/activity/restyleRelated: #266. Everything here describes the site after PR #265 merges.
Status: everything in the brief is included
All six priorities are drawn in
reference/News and Activity R2.dc.html:/news/at 1440 and 390px, with the panel collapsed and expanded./activity/at 1440 and 390px./news/at 1280 and 1024px, and the home page at 1280px.Changes the product owner asked for during this round (these override the brief)
/news/intro link to/activity/goes away. Readers still reach it from the rail, the panel, the home strip and the footer.countSinceand the timezone note that went with it.Parked, and not in this handoff
parked/future_idea_c3/. Don't build it.Files
reference/News and Activity R2.dc.htmlreference/together). Sections 1–5 match the priorities above.reference/NewsPage.dc.html/news/. Opened directly, it responds to the window width.?live=1turns on the sticky header and the rail, as the sheet's live 1280×720 and 390×844 viewports do.reference/HomeNews.dc.html,reference/ActivityLog.dc.html/activity/.reference/ActivityRail.dc.html,reference/ActivityRow.dc.htmlreference/activity-data.jsbuildRows,week,range,railRows,byWeek,byMonth,panelSummary. Port these to the Jekyll plugin; they are the executable form of the rules below.The reference files are HTML prototypes (inline styles, a small runtime). Recreate them in the site's stack: Jekyll, Bootstrap 5.2,
assets/main.scss, Bootstrap Icons 1.11.3 and a little vanilla JS. Fidelity is high: the colours, type, spacing and behaviour are final.1. Data and the shared row rules (every page)
Source
_data/activity/*.yml: one file per bot run per stream, e.g.2026-09-24-software.yml.softwarestream holds releases. Thelecturesstream holds lecture and translation updates.datecan be months earlier than its file's date;site.data.activity_rows, plus the grouped views below). Don't add a group key to the bot's output.date(a UTC calendar day,YYYY-MM-DD),type(release|lectures|translation),project,url, and optionallyversion,summaryandchanges: [{title, url}].Rows: merge by key, never by position
releaseentries with the samedateform one row.translationentries with the samedateand the same series form one row.projectwith its trailing(Language)removed. Parse it with/^(.*) \(([^)]+)\)$/: group 1 is the series, group 2 the language.Order
project, ignoring case (localeCompare(…, {sensitivity:'base'})).Row fields
project+version(the version at weight 400)urlprojecturl(the live lecture site)Simplified Chineseurl(the translated site)4 releases · same day/activity/#activity-YYYY-MM-DD3 editions(the count of unique languages; "1 edition" in the singular)/activity/#activity-YYYY-MM-DDEvery row also has a type word that is visually hidden:
Release:,Lecture update:,Translation:, orReleases:/Translations:for merged rows. The icons (bi-box-seam,bi-journal-text,bi-translate) arearia-hidden="true".Merged translations
urlof its entries.Dates
Formats:
%b %-d%b %-d, %YRules:
<time datetime>:YYYY-MM-DD;<time datetime="2026-W39">Sep 21–27</time>. Use Ruby'sDate#cwyear/#cweek: Dec 28, 2026 – Jan 3, 2027 is2026-W53.YYYY-MM-DDstrings. Never compare a post'sTime(Australia/Sydney) with an activityDate: that stops the build.Summaries are plain text, except that single backticks become
<code>. PR titles are plain text.2.
/news/: Option ALayout
xl).flex-wrap: wrap; column-gap: 18px), and each button keeps its own 2px underline..container:display:grid; grid-template-columns:minmax(0,2fr) minmax(0,1fr); column-gap:3rem— 832 + 416px at 1440, 712 + 356px at 1280;margin-bottom:2rem) and the grid.<aside class="activity-rail" aria-labelledby="activity-rail-title">comes before the news list in the HTML.grid-column:2; grid-row:1, and the news goes ingrid-column:1; grid-row:1.section.inner-pageneedsoverflow: clipon this page. The site-widesection { overflow: hidden }breaksposition: sticky.Rail, 1200px and wider
h2#activity-rail-title"Activity": Exo 2, 400, 1.4rem,#283039;#666, margin-top 6px;#e2e8f0bottom border.#f8f9fc,1px solid #e2e8f0border, 8px radius and margin-top 16px;flex: 1 0 autoin a full-height flex column);.05emletter-spacing,#666, margin0 0 12px(20px above every heading after the first).#e2e8f0line (the group hasmargin-left:5px; border-left:2px solid #e2e8f0), and each row haspadding:0 0 16px 18px.#0072bc, with a 2px border in the surface colour andbox-shadow:0 0 0 2px #e2e8f0, positionedleft:-7px; top:3px, andaria-hidden.#666, gap 6px. It holds the icon, the hidden type word, the date, and· tagwhen there is one.#283039, clamped to 2 lines, margin-top 3px. The version is weight 400,#444. Hover:#174867, underlined.#444, clamped to 2 lines (-webkit-line-clamp:2). Inline code is 12.5px monospace on#fff, with a#e2e8f0border.#0072bc, 6px radius, 15.2px bold,.6rem 1rempadding, margin-top 8px). Hover: filled#0072bcwith white text.bi-rss(14px bold, margin-top 12px), pointing to/activity/feed.xml. Omit it if the feed isn't added.Filters
Markup and states:
<div role="group" aria-label="Filter activity by type">containing four<button type="button" aria-pressed>: All, Releases, Lectures, Translations.#0072bc.#174867, with the existing.content-filtersgrow-in underline (0.3s).#444, with a 2px#444bar on the group's bottom border.:focus-visible:2px solid #0072bc, offset 2px.What each filter shows:
1px dashed #cbd5e1, 8px radius, centred 14.4px#444): "No releases yet", "No lecture updates yet" or "No translation updates yet".Markup to render:
data-typeand, if it is among the newest 6 overall,data-all.hiddenon the rows that don't match and on week groups that have no visible rows.hiddenin the HTML. Hide the filter group withhtml:not(.js) .activity-filters{display:none}.Behaviour:
aria-live="polite"paragraph announces the result:Sticky behaviour
top: min(var(--rail-top), calc(100vh - var(--rail-h) - 24px)), where:--rail-topiscalc(84px + var(--sponsor-bar-height, 0px) + 24px);--rail-his the wrapper's height, set by aResizeObserver(it changes on filter change, font load and resize).topmakes it scroll with the page until its bottom is 24px above the viewport's bottom, and it sticks there. "View all activity" can always be reached, and nothing is cut off. No inner scrollbar.html.js. Without JS the wrapper is static.At 1280 the heights are about 10–15% more, because text wraps sooner.
Mobile panel, below 1200px
#eef4fb, with a1px solid #dbe8f5border and 8px radius. It sits directly under the h1, with 20px before the first card.<h2><button aria-expanded aria-controls></button></h2>, full width, min-height 60px, padding12px 16px, laid out as a grid:bi-activity(20px,#0072bc), then the label, then a chevron (#444).#e3edf8. Text on it is only#283039and#444, never blue.#444);#444, the timeline line and dot ring in#dbe8f5, and the dot border in#eef4fb;document.documentElement.classList.add('js')in<head>, and use.js .activity-panel:not(.is-open) .activity-panel__body{display:none}.<h2>Activity</h2>, and show the body expanded.<aside>serves both modes. CSS shows either the rail head's h2 (1200px and wider) or the toggle (below 1200px, with JS).display:nonekeeps the hidden one out of the accessibility tree.News cards (
.news-card)#888to#666;#aaato#64748b..news-card:has(> .news-card-header:focus-visible){outline:2px solid #0072bc;outline-offset:2px}plus.news-card-header:focus-visible{outline:none}.:hasisn't supported (@supports not selector(:has(*))): an inset ring on the header,outline:2px solid #0072bc; outline-offset:-4px.workshop:#6EAC5B(2.72:1) →#4a7c3c(4.95:1);books:#D25663(4.00:1) →#b83d4b(5.52:1).3. Home "Latest News" with the c1 strip (
_layouts/home.html,#news)%b %-d, %Y) in#666;.qe-card, badge, excerpt truncated to 25 words, hover lift.display:flex; align-items:center; gap:20px; min-height:48px; padding:0 18px, background#f8f9fc,1px solid #e2e8f0border, 8px radius, 14px text;<h3>"Latest activity": 12px, 700, uppercase,.06emletter-spacing,#666, with a 14pxbi-activityicon in#0072bc,flex:none;<ul>of the three newest rows (display:flex; flex:1 1 auto; min-width:0). Each<li>takes an equal share (flex:1 1 0; min-width:0), haspadding:0 20pxand a1px solid #e2e8f0left divider, and is one link:#0072bc), the hidden type word, the date (13px,#666), then the bold title (#283039);nowrapand an ellipsis, so the strip never wraps, and the full text sits intitle;#174867, underlined.#0072bc,margin-left:auto), linking to/activity/./activity/.14px 16px 0;<ul>. Each<li>has padding8px 0and a1px solid #dbe8f5top border, and its whole item is one link with min-height 44px. The icons stay.4.
/activity/: the full log, restyledmax-width: 880px.<section id="activity-YYYY-MM" aria-labelledby>, margin-top 36px (28px below 576px);<h2>"September 2026": Exo 2, 1.4rem,#283039, padding-bottom 10px,1px solid #e2e8f0bottom border;<ol>of<li id="activity-YYYY-MM-DD">, each wrapping an<ol>of that day's rows.18px 0 20px, with a1px solid #edf0f5bottom border;#666: icon (#0072bc), hidden type word, date,· tag;#283039.url.#94a3b8.#444, max-width 760px.1px solid #e2e8f0, 6px radius,4px 10pxpadding, 14px bold#0072bc.#f3f5fabackground,#174867text.bi-github(#666), then an underlined PR-title link, then#1070in#666.<button aria-expanded aria-controls>readingbi-github+ "3 changes" + chevron (14px, bold,#0072bc; mobile min-height 44px), followed by<ul hidden>.2px solid #e2e8f0left border and 14px left padding. Each item is an underlined link, then#num.html{scroll-padding-top:calc(84px + var(--sponsor-bar-height,0px) + 16px)};hashchange, if the hash matches#activity-\d{4}-\d{2}, reset the filter to All before scrolling;/activity/#activity-2026-08-02lands on the Aug 2 row ("4 releases · same day").#666, margin-top 40px).5. Accessibility, first paint and motion
Contrast:
#666or darker: 5.74:1 on white, 5.45:1 on#f8f9fc.#0072bcis used only on#fff,#f8f9fcand#eef4fb(4.59:1). It is never used on#e3edf8or#dbe8f5; use#174867for text on hover surfaces.Controls:
2px solid #0072bc, offset 2px, on every control. News cards get theirs via:has(see section 2).Markup:
aria-hidden.<ol>); week headings are<h3>; month headings are<h2>.First paint and motion:
jsclass in<head>before first paint, and render everything that's collapsed by default already collapsed.@media (prefers-reduced-motion: reduce)removes the tab-underline, button and card-lift transitions.6. Tokens
#0072bc· hover#174867#283039· body#444· meta#666#f8f9fc· soft blue#eef4fb(border#dbe8f5, hover#e3edf8) · hover tint#f3f5fa#e2e8f0· divider#edf0f5· dashed and inline-link underline#cbd5e1/#94a3b8#4a7c3c· books#b83d4b· lectures#306998· tools#FCC837on#333.qe-cardhover0 4px 12px rgba(0,0,0,.08)with a 2px lift ·.news-cardhover0 2px 8px rgba(0,0,0,.06), no lift--sponsor-bar-height7. Acceptance checks
/news/./news/, the home page or/activity/./activity/#activity-2026-08-02lands on Aug 2 ("4 releases · same day") below the header and sponsor bar, with the filter reset to All.a11y: fix tag-pill contrast and make the news-card focus ring visible (…
mmcky commentedon Sep 29, 2026
The design review is complete: both Claude Design rounds are recorded here, and every decision is in the Decisions table above. The build continues in #271, where this issue is the Phase 2 item.
Split updates into News and an Activity feed (#265)