Repository navigation
Description
Part of #674. Groundwork, sequenced after #823 and before any control or screen converts.
Why this slice exists
The revamp's point was a nicer UI. The milestone decides the point of view (ledger desktop, field-first phone, one attention line) and three identity fixes (#834, #835, #836), but nothing owns the visual language itself. docs/decisions/674-ui-component-library.md says the accepted cost of MUI is that it "renders as a Google app until deliberately restyled; that work is the revamp's", and no slice picks that up. The design doc (#822, D6) ports today's font sizes into MUI variants, adopts MUI's 8px spacing and keeps the 6/10/16 radius scale. That is faithful to today, not nicer. Without this slice every screen conversion inherits the default Material look, and restyling afterwards means touching every screen twice.
Scope
Decide, in one place, what Cluckwork looks like on MUI, and encode it as theme overrides in web/src/theme/ so #826 onward inherit it:
- Type scale. Chosen, not ported: display, page title, section, body, label, figure, caption, at 1280 and 390. Inter stays; web: give display text an optical size using Inter's opsz axis #835's optical size lands on top.
- Colour use. The four farm palettes stay the single source (SPA revamp: implement the chosen direction — field-first phone (B), ledger desktop (A), one attention line (C) #674 record). Decide neutrals, surfaces, how much brand colour a screen carries, and the semantic colours for status, so a farm's palette reads as its own without every button shouting.
- Shape and density. Button and input shapes, corner radii per nesting level (SPA: elevation hierarchy — stop using one card treatment for stat cards, panels, toolbars and entry panes #651 D2), row height and padding in the ledger tables at 1280, target size and spacing at 390.
- Component styling.
MuiButton,MuiOutlinedInput,MuiTableCell,MuiChip,MuiDialog,MuiDrawer,MuiBottomNavigationoverrides, on top of web: settle the whole-app MUI baseline (CssBaseline, type, spacing, elevation) #823's baseline. No ripple by default; motion is a deliberate choice, not Material's. - The attention line. Direction C reduced to one line on both form factors: what it looks like when there is nothing to say, one thing, and several.
Out of scope: any screen conversion, the mark (#836), offline (#50), a chart library.
Step 1: mockup ideas
Two or three rendered directions of the Dashboard and Daily entry at 1280 and 390, built from the app's own seeded data (four houses 327/298/341 with House C not recorded, 63,122 eggs on hand by grade, the 14-day trend, four real orders), in the default aubergine palette and one other, light and night. Static HTML is fine; the point is to look, not to ship. The owner picks a direction or a combination, as on #656. Attach them to this issue with gh issue comment --attach, never committed to a branch.
Done when
- A direction is chosen on this issue by the owner.
- The theme overrides implementing it land in
web/src/theme/, pinned by the theme guard (web: design doc for the MUI revamp — component map, layout system, IA #822 G2) so the choices cannot drift, with mutation rows run red first. - Before/after screenshots at 1280 and 390, captured 1:1 from a stack rebuilt at the head under review, show the Dashboard under the new theme with no screen conversion applied yet. The after should already look different; if it does not, the overrides are inert (web: convert the Dashboard to MUI — ledger desktop, field-first phone #829's lesson).
- The design doc's D6 is amended to point here for typography, colour and shape, so web: design doc for the MUI revamp — component map, layout system, IA #822 and this issue do not disagree.
Constraints inherited
Sentence case everywhere (caps only on nav group dividers); elevation encodes what floats (#651); --shadow-card stays retired; the four palettes and both modes must keep 4.5:1 on every text pairing (styles.test.ts); Spanish and Tagalog run longer, so nothing is sized to the English string; precache ceiling per #825.
Activity
mforce commentedon Sep 14, 2026
Mockup direction 1: Ruled paper
The farm's ruled record book: numerals are the loudest thing on screen and every other mark is a hairline keeping them in line. Keeps the aubergine sidebar. Status is a dot plus a word, never a filled chip. The trend chart truncates its axis at 800 (the app starts at zero); that is a choice to accept or reject.
Rendered from static HTML with the app's real palette tokens and seeded numbers, at 1280x800 and 390x844, in the default aubergine palette (light) and the forest palette (night). The trend chart follows the current app's bar strip (#781), which the first drafts had missed because the committed
docs/images/dashboard.pngpredates it.Direction notes
Ruled paper
Cluckwork becomes the farm's ruled record book, where the numbers are the loudest thing on the screen and every other mark is a hairline whose only job is to keep them in line.
Type. Inter, six steps and nothing between them. 11.5 micro (units, nav dividers, share percentages), 13 label, 15 body, 17 ledger numeral, 22 total, 26 page title, plus one 28 display numeral for the phone house tiles, the stock total and the hen-day figure. Numerals are always tabular at weight 600, so a column of counts aligns by digit and a changed digit is the only thing that moves. Weight stops at 700. The current 800 with -0.02em tracking is gone, and only the title and the tile numeral carry -0.015em. Optical sizing is left to Inter's
opszaxis throughfont-optical-sizing: auto.Colour. Every colour token is copied unchanged from
web/src/styles.css. What this direction changes is the budget. Brand appears in four places, the nav rail, the primary button, the active nav marker and the day strip bars, and nowhere else, so a ledger row never carries brand. A grade is identified by a 10px square in its--grade-Nhue, and the five shares are carried once by a single 10px stacked rule rather than five separate bars, so grade colour never becomes a filled block that reads as a status. Status is a dot plus a word in--success,--warn,--mutedor--error, and there is no filled status pill anywhere. Night adds two derived tokens,--sheetand--float, because--surfaceis the one dark token the four palettes do not re-scope, and leaving it in place puts a plum sheet under a forest rail. In night the primary button takes a 1px--stat-accentedge, since the brand fill is mode independent and goes flat against a dark surface.Shape. Radius rises only with elevation. Rows and rules are 0, controls and marks are 3px, and 14px is reserved for things that float, which here means the phone house tiles, dialogs and sheets. Pill buttons are gone. Inputs and buttons are the same 3px rectangle, so a stepper reads as one instrument rather than three parts. A total closes with a 3px
doublerule, the way a ledger closes a column. The day strip follows the same logic, a column per day on a 4px gap with a 9px break between the two weeks, an average drawn as a dashed rule across the bars, and a partial day drawn as a 3px floor rather than a full bar.Density. 1280 is a 40px row, a 216px rail, a 1fr plus 320px split with a hairline between the columns, and no card anywhere. 390 is a 56px row, a 44px minimum target, 64px stepper buttons, full width everything, and cards only for the four house tiles. A row action is ruled text at 1280 and a 44px outlined button at 390, which is how "Kumpirmahin ang order (maglalaan ng stock)" survives both widths without anything being sized to an English string. The attention line stays one line at both widths, and at 390 only the first item survives while the rest fold into the count.
Rejected. Cards on the desktop dashboard, which is what ships today and what makes four houses look like eight panels. Filled status pills, which spend the most saturated colour on the words that need help least. Brand-tinted headers and rows, which put the farm's palette in competition with the grade hues on the one screen that shows both. A shadow on anything static. An 800 weight. Icons in ledger rows. A second chart, because one 14 day strip already answers the question the dashboard asks. A line across those 14 days, because a daily count has no values between two days, and the strip can show an unfinished day as a floor where a line can only draw it as a dip.
mforce commentedon Sep 14, 2026
Mockup direction 2: The ruled ledger, brand as a spine
White paper ruled with hairlines. The brand is a thin spine (a tinted nav rail instead of the aubergine slab, the active item's rule, one primary button, the focus ring), never a block. Underline inputs instead of boxes, pills retired, tabular numerals first. The one fill on the phone dashboard is the missing house's tile.
Rendered from static HTML with the app's real palette tokens and seeded numbers, at 1280x800 and 390x844, in the default aubergine palette (light) and the forest palette (night). The trend chart follows the current app's bar strip (#781), which the first drafts had missed because the committed
docs/images/dashboard.pngpredates it.Direction notes
Direction: the ruled ledger, brand as a spine
One sentence: the working screen is white paper ruled with hairlines, the brand colour is a thin spine (nav rail tint, active item rule, one primary button, focus ring) and never a slab, and every number is a tabular numeral first.
Type scale (Inter, optical size follows font-size)
Colour rules
--lavender(the palette's tinted paper) with--stat-accenttext, not a filled brand block. A forest farm reads green through the tint and the accent; the slab was the Slack tell.--linkblue leaves the data screens; it stays for prose (help).--stat-accent(allocated, in progress), hollow ring (draft),--warn(not recorded, low). No tinted badge fills.--tint-warnwith a--warnborder, because it is the one thing on the screen asking for a thumb.--rule(the hairline) between rows, and--rule-strong(28% ink) under headers, above totals, and on underline fields. Dark mode inherits both from the tokens; no new dark values.Shape and density
--shadow-baron the sticky action bar and the tab bar,--shadow-dialogon dialogs. Nothing else casts.--stat-accentfrom a zero baseline, 4px apart with a 9px week break, a dashed ink average across them, Avg and Peak in the header, the date range under the rule, hen-day as the section's display figure with its delta in success or warn. The dip day is--warn, a partial day is hatched, and a hover or focus readout sits in a reserved 28px row so nothing reflows. At 390 the 14 bars are 21px wide, the one target under 44px on the product; the strip is read, not operated.white-space: normalon every button); the Tagalog confirm button sits in a ledger cell at 1280 and becomes a full width 48px button at 390.Rejected
mforce commentedon Sep 14, 2026
Mockup direction 3: The quiet ledger
Ink and rule lines carry the hierarchy. Brand colour appears in exactly two places per screen (active nav mark, primary action) so a farm's palette reads as identity, not decoration. Keeps the aubergine sidebar, puts the numeral first in every row, and reserves radius for controls; a ledger row is flat and hairline-divided.
Rendered from static HTML with the app's real palette tokens and seeded numbers, at 1280x800 and 390x844, in the default aubergine palette (light) and the forest palette (night). The trend chart follows the current app's bar strip (#781), which the first drafts had missed because the committed
docs/images/dashboard.pngpredates it.Direction notes
Direction: the quiet ledger
Ink and rule lines carry the hierarchy; brand colour is spent on exactly two
things per screen (the active nav mark, the one primary action), so a
farm's palette reads as identity, not decoration.
Type scale (Inter, static weights 400/500/600/700/800)
Colour rules
semantic tokens only, never brand, so it cannot read as "the farm's colour."
card background, so it cannot read as a status colour either.
web/src/styles.css; only theshape tokens are this direction's own choice.
Shape and density
dialogs. A ledger row is flat and hairline divided, never rounded.
label so figures align down the page.
and all of daily entry, is full-width rows with 40-44px steppers. The
sticky bar and tab bar are the only shadows.
"nothing to say" (daily entry, plain text) and "one thing" (dashboard,
warn dot). "Several" is the same line plus a count, left undemonstrated
rather than inventing houses.
Rejected
mforce commentedon Sep 14, 2026
Direction pick (provisional, 2026-09-14). Owner leans direction 2 ("the ruled ledger, brand as a spine"); the agent recommends it too: it is the only direction that removes the aubergine slab, the one element that makes every palette look like Slack in a costume, and its tinted rail carries the farm palette as identity in both modes (forest night render above holds up). Brand colour in four places only; underline inputs; pills retired; status as dot plus word; the phone's single fill goes to the missing house.
Two grafts to carry into the theme work: direction 3's numeral-first rows for the Today list at 1280, and direction 1's full-row amber rule for the not-recorded house. One caution: underline fields have a smaller visible target than boxed ones; the CRUD dialogs' text fields keep a visible field surface at 390 so a gloved hand does not miss them. The trend chart follows the app's bar strip (#781) as it already does in the renders.
Owner: reply "confirmed" here (or name changes) and the theme overrides get built from this.
mforce commentedon Sep 14, 2026
Owner direction (2026-09-14): a mix rather than one candidate. Dashboard structure and controls from direction 1, colours from direction 2; daily entry, the phone menu and the phone daily entry as direction 2 does them. A combined mockup is being built and will be attached here for confirmation before any theme work starts.
mforce commentedon Sep 14, 2026
Combined mockup: direction 1's dashboard structure in direction 2's colours
Per the owner's mix (dashboard controls of 1, colours of 2, daily entry and phone menu of 2). Same real tokens, same seeded numbers, zero-baseline bar strip. Daily entry and the phone shell are direction 2's unchanged, so their renders are the ones on the direction 2 comment above; the two new views are the dashboard at 1280 (light aubergine, night forest) and at 390.
Direction notes
Combined direction: candidate 1's dashboard bones in candidate 2's colour and type
One sentence: the dashboard keeps candidate 1's structure and controls (Today rows with recorded times and the amber full-row rule on the missing house, sales ledger with the order number under the customer, Eggs on hand and Last 14 days in a right column, an attention line that folds into a count) and everything it wears comes from candidate 2, whose daily entry and phone shell are used unchanged.
From candidate 1 (structure, controls)
From candidate 2 (colour, type, rules, daily entry, phone shell)
--lavendertinted paper with--stat-accenttext, not a brand slab. Brand appears in four places: farm name, active nav item (2px rule plus text), primary button, focus ring.--stat-accent(allocated), hollow ring (draft),--warn(not recorded, low). No badge fills. Grade hues only in the stock meter and swatches. Links are ink, underlined in a 28% ink rule.--rulebetween rows,--rule-strong(28% ink) under headers, above totals, under fields. Controls 4px radius, cards 8px, dialogs 12px. Elevation only on the action bar, the tab bar and dialogs.--stat-accent, 4px apart with a 9px week break, a dashed ink average across them, Avg and Peak in the header, the date range under the rule, hen-day as the display figure with its delta. The dip day is--warn, today is hatched as a partial floor, the readout sits in a reserved 28px row and the dip day is selected by default so the render shows it. At 390 the bars are 21px, the one target under 44px; the strip is read, not operated.Rejected
Owner: reply "confirmed" to make this the #864 direction, or name what to change.
mforce commentedon Sep 14, 2026
Owner feedback on the combined mockup (2026-09-14): the phone dashboard cards are rejected, and the trend panel should follow direction 1's chart. Revision in progress: phone Today becomes a ruled list (with a compact-tile variant rendered alongside so the owner can choose), and the Last 14 days panel takes direction 1's presentation. Note for the eventual slice: direction 1's chart uses a non-zero floor ("scale from 800") where the app's strip is zero-based today (#780); adopting that presentation is a product decision the slice records.
mforce commentedon Sep 14, 2026
Combined mockup, revision 2
Per the owner: direction 1's chart in the trend panel (with its 800 floor, kept as drawn; the app's strip is zero-based today, #780, so adopting the floor is a product call for the slice), and the phone dashboard cards replaced. Two phone variants for the owner to choose between: a ruled list, and compact tiles with no buttons where the whole tile is the tap target.
Owner: name the phone variant (list or tiles) and say "confirmed", or name what else to change.
mforce commentedon Sep 14, 2026
Direction confirmed (owner, 2026-09-14): combined mockup revision 2, phone Today as the ruled list. Direction 1's dashboard structure and chart (800 floor kept as drawn, product call recorded for the slice), direction 2's colours, type, rules, daily entry and phone shell. The mockup HTML and its DIRECTION.md are committed with the slice as the design authority, per the discount-mockups precedent. Theme work starts now: #823's baseline first, then this issue's overrides on top, each with before/after captures.
8 remaining items
mforce commentedon Sep 16, 2026
Owner pick (2026-09-16), desktop: all three rendered changes are in for the slice: the single filled Record House C button at 1280 (amends the ruled-text sentence in
DIRECTION.md), the Yesterday by close reference under Today so far, and the ruled separators in the attention line. The desktop-only Needs attention list is not taken; it stays a note here.feat(web): whole-app MUI baseline, theme policy guard and the #740 ph…
feat(web): give Emotion the page nonce
fix(web): remove the hidden CSP-probe Chip from Login.tsx
feat(web): serve a per-request CSP nonce so Emotion's styles apply un…
feat(web): move the radius scale to 4/8/12 per the #864 direction
test(web): bring the jsdom shadow fallbacks in line with the #864 tokens
docs(designs): amend D3.3's Dashboard row to DIRECTION.md's confirmed…
fix(web): owner's read of the #883 screenshots — button radius, label…
feat(web): convert the Dashboard and app shell to MUI (#829) (#883)
feat(web): convert Daily entry to MUI, field-first on the phone (#888)
chore(main): release 0.1.2 (#802)
feat(web): replace NamedEntityPicker's combobox with MUI Autocomplete (…
feat(dashboard): redesign the Operations Desk and show order grade na…