1
0
mirror of https://github.com/squidfunk/mkdocs-material.git synced 2024-11-24 07:30:12 +01:00

Fixed tab indicator animation for right-to-left languages

This commit is contained in:
squidfunk 2021-12-19 11:00:31 +01:00
parent 4b2a97a51d
commit a32760bdee
9 changed files with 82 additions and 56 deletions

View File

@ -34,7 +34,7 @@
{% endif %}
{% endblock %}
{% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.ffa0dd14.min.css' | url }}">
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.3714f473.min.css' | url }}">
{% if config.theme.palette %}
{% set palette = config.theme.palette %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.e6a45f82.min.css' | url }}">
@ -213,7 +213,7 @@
</script>
{% endblock %}
{% block scripts %}
<script src="{{ 'assets/javascripts/bundle.1cbe63b4.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.f881a9a8.min.js' | url }}"></script>
{% for path in config["extra_javascript"] %}
<script src="{{ path | url }}"></script>
{% endfor %}

View File

@ -23,6 +23,9 @@
import {
Observable,
Subject,
animationFrameScheduler,
auditTime,
combineLatest,
defer,
finalize,
fromEvent,
@ -30,6 +33,8 @@ import {
mapTo,
merge,
startWith,
takeLast,
takeUntil,
tap
} from "rxjs"
@ -37,7 +42,8 @@ import {
getElement,
getElementOffset,
getElementSize,
getElements
getElements,
watchElementSize
} from "~/browser"
import { Component } from "../../_"
@ -97,33 +103,43 @@ export function watchContentTabs(
export function mountContentTabs(
el: HTMLElement
): Observable<Component<ContentTabs>> {
const { matches: reduce } = matchMedia("(prefers-reduced-motion)")
/* Mount component on subscription */
const container = getElement(".tabbed-labels", el)
return defer(() => {
const push$ = new Subject<ContentTabs>()
push$.subscribe({
combineLatest([push$, watchElementSize(el)])
.pipe(
auditTime(1, animationFrameScheduler),
takeUntil(push$.pipe(takeLast(1)))
)
.subscribe({
/* Handle emission */
next({ active }) {
const offset = getElementOffset(active)
const { width } = getElementSize(active)
/* Handle emission */
next([{ active }]) {
const offset = getElementOffset(active)
if (!reduce) {
const { width } = getElementSize(active)
/* Set tab indicator offset and width */
el.style.setProperty("--md-indicator-x", `${offset.x}px`)
el.style.setProperty("--md-indicator-width", `${width}px`)
/* Set tab indicator offset and width */
el.style.setProperty("--md-indicator-x", `${offset.x}px`)
el.style.setProperty("--md-indicator-width", `${width}px`)
}
/* Smoothly scroll container */
container.scrollTo({
behavior: "smooth",
left: offset.x
/* Smoothly scroll container */
container.scrollTo({
behavior: "smooth",
left: offset.x
})
},
/* Handle complete */
complete() {
el.style.removeProperty("--md-indicator-x")
el.style.removeProperty("--md-indicator-width")
}
})
},
/* Handle complete */
complete() {
el.style.removeProperty("--md-indicator-x")
el.style.removeProperty("--md-indicator-width")
}
})
/* Create and return component */
return watchContentTabs(el)

View File

@ -148,7 +148,7 @@ export function mountBackToTop(
/* Handle complete */
complete() {
el.style.top = ""
el.removeAttribute("data-md-state")
el.setAttribute("data-md-state", "hidden")
el.removeAttribute("tabindex")
}
})

View File

@ -87,24 +87,29 @@
display: contents;
}
// [js]: Show animated tab indicator
.js & {
position: relative;
// [screen and no reduced motion]: Disable animation
@media screen and (prefers-reduced-motion: no-preference) {
// Tab indicator
&::after {
position: absolute;
bottom: 0;
display: block;
width: var(--md-indicator-width);
height: 2px;
background: var(--md-accent-fg-color);
transform: translateX(var(--md-indicator-x));
transition:
width 250ms,
transform 250ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
content: "";
// [js]: Show animated tab indicator
.js & {
position: relative;
// Tab indicator
&::before {
position: absolute;
bottom: 0;
left: 0;
display: block;
width: var(--md-indicator-width);
height: 2px;
background: var(--md-accent-fg-color);
transform: translateX(var(--md-indicator-x));
transition:
width 250ms,
transform 250ms;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
content: "";
}
}
}
@ -229,6 +234,11 @@
@media screen {
color: var(--md-accent-fg-color);
// [reduced motion]: Show border
@media (prefers-reduced-motion) {
border-color: var(--md-accent-fg-color);
}
// [no-js]: Show border (indicator is animated with JavaScript)
.no-js & {
border-color: var(--md-accent-fg-color);

View File

@ -85,7 +85,7 @@
max-height 0ms 250ms,
z-index 250ms;
// [reduced-motion]: Disable animation
// [reduced motion]: Disable animation
@media (prefers-reduced-motion) {
transition: none;
}
@ -101,7 +101,7 @@
max-height 250ms,
z-index 0ms;
// [reduced-motion]: Disable animation
// [reduced motion]: Disable animation
@media (prefers-reduced-motion) {
transition: none;
}
@ -194,7 +194,7 @@
animation: pulse 2000ms infinite;
content: "";
// [reduced-motion]: Disable animation
// [reduced motion]: Disable animation
@media (prefers-reduced-motion) {
transition: none;
animation: none;
@ -212,7 +212,7 @@
background-color 250ms;
animation: none;
// [reduced-motion]: Disable animation
// [reduced motion]: Disable animation
@media (prefers-reduced-motion) {
transition: none;
}
@ -225,7 +225,7 @@
transition: transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1);
content: attr(data-md-annotation-id);
// [reduced-motion]: Disable animation
// [reduced motion]: Disable animation
@media (prefers-reduced-motion) {
transition: none;
}