Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(tab-button): badge is aligned in rtl #26986

Merged
merged 6 commits into from
Mar 23, 2023
Merged

fix(tab-button): badge is aligned in rtl #26986

merged 6 commits into from
Mar 23, 2023

Conversation

liamdebeasi
Copy link
Contributor

@liamdebeasi liamdebeasi commented Mar 20, 2023

Pull request checklist

Please check if your PR fulfills the following requirements:

  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been reviewed and added / updated if needed (for bug fixes / features)
    • Some docs updates need to be made in the ionic-docs repo, in a separate PR. See the contributing guide for details.
  • Build (npm run build) was run locally and any changes were pushed
  • Lint (npm run lint) has passed locally and any fixes were made for failures

Pull request type

Please check the type of change your PR introduces:

  • Bugfix
  • Feature
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • Documentation content changes
  • Other (please describe):

What is the current behavior?

Part of #17012, resolves #22739

RTL-aware mixins that do not make use of logical CSS properties rely on host-context to check the document's text direction. This CSS pseudo-class is only supported in Chromium browsers. As a result, certain RTL-aware mixins do not work in Safari and Firefox.

One of these mixins is the position mixin which uses top/right/bottom/left properties. In this particular case, the badge in ion-tab-button is not aligned correctly in RTL mode due to this issue.

What is the new behavior?

  • Created tech debt ticket to remove old host-context usage in the future
  • Updates the position mixin to make use of inset-inline-start and inset-inline-end which are the logical properties for left and right.

Source (MD)

::slotted(ion-badge) {
  @include border-radius($tab-button-md-badge-border-radius);
  @include padding($tab-button-md-badge-padding-top, $tab-button-md-badge-padding-end, $tab-button-md-badge-padding-bottom, $tab-button-md-badge-padding-start);
  @include position(8px, null, null, calc(50% + 6px));

  min-width: $tab-button-md-badge-min-width;

  font-size: $tab-button-md-badge-font-size;

  font-weight: normal;
}

Before

::slotted(ion-badge) {
  border-radius: 8px;
  padding-left: 2px;
  padding-right: 2px;
  padding-top: 3px;
  padding-bottom: 2px;
  left: calc(50% + 6px);
  top: 8px;
  min-width: 12px;
  font-size: 8px;
  font-weight: normal
}


[dir=rtl] ::slotted(ion-badge),:host-context([dir=rtl]) ::slotted(ion-badge) {
  left: unset;
  right: unset;
  right: calc(50% + 6px)
}

After

::slotted(ion-badge) {
  border-radius: 8px;
  padding-left: 2px;
  padding-right: 2px;
  padding-top: 3px;
  padding-bottom: 2px;
  top: 8px;
  min-width: 12px;
  font-size: 8px;
  font-weight: normal
}

@supports (inset-inline-start: 0) {
  ::slotted(ion-badge) {
    inset-inline-start: calc(50% + 6px)
  }
}

@supports not (inset-inline-start: 0) {
  ::slotted(ion-badge) {
    left: calc(50% + 6px)
  }

  [dir=rtl] ::slotted(ion-badge),:host-context([dir=rtl]) ::slotted(ion-badge) {
    left: unset;
    right: unset;
    right: calc(50% + 6px)
  }
}

Browsers that support inset-inline will use the logical properties. If they are not supported then it will fallback to using the old host-context method.

According to https://caniuse.com/?search=inset-inline, Chrome 87+ supports the logical properties. This fallback ensures that Chrome 79-86 still has RTL support through the use of host-context.

All versions of Firefox that Ionic 7 supports also supports inset-inline.

Safari 14.5+ supports inset-inline. The reported bug will persist in Safari 14.0-14.4, which is what is happening right now. 92% of iPhone users are on iOS 15-16, so I expect the impact of this lack of support to be minimal (https://developer.apple.com/support/app-store/).

  • This change also happens to fix a related fab button bug with the RTL layouts and the position mixin

Does this introduce a breaking change?

  • Yes
  • No

Other information

@stackblitz
Copy link

stackblitz bot commented Mar 20, 2023

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@liamdebeasi liamdebeasi changed the title mixin test fix(tab-button): badge is aligned in rtl Mar 20, 2023
@github-actions github-actions bot added the package: core @ionic/core package label Mar 20, 2023
@liamdebeasi liamdebeasi changed the base branch from main to feature-7.0 March 20, 2023 20:44
@liamdebeasi
Copy link
Contributor Author

liamdebeasi commented Mar 21, 2023

The item and select diffs in Safari/Firefox appear to be correct:

@include position(var(--position-offset), null, null, var(--position-offset));

The --position-offset variable was not applying correctly in RTL on these browsers.

@liamdebeasi liamdebeasi marked this pull request as ready for review March 21, 2023 13:13
@liamdebeasi liamdebeasi requested a review from a team as a code owner March 21, 2023 13:13
@liamdebeasi liamdebeasi removed the request for review from a team March 21, 2023 15:06
@brandyscarney
Copy link
Member

The expected changes look good, but I'm curious why you went the not @supports approach instead of how margin does it:

::slotted(ion-margin-example) {
  @include margin(10px, 12px, 14px, 16px);
}

becomes

::slotted(ion-margin-example) {
  margin-left: 16px;
  margin-right: 12px;
  margin-top: 10px;
  margin-bottom: 14px;
}
@supports (margin-inline-start: 0) or (-webkit-margin-start: 0) {
  ::slotted(ion-margin-example) {
    margin-left: unset;
    margin-right: unset;
    -webkit-margin-start: 16px;
    margin-inline-start: 16px;
    -webkit-margin-end: 12px;
    margin-inline-end: 12px;
  }
}

So it would be something like this:

@mixin position-horizontal($start: null, $end: null) {
  @if $start == $end {
    @include multi-dir() {
      left: $start;
      right: $end;
    }
  } @else {
    @include ltr() {
      left: $start;
      right: $end;
    }
    @include rtl() {
      left: unset;
      right: unset;

      left: $end;
      right: $start;
    }
  }
    
  @at-root {
    @supports (inset-inline-start: 0) {
      & {
        @if $start != null {
          left: unset;
        }
        @if $end != null {
          right: unset;
        }
        
        inset-inline-start: $start;
        inset-inline-end: $end;
      }
    }
  }
}

::slotted(ion-position-example) {
  @include position(10px, 12px, 14px, 16px);
}

becomes

::slotted(ion-position-example) {
  left: 16px;
  right: 12px;
  top: 10px;
  bottom: 14px;
}
[dir=rtl] ::slotted(ion-position-example), :host-context([dir=rtl]) ::slotted(ion-position-example) {
  left: unset;
  right: unset;
  left: 12px;
  right: 16px;
}

@supports (inset-inline-start: 0) {
  ::slotted(ion-position-example) {
    left: unset;
    right: unset;
    inset-inline-start: 16px;
    inset-inline-end: 12px;
  }
}

Granted I didn't test this out in Ionic, so this could very much be a bad approach, but that's why I'm asking. 🙂

@liamdebeasi
Copy link
Contributor Author

Good question! I considered it, but I didn't want to have to unset the left/right values when using inset-inline-*. I figured the applied styles would be a bit cleaner/easier to debug if left/right weren't even present.

Copy link
Member

@brandyscarney brandyscarney left a comment

Choose a reason for hiding this comment

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

Sounds good. I'm okay with this approach since we plan to remove it with future support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
package: core @ionic/core package
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants