mirror of
https://github.com/karatektus/pl_mail.git
synced 2026-10-25 10:04:18 +00:00
feat(ui): every select is a Tom Select, themed from the palette tokens
`select-field` got the closed control right — appearance:none, the app's fill, the app's chevron — and could never get the popup, because the popup is the one part of a form control CSS does not reach. color-scheme was the last thing left to try and it only picks light or dark: the list is still the platform's font, the platform's row height and the platform's highlight, sitting in front of a themed app in five of the six themes. Compose already had the answer for its address fields. This is that same widget on every other single-select in the app, so there is one dropdown here instead of two. - assets/controllers/ui/select_controller.js progressively enhances a native <select>. The element stays in the DOM as the source of truth, so forms post identically, `onchange="…requestSubmit()"` and `data-action="change->…"` keep firing, and no-JS renders the native control the stylesheet still styles. - The panel is parented to <body>: every call site is inside something that clips. It flips above the control when there is no room below and caps itself to the room there is, which Tom Select does not do on its own, and closes on scroll rather than being left behind by the pane it was anchored to. - Short lists lose the search box entirely, so a five-item picker behaves like the native control it replaced instead of blinking a text caret. - tom-select.css now skins .single as the twin of `select-field` — same fill, border, radius, chevron and height, the last one measured per call site so h-8 rows stay h-8. No per-theme rules: the six themes differ only in what the tokens resolve to. - The rule editor builds five selects in JavaScript and was missed by the last sweep; it stamps the attributes itself now. - Compose's font pickers are converted too, frameless so the format bar keeps its character. Their labels were the lookup keys, which is why they were English in a German UI; the values carry the keys now. - "No results found" arrives from Twig |trans (EN/DE/en_PI). Left native, deliberately: compose's multi-select address fields, which have a richer Tom Select of their own; the provider preset, enhanced by UX Autocomplete because it fetches its choices; and compose's sr-only account select, which is never shown. PageRendersTest now sweeps every page for a select that is none of those and carries no widget. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
06fd104799
commit
e453cc9516
22 files changed
+658
-43
No files matched your search
@@ -1,5 +1,6 @@
|
||||
{# templates/compose/_window.html.twig #}
|
||||
{% form_theme form '_layout/form/compose_theme.html.twig' %}
|
||||
{% import '_partials/_select.html.twig' as select %}
|
||||
|
||||
{#
|
||||
Renders in two places:
|
||||
@@ -152,7 +153,11 @@ Variables: form, message, ctx (inline, frame, thread, urlParams)
|
||||
<div data-compose--compose-target="collapsible"
|
||||
class="flex flex-col flex-1 min-h-0">
|
||||
|
||||
{# ── Hidden account select (submitted with form) ───────── #}
|
||||
{# ── Hidden account select (submitted with form) ─────────
|
||||
Deliberately not a Tom Select. It is never shown: the "From"
|
||||
line is a custom menu built from these options, and this is only
|
||||
the value the form posts. A widget here would be one the user
|
||||
cannot see and the screen reader would announce twice. #}
|
||||
<select id="{{ form.account.vars.id }}"
|
||||
name="{{ form.account.vars.full_name }}"
|
||||
data-compose--compose-target="accountSelect"
|
||||
@@ -321,27 +326,41 @@ Variables: form, message, ctx (inline, frame, thread, urlParams)
|
||||
bg-sunken
|
||||
rounded-full px-2 py-1">
|
||||
|
||||
{# Bare rather than framed: this is a strip of icon buttons,
|
||||
and two boxed fields in the middle of it would read as a
|
||||
different toolbar. Only the popup changes — which is the
|
||||
point, since the format bar scrolls horizontally on
|
||||
phones and a native popup was the one thing in it the
|
||||
theme never reached.
|
||||
|
||||
The option labels used to be the lookup keys, which is
|
||||
why they were English in a German UI. The values carry
|
||||
the key now and the labels are free to be translated. #}
|
||||
<select data-compose--compose-toolbar-target="fontFamily"
|
||||
data-action="change->compose--compose-toolbar#changeFontFamily"
|
||||
aria-label="{{ 'compose.font_family.label'|trans }}"
|
||||
{{ select.enhance(bare = true) }}
|
||||
class="shrink-0 bg-transparent border-none outline-none text-xs cursor-pointer px-1 py-0.5 rounded
|
||||
text-ink-muted
|
||||
hover:bg-hover transition-colors">
|
||||
<option>Sans Serif</option>
|
||||
<option>Serif</option>
|
||||
<option>Monospace</option>
|
||||
<option value="sans">{{ 'compose.font_family.sans'|trans }}</option>
|
||||
<option value="serif">{{ 'compose.font_family.serif'|trans }}</option>
|
||||
<option value="monospace">{{ 'compose.font_family.monospace'|trans }}</option>
|
||||
</select>
|
||||
|
||||
<div class="w-px h-4 bg-line mx-1 shrink-0"></div>
|
||||
|
||||
<select data-compose--compose-toolbar-target="fontSize"
|
||||
data-action="change->compose--compose-toolbar#changeFontSize"
|
||||
aria-label="{{ 'compose.font_size.label'|trans }}"
|
||||
{{ select.enhance(bare = true) }}
|
||||
class="shrink-0 bg-transparent border-none outline-none text-xs cursor-pointer px-1 py-0.5 rounded
|
||||
text-ink-muted
|
||||
hover:bg-hover transition-colors">
|
||||
<option>Small</option>
|
||||
<option selected>Normal</option>
|
||||
<option>Large</option>
|
||||
<option>Huge</option>
|
||||
<option value="small">{{ 'compose.font_size.small'|trans }}</option>
|
||||
<option value="normal" selected>{{ 'compose.font_size.normal'|trans }}</option>
|
||||
<option value="large">{{ 'compose.font_size.large'|trans }}</option>
|
||||
<option value="huge">{{ 'compose.font_size.huge'|trans }}</option>
|
||||
</select>
|
||||
|
||||
<div class="w-px h-4 bg-line mx-1 shrink-0"></div>
|
||||
|
||||
Reference in new issue
Block a user