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 <[email protected]>

* 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 <[email protected]>
Co-authored-by: DaniGuardiola <[email protected]>
Co-authored-by: ciampo <[email protected]>
Co-authored-by: tyxla <[email protected]>
Co-authored-by: mirka <[email protected]>
  • Loading branch information
6 people authored Oct 1, 2024
1 parent df81c28 commit 249f701
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

1 comment on commit 249f701

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 249f701.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/11130057048
📝 Reported issues:

Please sign in to comment.