Skip to content

The board page wears the band the games do, and the strip shows the whole photograph #970

Description

@ExtraToast

Parent

#922

Problem Statement

The board page was rebuilt as an island page, and it came out wrong.

The seats were given a component of their own: a vertical stack of rows, 481 lines, sharing nothing with the band the esports pages are drawn in. The association already has a way of showing a set of things it is proud of, and the board page did not use it. It read as a table of people rather than as the same site.

The group photograph was worse. The band ran edge to edge at a fixed short height, so the picture was made to cover the full width of the window. A window 2560 across asked for 2560 pixels of a photograph that has 1000, and the smallest board was drawn at two and a half times its size. The band was a 5.9:1 letterbox fed by pictures that are 1.13:1 to 1.57:1, so a quarter of each photograph was shown and the rest was cropped away. Six people posed for a picture and the page showed a strip across their chests, upscaled.

Around it, smaller faults. The board's name, year, cheer and description sat under the band as a separate block, so the caption was nowhere near the picture it captioned. The picture was cut on a diagonal that suited a band and not a photograph. The header explained how to operate the page rather than saying what a board is. The closing band invited the reader to stand in an election that does not exist, and offered membership as the way onto a board, which is not how it works.

Solution

The board page wears the band the games do, and the strip shows the whole photograph.

The band is the same component. What was the esports banner band becomes the island's slice band, and it takes a layout: one for a game, where the art fills the slice, and one for a person, where a face holds the left of the slice at its own width. Hover, the share of the row an open slice takes, the behaviour on a phone and the widths a picture is fetched at are the same code either way, because they are the same question whatever the art is of.

A member's slice reads as a person. The portrait stands full height on the left. Their name, their nickname and what they were sit on the picture, over a scrim, whether the slice is open or shut. Opening the slice does not rearrange that: what the slice grows is somewhere to the right for the blurb to be read, on a fade of the island's own ground, so prose is read on a flat surface rather than across somebody's face.

Only a member who wrote something can be opened. Half the board members wrote no blurb at all and four whole boards wrote none between them. A slice that grows to reveal an empty panel is worse than one that never offered, so a member with nothing behind them does not open. Where nobody on a board wrote anything, nothing in the band moves at all: it is a row of faces, and it does not pretend otherwise.

The strip keeps the width and the picture stops covering it. The photograph is given the strip's full height and whatever width its own proportions ask for. It is about 57% of the window across at any size, and it is never asked for more pixels than it has: the worst board goes from two and a half times its size to under it. Nothing is cropped. The picture dissolves at the edge the colour comes from rather than stopping at a line, and there is no diagonal across it.

The board's own colour carries the page. The name, the year, the cheer and the description move into the strip, beside the picture, on a wash of the board's colour that fades in over the picture's right edge. A second, slighter wash comes in from the top left and falls away toward the bottom right, so the picture is lit from a corner rather than washed flat. The wash is a tint and not a fill: the page's ground shows through it, and it is drawn with the same tokens the timeline lights its bands with, so the two cannot drift apart.

The words say what a board is. The header describes the thing rather than the page. The closing band drops the election, because there is not one: anybody in the association can ask, there is no season to wait for and nothing to join first.

User Stories

A visitor reading a board

  1. As a visitor, I want the board page to look like the rest of the site, so that I do not wonder whether I have left it.
  2. As a visitor, I want the group photograph shown whole, so that I can see the board rather than a strip taken out of the middle of it.
  3. As a visitor, I want the photograph drawn sharp, so that six people who posed for a picture are not shown to me upscaled.
  4. As a visitor, I want the photograph big enough to make out faces, so that the strip does not read as a line with a stamp at one end.
  5. As a visitor on a wide display, I want the photograph to stay sharp there too, so that the better my screen the worse it does not get.
  6. As a visitor, I want the picture to dissolve into the colour beside it, so that the two do not meet at a hard line.
  7. As a visitor, I want no diagonal cut across the photograph, so that a picture of people is not sliced like a banner.
  8. As a visitor, I want the board's name, year, cheer and description beside the photograph, so that the caption is next to the thing it captions.
  9. As a visitor, I want the board number and year set large enough to read at a glance, so that I know which board I am looking at without hunting.
  10. As a visitor, I want the whole page tinted in the board's own colour, so that moving through the history feels like moving between boards.
  11. As a visitor, I want the colour to be a tint rather than a slab, so that the page still looks like the site underneath.
  12. As a visitor, I want the light on the photograph to come from a corner, so that the picture has some depth rather than a flat wash over it.
  13. As a visitor, I want each board member shown as a face, so that a board is people and not rows.
  14. As a visitor, I want a member's portrait shown full height, so that I see them rather than a thumbnail.
  15. As a visitor, I want nobody's forehead cut off, so that a portrait is a portrait.
  16. As a visitor, I want a member's name, nickname and role on their picture, so that I can tell who is who before I touch anything.
  17. As a visitor, I want a member's slice to grow when I hover it, so that reading about them is one movement.
  18. As a visitor, I want the name to stay on the picture when the slice opens, so that nothing I was reading jumps somewhere else.
  19. As a visitor, I want the blurb to appear to the right of the picture, so that I am reading prose on a flat surface.
  20. As a visitor, I want the blurb to fit inside the slice, so that no line of it is cut off.
  21. As a visitor, I want a member who wrote nothing not to open, so that I never grow a panel to find it empty.
  22. As a visitor reading a board where nobody wrote anything, I want nothing to move at all, so that the page does not offer me something it does not have.
  23. As a visitor, I want the nickname shown the way the history published it, so that the name reads as it always has.
  24. As a visitor on a phone, I want the strip and the faces to stack, so that the history is readable on the device I am holding.
  25. As a visitor on a phone, I want the picture to fade downwards into the words under it, so that the join works when the layout turns.
  26. As a visitor in light mode, I want a pale board colour to still be readable, so that a board's own choice does not cost me the words.
  27. As a visitor in dark mode, I want a deep board colour to still be readable, so that the same holds the other way.
  28. As a visitor who has asked for reduced motion, I want nothing to animate, so that reading a history does not make me unwell.
  29. As a visitor, I want a board with no photograph to still occupy the strip properly, so that half the history does not look broken.
  30. As a visitor, I want the page to tell me what a board is, so that I learn something rather than being told how to scroll.
  31. As a visitor, I want to be told plainly how to get onto a board, so that I am not waiting for an election that does not happen.
  32. As a visitor, I want not to be told to become a member first, so that I am not sent somewhere that has nothing to do with it.

A board member editing

  1. As a board member, I want the pencil and the plus to keep working on the new band, so that the restyle does not cost me the editor.
  2. As a board member, I want the way in to sit at the end of the band, so that adding somebody is where adding things has always been.
  3. As a board member, I want a visitor to see none of the affordances, so that the page reads as a page.
  4. As a board member, I want a member with no blurb still to be editable, so that not opening is about reading and not about editing.

A maintainer

  1. As a maintainer, I want one band component rather than two, so that hover, growth, the phone case and the picture widths cannot drift apart.
  2. As a maintainer, I want the band's name to stop claiming the art is a banner, so that the name is not a lie for half its callers.
  3. As a maintainer, I want the bespoke row component gone, so that there is not a second way to draw a list of people.
  4. As a maintainer, I want the washes drawn with the island's own tokens, so that the boards and the timeline are lit by one decision.
  5. As a maintainer, I want the esports pages provably unchanged, so that generalising the band is not a change to games.
  6. As a maintainer, I want nothing under the shared components importing a domain, so that the boundary the island was moved for holds.
  7. As a maintainer, I want the reason a picture is sized the way it is written down, so that the next person does not reinstate full-bleed and the upscaling with it.
  8. As a maintainer, I want board members called members, so that the frontend, the api and the glossary use one word.

Implementation Decisions

The band becomes the island's, with two layouts

The esports banner band is renamed to the island's slice band and gains a layout choice. One layout is a game's, where the art covers the slice and the words sit on it. The other is a person's, where the picture holds the left of the slice at its own width and the words are arranged around it. Everything else, the hover, the share of the row an open slice takes, the scroll-driven behaviour where there is no pointer, the arithmetic that decides how wide a copy of a picture to fetch, is shared and unbranched.

The rename reaches the two esports pages and the band's own unit test. The band's internal class names are deliberately left alone: nine end-to-end specs select on them, and those specs are the evidence that the esports pages did not change. Renaming the evidence to match a refactor defeats the point of having it. This is recorded rather than fixed.

The bespoke row component built for the seats, and its unit test, are deleted.

A slice may decline to open

An item in the band gains a say in whether it opens onto anything. Absent, it opens, so a game is unaffected. A board member is expandable only where they wrote a blurb.

One place in the band decides this, and every route to opening a slice goes through it: a pointer arriving, focus arriving, a click, the slice the band settles on when it first draws, and the slice named from outside after something is added. Where no item in the band can open, the band settles on nothing and no slice grows, which is what makes a board where nobody wrote anything sit still rather than animate into an empty panel.

A member's slice

The portrait is drawn at full height and its own width, so it is never cropped to fit a box, and it is anchored so that a head is never cut off the top. It dissolves at its right edge into the fade beside it.

The name, the nickname and the role sit at the foot of the picture over a scrim, and stay there when the slice opens. The blurb, when the slice opens, occupies the area to the right of the picture on a fade of the island's ground carrying a little of the board's colour, vertically centred, with the width it actually has rather than the width of the whole slice. The band is taller in this layout than in the game layout, because a face needs height a landscape does not.

The strip

The strip runs the full width of the window. The photograph is given the strip's height and whatever width its proportions ask for, which is the whole of the resolution fix: it is about 57% of the window across at any size and is never asked for more pixels than it has. The height is capped deliberately below the point at which the smallest photograph the association owns would be upscaled, and that reasoning is written where the number is.

Nothing is cropped, and there is no diagonal across the picture. The picture is masked so it fades out at the edge the colour arrives from, because a wash subtle enough to see the ground through is invisible over a dark photograph and the two would otherwise meet at a line however far the colour was pulled back. Stacked, the mask turns and the picture fades downwards into the words instead.

The board's identity moves out of the page and into the strip: number and year as an eyebrow, then the name, the cheer, and the description, beside the picture rather than under it, capped so they do not stretch across a window's worth of colour.

The washes

Two washes on the picture. One comes in from the right, over the picture's edge, and carries the words. One comes in from the top left and falls away toward the bottom right, lighting the picture from a corner. Both are the board's own colour and both are slight.

Every wash is drawn by mixing the accent with transparency using the island's existing band-wash tokens, which are what the timeline lights its bands with and which already differ between the two themes. Nothing paints a raw accent as a fill. This is why the page's ground shows through the colour, and it is why a board's colour cannot look right on the timeline and wrong on the strip.

The accent is a fill and not an ink: what adapts to a pale or a deep board colour is the text drawn on it, by the rule the domain already owns, rather than the colour being moved toward readability.

The words

The header describes what a board is and no longer describes the page. The closing band drops the election and the handover season, and stops offering membership as the route onto a board: anybody in the association can ask. The two ways of asking lead, and nothing is placed in front of them.

No em-dashes in reader-facing copy.

The rename

Board members are members, not seats. The api already says member throughout, in its endpoints, its services and its responses, so this is a correction of a word introduced on the frontend and in the glossary rather than a new convention. It reaches the member dialog, the ordering rule, the domain's public entry, the adapter, the page, the test identifiers, the specs, and the glossary entry.

Whether it lands in this change or its own is a sequencing decision, not a design one. Folding it in means one migration of the end-to-end specs instead of two; keeping it separate means a reviewable design diff and a reviewable rename diff.

Testing Decisions

A good test here asserts what somebody can observe and would notice: which slices can be opened, what moves when a pointer arrives, where the words are, and whether a picture is asked for more pixels than it has. It does not assert a gradient stop, a fade length or a colour mix. Those are being tuned by eye against screenshots, and a test that pins them only ever breaks when they are deliberately retuned, which teaches the next person to delete it.

Two seams, both already in use. No new seam.

Playwright at the board page, api mocked

The highest seam available and the one that carries this change. Prior art: the board specs already in the suite, and the twenty-four esports specs on the same band.

Covers: a member with a blurb opens on hover and a member without one does not move; a board where nobody wrote a blurb animates nothing at all; a member with no blurb is still editable; the name, nickname and role stay over the portrait when a slice opens while the blurb appears to its right; no line of a blurb is cut off; the picture is never served a copy wider than its own source, which is the defect that started this and the one thing about appearance worth pinning; the board's number and year, name, cheer and description are in the strip rather than under it; a board with no photograph still fills the strip; both themes; reduced motion; the stacked layout; and that a visitor sees no affordances.

The picture assertion is worth stating precisely, because it is the regression that would otherwise return silently: read the copy the browser actually fetched and compare it to the source's own width. Note that a browser reports a density-corrected intrinsic width for an image chosen from a width-descriptor source set, so the fetched copy has to be measured off a plain image element rather than the one the band drew. That trap has already been paid for once in this epic.

Unit tests for the rules

The pure rules the page reads a board through are already covered and stay covered: the numeral, the academic year, the ordering of members, the ink that reads on a given fill. The expandability rule is a property of an item rather than a function of its own, so it is asserted at the seam above rather than given a test of its own.

The regression guard on the esports pages

The band is shared, so the proof that generalising it changed nothing about games is the existing esports suite passing unchanged: its end-to-end specs, its unit test on the band, and its system test. This is why the band's internal class names were not renamed.

What is reviewed rather than tested

The two washes, the fade lengths, the mask, the numeral's size and position, and the exact proportion of the picture. These are being iterated on screenshots with the author. When they settle, they settle as CSS with the reasoning written beside the numbers, not as assertions.

Out of Scope

  • Visual regression snapshots. Considered and declined: no suite in this repository has baselines, so it would mean new tooling, committed reference images and a suite that fails on a renderer difference. The appearance is reviewed by eye instead.
  • Computed-style assertions on the washes. Also declined. They assert implementation rather than behaviour, and this is exactly where a known trap lives: the browser serialises a colour mix in a different colour space than it was written in, so a parsed assertion can pass while measuring the wrong numbers.
  • The band's internal class names. They still say team, which is a game's word. Renaming them would break the nine specs that are the evidence the esports pages still work.
  • The board copy itself. Cheers for most boards, descriptions for all of them, and several accents are still to be supplied by the author. The page renders nothing rather than a placeholder where they are blank.
  • Dropping the asset-file-name columns and the frontend's board asset directory. That is the last ticket of the epic and it is blocked on this one only in the sense that both touch the same page.
  • The numeral. Whether the large Roman numeral on the photograph survives at all is an open question with the author: the eyebrow beside it now says the same thing.
  • Anything on the esports pages. They gain a renamed import and nothing else.

Further Notes

  • The measurements that motivated this. At a 2560px window the old strip was 5.93:1. Against it: the smallest board's photograph, 1000x667, was upscaled 2.56 times with 25% of its height shown; the next, 1300x827, 1.97 times with 27% shown; even the largest, 2160x1440, was upscaled 1.19 times. In the island's column with the picture at its own proportions, every one of the five downscales, the worst at 0.67, and between 71% and 99% of each photograph is shown. Taller again, at the height chosen here, the worst case is 0.86.
  • The real data is what makes the expandability rule matter. Twenty-one of the forty-six board members have a portrait; twenty-five do not. Boards one to five recorded no blurbs at all, board six recorded portraits but no blurbs, and only boards seven, eight and nine have both. Four boards have no group photograph. A design that only works on the three complete boards would be wrong for most of the history.
  • Source portraits are 600 across and 814 to 928 tall, so a face is taller than it is wide and the band's height is what decides how wide a portrait comes out.
  • The washes are drawn with tokens the timeline already owns, at 10% and 20% in the dark theme and 17% and 34% in the light one. That is why the colour reads as a highlight rather than a fill, and it is a deliberate coupling rather than a coincidence.
  • A word on how this was arrived at. The first attempt at this page was rejected outright by the author, and every decision above came out of iterating on screenshots with them rather than from a plan. The measurements were taken because the author asked for the resolution to be analysed rather than guessed at, and two of the faults found on the way, a wash painted over its own text and a blurb clipped by a body wider than its slice, were only visible in a rendered page.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentSized and specified for an agent to pick up

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions