@uni-design-system/uni-angular 10.2.0 → 10.3.0
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
# @uni-design-system/uni-angular
|
|
2
2
|
|
|
3
|
+
## 10.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`ab1689a`](https://github.com/uni-design-system/uni/commit/ab1689a8e6ddf26943403ec32e5d4871bc9f0fb6) Thanks [@gaenglish](https://github.com/gaenglish)! - `uni-button`: the focus ring is themed, and the theme now outranks the reset.
|
|
8
|
+
|
|
9
|
+
**Five of the twelve variants had no visible keyboard focus ring.** The ring
|
|
10
|
+
resolved the variant _name_ as a colour token — the pattern 10.2.0 removed from
|
|
11
|
+
checkbox, radio and toggle, missed on the one component where it costs an
|
|
12
|
+
accessibility failure rather than a wrong colour:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
outline: `2px solid ${this.theme.colors()[this.variant()]}`;
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`ghost` resolves to `transparent`, so its ring was drawn invisibly.
|
|
19
|
+
`light`, `onLight`, `dark` and `onDark` have no colour token at all, so the
|
|
20
|
+
declaration became `2px solid undefined` and the parser dropped it — as would
|
|
21
|
+
any intent a consumer registers. In every case `outline-offset` survived, so
|
|
22
|
+
the element still shifted on focus and the missing ring went unnoticed. This
|
|
23
|
+
was live without the registry involved.
|
|
24
|
+
|
|
25
|
+
The colour now comes from the variant's theme entry via `variantOptions`, the
|
|
26
|
+
mechanism the selection controls already use, and falls back to the reserved
|
|
27
|
+
`primary` accent rather than to nothing. Each variant keeps the ring colour it
|
|
28
|
+
had; `ghost` gains a visible one. The ring also routes through the shared
|
|
29
|
+
`focusRingStyle`, so a theme defining `focusRing` primitives restyles the button
|
|
30
|
+
alongside every other control.
|
|
31
|
+
|
|
32
|
+
**A theme could not give a button a border.** `border`, `outline`, `overflow`
|
|
33
|
+
and `transition` were applied _after_ the theme's styles, so a variant
|
|
34
|
+
declaring a border was silently erased and `!important` was the only way
|
|
35
|
+
through — which then spread to every state adjusting that border, since the
|
|
36
|
+
shorthand outranks the longhand.
|
|
37
|
+
|
|
38
|
+
The base theme was caught by its own reset: `secondary` is commented "Hollow"
|
|
39
|
+
and declares `1px solid`, and has been rendering borderless. **It now renders
|
|
40
|
+
its border** — the one visible change here for anyone on the default theme.
|
|
41
|
+
|
|
42
|
+
Those four properties move ahead of the theme's styles, resolving the
|
|
43
|
+
`TODO: Set priority on theme-defined styles` that sat on this line. Structure
|
|
44
|
+
the component genuinely owns — `position` for the ripple, the symbol slots —
|
|
45
|
+
stays after, and the reset still applies to every variant that does not
|
|
46
|
+
override it.
|
|
47
|
+
|
|
48
|
+
**`uni-icon-button`'s hover moved to the theme too.** It branched on
|
|
49
|
+
`variant() === 'ghost'` to choose between a raised shadow and a translucent
|
|
50
|
+
wash, after the theme's own styles. Being a binary partition, every intent a
|
|
51
|
+
consumer registered fell into the not-ghost half and was given a lift whether
|
|
52
|
+
or not it suited — a recessive intent included — and no theme could correct it.
|
|
53
|
+
Both themes in this repo declare a ghost hover and had it silently overridden.
|
|
54
|
+
|
|
55
|
+
Both treatments now live in `iconButton.variants` beside the colours they belong
|
|
56
|
+
with. Rendering is unchanged for the variants the theme styles; a variant it
|
|
57
|
+
does not style no longer receives a hover it never asked for, and the `disabled`
|
|
58
|
+
variant loses one it should never have had, since its block is also spread into
|
|
59
|
+
`&:disabled`.
|
|
60
|
+
|
|
61
|
+
**`uni-icon-button` had no focus indicator at all.** Its structural block cleared
|
|
62
|
+
the user-agent outline and put nothing back, in every variant — so the close
|
|
63
|
+
affordance in every dialog and drawer header was unreachable-looking under
|
|
64
|
+
keyboard navigation. This was not reported; it was found while verifying the
|
|
65
|
+
button fix above.
|
|
66
|
+
|
|
67
|
+
It now draws the shared ring, with its colour read from the same
|
|
68
|
+
`variantOptions.focusColor` the button uses. The indicator is applied last on
|
|
69
|
+
purpose: its appearance is the theme's, through `focusColor` and the `focusRing`
|
|
70
|
+
primitives, but whether one exists is not a style a theme should be able to
|
|
71
|
+
switch off by accident.
|
|
72
|
+
|
|
73
|
+
## 10.2.1
|
|
74
|
+
|
|
3
75
|
## 10.2.0
|
|
4
76
|
|
|
5
77
|
### Minor Changes
|
|
@@ -3173,23 +3173,47 @@ class UniIconButtonComponent {
|
|
|
3173
3173
|
!this.loading() && {
|
|
3174
3174
|
padding: 0,
|
|
3175
3175
|
},
|
|
3176
|
-
|
|
3177
|
-
|
|
3178
|
-
|
|
3179
|
-
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
|
|
3183
|
-
|
|
3184
|
-
|
|
3185
|
-
|
|
3176
|
+
// The hover treatment is the theme's, declared per variant alongside the
|
|
3177
|
+
// colours it belongs with. It used to live here as a pair of branches on
|
|
3178
|
+
// `variant() === 'ghost'`, which was the last place a component decided a
|
|
3179
|
+
// variant's *appearance* from its *name*.
|
|
3180
|
+
//
|
|
3181
|
+
// That partition was binary, so under an open registry every intent a
|
|
3182
|
+
// consumer registered fell into the not-ghost half and got a raised
|
|
3183
|
+
// shadow whether or not it suited — a recessive intent included. And
|
|
3184
|
+
// because the branches were applied after the theme's own styles, no
|
|
3185
|
+
// theme could correct it: both themes in this repo declare a ghost hover
|
|
3186
|
+
// and had it silently overridden.
|
|
3186
3187
|
!this.loading() && {
|
|
3187
3188
|
'&:disabled': {
|
|
3188
3189
|
...this.config().variants?.disabled,
|
|
3189
3190
|
},
|
|
3190
3191
|
},
|
|
3192
|
+
// The keyboard-focus indicator (WCAG 2.4.7). The structural block above
|
|
3193
|
+
// clears the user-agent outline and, until now, put nothing back — so an
|
|
3194
|
+
// icon button had no focus indicator at all, in any variant. That is the
|
|
3195
|
+
// close affordance in every dialog and drawer header.
|
|
3196
|
+
//
|
|
3197
|
+
// Applied last on purpose: its *appearance* is the theme's, through
|
|
3198
|
+
// `focusColor` and the `focusRing` primitives `focusRingStyle` reads, but
|
|
3199
|
+
// whether an indicator exists is not a style choice a theme should be
|
|
3200
|
+
// able to switch off by accident.
|
|
3201
|
+
{
|
|
3202
|
+
'&:focus-visible': { ...this.theme.focusRingStyle(this.focusRingColor()) },
|
|
3203
|
+
},
|
|
3191
3204
|
]);
|
|
3192
3205
|
}, ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
3206
|
+
/**
|
|
3207
|
+
* The focus ring's colour, from the variant's theme entry — never from the
|
|
3208
|
+
* variant *name*, which is what left `uni-button`'s ring transparent on
|
|
3209
|
+
* `ghost` and absent on every unthemed intent. Falls back to the reserved
|
|
3210
|
+
* `primary` accent so a ring always renders.
|
|
3211
|
+
*/
|
|
3212
|
+
focusRingColor = computed(() => {
|
|
3213
|
+
const colors = this.theme.colors();
|
|
3214
|
+
const token = this.config().variantOptions?.[this.variant()]?.focusColor;
|
|
3215
|
+
return (token && colors[token]) || colors['primary'];
|
|
3216
|
+
}, ...(ngDevMode ? [{ debugName: "focusRingColor" }] : /* istanbul ignore next */ []));
|
|
3193
3217
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.12", ngImport: i0, type: UniIconButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3194
3218
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.12", type: UniIconButtonComponent, isStandalone: true, selector: "button[uni-icon-button], button[icon-button]", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, iconName: { classPropertyName: "iconName", publicName: "iconName", isSignal: true, isRequired: false, transformFunction: null }, symbolName: { classPropertyName: "symbolName", publicName: "symbolName", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, disable: { classPropertyName: "disable", publicName: "disable", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, opticalSize: { classPropertyName: "opticalSize", publicName: "opticalSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.disabled": "disable() || loading() || null", "attr.aria-busy": "loading() ? 'true' : null", "attr.aria-label": "ariaLabel() || null", "class": "className()" } }, hostDirectives: [{ directive: RippleDirective }], ngImport: i0, template: `
|
|
3195
3219
|
@if (loading()) {
|
|
@@ -5495,18 +5519,28 @@ class UniButtonComponent extends BaseComponent {
|
|
|
5495
5519
|
// radii/families in older themes) keep winning.
|
|
5496
5520
|
this.theme.radius(this.componentOptions().borderRadius),
|
|
5497
5521
|
{ ...this.theme.typeface(this.componentOptions().typeface) },
|
|
5498
|
-
|
|
5499
|
-
|
|
5500
|
-
|
|
5522
|
+
// Presentational defaults, deliberately *before* `style()` so the theme
|
|
5523
|
+
// outranks them. They used to sit after it, which made them unthemeable:
|
|
5524
|
+
// a variant could not give a button a border without `!important`, and
|
|
5525
|
+
// the shorthand then forced `!important` onto every state that adjusted
|
|
5526
|
+
// it. The base theme was caught by this too — its `secondary` variant is
|
|
5527
|
+
// commented "Hollow" and declares `1px solid`, which this block erased.
|
|
5501
5528
|
{
|
|
5502
|
-
display: 'flex',
|
|
5503
|
-
alignItems: 'center',
|
|
5504
|
-
position: 'relative',
|
|
5505
5529
|
overflow: 'hidden',
|
|
5506
5530
|
outline: 0,
|
|
5507
5531
|
border: 0,
|
|
5508
5532
|
cursor: 'pointer',
|
|
5509
5533
|
transition: 'all 0.28s ease',
|
|
5534
|
+
},
|
|
5535
|
+
this.style() && {
|
|
5536
|
+
...this.style(),
|
|
5537
|
+
},
|
|
5538
|
+
// Structure the component genuinely owns: `position` anchors the ripple,
|
|
5539
|
+
// and the rest is its internal slot layout.
|
|
5540
|
+
{
|
|
5541
|
+
display: 'flex',
|
|
5542
|
+
alignItems: 'center',
|
|
5543
|
+
position: 'relative',
|
|
5510
5544
|
'&:disabled': {
|
|
5511
5545
|
cursor: 'not-allowed !important',
|
|
5512
5546
|
},
|
|
@@ -5526,14 +5560,14 @@ class UniButtonComponent extends BaseComponent {
|
|
|
5526
5560
|
fontSize: this.symbolSize(),
|
|
5527
5561
|
},
|
|
5528
5562
|
},
|
|
5529
|
-
// Hover/pressed styling
|
|
5530
|
-
//
|
|
5531
|
-
//
|
|
5563
|
+
// Hover/pressed styling lives in the theme's button variants (solid vs.
|
|
5564
|
+
// hollow, per-variant states). The keyboard-focus indicator (WCAG 2.4.7)
|
|
5565
|
+
// stays component-owned, but its *colour* is the theme's — see
|
|
5566
|
+
// `focusRingColor`. Routed through the shared `focusRingStyle` so a theme
|
|
5567
|
+
// defining `focusRing` border/shadow primitives restyles it here too,
|
|
5568
|
+
// exactly as it already does for checkbox, radio and toggle.
|
|
5532
5569
|
{
|
|
5533
|
-
'&:focus-visible': {
|
|
5534
|
-
outline: `2px solid ${this.theme.colors()[this.variant()]}`,
|
|
5535
|
-
outlineOffset: '2px',
|
|
5536
|
-
},
|
|
5570
|
+
'&:focus-visible': { ...this.theme.focusRingStyle(this.focusRingColor()) },
|
|
5537
5571
|
},
|
|
5538
5572
|
this.fullWidth() && {
|
|
5539
5573
|
width: '100%',
|
|
@@ -5552,6 +5586,27 @@ class UniButtonComponent extends BaseComponent {
|
|
|
5552
5586
|
},
|
|
5553
5587
|
},
|
|
5554
5588
|
]), ...(ngDevMode ? [{ debugName: "className" }] : /* istanbul ignore next */ []));
|
|
5589
|
+
/**
|
|
5590
|
+
* The focus ring's colour, from the variant's theme entry.
|
|
5591
|
+
*
|
|
5592
|
+
* This used to be `colors[variant()]` — the variant *name* resolved as a
|
|
5593
|
+
* colour token. That held together only while every variant happened to also
|
|
5594
|
+
* be a colour, and it failed silently in both directions: `ghost` resolves to
|
|
5595
|
+
* `transparent`, and `light`/`onLight`/`dark`/`onDark` (and any name a
|
|
5596
|
+
* consumer registers) resolve to nothing, emitting `2px solid undefined`
|
|
5597
|
+
* which the parser drops. `outline-offset` survived either way, so the
|
|
5598
|
+
* element still shifted on focus and the missing ring went unnoticed.
|
|
5599
|
+
*
|
|
5600
|
+
* Falls back to the reserved `primary` accent rather than to `currentColor`:
|
|
5601
|
+
* the ring is drawn outside the element, so on a filled button
|
|
5602
|
+
* `currentColor` is the label colour and would sit near-invisibly against
|
|
5603
|
+
* the page rather than the button.
|
|
5604
|
+
*/
|
|
5605
|
+
focusRingColor = computed(() => {
|
|
5606
|
+
const colors = this.theme.colors();
|
|
5607
|
+
const token = this.variantRoles()?.focusColor;
|
|
5608
|
+
return (token && colors[token]) || colors['primary'];
|
|
5609
|
+
}, ...(ngDevMode ? [{ debugName: "focusRingColor" }] : /* istanbul ignore next */ []));
|
|
5555
5610
|
symbolSize = computed(() => {
|
|
5556
5611
|
const fontSize = parseFloat(String(this.style()['fontSize'] ?? ''));
|
|
5557
5612
|
// Fall back to the default icon size when the theme defines no fontSize
|