@yuneta/gobj-ui 7.23.131 → 7.23.132
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2290,6 +2290,56 @@ too; the shell's stylesheet raises Bulma's 30% alpha to 70% (2.47:1 → 7.96 in
|
|
|
2290
2290
|
dark) where Bulma declares the variable, since a `:root` override does not
|
|
2291
2291
|
reach it.
|
|
2292
2292
|
|
|
2293
|
+
### A control without a name is a bug: `title` + `aria-label`, always
|
|
2294
|
+
|
|
2295
|
+
**Every control this library draws — and every control an app draws with it —
|
|
2296
|
+
carries a `title` AND an `aria-label`, and both are translatable.** A control
|
|
2297
|
+
is any `input`, `select`, `textarea`, `button`, or anything that behaves as
|
|
2298
|
+
one. All four attributes are written where the control is built:
|
|
2299
|
+
|
|
2300
|
+
```js
|
|
2301
|
+
['button', {class: 'FOO_SAVE button',
|
|
2302
|
+
title: t('save'), 'data-i18n-title': 'save',
|
|
2303
|
+
'aria-label': t('save'), 'data-i18n-aria-label': 'save'}, …]
|
|
2304
|
+
```
|
|
2305
|
+
|
|
2306
|
+
It is a floor, not a preference. The ecosystem was swept against it — the
|
|
2307
|
+
deployed page of six SPAs, read control by control — and the target is **zero
|
|
2308
|
+
controls without a name**. Three things it exists to stop, each of which
|
|
2309
|
+
shipped:
|
|
2310
|
+
|
|
2311
|
+
| What looks like a name | Why it is not |
|
|
2312
|
+
|---|---|
|
|
2313
|
+
| A `<label>` **beside** the control (Bulma's `field`) | No `for`, no wrapping: it names the box for the eye and for nothing else |
|
|
2314
|
+
| `<label for="x">` over a control carrying only `name="x"` | `for` matches an **`id`**, which the control does not have — correct-looking source, no association |
|
|
2315
|
+
| A `placeholder` | Gone the moment something is typed; a reader need not announce it |
|
|
2316
|
+
| The visible text | Disappears with `is-hidden-mobile`; and where the text is the STATE (`on`/`off`), it does not say what the control DOES |
|
|
2317
|
+
|
|
2318
|
+
A `<label>` that **wraps** its control is the one shape that needs no
|
|
2319
|
+
`aria-label` — the label IS the accessible name. And a **literal**
|
|
2320
|
+
`aria-label` next to a visible `i18n` label is worse than none: it OVERRIDES
|
|
2321
|
+
the translated text for a reader.
|
|
2322
|
+
|
|
2323
|
+
Two things carry no attribute anyone can set, and are named after the render
|
|
2324
|
+
instead — and again on every rebuild, because a name written onto a widget's
|
|
2325
|
+
DOM is a race with the next one:
|
|
2326
|
+
|
|
2327
|
+
- **What a widget draws for itself**: Tabulator's header filters and its
|
|
2328
|
+
row-selection checkbox (`yui_tabulator_name_filters` /
|
|
2329
|
+
`yui_tabulator_name_row_selects`, hung off `columnsLoaded` and
|
|
2330
|
+
`renderComplete`), Tom Select's box in front of the `<select>` it hides
|
|
2331
|
+
(`name_form_control`).
|
|
2332
|
+
- **An `<option>`**, which is text like any other: it carries `data-i18n`,
|
|
2333
|
+
with `value` kept explicit — a translated option with no value tells the FSM
|
|
2334
|
+
to enter a mode that does not exist.
|
|
2335
|
+
|
|
2336
|
+
**How to check it.** Not with a grep: dump `title`/`aria-label` from the
|
|
2337
|
+
DEPLOYED DOM, resolve each control's name the way a reader does (`aria-label`
|
|
2338
|
+
→ `label[for]` → a wrapping `<label>` → the text → `title` → `placeholder`),
|
|
2339
|
+
then switch language and diff. A key that arrives as a VARIABLE — from a data
|
|
2340
|
+
table, a helper's argument, a local alias of `t()` — is invisible to
|
|
2341
|
+
`validate-locales` and shows up only there.
|
|
2342
|
+
|
|
2293
2343
|
### i18n: a string must be able to CHANGE language, not just be translated once
|
|
2294
2344
|
|
|
2295
2345
|
Passing a string through `t()` is **not** enough. `refresh_language()` only
|