chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
The pages colour by purpose, not hue: danger, success, attention, done and neutral
web/src/app.css+23−23
| @@ -96,9 +96,9 @@ li .title:has(+.labels){margin-right:var(--space-2)} | ||
.bars i.d{background:var(--rem)} | ||
| ||
/* What a pull or issue is in: as text, and as a filled pill. */ | ||
.st.open{color:var(--open)}.st.merged{color:var(--merged)}.st.closed{color:var(--closed-issue)}.st.closed.pull{color:var(--closed-pull)}.st.draft{color:var(--gray)} | ||
.st.open{color:var(--open)}.st.merged{color:var(--merged)}.st.closed{color:var(--closed-issue)}.st.closed.pull{color:var(--closed-pull)}.st.draft{color:var(--neutral)} | ||
.pill{display:inline-flex;align-items:center;gap:var(--space-1-5);height:var(--control);padding:0 var(--space-3);border-radius:var(--radius-full);color:var(--on-solid);font-weight:var(--weight-medium);font-size:var(--text-sm)} | ||
.pill.open{background:var(--open)}.pill.merged{background:var(--merged)}.pill.closed{background:var(--closed-issue)}.pill.closed.pull{background:var(--closed-pull)}.pill.draft{background:var(--gray)} | ||
.pill.open{background:var(--open)}.pill.merged{background:var(--merged)}.pill.closed{background:var(--closed-issue)}.pill.closed.pull{background:var(--closed-pull)}.pill.draft{background:var(--neutral)} | ||
| ||
/* What a check or a commit's checks came to. */ | ||
.checks{display:inline-flex;align-items:center;gap:var(--space-1);font:var(--weight-normal) var(--text-sm) var(--font-sans);color:var(--mute);font-variant-numeric:tabular-nums} | ||
| @@ -187,7 +187,7 @@ a.row:hover{background:var(--hover)} | ||
.notifications .invite-answer{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);flex-basis:100%;padding-left:calc(var(--avatar-md) + var(--space-3));font-size:var(--text-sm)} | ||
.notifications .invite-answer p{flex-basis:100%} | ||
.notifications li p.invite-said{color:var(--fg)} | ||
.notifications li p.problem{color:var(--red)} | ||
.notifications li p.problem{color:var(--danger)} | ||
.notifications-head .gear{display:flex;margin-left:auto;color:var(--mute)} | ||
.notifications-head .gear:hover{color:var(--fg)} | ||
.notification-kinds{margin:0 0 var(--space-2)} | ||
| @@ -319,7 +319,7 @@ a.row:hover{background:var(--hover)} | ||
.org-invitation .choice{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-2);padding:var(--space-3);border:var(--border);border-radius:var(--radius-md);background:var(--bg);color:var(--fg)} | ||
.org-invitation .choice p{color:var(--mute);font-size:var(--text-sm)} | ||
.org-invitation .decline{font-size:var(--text-sm)} | ||
.org-invitation .problem{color:var(--red)} | ||
.org-invitation .problem{color:var(--danger)} | ||
.text-button{padding:0;border:0;background:none;color:inherit;font:inherit;text-decoration:underline;text-decoration-color:var(--link-line);text-underline-offset:var(--underline-offset);cursor:pointer} | ||
.text-button:disabled{opacity:0.6;cursor:default} | ||
.org-invite{margin-bottom:var(--space-6)} | ||
| @@ -391,7 +391,7 @@ a.row:hover{background:var(--hover)} | ||
.reaction-pick{display:inline-flex;align-items:center;justify-content:center;width:var(--control);height:var(--control);border:0;border-radius:var(--radius-md);background:none;font-size:var(--text-lg);cursor:pointer} | ||
.reaction-pick:hover{background:var(--hover)} | ||
.reaction-pick[aria-pressed=true]{background:var(--accent-soft)} | ||
.reaction-error{font-size:var(--text-xs);color:var(--red)} | ||
.reaction-error{font-size:var(--text-xs);color:var(--danger)} | ||
.star .count{display:inline-flex;align-items:center;height:var(--control);padding:0 var(--space-2-5);border:var(--border);border-left:0;border-radius:0 var(--radius-md) var(--radius-md) 0;font:var(--weight-medium) var(--text-xs) var(--font-sans);color:var(--fg)} | ||
.toolbar-end{margin-left:auto;display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)} | ||
.clone-menu>.menu{left:auto;right:0;width:26rem;padding:0 0 var(--space-3)} | ||
| @@ -723,9 +723,9 @@ a.row:hover{background:var(--hover)} | ||
select.field{height:var(--control);padding-block:0} | ||
:is(input,select,textarea).field:focus{outline:0;border-color:var(--primary);box-shadow:var(--ring)} | ||
textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text-sm)} | ||
.problem{color:var(--red);font-size:var(--text-sm)} | ||
.problem{color:var(--danger);font-size:var(--text-sm)} | ||
/* What a name typed for a repository is: a hint, red when it cannot be given. */ | ||
.form .name-check.bad{color:var(--red)} | ||
.form .name-check.bad{color:var(--danger)} | ||
.item-head{display:flex;align-items:flex-start;gap:var(--space-3)} | ||
.item-head .item-title{flex:1;min-width:0} | ||
.title-edit{display:flex;flex-wrap:wrap;gap:var(--space-2)} | ||
| @@ -734,7 +734,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.action-menu>summary{display:inline-grid;place-items:center;width:var(--control-sm);height:var(--control-sm);border-radius:var(--radius-md);color:var(--mute)} | ||
.action-menu>summary:hover,.action-menu[open]>summary{background:var(--hover);color:var(--fg)} | ||
.action-menu>.menu{left:auto;right:0;min-width:12rem} | ||
.menu-item.danger{color:var(--red)} | ||
.menu-item.danger{color:var(--danger)} | ||
.label-menu .menu-item{align-items:center;gap:var(--space-2)} | ||
.composer{display:flex;flex-direction:column;gap:var(--space-3);padding:var(--space-3)} | ||
.composer .review{display:flex;flex-wrap:wrap;gap:var(--space-2) var(--space-4);margin:0;padding:0;border:0;font-size:var(--text-sm)} | ||
| @@ -850,7 +850,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.dialog label{font-size:var(--text-sm);font-weight:var(--weight-medium)} | ||
.dialog input{height:var(--control);padding:0 var(--space-2-5);border:var(--border);border-radius:var(--radius-md);background:var(--bg);color:var(--fg);font:var(--text-field) var(--font-sans)} | ||
.dialog input:focus{outline:0;border-color:var(--primary);box-shadow:var(--ring)} | ||
.dialog .problem{color:var(--red);font-size:var(--text-sm)} | ||
.dialog .problem{color:var(--danger);font-size:var(--text-sm)} | ||
.dialog:has(.handle-input){overflow:visible} | ||
.handle-input{position:relative;display:grid} | ||
.handle-list{position:absolute;z-index:var(--z-menu);top:calc(100% + var(--space-1));left:0;right:0;padding:var(--space-1);border:var(--border);border-radius:var(--radius-md);background:var(--bg);box-shadow:var(--shadow-pop)} | ||
| @@ -965,7 +965,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.agent-chat li{position:relative} | ||
.agent-chat li.hidden{visibility:hidden} | ||
.agent-chat .rest{visibility:hidden} | ||
.agent-chat .tool .mark{flex:none;align-self:center;width:var(--chat-mark);height:var(--chat-mark);border-radius:var(--radius-full);background:var(--green)} | ||
.agent-chat .tool .mark{flex:none;align-self:center;width:var(--chat-mark);height:var(--chat-mark);border-radius:var(--radius-full);background:var(--success)} | ||
.agent-chat .tool.running .mark{background:var(--running)} | ||
.agent-chat .dots{visibility:visible;position:absolute;left:0;top:0;display:flex;gap:var(--space-1);padding-top:var(--space-1-5)} | ||
.agent-chat .dots i{width:var(--chat-mark);height:var(--chat-mark);border-radius:var(--radius-full);background:var(--faint)} | ||
| @@ -1033,7 +1033,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.merge-box .actions .next a,.hint a{color:var(--fg);text-decoration:underline;text-decoration-color:var(--link-line);text-underline-offset:var(--underline-offset)} | ||
.merge-box .keep{display:inline-flex;align-items:center;gap:var(--space-1-5);font-size:var(--text-sm);color:var(--mute)} | ||
.more-menu>.menu,.rerun-menu>.menu{left:auto;right:0;min-width:12rem} | ||
.merge-box .problem,.rerun-menu .problem,.runner-list .problem,.secret-list .problem{padding:var(--space-2) var(--pad-x);color:var(--red);font-size:var(--text-sm);overflow-wrap:anywhere} | ||
.merge-box .problem,.rerun-menu .problem,.runner-list .problem,.secret-list .problem{padding:var(--space-2) var(--pad-x);color:var(--danger);font-size:var(--text-sm);overflow-wrap:anywhere} | ||
.rerun-menu>summary.btn{height:var(--control-sm);padding:0 var(--space-2);font-size:var(--text-xs);color:var(--fg)} | ||
.dialog select{height:var(--control);padding:0 var(--space-2);border:var(--border);border-radius:var(--radius-md);background:var(--bg);color:var(--fg);font:var(--text-field) var(--font-sans)} | ||
.dialog .label-like{font-size:var(--text-sm);font-weight:var(--weight-medium)} | ||
| @@ -1058,7 +1058,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.delete-data .shared{display:flex;align-items:baseline;gap:var(--space-2);margin-left:auto;font-size:var(--text-xs)} | ||
.delete-data .shared a{color:var(--primary)} | ||
.delete-data .data-counts li{justify-content:space-between} | ||
.delete-data progress{width:100%;accent-color:var(--red)} | ||
.delete-data progress{width:100%;accent-color:var(--danger)} | ||
.delete-data .hint{color:var(--mute);font-size:var(--text-sm)} | ||
.runner-list .boxhead,.secret-list .boxhead{flex-direction:column;align-items:flex-start;gap:var(--space-0-5)} | ||
.runner-list .boxhead .mute,.secret-list .boxhead .mute{font-size:var(--text-sm)} | ||
| @@ -1106,7 +1106,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.settings-form .btn{flex:none} | ||
.settings-form .btn.primary{align-self:flex-start} | ||
.hint{color:var(--mute);font-size:var(--text-xs);font-weight:var(--weight-medium)} | ||
.settings-form .problem{color:var(--red);font-size:var(--text-sm)} | ||
.settings-form .problem{color:var(--danger);font-size:var(--text-sm)} | ||
.inline-form{display:flex;flex-wrap:wrap;gap:var(--space-2)} | ||
.inline-form input,.inline-form select{flex:1 1 12rem;width:auto} | ||
.link-row{display:flex;flex-wrap:wrap;gap:var(--space-2);margin-bottom:var(--space-2)} | ||
| @@ -1150,7 +1150,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.profile-actions .follow{flex:1} | ||
.actor-menu>.menu{left:auto;right:0;min-width:14rem} | ||
.menu-note{padding:var(--space-1) var(--space-3);font-size:var(--text-sm)} | ||
.menu-note.problem{color:var(--red)} | ||
.menu-note.problem{color:var(--danger)} | ||
| ||
@media (max-width:640px){ | ||
.settings-page{grid-template-columns:minmax(0,1fr)} | ||
| @@ -1174,7 +1174,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.form textarea{height:auto;min-height:5rem;padding:var(--space-2) var(--space-2-5);resize:vertical} | ||
.form :is(input,select,textarea):focus{outline:0;border-color:var(--primary);box-shadow:var(--ring)} | ||
.form .hint{color:var(--mute);font-size:var(--text-xs);margin-bottom:var(--space-2)} | ||
.form .problem{color:var(--red);font-size:var(--text-sm)} | ||
.form .problem{color:var(--danger);font-size:var(--text-sm)} | ||
.owned{display:flex;align-items:center;gap:var(--space-2)} | ||
.owned>.handle-input{flex:1;min-width:0} | ||
.owned>.mute{flex:none;font-size:var(--text-sm)} | ||
| @@ -1191,18 +1191,18 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.setting h2{font-size:var(--text-lg);font-weight:var(--weight-semibold);padding-bottom:var(--space-2);border-bottom:var(--border);margin-bottom:var(--space-2)} | ||
.setting h3{font-size:var(--text-sm);font-weight:var(--weight-semibold)} | ||
.setting .hint{color:var(--mute);font-size:var(--text-xs)} | ||
.setting .problem,.offer .problem{color:var(--red);font-size:var(--text-sm)} | ||
.setting .problem,.offer .problem{color:var(--danger);font-size:var(--text-sm)} | ||
.setting .actions{display:flex;align-items:center;gap:var(--space-3)} | ||
.setting .actions .mute{font-size:var(--text-sm)} | ||
.setting.danger{border:var(--border);border-color:var(--red);border-radius:var(--radius-md);padding:var(--space-4)} | ||
.setting.danger h2{color:var(--red)} | ||
.setting.danger{border:var(--border);border-color:var(--danger);border-radius:var(--radius-md);padding:var(--space-4)} | ||
.setting.danger h2{color:var(--danger)} | ||
.danger-row{display:flex;align-items:center;justify-content:space-between;gap:var(--space-4)} | ||
.danger-row+.danger-row,.setting.danger .form+.danger-row,.setting.danger .problem+.danger-row{padding-top:var(--space-4);border-top:var(--border)} | ||
.setting.danger .form{max-width:var(--measure)} | ||
.btn.danger{color:var(--red)} | ||
.btn.danger:hover{background:var(--red);border-color:var(--red);color:var(--on-solid)} | ||
.btn.danger.solid{justify-content:center;margin-top:var(--space-2);background:var(--red);border-color:var(--red);color:var(--on-solid)} | ||
.btn.danger.solid:disabled{background:var(--bg);color:var(--red)} | ||
.btn.danger{color:var(--danger)} | ||
.btn.danger:hover{background:var(--danger);border-color:var(--danger);color:var(--on-solid)} | ||
.btn.danger.solid{justify-content:center;margin-top:var(--space-2);background:var(--danger);border-color:var(--danger);color:var(--on-solid)} | ||
.btn.danger.solid:disabled{background:var(--bg);color:var(--danger)} | ||
.offer{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);margin:0 0 var(--space-4);padding:var(--row-y) var(--pad-x);border-radius:var(--radius-md);background:var(--notice);color:var(--notice-fg)} | ||
.offer p:first-child{flex:1;min-width:0} | ||
.archived-note{margin:0 0 var(--space-4);padding:var(--row-y) var(--pad-x);border-radius:var(--radius-md);background:var(--notice);color:var(--notice-fg)} | ||
| @@ -1378,7 +1378,7 @@ textarea.field{resize:vertical;font-family:var(--font-mono);font-size:var(--text | ||
.admin-form label{font-size:var(--text-sm);font-weight:var(--weight-medium)} | ||
.admin-form input{height:var(--control);padding:0 var(--space-2-5);border:var(--border);border-radius:var(--radius-md);background:var(--bg);color:var(--fg);font:var(--text-field) var(--font-mono)} | ||
.admin-form input:focus{outline:0;border-color:var(--primary);box-shadow:var(--ring)} | ||
.admin-form .problem{color:var(--red);font-size:var(--text-sm)} | ||
.admin-form .problem{color:var(--danger);font-size:var(--text-sm)} | ||
.admin-actions{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)} | ||
.reports p{overflow-wrap:anywhere} | ||
.usage{overflow-x:auto} | ||
web/src/tokens.css+16−7
| @@ -47,14 +47,23 @@ | ||
--notice-fg: #6b4a00; | ||
--notice-track: #f0e2a0; | ||
| ||
/* What a colour is for, as GitHub's Primer names it, over the hues | ||
above, which each theme sets: the pages take these, never a hue, so | ||
a theme may draw success in blue and nothing it says is wrong. */ | ||
--success: var(--green); | ||
--danger: var(--red); | ||
--attention: var(--yellow); | ||
--done: var(--purple); | ||
--neutral: var(--gray); | ||
| ||
/* What a pull, an issue, a check or a line is in. */ | ||
--open: var(--green); | ||
--merged: var(--purple); | ||
--closed-pull: var(--red); | ||
--closed-issue: var(--gray); | ||
--running: var(--yellow); | ||
--add: var(--green); | ||
--rem: var(--red); | ||
--open: var(--success); | ||
--merged: var(--done); | ||
--closed-pull: var(--danger); | ||
--closed-issue: var(--neutral); | ||
--running: var(--attention); | ||
--add: var(--success); | ||
--rem: var(--danger); | ||
| ||
/* Diffs: a line added or removed, its number, and the words that changed in it. */ | ||
--ins: #e6ffec; | ||
AGENTS.md+3−1
| @@ -69,7 +69,9 @@ is for that loop. | ||
- The pages' styles are `web/src/app.css`, and every colour, size, | ||
space, radius and weight in it is a token from `web/src/tokens.css`: | ||
take one by name rather than writing a value, and add one there when | ||
none fits. Every colour that is text meets WCAG AA (4.5:1) on what | ||
none fits. A colour for what it means is its role, `--danger`, | ||
`--success`, `--attention`, `--done` or `--neutral`, never the hue | ||
under it (`--red`), so a theme can draw success in blue. Every colour that is text meets WCAG AA (4.5:1) on what | ||
it is drawn on, in every theme: `harness/contrast.mjs` checks it, in | ||
`web` and `just lint`, and a new colour that is text goes in its | ||
`PAIRS`. A menu that opens is a `<details class="popover …">`. | ||