fix(a11y): name account controls per account, stop hardcoding white on accent

A-04: every account rendered a folder toggle labelled "Toggle account folders",
so three accounts gave three controls a screen reader reads identically. The
address is in the label now, and the account link is named explicitly rather
than by a `truncate` span that CSS can cut mid-address.

A-07 (second half): computing --rgb-accent-ink by luminance achieves nothing
while 63 call sites paint `text-white` on `bg-accent` directly. They now use
text-accent-ink and inherit the measured choice. The two left behind are white
over a black gradient and over a danger fill, which are not the accent.

H-05: the search box kept a stale query when a folder was clicked — the input
survives the Turbo visit and a folder page has no `q` to overwrite it with, so
the box claimed a filter the list below it had not applied. It now tracks `?q=`
in the address bar, which is also right on the way back in.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Claude committed 2026-08-11 17:20:54 +02:00
1 parent 5ff870c3b7
commit 1836e673e7
58 files changed
+138 -71

No files matched your search

@@ -64,11 +64,55 @@ export default class extends Controller {
connect() {
this._boundOutside = this._handleOutsideClick.bind(this);
document.addEventListener("click", this._boundOutside, { capture: true });
// The box must always say what the results below it were filtered by.
// Clicking a folder after a search used to leave the query sitting in
// the box above an unfiltered list — the search input survives the
// visit, and the folder page has no `q` to overwrite it with, so the
// box claimed a filter that was not applied.
//
// Synced from the URL rather than cleared on navigation, because the
// rule is not "clear it when leaving search" — it is "the box shows the
// query in the address bar". That is also true going the other way: a
// link straight to /mail/search?q=x, a reload, or back into a search
// from a folder all fill the box in, and none of them are a case
// clearing logic would have covered.
this._boundSync = this.#syncToUrl.bind(this);
this.#syncToUrl();
// connect() alone is not enough: the element can survive a Turbo visit,
// in which case the controller is never re-connected and only the URL
// changed.
document.addEventListener("turbo:load", this._boundSync);
document.addEventListener("turbo:frame-load", this._boundSync);
}
disconnect() {
clearTimeout(this.#debounce);
document.removeEventListener("click", this._boundOutside, { capture: true });
document.removeEventListener("turbo:load", this._boundSync);
document.removeEventListener("turbo:frame-load", this._boundSync);
}
/** Make the box agree with `?q=` in the address bar. */
#syncToUrl() {
if (false === this.hasInputTarget) {
return;
}
// Never yank the text out from under someone mid-type. A frame load can
// land while the box has focus — the list refreshing underneath is the
// ordinary case — and the address bar is not the authority on a query
// that has not been submitted yet.
if (document.activeElement === this.inputTarget) {
return;
}
const query = new URLSearchParams(window.location.search).get("q") ?? "";
if (this.inputTarget.value !== query) {
this.inputTarget.value = query;
}
}
// ── Input events ──────────────────────────────────────────────────────
@@ -98,7 +98,7 @@ export default class extends Controller {
b.className =
"px-2.5 h-7 text-xs font-medium transition-colors cursor-pointer " +
(node.operator === op.value
? "bg-accent text-white"
? "bg-accent text-accent-ink"
: "text-ink-soft hover:bg-hover")
b.addEventListener("click", () => {
this._at(path).operator = op.value
+14 -3
View File
@@ -20,10 +20,15 @@
not the anchor: on the anchor the pill stops before the chevron and
cuts the row in half. #}
<div class="nav-item flex items-center transition-colors text-ink-muted">
{# Named explicitly rather than by the address inside it: that span
is `truncate`, and a name a screen reader reads as "kontakt@…"
because CSS ran out of room is not a name. #}
<a
href="{{ path('app_mail_account', { account: account.id }) }}"
data-ui--sidebar-target="link"
data-action="{{ _drawerClose }}"
aria-label="{{ 'sidebar.accounts.open'|trans({ '%account%': account.displayAddress }) }}"
title="{{ account.displayAddress }}"
class="flex items-center gap-2 py-2 flex-1 min-w-0"
>
<span class="w-2 h-2 rounded-full flex-shrink-0 {{ account.isActive ? 'bg-green-400' : 'bg-ink-faint' }}"></span>
@@ -33,11 +38,17 @@
it will go is not visible to a screen reader — nor, since the
open account moved into the user's settings, to anything else
that has to know the state before pressing it. The controller
keeps it in step. #}
keeps it in step.
The account's address is IN the label. Every account renders one
of these, so "Toggle account folders" three times over is three
controls a screen-reader user cannot tell apart — the list of
buttons on the page reads the same word three times and none of
them says which mailbox it opens. #}
<button
type="button"
aria-label="{{ 'sidebar.accounts.toggle'|trans }}"
title="{{ 'sidebar.accounts.toggle'|trans }}"
aria-label="{{ 'sidebar.accounts.toggle'|trans({ '%account%': account.displayAddress }) }}"
title="{{ 'sidebar.accounts.toggle'|trans({ '%account%': account.displayAddress }) }}"
aria-expanded="{{ expanded ? 'true' : 'false' }}"
aria-controls="account-folders-{{ account.id }}"
data-settings--account-expand-target="toggle"
+2 -2
View File
@@ -115,13 +115,13 @@ The button itself carries `group` and `relative`.
>
{# Checkmark — shown when all selected #}
<svg data-mail--list-toolbar-target="checkmark"
class="hidden w-2.5 h-2.5 text-white pointer-events-none"
class="hidden w-2.5 h-2.5 text-accent-ink pointer-events-none"
viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="2.2">
<polyline points="1.5,5 3.8,7.5 8.5,2.5"/>
</svg>
{# Dash — shown when some (but not all) selected #}
<svg data-mail--list-toolbar-target="indeterminate"
class="hidden w-2.5 h-2.5 text-white pointer-events-none"
class="hidden w-2.5 h-2.5 text-accent-ink pointer-events-none"
viewBox="0 0 10 10" fill="none" stroke="currentColor" stroke-width="2.2">
<line x1="2" y1="5" x2="8" y2="5"/>
</svg>
+1 -1
View File
@@ -67,7 +67,7 @@ the app ended up with four slightly different modal footers.
<button
type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-1
transition-colors duration-100
{% if danger %}
+2 -2
View File
@@ -5,7 +5,7 @@ having to re-render the markup. `key` must match a key from
app_mail_sidebar_counts.
#}
{% macro unread_badge(count, key) %}
<span class="rail-hide text-xs font-semibold px-1.5 py-0.5 rounded-full bg-accent text-white{{ count > 0 ? '' : ' hidden' }}"
<span class="rail-hide text-xs font-semibold px-1.5 py-0.5 rounded-full bg-accent text-accent-ink{{ count > 0 ? '' : ' hidden' }}"
data-ui--sidebar-target="badge"
data-count-key="{{ key }}">{{ count }}</span>
{% endmacro %}
@@ -139,7 +139,7 @@ controller instead — the scroll position and which trees are open.
data-turbo-frame="compose_dock"
data-action="{{ _drawerClose }}"
title="{{ 'sidebar.compose'|trans }}"
class="compose-link w-full flex items-center justify-center gap-2 bg-accent hover:bg-accent-strong text-white text-sm font-medium rounded-lg px-3 py-row transition-colors">
class="compose-link w-full flex items-center justify-center gap-2 bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium rounded-lg px-3 py-row transition-colors">
<i class="fa-solid fa-plus w-4 h-4" aria-hidden="true"></i>
<span class="rail-hide">{{ 'sidebar.compose'|trans }}</span>
</a>
+1 -1
View File
@@ -127,7 +127,7 @@ the conversation it answers.
aria-hidden="true">{{ sender|avatar_initial(senderSeed) }}</span>
<span class="absolute inset-0 flex items-center justify-center rounded-full
bg-accent text-white
bg-accent text-accent-ink
opacity-0 transition-opacity
peer-checked:opacity-100 group-hover/avatar:opacity-100
peer-focus-visible:ring-2 peer-focus-visible:ring-accent peer-focus-visible:ring-offset-1"
+1 -1
View File
@@ -268,7 +268,7 @@
<button id="user-menu-btn"
data-admin--log-alert-target="ring"
data-action="click->ui--user-menu#toggle"
class="flex cursor-pointer items-center justify-center w-8 h-8 rounded-full bg-accent hover:ring-2 hover:ring-accent/60 hover:ring-offset-1 ring-offset-surface text-white text-xs font-semibold transition-all
class="flex cursor-pointer items-center justify-center w-8 h-8 rounded-full bg-accent hover:ring-2 hover:ring-accent/60 hover:ring-offset-1 ring-offset-surface text-accent-ink text-xs font-semibold transition-all
{% if unseenLogs %}ring-2 ring-offset-1 {{ unseenLogs.tone == 'danger' ? 'ring-red-500' : 'ring-amber-500' }}{% endif %}"
aria-label="{{ 'header.user_menu.label'|trans({ '%email%': app.user.email }) }}"
title="{{ unseenLogs
+1 -1
View File
@@ -25,7 +25,7 @@
{{ 'form.cancel'|trans }}
</button>
<button type="submit"
class="px-4 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="px-4 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
{{ 'form.submit'|trans }}
</button>
</div>
+1 -1
View File
@@ -90,7 +90,7 @@
</button>
<button type="submit"
data-settings--account-form-target="submitBtn"
class="px-4 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="px-4 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
{{ 'form.submit'|trans }}
</button>
</div>
+1 -1
View File
@@ -77,7 +77,7 @@
<input type="hidden" name="_token" value="{{ csrf_token('admin_db_stat_statements_enable') }}">
<button type="submit"
class="inline-flex items-center gap-1.5 px-3 h-8 rounded-lg text-xs font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-bolt text-[11px]" aria-hidden="true"></i>
{{ 'admin.db.extension_enable'|trans }}
</button>
+2 -2
View File
@@ -79,7 +79,7 @@
data-turbo-confirm="{{ 'admin.maintenance.restart_confirm'|trans }}" class="mt-2">
<input type="hidden" name="_token" value="{{ csrf_token('admin_restart_workers') }}">
<button type="submit"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-arrows-rotate" aria-hidden="true"></i>
{{ 'admin.maintenance.restart'|trans }}
</button>
@@ -489,7 +489,7 @@
<form method="post" action="{{ path('app_admin_failed_retry', { id: row.id }) }}" data-turbo-frame="_top">
<input type="hidden" name="_token" value="{{ csrf_token('admin_failed_' ~ row.id) }}">
<button type="submit"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-rotate-right" aria-hidden="true"></i>
{{ 'admin.failed.retry'|trans }}
</button>
+2 -2
View File
@@ -66,7 +66,7 @@ is half-typed.
<button type="submit" id="config-backup-apply"
class="shrink-0 inline-flex items-center gap-2 h-9 px-4 rounded-lg text-sm font-medium
text-white bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
text-accent-ink bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
<i class="fa-solid fa-download text-xs" aria-hidden="true"></i>
{{ 'admin.config_backup.review.apply'|trans }}
</button>
@@ -139,7 +139,7 @@ is half-typed.
<div class="flex justify-end">
<button type="submit" id="config-backup-export"
class="inline-flex items-center gap-2 h-9 px-4 rounded-lg text-sm font-medium
text-white bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
text-accent-ink bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
<i class="fa-solid fa-file-arrow-down text-xs" aria-hidden="true"></i>
{{ 'admin.config_backup.export.submit'|trans }}
</button>
+1 -1
View File
@@ -98,7 +98,7 @@ poll would empty a field mid-paste.
<div class="flex justify-end">
<button type="submit"
class="inline-flex items-center gap-2 h-9 px-4 rounded-lg text-sm font-medium
text-white bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
text-accent-ink bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
<i class="fa-solid fa-floppy-disk text-xs" aria-hidden="true"></i>
{{ 'admin.push.fcm.save'|trans }}
</button>
+1 -1
View File
@@ -62,7 +62,7 @@ they make lands on /install with no memory of what happened here.
{% endif %}
<a href="{{ path('app_install') }}"
class="mt-7 block w-full text-center bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors">
class="mt-7 block w-full text-center bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors">
{{ 'admin.reset.done.continue'|trans }}
</a>
</div>
+1 -1
View File
@@ -83,7 +83,7 @@ Blocks, rendered inside the day loop and able to read `dayKey` and `dayEntries`:
</div>
{% if isToday %}
<div class="mx-auto mt-0.5 w-6 h-6 flex items-center justify-center rounded-full
bg-accent text-white text-sm font-semibold tabular-nums">
bg-accent text-accent-ink text-sm font-semibold tabular-nums">
{{ dayKey|date('j') }}
</div>
{% else %}
+1 -1
View File
@@ -437,7 +437,7 @@ behaviour.
</button>
<button type="submit"
class="px-4 py-2 rounded-lg text-sm bg-accent text-white hover:opacity-90 transition-opacity">
class="px-4 py-2 rounded-lg text-sm bg-accent text-accent-ink hover:opacity-90 transition-opacity">
{{ 'calendar.event.save'|trans }}
</button>
</div>
+1 -1
View File
@@ -106,7 +106,7 @@ Variables:
{% if calendars is not empty %}
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100">{{ 'calendar.ics.import.submit'|trans }}</button>
+1 -1
View File
@@ -106,7 +106,7 @@ Variables:
transition-colors duration-100">{{ 'form.cancel'|trans }}</button>
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100">{{ 'calendar.ics.subscribe.submit'|trans }}</button>
+1 -1
View File
@@ -94,7 +94,7 @@ Variables:
<button type="submit"
class="inline-flex items-center gap-1.5 px-3 h-8 rounded-lg text-xs font-medium transition-colors cursor-pointer
{{ answer == status
? 'bg-accent text-white'
? 'bg-accent text-accent-ink'
: 'border border-line text-ink-muted hover:bg-hover hover:text-ink' }}">
<i class="{{ answer.icon }} text-[10px]" aria-hidden="true"></i>
{{ answer.action|trans }}
+1 -1
View File
@@ -95,7 +95,7 @@ Blocks, both rendered inside the cell loop and both able to read `dayKey`,
<div class="flex items-center justify-between shrink-0 px-0.5">
{% if isToday %}
<span class="w-5 h-5 flex items-center justify-center rounded-full
bg-accent text-white text-xs font-semibold tabular-nums">
bg-accent text-accent-ink text-xs font-semibold tabular-nums">
{{ dayKey|date('j') }}
</span>
{% else %}
+1 -1
View File
@@ -69,7 +69,7 @@ Variables:
<input type="hidden" name="_token" value="{{ csrf_token('calendar_proposal' ~ proposal.message.id) }}">
<button type="submit"
class="inline-flex items-center gap-1.5 px-3 h-8 rounded-lg text-xs font-medium transition-colors cursor-pointer bg-accent text-white">
class="inline-flex items-center gap-1.5 px-3 h-8 rounded-lg text-xs font-medium transition-colors cursor-pointer bg-accent text-accent-ink">
<i class="fa-solid fa-calendar-plus text-[10px]" aria-hidden="true"></i>
{{ 'calendar.proposal.action.add'|trans }}
</button>
+1 -1
View File
@@ -143,7 +143,7 @@ Variables:
{% if error is null %}
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100">{{ 'settings.calendars.subscribe.save'|trans }}</button>
@@ -164,7 +164,7 @@ one) `placed`:
{% if isToday %}
<span class="w-5 h-5 -my-0.5 flex items-center justify-center rounded-full
bg-accent text-white text-xs font-semibold tabular-nums">
bg-accent text-accent-ink text-xs font-semibold tabular-nums">
{{ dayKey|date('j') }}
</span>
{% else %}
+1 -1
View File
@@ -55,7 +55,7 @@ calendar has no ends, so it never does.
data-ui--modal-src-value="{{ path('app_calendar_event_new') }}"
data-ui--modal-title-value="{{ 'calendar.event.new'|trans }}"
class="w-7 h-7 flex items-center justify-center rounded-lg shrink-0
bg-accent text-white hover:opacity-90 transition-opacity"
bg-accent text-accent-ink hover:opacity-90 transition-opacity"
aria-label="{{ 'calendar.event.new'|trans }}"
><i class="fa-solid fa-plus text-xs" aria-hidden="true"></i></button>
{% endblock %}
+1 -1
View File
@@ -144,7 +144,7 @@ Blocks:
{% if compact %}aria-label="{{ label }}" title="{{ label }}"{% endif %}
class="flex items-center justify-center text-xs transition-colors
{{ compact ? 'w-7 h-7' : 'px-2.5 py-1' }}
{{ candidate == view ? 'bg-accent text-white' : 'text-ink-muted hover:bg-hover hover:text-ink' }}"
{{ candidate == view ? 'bg-accent text-accent-ink' : 'text-ink-muted hover:bg-hover hover:text-ink' }}"
>
{%- if compact -%}
<i class="fa-solid {{ viewIcons[candidate.value] }}" aria-hidden="true"></i>
+1 -1
View File
@@ -14,7 +14,7 @@ to give it. A dead end with a way out beats a stack trace.
<p class="mt-1.5 text-sm text-ink-muted">{{ 'compose.no_account.body'|trans }}</p>
<a href="{{ path('app_settings_index', { section: 'accounts' }) }}"
class="mt-5 inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-white
class="mt-5 inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong transition-colors">
{{ 'compose.no_account.cta'|trans }}
</a>
@@ -29,7 +29,7 @@
opens directly. #}
<a href="{{ uri }}"
class="inline-flex items-center gap-1.5 px-3 h-9 rounded-lg text-xs font-medium
bg-accent hover:bg-accent-strong text-white transition-colors">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors">
<i class="fa-solid fa-arrow-up-right-from-square text-[11px]" aria-hidden="true"></i>
{{ 'settings.device_pairing.open_in_app'|trans }}
</a>
+1 -1
View File
@@ -229,7 +229,7 @@ gap under the shortcuts row.
<button type="button"
data-action="click->integration--integration-picker#attach"
data-integration--integration-picker-target="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong transition-colors disabled:opacity-50">
{{ 'integration.picker.attach'|trans }}
</button>
+1 -1
View File
@@ -117,7 +117,7 @@ like it needed a decision.
data-integration--integration-picker-target="mode">
<span class="inline-flex items-center gap-1.5 h-7 px-2.5 rounded-lg text-[11px] font-medium
text-ink-faint bg-field border border-field
peer-checked:bg-accent peer-checked:text-white peer-checked:border-accent
peer-checked:bg-accent peer-checked:text-accent-ink peer-checked:border-accent
peer-checked:opacity-100
transition-colors">
<i class="fa-solid fa-link text-[9px]" aria-hidden="true"></i>
+1 -1
View File
@@ -41,7 +41,7 @@ selection, which pulled its corners away from the ring.
{% endif %}
<span class="pointer-events-none absolute top-1.5 right-1.5 w-5 h-5 rounded-full
bg-accent text-white text-[10px] items-center justify-center
bg-accent text-accent-ink text-[10px] items-center justify-center
hidden peer-checked:flex">
<i class="fa-solid fa-check" aria-hidden="true"></i>
</span>
+1 -1
View File
@@ -71,7 +71,7 @@ The action buttons hide themselves while a compose card is open; see the
data-action="click->compose--inline-send#cancel"
class="inline-flex items-center gap-2 px-4 py-2 rounded-full text-sm font-medium
text-accent bg-accent-soft border border-accent/30
hover:bg-accent hover:text-white transition-colors cursor-pointer"
hover:bg-accent hover:text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-paper-plane text-xs" aria-hidden="true"></i>
<span>{{ 'compose.sending'|trans }}</span>
+1 -1
View File
@@ -30,7 +30,7 @@ that does.
<a
href="{{ path('app_default_index') }}"
data-turbo-frame="_top"
class="inline-flex items-center justify-center h-9 px-5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-9 px-5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
+1 -1
View File
@@ -138,7 +138,7 @@ nothing to explain passes no aside_template and the grid collapses to one.
<button
type="submit"
id="onboarding-next"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
@@ -64,7 +64,7 @@ account in the list instead of moving on. Next is still the way forward.
name="stay_on_step"
value="1"
id="onboarding-account-add"
class="inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
@@ -53,7 +53,7 @@ form, and HTML has no nested forms.
name="stay_on_step"
value="1"
id="onboarding-integration-save"
class="inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
@@ -33,7 +33,7 @@ full navigation to a step URL renders it unstyled.
<button type="button"
data-action="click->ui--clipboard#copy"
class="mt-2 inline-flex items-center gap-1.5 px-3 h-9 rounded-lg text-xs font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-copy text-[11px]" aria-hidden="true"></i>
<span data-ui--clipboard-target="label">{{ 'settings.security.codes.copy'|trans }}</span>
</button>
@@ -106,7 +106,7 @@ full navigation to a step URL renders it unstyled.
value="1"
id="onboarding-2fa-confirm"
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
{{ 'settings.security.enrol.submit'|trans }}
</button>
</div>
@@ -128,7 +128,7 @@ full navigation to a step URL renders it unstyled.
<a href="{{ enrolUrl }}" data-turbo-frame="modal"
id="onboarding-2fa-open"
class="inline-flex items-center gap-2 mt-4 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors">
<i class="fa-solid fa-shield-halved text-xs" aria-hidden="true"></i>
{{ 'settings.security.enable'|trans }}
</a>
+1 -1
View File
@@ -94,7 +94,7 @@
<button
type="submit"
data-core--submit-once-target="button"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface disabled:opacity-60 disabled:cursor-not-allowed"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface disabled:opacity-60 disabled:cursor-not-allowed"
>
{{ 'two_factor.form.submit'|trans }}
</button>
+1 -1
View File
@@ -95,7 +95,7 @@
<button
type="submit"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface"
class="mt-6 w-full bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface"
>
{{ 'login.form.submit'|trans }}
</button>
+1 -1
View File
@@ -45,7 +45,7 @@
{{ form_widget(aliasForm.address) }}
</div>
<button type="submit"
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-plus text-xs" aria-hidden="true"></i>
{{ 'settings.aliases.add'|trans }}
</button>
+2 -2
View File
@@ -29,7 +29,7 @@
<button type="button"
data-action="click->ui--clipboard#copy"
class="shrink-0 inline-flex items-center gap-1.5 px-3 h-9 rounded-lg text-xs font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-copy text-[11px]" aria-hidden="true"></i>
<span data-ui--clipboard-target="label">{{ 'settings.app_passwords.copy'|trans }}</span>
</button>
@@ -90,7 +90,7 @@ single field is, and a label would push this inline row onto two lines.
</div>
<button type="submit"
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-plus text-xs" aria-hidden="true"></i>
{{ 'settings.app_passwords.generate'|trans }}
</button>
+1 -1
View File
@@ -64,7 +64,7 @@ Variables:
data-action="click->ui--modal#open"
data-ui--modal-title-value="{{ 'calendar.form.add'|trans }}"
data-ui--modal-src-value="{{ path('app_settings_calendar_new') }}"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-plus text-[10px]" aria-hidden="true"></i>
{{ 'calendar.form.add'|trans }}
+1 -1
View File
@@ -34,7 +34,7 @@ Variables:
<a href="{{ path('app_settings_filters_new') }}"
data-turbo-frame="filter-editor"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-plus text-[10px]" aria-hidden="true"></i>
{{ 'settings.filters.add'|trans }}
</a>
+1 -1
View File
@@ -23,7 +23,7 @@ Variables:
data-action="click->ui--modal#open"
data-ui--modal-title-value="{{ 'sidebar.labels.add'|trans }}"
data-ui--modal-src-value="{{ path('app_label_new') }}"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-plus text-[10px]" aria-hidden="true"></i>
{{ 'sidebar.labels.add'|trans }}
+1 -1
View File
@@ -32,7 +32,7 @@
data-settings--web-push-target="toggle"
data-action="click->settings--web-push#toggle"
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer
disabled:cursor-not-allowed disabled:opacity-40">
<i class="fa-solid fa-bell text-xs" aria-hidden="true"></i>
{{ 'settings.notifications.toggle'|trans }}
+1 -1
View File
@@ -25,7 +25,7 @@ find.
<button
type="submit"
id="profile-save"
class="mt-6 inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-white
class="mt-6 inline-flex items-center justify-center h-9 px-4 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong active:bg-blue-800
focus:outline-none focus-visible:ring-2 focus-visible:ring-accent focus-visible:ring-offset-1
transition-colors duration-100"
+3 -3
View File
@@ -27,7 +27,7 @@
<button type="button"
data-action="click->ui--clipboard#copy"
class="mt-2 inline-flex items-center gap-1.5 px-3 h-9 rounded-lg text-xs font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
<i class="fa-solid fa-copy text-[11px]" aria-hidden="true"></i>
<span data-ui--clipboard-target="label">{{ 'settings.security.codes.copy'|trans }}</span>
</button>
@@ -238,7 +238,7 @@
</div>
<button type="submit"
class="shrink-0 inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer">
{{ 'settings.security.enrol.submit'|trans }}
</button>
</form>
@@ -268,7 +268,7 @@
<a href="{{ path('app_settings_index', { section: 'security', enrol: 1 }) }}"
class="inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors">
bg-accent hover:bg-accent-strong text-accent-ink transition-colors">
<i class="fa-solid fa-shield-halved text-xs" aria-hidden="true"></i>
{{ 'settings.security.enable'|trans }}
</a>
+1 -1
View File
@@ -205,7 +205,7 @@ Variables:
{{ 'form.cancel'|trans }}
</a>
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink bg-accent hover:bg-accent-strong transition-colors cursor-pointer">
{{ 'form.submit'|trans }}
</button>
</div>
+1 -1
View File
@@ -387,7 +387,7 @@
data-ui--modal-title-value="{{ 'sidebar.accounts.add'|trans }}"
data-ui--modal-src-value="{{ path('app_account_new') }}"
class="inline-flex items-center gap-2 px-3 h-9 rounded-lg text-sm font-medium
bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer"
bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-plus text-xs" aria-hidden="true"></i>
{{ 'sidebar.accounts.add'|trans }}
@@ -130,7 +130,7 @@ Variables:
<div class="flex flex-wrap gap-2">
{% for weekday in 1..7 %}
<label class="cursor-pointer rounded-lg border border-field bg-field px-2.5 py-1.5 text-xs text-ink-soft
has-[:checked]:border-accent has-[:checked]:bg-accent has-[:checked]:text-white">
has-[:checked]:border-accent has-[:checked]:bg-accent has-[:checked]:text-accent-ink">
<input type="checkbox"
name="weekdays[]"
value="{{ weekday }}"
@@ -242,7 +242,7 @@ Variables:
text-ink-soft bg-field border border-field hover:bg-hover transition-colors">{{ 'form.cancel'|trans }}</button>
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong transition-colors">{{ 'form.submit'|trans }}</button>
</div>
</form>
@@ -159,7 +159,7 @@ Variables:
text-ink-soft bg-field border border-field hover:bg-hover transition-colors">{{ 'form.cancel'|trans }}</button>
<button type="submit"
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-white
class="inline-flex items-center justify-center h-8 px-3.5 rounded-lg text-sm font-medium text-accent-ink
bg-accent hover:bg-accent-strong transition-colors">{{ 'form.submit'|trans }}</button>
</div>
</form>
+2 -2
View File
@@ -67,7 +67,7 @@ Variables:
data-action="click->ui--modal#open"
data-ui--modal-title-value="{{ 'calendar.share.form.add'|trans }}"
data-ui--modal-src-value="{{ path('app_settings_sharing_link_new') }}"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-plus text-[10px]" aria-hidden="true"></i>
{{ 'calendar.share.form.add'|trans }}
@@ -160,7 +160,7 @@ Variables:
data-action="click->ui--modal#open"
data-ui--modal-title-value="{{ 'calendar.booking.form.add'|trans }}"
data-ui--modal-src-value="{{ path('app_settings_sharing_booking_new') }}"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-white transition-colors cursor-pointer"
class="inline-flex items-center gap-1.5 px-2.5 h-8 rounded-lg text-xs font-medium bg-accent hover:bg-accent-strong text-accent-ink transition-colors cursor-pointer"
>
<i class="fa-solid fa-plus text-[10px]" aria-hidden="true"></i>
{{ 'calendar.booking.form.add'|trans }}
+1 -1
View File
@@ -55,7 +55,7 @@ password in a max-w-sm card reads as a wall.
<button
type="submit"
id="install-submit"
class="mt-7 w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface"
class="mt-7 w-full bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-accent focus:ring-offset-2 ring-offset-surface"
>
{{ 'setup.install.submit'|trans }}
</button>
+3 -3
View File
@@ -89,7 +89,7 @@ action and is never hidden.
<a href="{{ hasUsers ? path('app_login') : path('app_install') }}"
id="restore-finish"
class="mt-4 block w-full text-center bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors">
class="mt-4 block w-full text-center bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors">
{{ (hasUsers ? 'setup.restore.sign_in' : 'setup.restore.continue')|trans }}
</a>
{% endset %}
@@ -127,7 +127,7 @@ action and is never hidden.
</div>
<button type="submit" id="restore-apply"
class="w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors">
class="w-full bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors">
{{ 'admin.config_backup.review.apply'|trans }}
</button>
</form>
@@ -156,7 +156,7 @@ action and is never hidden.
</div>
<button type="submit" id="restore-submit"
class="w-full bg-accent hover:bg-accent-strong text-white text-sm font-medium py-2 rounded-lg transition-colors">
class="w-full bg-accent hover:bg-accent-strong text-accent-ink text-sm font-medium py-2 rounded-lg transition-colors">
{{ 'setup.restore.submit'|trans }}
</button>
</form>
+2 -1
View File
@@ -2094,7 +2094,8 @@ sidebar:
heading: Konten
loading: Wird geladen…
none: Noch keine Konten
toggle: Kontoordner ein-/ausklappen
open: '%account% öffnen'
toggle: 'Ordner in %account% ein-/ausklappen'
compose: Schreiben
labels:
add: Label erstellen
+2 -1
View File
@@ -2054,7 +2054,8 @@ sidebar:
heading: Accounts
loading: Loading…
none: No accounts yet
toggle: Toggle account folders
open: 'Open %account%'
toggle: 'Show or hide folders in %account%'
compose: Compose
labels:
add: Create label
+2 -1
View File
@@ -1731,7 +1731,8 @@ sidebar:
heading: Th' crew
loading: Haulin' aboard…
none: No crew yet
toggle: Open or close the crew's lockers
open: 'Board %account%'
toggle: 'Open or close the lockers in %account%'
compose: Scribble
labels:
add: Hoist a new flag
@@ -0,0 +1,9 @@
#!/bin/sh
J=/tmp/claude-1000/-home-karatektus-plmailstuff/b28e1914-8509-423e-8a57-1bb9498e8e5c/scratchpad/c2.txt
rm -f "$J"
curl -s -c "$J" -o /dev/null http://127.0.0.1:8013/login
curl -s -b "$J" -c "$J" -X POST \
-H 'Sec-Fetch-Site: same-origin' \
-d 'email=e2e@plmail.test' -d 'password=testpass123' -d '_csrf_token=csrf-token' \
-o /dev/null -w 'login: %{http_code} -> %{redirect_url}\n' \
http://127.0.0.1:8013/login