Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/native/app/(tabs)/expenses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ export default function Expenses() {
<Pad gap={14}>
<ScopeRow />
<View style={{ flexDirection: "row", alignItems: "center", justifyContent: "space-between", gap: 8 }}>
<View accessibilityRole="radiogroup" style={{ flexDirection: "row", padding: 3, gap: 2, borderRadius: 11, backgroundColor: c.recessed }}>
<View accessibilityRole="radiogroup" style={{ flexDirection: "row", padding: 3, gap: 2, borderRadius: radius.pill, backgroundColor: c.recessed }}>
{(["all", "open", "settled"] as Filter[]).map((value) => {
const on = filter === value;
return <Pressable key={value} accessibilityRole="radio" accessibilityState={{ selected: on }} onPress={() => setFilter(value)}
style={{ height: 32, paddingHorizontal: 14, borderRadius: 8, justifyContent: "center", backgroundColor: on ? c.frame : "transparent" }}>
style={{ height: 32, paddingHorizontal: 14, borderRadius: radius.pill, justifyContent: "center", backgroundColor: on ? c.frame : "transparent" }}>
<Text style={{ fontSize: 13, fontWeight: "500", color: on ? c.onFrame : c.ink2 }}>{value[0].toUpperCase() + value.slice(1)}</Text>
</Pressable>;
})}
Expand Down
2 changes: 1 addition & 1 deletion apps/native/src/ui/kit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function Button({ label, onPress, variant = "primary", size = "md", block
disabled={disabled || busy}
onPress={() => { tap(); onPress?.(); }}
style={({ pressed }) => [{
height, paddingHorizontal: size === "sm" ? 12 : size === "lg" ? 20 : 16, borderRadius: radius.control, backgroundColor: bg,
height, paddingHorizontal: size === "sm" ? 14 : size === "lg" ? 22 : 18, borderRadius: radius.pill, backgroundColor: bg,
flexDirection: "row", alignItems: "center", justifyContent: "center", gap: 8, alignSelf: block ? "stretch" : "flex-start",
opacity: disabled ? 0.45 : pressed ? 0.85 : 1,
}, variant === "secondary" || variant === "danger" ? { borderWidth: 1, borderColor: variant === "danger" ? c.late : c.outline } : null]}>
Expand Down
2 changes: 1 addition & 1 deletion apps/web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
<link rel="manifest" href="/manifest.webmanifest" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#1a1e2b" />
<meta name="theme-color" content="#14243b" />
<meta name="apple-mobile-web-app-title" content="Commune" />
<title>Commune</title>
<meta
Expand Down
2 changes: 1 addition & 1 deletion apps/web/public/manifest.webmanifest
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"scope": "/",
"display": "standalone",
"background_color": "#f5f1ea",
"theme_color": "#1a1e2b",
"theme_color": "#14243b",
"icons": [
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png" },
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/screens/Hub.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
@layer screens {
/* The live Hub follows the selected desktop prototype. Other screens keep their own layout. */
.a-body.hub-editorial {
--hub-ink: #1a1e2b;
--hub-ink: var(--navy);
--hub-muted: #737d79;
--hub-paper: #f5f1ea;
--hub-panel: #fffefa;
Expand Down
2 changes: 1 addition & 1 deletion apps/web/src/styles/calendar-date.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
border: 1px solid #e8e2d8;
border-radius: 10px;
background: #fffdf9;
color: #1a1e2b;
color: #14243b;
text-align: center;
font-variant-numeric: tabular-nums;
}
Expand Down
9 changes: 5 additions & 4 deletions apps/web/src/styles/design-system.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* Approved design-language primitives. Auth and Operations retain their layouts. */
.a-body:not(.is-gate) {
--ink: #1a1e2b;
--ink: #14243b;
--ink-soft: #60706b;
background: var(--paper);
}
Expand All @@ -9,9 +9,10 @@
--ink-soft: #b5bdca;
}
.a-header-title h1 {
font-size: 21px;
font-weight: 550;
letter-spacing: -0.5px;
font-family: var(--font-display);
font-size: 24px;
font-weight: 400;
letter-spacing: -0.035em;
}
.a-content :is(.a-btn, .c-hub-button),
.a-windows .a-btn,
Expand Down
146 changes: 146 additions & 0 deletions apps/web/src/styles/harmony.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/*
* Harmony with the website (12 October 2026). The marketing site leads and
* the app borrows its signatures: light DM Sans headlines with tight
* tracking, one navy (#14243b), round sage buttons, the white highlight
* behind the amount, small uppercase labels and rounder cards. Inter stays
* for rows, figures and forms. Sage stays for what is settled and good
* (Edem kept the green and took the website's round shape, 12 October).
* Plan: https://claude.ai/artifact/K1Wao31fQRzg4fPFNtFXw2
* In the overrides layer, after the design-language primitives, so one file
* holds the whole change.
*/

:root {
--action: var(--sage);
--action-hover: #24583f;
--on-action: #ffffff;
}
.a-body.is-dark {
--action: #7cc39f;
--action-hover: #95d2b2;
--on-action: #0c1912;
}

/* Headlines: the website's light display type. */
.a-window-bar h2,
.c-product-dialog h2,
.ops-yours > h2,
.ops-board-head > span,
.a-content :is(.a-panel, .a-card) h2,
.c-home-head h2,
.c-hub .c-hub-identity h2 {
font-family: var(--font-display);
font-weight: 400;
}
.a-window-bar h2,
.c-product-dialog h2 {
font-size: 22px;
letter-spacing: -0.03em;
}
.a-content :is(.a-panel, .a-card) h2,
.c-home-head h2,
.ops-board-head > span {
font-size: 20px;
letter-spacing: -0.025em;
}
.c-hub .c-hub-identity h2 {
letter-spacing: -0.04em;
}
.ops-yours > h2 {
font-size: 30px;
letter-spacing: -0.035em;
}
.c-home-display {
font-weight: 400;
letter-spacing: -0.04em;
}
.c-home-square .c-home-display {
letter-spacing: -0.045em;
}

/* The website's white highlight, behind the amounts Home opens on. It
carries its own ink, so it reads on the phone's navy band too. */
.c-home-standing .c-home-display em {
padding: 0 0.16em 0.04em;
border-radius: 12px;
background: var(--home-surface);
color: var(--home-ink);
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
}

/* The website's small label: uppercase, 12px, spaced. */
.c-home-over,
.c-home-group h3 {
font-size: 12px;
font-weight: 500;
letter-spacing: 0.08em;
text-transform: uppercase;
}

/* Buttons: the website's round shape, in the app's green. */
.a-body :is(.a-btn, .c-home-btn, .ops-add, .c-hub-button) {
border-radius: var(--radius-pill);
}
.a-body .a-btn:not(.ghost, .danger, .nudge),
.a-body .ops-add,
.a-body :is(.a-seg, .a-note-types) button.is-on,
.a-body .c-split-methods button[aria-pressed=true] {
background: var(--action);
color: var(--on-action);
}
.a-body .a-btn:not(.ghost, .danger, .nudge):hover:not(:disabled),
.a-body .ops-add:hover:not(:disabled) {
background: var(--action-hover);
}
.c-home {
--home-action: var(--action);
--home-action-hover: var(--action-hover);
--home-on-action: var(--on-action);
}

/* Rounder cards, as on the website. */
.a-card {
border-radius: var(--radius-surface);
}

/* This Hub: the same green pills and display headings. Links that
used the green action colour keep green for text, as on the website. */
.c-hub {
--hub-action: var(--action);
--hub-action-text: var(--on-action);
--hub-action-hover: var(--action-hover);
}
.c-hub-link,
.c-hub-note-row:hover strong {
color: var(--text-green);
}
.c-hub :is(.c-hub-attention-end button, .c-hub-invite, .c-hub-settings) {
border-radius: var(--radius-pill);
}
.c-hub-section-title {
font-family: var(--font-display);
font-weight: 400;
font-size: 20px;
letter-spacing: -0.025em;
}

/* Home on wider screens: the sentence and the next step share one pale
green panel (the landing page's green), the white next step held inside
it, so the two read as one shape, as the navy band and the next step do
on a phone (Edem, 13 October). */
.c-home {
--home-panel: #dce8d3;
}
.a-body.is-dark .c-home {
--home-panel: #253b34;
}
@media (min-width: 561px) {
.c-home-top {
gap: 0;
padding: 28px 16px 16px;
border-radius: var(--radius-surface);
background: var(--home-panel);
}
.c-home-top > .c-home-standing { padding: 0 16px 28px; }
}
1 change: 1 addition & 0 deletions apps/web/src/styles/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@
@import "./overrides.css" layer(overrides);
@import "./design-system.css" layer(overrides);
@import "./motion.css" layer(overrides);
@import "./harmony.css" layer(overrides);
/* Font faces only, which layers do not affect. */
@import "./fonts.css";
10 changes: 6 additions & 4 deletions apps/web/src/styles/shared.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
--focus-ring: var(--sage);
--danger: #9b2c2c;
--danger-soft: #fde8e4;
--navy: #1a1e2b;
--navy-2: #1f2330;
--navy-3: #21262f;
--navy: #14243b;
--navy-2: #1b2d47;
--navy-3: #203450;
--ink: #171b24;
--ink-soft: #667085;
--peach: #efdccf;
Expand All @@ -33,11 +33,13 @@
--shadow-sm: 0 1px 3px rgba(23, 27, 36, 0.06), 0 1px 2px rgba(23, 27, 36, 0.04);
--shadow: 0 4px 12px rgba(23, 27, 36, 0.07), 0 1px 3px rgba(23, 27, 36, 0.05);
--radius-control: 9px;
--radius-surface: 15px;
--radius-surface: 24px;
--radius-pill: 999px;
--radius: var(--radius-surface);
--radius-sm: var(--radius-control);
--font: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
/* The website's display face, for headlines (harmony.css). */
--font-display: "DM Sans", var(--font);
/* Motion (design panel, 11 October 2026, medium direction). Every duration
and curve in the app is one of these. Things arrive over the medium
time and leave over the short one; the long one is for the all-square
Expand Down
6 changes: 3 additions & 3 deletions apps/web/tests/design-tokens.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ describe("shared page header contract", () => {
expect(styles.hub).not.toMatch(/\.hub-editorial\s+\.a-header(?:\b|[-\s])/);
expect(declarations("app", ".a-header")).toContain("padding: 12px 28px;");
expect(declarations("app", ".a-header")).toContain("color: var(--ink);");
expect(declarations("primitives", ".a-header-title h1")).toContain("font-size: 21px;");
expect(declarations("primitives", ".a-header-title h1")).toContain("font-weight: 550;");
expect(declarations("primitives", ".a-header-title h1")).toContain("font-size: 24px;");
expect(declarations("primitives", ".a-header-title h1")).toContain("font-weight: 400;");
});
});

Expand All @@ -46,7 +46,7 @@ describe("Settle share action alignment", () => {
describe("shared corner contracts", () => {
it("defines a single control/surface family with legacy aliases", () => {
expect(styles.shared).toContain("--radius-control: 9px;");
expect(styles.shared).toContain("--radius-surface: 15px;");
expect(styles.shared).toContain("--radius-surface: 24px;");
expect(styles.shared).toContain("--radius: var(--radius-surface);");
expect(styles.shared).toContain("--radius-sm: var(--radius-control);");
expect(styles.primitives).not.toMatch(/--radius(?:-sm)?:\s*\d/);
Expand Down
5 changes: 3 additions & 2 deletions apps/web/tests/stylesheets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,12 @@ describe("cascade layers", () => {
'@import "./overrides.css" layer(overrides);',
'@import "./design-system.css" layer(overrides);',
'@import "./motion.css" layer(overrides);',
'@import "./harmony.css" layer(overrides);',
'@import "./fonts.css";',
]);
expect(stylesheets(resolve(src, "styles")).sort()).toEqual([
"styles/app.css", "styles/auth.css", "styles/calendar-date.css", "styles/design-system.css",
"styles/fonts.css", "styles/index.css", "styles/legal.css", "styles/motion.css", "styles/overrides.css", "styles/shared.css",
"styles/fonts.css", "styles/harmony.css", "styles/index.css", "styles/legal.css", "styles/motion.css", "styles/overrides.css", "styles/shared.css",
]);
expect(topLevel(read("styles/fonts.css")).every((block) => block === "@font-face")).toBe(true);
});
Expand Down Expand Up @@ -95,7 +96,7 @@ describe("colours", () => {
const fixed = new Map([...definitions]
.filter(([, values]) => values.length === 1 && /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(values[0]))
.map(([name, [value]]) => [hex(value), name]));
expect(fixed.get("1a1e2b")).toBe("--navy");
expect(fixed.get("14243b")).toBe("--navy");
expect(fixed.get("2d6a4f")).toBe("--sage");
const literals = css.flatMap(([path, text]) => [...text.replace(/--[\w-]+\s*:[^;}]+/g, "").matchAll(/#([0-9a-f]{6}|[0-9a-f]{3})\b/gi)]
.filter(([match]) => fixed.has(hex(match)))
Expand Down