mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-11-10 00:27:41 +08:00
fix(toggle): swipe gesture applies to knob (#27255)
Issue number: resolves #27254
---------
<!-- Please refer to our contributing documentation for any questions on
submitting a pull request, or let us know here if you need any help:
https://ionicframework.com/docs/building/contributing -->
<!-- Some docs updates need to be made in the `ionic-docs` repo, in a
separate PR. See
https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#modifying-documentation
for details. -->
<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->
<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->
## What is the current behavior?
<!-- Please describe the current behavior that you are modifying. -->
The swipe gesture is currently applied to the entire `ion-toggle`
element. This was fine for the legacy syntax, but with the modern syntax
it means users can swipe on the label text which is not correct.
## What is the new behavior?
<!-- Please describe the behavior or changes that are being added by
this PR. -->
- The toggle now creates the gesture on the `.toggle-icon` element which
is the container for the knob for both modern and legacy syntaxes.
- Moved `touch-action: none` to the host of the legacy toggle. This was
preventing scrolling from happening on the modern toggle. I double
checked with native iOS and you can scroll when a pointer moves over a
toggle.
The structure of this fix was designed to match what `ion-range` does:
a8749929e0/core/src/components/range/range.tsx (L282-L296)
| Modern | Legacy |
| - | - |
| <video
src="https://user-images.githubusercontent.com/2721089/233431240-11f0c94f-d86b-4975-afd5-e534262a6f16.mov"></video>
| <video
src="https://user-images.githubusercontent.com/2721089/233431275-6c6f7fef-6cc0-4adc-8915-6fd5c3795ade.mov"></video>
|
## Does this introduce a breaking change?
- [ ] Yes
- [x] No
<!-- If this introduces a breaking change, please describe the impact
and migration path for existing applications below. -->
## Other information
<!-- Any other information that is important to this PR such as
screenshots of how the component looks before and after the change. -->
This commit is contained in:
@ -33,7 +33,6 @@
|
||||
outline: none;
|
||||
|
||||
cursor: pointer;
|
||||
touch-action: none;
|
||||
user-select: none;
|
||||
z-index: $z-index-item-input;
|
||||
}
|
||||
@ -50,6 +49,8 @@
|
||||
|
||||
:host(.legacy-toggle) {
|
||||
contain: content;
|
||||
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
:host(.ion-focused) input {
|
||||
@ -240,8 +241,6 @@ input {
|
||||
|
||||
background: var(--track-background);
|
||||
|
||||
pointer-events: none;
|
||||
|
||||
overflow: inherit;
|
||||
}
|
||||
|
||||
|
||||
@ -40,6 +40,8 @@ export class Toggle implements ComponentInterface {
|
||||
private lastDrag = 0;
|
||||
private legacyFormController!: LegacyFormController;
|
||||
private inheritedAttributes: Attributes = {};
|
||||
private toggleTrack?: HTMLElement;
|
||||
private didLoad = false;
|
||||
|
||||
// This flag ensures we log the deprecation warning at most once.
|
||||
private hasLoggedDeprecationWarning = false;
|
||||
@ -157,23 +159,42 @@ export class Toggle implements ComponentInterface {
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
const { el } = this;
|
||||
|
||||
this.legacyFormController = createLegacyFormController(el);
|
||||
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
el,
|
||||
gestureName: 'toggle',
|
||||
gesturePriority: 100,
|
||||
threshold: 5,
|
||||
passive: false,
|
||||
onStart: () => this.onStart(),
|
||||
onMove: (ev) => this.onMove(ev),
|
||||
onEnd: (ev) => this.onEnd(ev),
|
||||
});
|
||||
this.disabledChanged();
|
||||
this.legacyFormController = createLegacyFormController(this.el);
|
||||
|
||||
/**
|
||||
* If we have not yet rendered
|
||||
* ion-toggle, then toggleTrack is not defined.
|
||||
* But if we are moving ion-toggle via appendChild,
|
||||
* then toggleTrack will be defined.
|
||||
*/
|
||||
if (this.didLoad) {
|
||||
this.setupGesture();
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.setupGesture();
|
||||
this.didLoad = true;
|
||||
}
|
||||
|
||||
private setupGesture = async () => {
|
||||
const { toggleTrack } = this;
|
||||
|
||||
if (toggleTrack) {
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
el: toggleTrack,
|
||||
gestureName: 'toggle',
|
||||
gesturePriority: 100,
|
||||
threshold: 5,
|
||||
passive: false,
|
||||
onStart: () => this.onStart(),
|
||||
onMove: (ev) => this.onMove(ev),
|
||||
onEnd: (ev) => this.onEnd(ev),
|
||||
});
|
||||
this.disabledChanged();
|
||||
}
|
||||
};
|
||||
|
||||
disconnectedCallback() {
|
||||
if (this.gesture) {
|
||||
this.gesture.destroy();
|
||||
@ -273,7 +294,7 @@ export class Toggle implements ComponentInterface {
|
||||
|
||||
const { enableOnOffLabels, checked } = this;
|
||||
return (
|
||||
<div class="toggle-icon" part="track">
|
||||
<div class="toggle-icon" part="track" ref={(el) => (this.toggleTrack = el)}>
|
||||
{/* The iOS on/off labels are rendered outside of .toggle-icon-wrapper,
|
||||
since the wrapper is translated when the handle is interacted with and
|
||||
this would move the on/off labels outside of the view box */}
|
||||
|
||||
Reference in New Issue
Block a user