Pasted and dropped images used to get the file name as alt text, and
there was no way to change it. Now a small dialog asks what the image
shows right after it is inserted, with a "Decorative image" option that
writes alt="". An image already in the text can be described from the
toolbar or from the ALT button on the selected image. The plain-text
part of an HTML mail writes described images as "[Image: ...]" and
leaves decorative ones out.
The formatting toolbar now also re-renders when only the selection
changes, so its pressed states and the image button follow the caret.
Settings get a page of their own for accessibility, with presets on top
(screen reader, low vision, dyslexia, focus, keyboard and motor, motion
and seizure safe, deaf and hard of hearing) that change several options
at once and can be undone, then the options by topic, and a reset.
Text size used to be a fixed 14/16/18px on the root, which threw away
the size people set in their browser. It is now a percentage of the
browser's size, from 87.5% to 200%. Motion, contrast and transparency
follow the system by default and can be overridden either way; the
old Animations switch becomes Reduce motion. The visual options are
applied before the first paint, so the page no longer flashes at the
wrong size.
- `lib/accessibility-settings.ts`: the new settings, their allowed
values, and the code that writes them onto `<html>`
- `app/accessibility.css`: bundled fonts (Atkinson Hyperlegible Next,
Lexend, OpenDyslexic), text spacing, a focus outline that survives
Windows contrast themes, more-contrast colours on any theme, reduced
transparency, a large pointer
- admins can preset every new option but lock only shortcuts, send
confirmation and the notification duration; a lock on text size or
another reading aid works as a default
- always-light mail and toolbar labels now sync, and imports drop
values the page doesn't know
- font size and animations move off Appearance, the plain text font
off Reading; everyday settings such as conversation view and undo
send show on both their own page and Accessibility
A plugin's results to a search came all at once after its handler answered,
with nothing before: the block then appeared above the message list and
pushed it down, under a pointer about to click a row. onProvideSearchResults
handlers that search elsewhere (a CRM's search by meaning) take seconds.
Each plugin's answer now shows as it comes, and the store keeps the plugins
still asked. One that has not answered after 300 ms gets the block at a fixed
height with placeholder rows under "Searching for more results…"; its
entries then fill that height, so the list moves once, with its own results.
A plugin that answers at once (one not searching for this query) shows
nothing.
An entry from onProvideSearchResults may wrap what matched in <mark>, as
SearchSnippet/get does, and the block above the message list highlights
it with the list's own SearchSnippetText. The host keeps the marks,
escapes everything else and cuts the snippet by its text, closing a mark
it cuts, so the snippet is still never rendered as HTML.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The export declared VERSION:3.0 but wrote vCard 4.0 syntax, and wrote the JSContact phone feature \"mobile\" as TYPE=MOBILE, which is no vCard type, so importers dropped such numbers.
- Declare VERSION:4.0 and write 4.0 throughout: basic-format dates and timestamps, data: URIs for inline media, VALUE=text for a UID or RELATED that is no URI, geo: URIs, lines folded at 75 octets, CRLF after every line, and the webmail's own PRODID.
- Map "mobile" to CELL and back; MAIN-NUMBER and x- types are kept.
- Write N before FN: some importers ignore the name otherwise.
- The contact form stores mobile phones as "mobile" (RFC 9553) and still reads the "cell" it used to write.