Skip to content
This repository was archived by the owner on Jan 13, 2025. It is now read-only.

Commit 311ab4d

Browse files
feat(focus-ring): support variable shapes in outward variant
PiperOrigin-RevId: 512635421
1 parent fa27ba6 commit 311ab4d

File tree

5 files changed

+361
-6
lines changed

5 files changed

+361
-6
lines changed

packages/mdc-focus/_focus-ring-outward-theme.scss

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
@use '@material/theme/keys';
88
@use '@material/theme/validate';
9+
@use '@material/shape/shape';
910
@use './focus-ring-shared-theme';
1011

1112
$_custom-property-prefix: 'focus-ring-outward';
@@ -15,6 +16,9 @@ $default-outward-theme: map.merge(
1516
focus-ring-shared-theme.$default-shared-theme,
1617
(
1718
focus-ring-shared-theme.$ring-offset-key: 2px,
19+
// Target shape can be provided as a single value, or as a list with
20+
// 1-4 values where each value would correspond to border radius of one
21+
// or more corners.
1822
focus-ring-shared-theme.$target-shape-key: 0px,
1923
)
2024
);
@@ -26,22 +30,42 @@ $default-outward-theme: map.merge(
2630
/// @param {Map} $theme - A map with one or more of the keys of $default-outward-theme.
2731
@mixin theme($theme) {
2832
$theme: validate.theme($default-outward-theme, $theme);
33+
$theme: _expand-target-shape-value($theme);
2934
@include keys.declare-custom-properties($theme, $_custom-property-prefix);
3035
}
3136

3237
@mixin theme-styles($theme: $default-outward-theme) {
3338
$theme: validate.theme-styles($default-outward-theme, $theme);
39+
$theme: _expand-target-shape-value($theme);
3440
$theme: keys.create-theme-vars($theme, $_custom-property-prefix);
3541

3642
$ring-color: map.get($theme, focus-ring-shared-theme.$ring-color-key);
3743
$ring-offset: map.get($theme, focus-ring-shared-theme.$ring-offset-key);
3844
$track-width: map.get($theme, focus-ring-shared-theme.$track-width-key);
39-
$target-shape: map.get($theme, focus-ring-shared-theme.$target-shape-key);
45+
$target-shape-start-start: map.get(
46+
$theme,
47+
'#{focus-ring-shared-theme.$target-shape-key}-start-start'
48+
);
49+
$target-shape-start-end: map.get(
50+
$theme,
51+
'#{focus-ring-shared-theme.$target-shape-key}-start-end'
52+
);
53+
$target-shape-end-end: map.get(
54+
$theme,
55+
'#{focus-ring-shared-theme.$target-shape-key}-end-end'
56+
);
57+
$target-shape-end-start: map.get(
58+
$theme,
59+
'#{focus-ring-shared-theme.$target-shape-key}-end-start'
60+
);
4061

4162
/// Mold the focus ring to the target shape.
4263
/// See the diagram for insights into why the border-radius calc is needed:
4364
/// http://screen/9J9CzpCxJxxDHCb.png
44-
border-radius: calc($target-shape + $ring-offset);
65+
border-start-start-radius: calc($target-shape-start-start + $ring-offset);
66+
border-start-end-radius: calc($target-shape-start-end + $ring-offset);
67+
border-end-end-radius: calc($target-shape-end-end + $ring-offset);
68+
border-end-start-radius: calc($target-shape-end-start + $ring-offset);
4569
inset: calc(-1 * $ring-offset);
4670
box-shadow: 0 0 0 $track-width $ring-color;
4771
// HCM ignores box-shadow, so a transparent outline is added to ensure
@@ -76,3 +100,23 @@ $default-outward-theme: map.merge(
76100
}
77101
}
78102
}
103+
104+
/// Replaces target shape value or list provided in theme with four key-value
105+
/// pairs corresponding to four corners' border radiuses.
106+
///
107+
/// @example:
108+
/// _expand-target-shape-value(('target-shape': 4px)) =>
109+
/// (
110+
/// 'target-shape-start-start': 4px,
111+
/// 'target-shape-start-end': 4px,
112+
/// 'target-shape-end-end': 4px,
113+
/// 'target-shape-end-start': 4px
114+
/// )
115+
///
116+
@function _expand-target-shape-value($theme) {
117+
@return shape.resolve-theme(
118+
$theme,
119+
meta.get-function('resolver', $module: 'shape'),
120+
focus-ring-shared-theme.$target-shape-key
121+
);
122+
}

packages/mdc-focus/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
},
1616
"dependencies": {
1717
"@material/theme": "^14.0.0",
18-
"@material/tokens": "^14.0.0"
18+
"@material/tokens": "^14.0.0",
19+
"@material/shape": "^14.0.0"
1920
}
2021
}

packages/mdc-focus/test/focus-ring-outward-theme.test.scss

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,13 @@
2929
}
3030

3131
@include test.expect {
32+
--mdc-focus-ring-outward-target-shape-start-start: 5px;
33+
--mdc-focus-ring-outward-target-shape-start-end: 5px;
34+
--mdc-focus-ring-outward-target-shape-end-end: 5px;
35+
--mdc-focus-ring-outward-target-shape-end-start: 5px;
3236
--mdc-focus-ring-outward-color: blue;
3337
--mdc-focus-ring-outward-offset: 2px;
3438
--mdc-focus-ring-outward-track-width: 3px;
35-
--mdc-focus-ring-outward-target-shape: 5px;
3639
}
3740
}
3841
}
@@ -55,8 +58,20 @@
5558
}
5659

5760
@include test.contains {
58-
border-radius: calc(
59-
var(--mdc-focus-ring-outward-target-shape, 5px) +
61+
border-start-start-radius: calc(
62+
var(--mdc-focus-ring-outward-target-shape-start-start, 5px) +
63+
var(--mdc-focus-ring-outward-offset, 2px)
64+
);
65+
border-start-end-radius: calc(
66+
var(--mdc-focus-ring-outward-target-shape-start-end, 5px) +
67+
var(--mdc-focus-ring-outward-offset, 2px)
68+
);
69+
border-end-end-radius: calc(
70+
var(--mdc-focus-ring-outward-target-shape-end-end, 5px) +
71+
var(--mdc-focus-ring-outward-offset, 2px)
72+
);
73+
border-end-start-radius: calc(
74+
var(--mdc-focus-ring-outward-target-shape-end-start, 5px) +
6075
var(--mdc-focus-ring-outward-offset, 2px)
6176
);
6277
inset: calc(-1 * var(--mdc-focus-ring-outward-offset, 2px));

packages/mdc-shape/_shape.scss

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -367,3 +367,70 @@ $category-keywords: (
367367

368368
@return $theme;
369369
}
370+
371+
/// Resolves a shape value by expanding it into logical values for each corner.
372+
///
373+
/// @example - scss
374+
///
375+
/// resolver($shape: (4px 4px 0 0)) =>
376+
/// (
377+
/// start-start: 4px,
378+
/// start-end: 4px,
379+
/// end-end: 0,
380+
/// end-start: 0,
381+
/// )
382+
///
383+
/// resolver($shape: 4px) =>
384+
/// (
385+
/// start-start: 4px,
386+
/// start-end: 4px,
387+
/// end-end: 4px,
388+
/// end-start: 4px,
389+
/// )
390+
391+
/// @param {Number|List} $shape - The shape token's value.
392+
/// @return {Map} A map with logical tokens for each corner's value.
393+
@function resolver($shape) {
394+
@if meta.type-of($shape) != 'list' {
395+
@return (
396+
start-start: $shape,
397+
start-end: $shape,
398+
end-end: $shape,
399+
end-start: $shape
400+
);
401+
}
402+
403+
@if list.length($shape) == 1 {
404+
@return (
405+
start-start: list.nth($shape, 1),
406+
start-end: list.nth($shape, 1),
407+
end-end: list.nth($shape, 1),
408+
end-start: list.nth($shape, 1)
409+
);
410+
}
411+
412+
@if list.length($shape) == 2 {
413+
@return (
414+
start-start: list.nth($shape, 1),
415+
start-end: list.nth($shape, 2),
416+
end-end: list.nth($shape, 1),
417+
end-start: list.nth($shape, 2)
418+
);
419+
}
420+
421+
@if list.length($shape) == 3 {
422+
@return (
423+
start-start: list.nth($shape, 1),
424+
start-end: list.nth($shape, 2),
425+
end-end: list.nth($shape, 3),
426+
end-start: list.nth($shape, 2)
427+
);
428+
}
429+
430+
@return (
431+
start-start: list.nth($shape, 1),
432+
start-end: list.nth($shape, 2),
433+
end-end: list.nth($shape, 3),
434+
end-start: list.nth($shape, 4)
435+
);
436+
}

0 commit comments

Comments
 (0)