Skip to content

Commit

Permalink
ToggleGroupControl: improve animation (#65175)
Browse files Browse the repository at this point in the history
* Refactor utils and switch Tabs indicator animation to `transform`.

* docs tweak

* Update packages/components/src/tabs/styles.ts

Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>

* Add RTL support.

* Addressed @ciampo's comments.

* Correct for antialiasing rounding.

* Make antialiasing adjustment optional.

* Use larger base value and revert antialiasing adjustment code.

* DRY RTL

* Remove RTL story (redundant since Storybook has a dynamic setting to test RTL).

* Fix bug.

* Fix bug (for real this time).

* Add changelog entry.

* De-cleverfy code.

* Sync useResizeObserver with #64943 and make useTrackElementOffsetRect resilient.

* Deduplicate utility and clean up.

* Minor Tabs code improvement.

* Replace framer motion animation with faster CSS animation.

* DRY antialiasing factor.

* Changelogs.

* Various improvements, fixes, and feedback addressed.

* Simplify.

* Simplify using derived state.

* Add similar useOnValueUpdate detail to Tabs.

* Fix skipping animation.

* Add similar detail to Tabs animation.

* Fix setState depth issue.

* Fix unit test error.

* Add changelog entries

* Fix changelog

* Update test snapshot.

* Depends less on React.

* Switch to layout effect for `useOnValueUpdate`

* Switched to transform strategy.

* Fix resizing bug.

* Transition border-radius too.

* Undo Tabs changes (no longer relevant).

* DRY animation code.

* Avoid useless re-runs in effect.

* Rename `activeElement` -> `selectedElement` for clarity.

* Rename `--indicator-` -> `--selected-` for accuracy.

* Minor tweak.

* Add safe defaults to CSS custom properties.

* Tweak `useSubelementAnimation`.

* Fix parent missing when there's no selected option.

* Update snapshots

* Add docs to utility.

* Added note about border-radius.

---------

Co-authored-by: Marco Ciampini <marco.ciampo@gmail.com>
Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org>
Co-authored-by: ciampo <mciampini@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
Co-authored-by: mirka <0mirka00@git.wordpress.org>
  • Loading branch information
6 people authored and draganescu committed Oct 2, 2024
1 parent 5b6b849 commit dbd79a7
Show file tree
Hide file tree
Showing 11 changed files with 395 additions and 114 deletions.
4 changes: 4 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- `ToolsPanel`: atomic one-step state update when (un)registering panels ([#65564](https://github.com/WordPress/gutenberg/pull/65564)).
- `Navigator`: fix `isInitial` logic ([#65527](https://github.com/WordPress/gutenberg/pull/65527)).
- `ToggleGroupControl`: Fix arrow key navigation in RTL ([#65735](https://github.com/WordPress/gutenberg/pull/65735)).
- `ToggleGroupControl`: indicator doesn't jump around when the layout around it changes ([#65175](https://github.com/WordPress/gutenberg/pull/65175)).

### Deprecations

Expand All @@ -21,6 +23,8 @@
- `Navigator`: add support for exit animation ([#64777](https://github.com/WordPress/gutenberg/pull/64777)).
- `Guide`: Update finish button to use the new default size ([#65680](https://github.com/WordPress/gutenberg/pull/65680)).
- `BorderControl`: Use `__next40pxDefaultSize` prop for Reset button ([#65682](https://github.com/WordPress/gutenberg/pull/65682)).
- `Navigator`: stabilize APIs ([#64613](https://github.com/WordPress/gutenberg/pull/64613)).
- `ToggleGroupControl`: indicator animation is now more lightweight and performant ([#65175](https://github.com/WordPress/gutenberg/pull/65175)).

## 28.8.0 (2024-09-19)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,55 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
outline-offset: -2px;
}
@media not ( prefers-reduced-motion ) {
.emotion-8.is-animation-enabled::before {
transition-property: transform,border-radius;
transition-duration: 0.2s;
transition-timing-function: ease-out;
}
}
.emotion-8::before {
content: '';
position: absolute;
pointer-events: none;
background: #1e1e1e;
outline: 2px solid transparent;
outline-offset: -3px;
--antialiasing-factor: 100;
border-radius: calc(
1px /
(
var( --selected-width, 0 ) /
var( --antialiasing-factor )
)
)/1px;
left: -1px;
width: calc( var( --antialiasing-factor ) * 1px );
height: calc( var( --selected-height, 0 ) * 1px );
transform-origin: left top;
-webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
}
.emotion-10 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
Expand Down Expand Up @@ -150,17 +199,7 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
line-height: 1;
}
.emotion-15 {
background: #1e1e1e;
border-radius: 1px;
position: absolute;
inset: 0;
z-index: 1;
outline: 2px solid transparent;
outline-offset: -3px;
}
.emotion-18 {
.emotion-17 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
Expand Down Expand Up @@ -204,22 +243,22 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
}
@media not ( prefers-reduced-motion ) {
.emotion-18 {
.emotion-17 {
-webkit-transition: background 160ms linear,color 160ms linear,font-weight 60ms linear;
transition: background 160ms linear,color 160ms linear,font-weight 60ms linear;
}
}
.emotion-18::-moz-focus-inner {
.emotion-17::-moz-focus-inner {
border: 0;
}
.emotion-18[disabled] {
.emotion-17[disabled] {
opacity: 0.4;
cursor: default;
}
.emotion-18:active {
.emotion-17:active {
background: #fff;
}
Expand Down Expand Up @@ -280,20 +319,14 @@ exports[`ToggleGroupControl controlled should render correctly with icons 1`] =
</svg>
</div>
</button>
<div>
<div
class="emotion-15"
role="presentation"
/>
</div>
</div>
<div
class="emotion-10 emotion-11"
>
<button
aria-checked="false"
aria-label="Lowercase"
class="emotion-18 components-toggle-group-control-option-base"
class="emotion-17 components-toggle-group-control-option-base"
data-value="lowercase"
data-wp-c16t="true"
data-wp-component="ToggleGroupControlOptionBase"
Expand Down Expand Up @@ -392,6 +425,55 @@ exports[`ToggleGroupControl controlled should render correctly with text options
outline-offset: -2px;
}
@media not ( prefers-reduced-motion ) {
.emotion-8.is-animation-enabled::before {
transition-property: transform,border-radius;
transition-duration: 0.2s;
transition-timing-function: ease-out;
}
}
.emotion-8::before {
content: '';
position: absolute;
pointer-events: none;
background: #1e1e1e;
outline: 2px solid transparent;
outline-offset: -3px;
--antialiasing-factor: 100;
border-radius: calc(
1px /
(
var( --selected-width, 0 ) /
var( --antialiasing-factor )
)
)/1px;
left: -1px;
width: calc( var( --antialiasing-factor ) * 1px );
height: calc( var( --selected-height, 0 ) * 1px );
transform-origin: left top;
-webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
}
.emotion-10 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
Expand Down Expand Up @@ -612,6 +694,55 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`]
outline-offset: -2px;
}
@media not ( prefers-reduced-motion ) {
.emotion-8.is-animation-enabled::before {
transition-property: transform,border-radius;
transition-duration: 0.2s;
transition-timing-function: ease-out;
}
}
.emotion-8::before {
content: '';
position: absolute;
pointer-events: none;
background: #1e1e1e;
outline: 2px solid transparent;
outline-offset: -3px;
--antialiasing-factor: 100;
border-radius: calc(
1px /
(
var( --selected-width, 0 ) /
var( --antialiasing-factor )
)
)/1px;
left: -1px;
width: calc( var( --antialiasing-factor ) * 1px );
height: calc( var( --selected-height, 0 ) * 1px );
transform-origin: left top;
-webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
}
.emotion-10 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
Expand Down Expand Up @@ -702,17 +833,7 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`]
line-height: 1;
}
.emotion-15 {
background: #1e1e1e;
border-radius: 1px;
position: absolute;
inset: 0;
z-index: 1;
outline: 2px solid transparent;
outline-offset: -3px;
}
.emotion-18 {
.emotion-17 {
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
Expand Down Expand Up @@ -756,22 +877,22 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`]
}
@media not ( prefers-reduced-motion ) {
.emotion-18 {
.emotion-17 {
-webkit-transition: background 160ms linear,color 160ms linear,font-weight 60ms linear;
transition: background 160ms linear,color 160ms linear,font-weight 60ms linear;
}
}
.emotion-18::-moz-focus-inner {
.emotion-17::-moz-focus-inner {
border: 0;
}
.emotion-18[disabled] {
.emotion-17[disabled] {
opacity: 0.4;
cursor: default;
}
.emotion-18:active {
.emotion-17:active {
background: #fff;
}
Expand Down Expand Up @@ -832,20 +953,14 @@ exports[`ToggleGroupControl uncontrolled should render correctly with icons 1`]
</svg>
</div>
</button>
<div>
<div
class="emotion-15"
role="presentation"
/>
</div>
</div>
<div
class="emotion-10 emotion-11"
>
<button
aria-checked="false"
aria-label="Lowercase"
class="emotion-18 components-toggle-group-control-option-base"
class="emotion-17 components-toggle-group-control-option-base"
data-value="lowercase"
data-wp-c16t="true"
data-wp-component="ToggleGroupControlOptionBase"
Expand Down Expand Up @@ -938,6 +1053,55 @@ exports[`ToggleGroupControl uncontrolled should render correctly with text optio
outline-offset: -2px;
}
@media not ( prefers-reduced-motion ) {
.emotion-8.is-animation-enabled::before {
transition-property: transform,border-radius;
transition-duration: 0.2s;
transition-timing-function: ease-out;
}
}
.emotion-8::before {
content: '';
position: absolute;
pointer-events: none;
background: #1e1e1e;
outline: 2px solid transparent;
outline-offset: -3px;
--antialiasing-factor: 100;
border-radius: calc(
1px /
(
var( --selected-width, 0 ) /
var( --antialiasing-factor )
)
)/1px;
left: -1px;
width: calc( var( --antialiasing-factor ) * 1px );
height: calc( var( --selected-height, 0 ) * 1px );
transform-origin: left top;
-webkit-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-moz-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
-ms-transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
transform: translateX( calc( var( --selected-left, 0 ) * 1px ) ) scaleX(
calc(
var( --selected-width, 0 ) / var( --antialiasing-factor )
)
);
}
.emotion-10 {
display: -webkit-inline-box;
display: -webkit-inline-flex;
Expand Down
Loading

0 comments on commit dbd79a7

Please sign in to comment.