feat(i18n): add RTL support for Arabic, Persian and Urdu (#831)

* feat(i18n): add RTL support and Arabic/Persian translations

- Add `dir` attribute to `<html>` via `.Site.Language.Direction`
- Convert physical CSS properties to logical properties across ~30 SCSS files
- Add `[dir="rtl"]` overrides for elements that need physical direction (code blocks, translate, icons)
- Add `logical-direction.html` template function for config value normalization
- Add RTL-aware deprecation warnings for old "left"/"right" config values
- Rename github corner, TOC position, reading progress config values from "left"/"right" to "start"/"end"
- Add Arabic (ar.toml) and Persian (fa.toml) i18n translation files
- Update multilingual documentation with RTL language configuration guide

* feat(shortcodes): add RTL support for tabs and refactor border-radius mixin

- Rename tabs placement values from "left"/"right" to "start"/"end" with deprecation warnings
- Convert all physical directional properties in tabs SCSS to logical properties
- Add RTL overrides for translate and box-shadow in tabs
- Add "start"/"end" support to border-radius mixin using CSS logical properties
- Refactor fixit-decryptor to use border-radius(start/end) mixin

* feat(assets): add RTL support for toc-dialog slide animation

The mobile toc-dialog always slid in from the right (100vw). In RTL
mode it should slide from the left (-100vw), matching the
border-inline-start/margin-inline-end anchoring.

* feat(assets): add RTL support for post-tag comma separator

* refactor(assets): extract RTL styles into dedicated _rtl.scss

* feat(assets): add RTL support for theme-switch and directional icons

* feat(i18n): add RTL support and improve i18n

- Add RTL typography corrections for Arabic-script languages (:lang(ar/fa/ur))
- Remove fa-list-ol from RTL flip list (numbers get mirrored)
- Add Urdu translation file (i18n/ur.toml)
- Rename noMoretTranslations to noTranslations and simplify all translations
- Update json-viewer-element from 1.0.4 to 1.0.6
- Add RTL test posts (index.en.md, index.ar.md)
- Fix layout partials for RTL support

See https://fixit.lruihao.cn/docs/content-management/introduction/#rtl-language-support
This commit is contained in:
Cell
2026-08-24 00:22:34 +08:00
committed by GitHub
parent 8b6806bbf3
commit 5f1e79f49c
75 changed files with 1613 additions and 223 deletions
+2 -2
View File
@@ -34,8 +34,8 @@ libFiles:
gitalkJS: gitalk@1.8.0/dist/gitalk.min.js
# instant.page@5.2.0 https://github.com/instantpage/instant.page
instantPage: instant.page@5.2.0/instantpage.min.js
# json-viewer-element@1.0.4 https://github.com/Lruihao/json-viewer-element
jsonViewerElementJS: json-viewer-element@1.0.4/dist/json-viewer-element.umd.js
# json-viewer-element@1.0.6 https://github.com/Lruihao/json-viewer-element
jsonViewerElementJS: json-viewer-element@1.0.6/dist/json-viewer-element.umd.js
# katex@0.17.0 https://github.com/KaTeX/KaTeX
katexCopyTexJS: katex@0.17.0/dist/contrib/copy-tex.min.js
katexCSS: katex@0.17.0/dist/katex.min.css
+2 -2
View File
@@ -34,8 +34,8 @@ libFiles:
gitalkJS: gitalk@1.8.0/dist/gitalk.min.js
# instant.page@5.2.0 https://github.com/instantpage/instant.page
instantPage: instant.page@5.2.0/instantpage.js
# json-viewer-element@1.0.4 https://github.com/Lruihao/json-viewer-element
jsonViewerElementJS: json-viewer-element@1.0.4/dist/json-viewer-element.umd.js
# json-viewer-element@1.0.6 https://github.com/Lruihao/json-viewer-element
jsonViewerElementJS: json-viewer-element@1.0.6/dist/json-viewer-element.umd.js
# katex@0.17.0 https://github.com/KaTeX/KaTeX
katexCopyTexJS: katex@0.17.0/dist/contrib/copy-tex.min.js
katexCSS: katex@0.17.0/dist/katex.min.css
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -7,7 +7,7 @@
padding: 0.5rem 1rem;
margin-block: 1rem;
color: inherit;
border-left: 0.25em solid fi-var(alert-border-color);
border-inline-start: 0.25em solid fi-var(alert-border-color);
> :first-child {
margin-top: 0;
+18 -8
View File
@@ -22,13 +22,13 @@
display: inline-block;
width: fi-var(color-code-size);
height: fi-var(color-code-size);
@include border-radius(full);
margin-right: 0.25em;
margin-inline-end: 0.25em;
vertical-align: middle;
border: 1px solid;
pointer-events: none;
translate: 0 -1px;
border-color: light-dark(#d1d9e0b3, #3d444db3);
@include border-radius(full);
}
}
@@ -42,6 +42,7 @@
font-family: fi-var(code-font-family);
background-color: fi-var(code-block-background-color);
tab-size: 4;
direction: ltr;
@include border-radius;
+ pre {
@@ -91,6 +92,7 @@
.highlight {
margin: 0.5rem 0;
position: relative;
direction: ltr;
@include border-radius;
// lineNumbersInTable=true
@@ -161,7 +163,7 @@
&:not(.code-block) {
.lntd:last-child pre.chroma {
padding-left: 0;
padding-inline-start: 0;
}
}
@@ -224,6 +226,10 @@
@include border-radius(top);
@include sticky-top-offset;
[dir="rtl"] & {
direction: rtl;
}
+ .code-wrapper {
@include border-radius(bottom);
@@ -237,7 +243,7 @@
padding: 0.4rem;
&::after {
padding-left: 0.2rem;
padding-inline-start: 0.2rem;
content: attr(data-name, fi-var(code-type, 'Code'));
}
@@ -366,7 +372,7 @@
.copy-icon-btn {
position: absolute;
top: 0.5rem;
right: 0.5rem;
inset-inline-end: 0.5rem;
}
// classic mode code block collapsed
@@ -483,7 +489,7 @@
counter-increment: codeNos;
content: counter(codeNos);
white-space: nowrap;
text-align: right;
text-align: end;
width: calc(#{fi-var(line-digit)} * 1ch);
min-width: 0.75rem;
padding-inline: 0.75rem;
@@ -509,7 +515,7 @@
&:not(.line-nos-hidden) {
.lntd:last-child pre.chroma:not([contenteditable='true']),
.code-wrapper > pre.chroma:not(:has(.ln)) {
padding-left: 0;
padding-inline-start: 0;
}
}
@@ -616,7 +622,7 @@
&:not(:last-child)::after {
content: '';
position: absolute;
right: 0;
inset-inline-end: 0;
top: 50%;
translate: 0 -50%;
width: 1px;
@@ -653,6 +659,10 @@
pointer-events: none;
transition: 0.3s ease-in-out;
@include border-radius;
[dir="rtl"] & {
translate: -2px 2px;
}
}
}
+25 -14
View File
@@ -15,14 +15,14 @@
display: inline-block;
width: max-content;
rotate: 30deg;
margin-right: 0.25em;
margin-inline-end: 0.25em;
color: fi-var(danger);
}
.icon-repost {
display: inline-block;
width: max-content;
margin-right: 0.25em;
margin-inline-end: 0.25em;
color: fi-var(success);
}
@@ -116,21 +116,25 @@
text-rendering: auto;
-webkit-font-smoothing: antialiased;
position: absolute;
left: 5%;
inset-inline-start: 5%;
top: 50%;
translate: 0 -50%;
color: fi-var(hr-active-color);
font-size: 20px;
line-height: 1;
transition: left 1s ease-in-out, color 0.3s ease, border-color 0.3s ease;
transition: inset-inline-start 1s ease-in-out, color 0.3s ease, border-color 0.3s ease;
font-family: var(--fa-family-classic);
font-weight: 600;
content: '\f0c4';
@include z-index(base);
[dir="rtl"] & {
scale: -1 1;
}
}
&:hover::before {
left: calc(95% - 20px);
inset-inline-start: calc(95% - 20px);
}
}
}
@@ -217,7 +221,7 @@
}
:is(ol, ul) :is(ol, ul) {
padding-left: 20px;
padding-inline-start: 20px;
}
li::marker {
@@ -232,7 +236,8 @@
&[data-task] {
list-style: none;
@include task-icon {
margin: 0 0.25em 0 -1.5em;
margin-block: 0;
margin-inline: -1.5em 0.25em;
color: fi-var(task-icon-color, fi-var(secondary));
};
@include task-text {
@@ -343,12 +348,12 @@
th,
td {
padding: 0.3rem 1rem;
border-right: 1px solid fi-var(table-border-color);
border-inline-end: 1px solid fi-var(table-border-color);
border-bottom: 1px solid fi-var(table-border-color);
}
tr > :last-child {
border-right: none;
border-inline-end: none;
}
> :last-child > tr:last-child > * {
@@ -392,14 +397,14 @@
blockquote {
display: block;
border-left: 0.25em solid fi-var(global-border-color);
border-inline-start: 0.25em solid fi-var(global-border-color);
color: fi-var(blockquote-color);
padding: 0 1em;
margin: 1rem 0;
ul,
ol {
padding-left: 1.5em;
padding-inline-start: 1.5em;
}
dl dd {
@@ -427,7 +432,7 @@
ol {
margin-block: 1em;
padding-left: 1rem;
padding-inline-start: 1rem;
}
hr {
@@ -465,6 +470,7 @@
.diagram-container {
position: relative;
margin-block: 0.5rem;
direction: ltr;
> .copy-icon-btn {
position: absolute;
@@ -480,12 +486,17 @@
overflow-y: hidden;
// neutralize the margin-right setting of .katex .vlist-t2
// to prevent scrollbars from appearing when the width is not full
padding-right: 2px;
padding-inline-end: 2px;
}
.katex {
display: inline-block;
direction: ltr;
}
.katex-error {
padding: 0.14em 0.28em;
background-color: mark;
cursor: help;
direction: ltr;
@include border-radius;
}
@@ -526,7 +537,7 @@
&.special {
.single-title,
.single-subtitle {
text-align: right;
text-align: end;
}
}
}
+5 -3
View File
@@ -165,8 +165,9 @@ article fixit-encryptor {
.fixit-decryptor-field {
flex: 1;
height: 2.5rem;
border-right: none;
border-radius: fi-var(global-border-radius) 0 0 fi-var(global-border-radius);
border-inline-end: none;
@include border-radius(start);
@include border-radius(end, 0);
&:focus-within + .fixit-decryptor-btn {
border-color: var(--fi-primary);
@@ -177,8 +178,9 @@ article fixit-encryptor {
.fixit-decryptor-btn {
width: auto;
padding: 0 0.85rem;
border-radius: 0 fi-var(global-border-radius) fi-var(global-border-radius) 0;
transition: border-color 0.2s ease, box-shadow 0.2s ease;
@include border-radius(start, 0);
@include border-radius(end);
}
&.decrypted > .fixit-decryptor-container {
@@ -8,10 +8,10 @@
position: relative;
margin: 1rem 0;
padding: 0 0.75rem;
border-left: .25rem solid;
border-inline-start: .25rem solid;
overflow: hidden;
background-color: fi-var(admonition-bg-color);
border-left-color: fi-var(admonition-color);
border-inline-start-color: fi-var(admonition-color);
@include border-radius;
.admonition-title {
@@ -30,11 +30,12 @@
// title-only admonition without content
&:not(:has(+ .details-content)) {
@include set-fi-var(admonition-title-font-weight, normal);
padding: 0.75rem 1rem 0.75rem 2.2rem;
padding-inline: 2.2rem 1rem;
padding-block: 0.75rem;
border: 0;
i.icon {
left: 1.1rem;
inset-inline-start: 1.1rem;
font-size: 1rem;
}
}
@@ -73,15 +74,23 @@
font-size: 0.85rem;
position: absolute;
top: 50%;
left: 0.9rem;
inset-inline-start: 0.9rem;
translate: -50% -50%;
[dir="rtl"] & {
translate: 50% -50%;
}
}
i.details-icon {
position: absolute;
top: 50%;
right: 0.9rem;
inset-inline-end: 0.9rem;
translate: 50% -50%;
[dir="rtl"] & {
translate: -50% -50%;
}
}
// set color for each admonition type
@@ -20,8 +20,8 @@
position: absolute;
top: 0.75rem;
bottom: 0.75rem;
left: 0;
right: 0;
inset-inline-start: 0;
inset-inline-end: 0;
background-image: fi-var(logo-img);
background-repeat: no-repeat;
filter: blur(0.5rem);
@@ -67,20 +67,22 @@
width: 1rem;
height: 1rem;
flex-shrink: 0;
margin-right: 0.25rem;
margin-inline-end: 0.25rem;
}
&url {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
// URL direction should stay LTR
direction: ltr;
}
&shortcut-icon {
width: 4rem;
height: 4rem;
flex-shrink: 0;
margin-left: 0.25rem;
margin-inline-start: 0.25rem;
&:is(i) {
text-align: center;
@@ -95,7 +97,7 @@
width: 4rem;
height: 4rem !important;
flex-shrink: 0;
margin-left: 0.25rem;
margin-inline-start: 0.25rem;
object-fit: cover;
@include border-radius(full);
}
@@ -1,7 +1,7 @@
@use "core/functions" as *;
.single blockquote.blockquote-center {
border-left: none;
border-inline-start: none;
margin: 40px 0;
padding: 0;
position: relative;
@@ -10,7 +10,7 @@
&::after,
&::before {
left: 0;
inset-inline-start: 0;
line-height: 1;
opacity: 0.6;
position: absolute;
@@ -19,19 +19,27 @@
&::before {
border-top: 1px solid fi-var(global-border-color);
text-align: left;
text-align: start;
top: -20px;
font-family: var(--fa-family-classic);
font-weight: 900;
content: '\f10d';
[dir="rtl"] & {
content: '\f10e';
}
}
&::after {
border-bottom: 1px solid fi-var(global-border-color);
bottom: -20px;
text-align: right;
text-align: end;
font-family: var(--fa-family-classic);
font-weight: 900;
content: '\f10e';
[dir="rtl"] & {
content: '\f10d';
}
}
}
+1 -1
View File
@@ -12,7 +12,7 @@
position: absolute;
width: 100%;
height: 100%;
left: 0;
inset-inline-start: 0;
top: 0;
}
@@ -8,6 +8,7 @@
line-height: 1;
margin-block: 0.5rem;
transition: box-shadow 0.2s ease;
direction: ltr;
@include border-radius;
&:hover {
+6 -2
View File
@@ -18,7 +18,7 @@
svg {
max-width: 100%;
height: auto;
height: auto;
}
}
@@ -60,12 +60,16 @@
&::before {
content: '';
position: absolute;
left: 0;
inset-inline-start: 0;
top: 50%;
width: 1px;
translate: -2px -50%;
height: fi-var(code-block-font-size);
background-color: fi-var(global-border-color-weight);
[dir="rtl"] & {
translate: 2px -50%;
}
}
}
+69 -35
View File
@@ -73,8 +73,8 @@ tab-container {
}
}
&[placement='left'],
&[placement='right'] {
&[placement='start'],
&[placement='end'] {
max-width: 100%;
&::part(tablist-wrapper) {
@@ -103,7 +103,7 @@ tab-container {
flex-direction: column-reverse;
}
&[placement='right'] {
&[placement='end'] {
flex-direction: row-reverse;
}
@@ -166,8 +166,8 @@ tab-container {
}
}
&[placement='left'],
&[placement='right'] {
&[placement='start'],
&[placement='end'] {
> .tab-button {
@include tab-button-size(1rem, 0);
}
@@ -202,34 +202,44 @@ tab-container {
}
// Left placement
&[placement='left'] {
&[placement='start'] {
&::part(tablist-tab-wrapper) {
border-right: 2px solid fi-var(global-border-color);
border-inline-end: 2px solid fi-var(global-border-color);
}
&::part(tablist-wrapper)::before {
box-shadow: inset -2px 0 0 fi-var(primary);
translate: 2px 0;
[dir="rtl"] & {
box-shadow: inset 2px 0 0 fi-var(primary);
translate: -2px 0;
}
}
> .tab-button {
text-align: right;
text-align: end;
}
}
// Right placement
&[placement='right'] {
&[placement='end'] {
&::part(tablist-tab-wrapper) {
border-left: 2px solid fi-var(global-border-color);
border-inline-start: 2px solid fi-var(global-border-color);
}
&::part(tablist-wrapper)::before {
box-shadow: inset 2px 0 0 fi-var(primary);
translate: -2px 0;
[dir="rtl"] & {
box-shadow: inset -2px 0 0 fi-var(primary);
translate: 2px 0;
}
}
> .tab-button {
text-align: left;
text-align: start;
}
}
}
@@ -268,8 +278,8 @@ tab-container {
}
}
&[placement='left'],
&[placement='right'] {
&[placement='start'],
&[placement='end'] {
padding-bottom: 0.5rem;
&::part(tablist) {
@@ -296,27 +306,35 @@ tab-container {
}
// Left placement
&[placement='left'] {
&[placement='start'] {
&::part(tablist) {
margin-left: 0.5rem;
margin-inline-end: 0.5rem;
}
> .tab-button {
&:hover {
translate: 2px 0;
[dir="rtl"] & {
translate: -2px 0;
}
}
}
}
// Right placement
&[placement='right'] {
&[placement='end'] {
&::part(tablist) {
margin-right: 0.5rem;
margin-inline-start: 0.5rem;
}
> .tab-button {
&:hover {
translate: -2px 0;
[dir="rtl"] & {
translate: 2px 0;
}
}
}
}
@@ -362,13 +380,13 @@ tab-container {
> .tab-button {
&:first-of-type {
position: sticky;
left: 0;
inset-inline-start: 0;
@include z-index(base, 1);
}
&:last-of-type {
position: sticky;
right: 0;
inset-inline-end: 0;
@include z-index(base, 1);
}
}
@@ -417,44 +435,52 @@ tab-container {
}
// Left placement
&[placement='left'] {
&[placement='start'] {
&::part(tablist-tab-wrapper) {
border-right: 1px solid fi-var(global-border-color);
border-inline-end: 1px solid fi-var(global-border-color);
}
> .tab-button {
translate: 1px 0;
@include border-radius(left);
@include border-radius(start);
[dir="rtl"] & {
translate: -1px 0;
}
&[aria-selected='true'] {
border-right-color: fi-var(global-background-color);
border-inline-end-color: fi-var(global-background-color);
}
}
> .tab-panel {
border-left: none;
@include border-radius(right);
border-inline-start: none;
@include border-radius(end);
}
}
// Right placement
&[placement='right'] {
&[placement='end'] {
&::part(tablist-tab-wrapper) {
border-left: 1px solid fi-var(global-border-color);
border-inline-start: 1px solid fi-var(global-border-color);
}
> .tab-button {
translate: -1px 0;
@include border-radius(right);
@include border-radius(end);
[dir="rtl"] & {
translate: 1px 0;
}
&[aria-selected='true'] {
border-left-color: fi-var(global-background-color);
border-inline-start-color: fi-var(global-background-color);
}
}
> .tab-panel {
border-right: none;
@include border-radius(left);
border-inline-end: none;
@include border-radius(start);
}
}
}
@@ -608,14 +634,22 @@ tab-container .tab-panel:not([hidden]) {
border-top: 2px solid fi-var(tab-button-border-color);
}
&[placement='left'] > .tab-button {
&[placement='start'] > .tab-button {
translate: 2px 0;
border-right: 2px solid fi-var(tab-button-border-color);
border-inline-end: 2px solid fi-var(tab-button-border-color);
[dir="rtl"] & {
translate: -2px 0;
}
}
&[placement='right'] > .tab-button {
&[placement='end'] > .tab-button {
translate: -2px 0;
border-left: 2px solid fi-var(tab-button-border-color);
border-inline-start: 2px solid fi-var(tab-button-border-color);
[dir="rtl"] & {
translate: 2px 0;
}
}
}
@@ -81,7 +81,7 @@
position: absolute;
top: 1.25rem;
translate: 0 -50%;
left: 0;
inset-inline-start: 0;
text-align: center;
border-style: solid;
color: transparent;
@@ -99,7 +99,7 @@
content: '';
position: absolute;
top: 0;
left: calc(#{fi-var(timeline-circle-size)} / 2 + #{fi-var(timeline-width)} / 2);
inset-inline-start: calc(#{fi-var(timeline-circle-size)} / 2 + #{fi-var(timeline-width)} / 2);
width: fi-var(timeline-width);
height: 100%;
background-color: fi-var(timeline-color);
+1
View File
@@ -1,4 +1,5 @@
@use "common";
@use "reboot";
@use "root";
@use "rtl";
@use "layouts";
+2 -16
View File
@@ -219,7 +219,7 @@ fieldset {
// 2. Fix wrapping bug.
legend {
float: left; // 1
float: inline-start; // 1
width: 100%;
padding: 0;
margin-bottom: 0.5rem;
@@ -228,7 +228,7 @@ legend {
font-size: 1.5rem;
+ * {
clear: left; // 2
clear: inline-start; // 2
}
}
@@ -276,20 +276,6 @@ textarea {
}
}
// 1. A few input types should stay LTR
// See https://rtlstyling.com/posts/rtl-styling#form-inputs
// 2. RTL only output
// See https://rtlcss.com/learn/usage-guide/control-directives/#raw
/* rtl:raw:
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
*/
// Remove the inner padding in Chrome and Safari on macOS.
::-webkit-search-decoration {
+50
View File
@@ -0,0 +1,50 @@
/// ==================================================================================
/// Right-to-Left (RTL) Support
///
/// @see https://rtlstyling.com/posts/rtl-styling/
/// @see https://developer.apple.com/design/human-interface-guidelines/right-to-left/
/// ==================================================================================
[dir="rtl"] {
// A few input types should stay LTR
[type="tel"],
[type="url"],
[type="email"],
[type="number"] {
direction: ltr;
}
// Flip directional icons in RTL
.fa-tags,
.fa-tag,
.fa-folder,
.fa-folder-tree,
.fa-folder-open,
.fa-folder-closed,
.fa-pencil,
.fa-pen-to-square,
.fa-pen-clip,
.fa-square-pen,
.fa-list-ul,
.fa-list-check,
.fa-clipboard-list,
.fa-rectangle-list,
.fa-comments,
.fa-comment,
.fa-comment-dots,
.fa-message,
.fa-retweet,
.octicon-report-16 {
scale: -1 1;
}
}
// Arabic-script languages (Arabic, Persian, Urdu) typography corrections
// Hebrew and other non-connected RTL scripts don't need these adjustments
// Letter-spacing breaks connected letter forms
:lang(ar),
:lang(fa),
:lang(ur) {
letter-spacing: 0;
}
+1 -2
View File
@@ -17,8 +17,7 @@ footer {
.footer-divider:not(:first-child)::before {
content: '|';
margin-left: 0.25rem;
margin-right: 0.25rem;
margin-inline: 0.25rem;
}
.hugo-icon,
+18 -6
View File
@@ -119,7 +119,7 @@ header {
list-style: none;
.dropdown-icon {
margin-left: 0.25rem;
margin-inline-start: 0.25rem;
font-size: .875em;
color: fi-var(global-font-color);
@@ -155,6 +155,10 @@ header {
position: relative;
@include focus-visible-ring;
[dir="rtl"] & {
scale: -1 1;
}
i {
display: inline-block;
rotate: 225deg;
@@ -195,10 +199,10 @@ header {
padding: 0 2rem;
height: 100%;
&[data-github-corner='left'] {
&[data-github-corner='start'] {
padding-inline-start: fi-var(header-height);
}
&[data-github-corner='right'] {
&[data-github-corner='end'] {
padding-inline-end: fi-var(header-height);
}
@@ -211,9 +215,17 @@ header {
&:hover .sub-menu {
display: block;
translate: -0.5rem 0;
[dir="rtl"] & {
translate: 0.5rem 0;
}
}
&.language-switch:hover .sub-menu {
translate: calc(1.75rem - 100%) 0;
[dir="rtl"] & {
translate: calc(100% - 1.75rem) 0;
}
}
}
@@ -229,7 +241,7 @@ header {
width: 0;
margin: 18.5px 0.5rem;
padding: 0;
border-left: 1.5px solid fi-var(global-border-color);
border-inline-start: 1.5px solid fi-var(global-border-color);
}
}
@@ -448,7 +460,7 @@ header {
.language-select {
position: absolute;
opacity: 0;
left: 0;
inset-inline-start: 0;
top: 0;
width: 100%;
height: 100%;
@@ -457,7 +469,7 @@ header {
}
.sub-menu {
padding-left: 0;
padding-inline-start: 0;
display: none;
&.open {
+8 -5
View File
@@ -1,12 +1,13 @@
@use "core/functions" as *;
/// Mixin to set border-radius
/// @param {String|Number|List} $value - The value of the border-radius, position (top, bottom, left, right) or keyword (full)
/// @param {String|Number|List} $value - The value of the border-radius, position (top, bottom, start, end) or keyword (full)
/// @param {Number} $radius - The radius of the border (only for position)
/// @example
/// @include border-radius;
/// @include border-radius(full);
/// @include border-radius(top);
/// @include border-radius(start);
/// @include border-radius(top, 10px);
/// @include border-radius(10px 20px 10px 20px);
@mixin border-radius($value: fi-var(global-border-radius), $radius: fi-var(global-border-radius)) {
@@ -16,10 +17,12 @@
border-radius: $radius $radius 0 0;
} @else if $value == bottom {
border-radius: 0 0 $radius $radius;
} @else if $value == left {
border-radius: $radius 0 0 $radius;
} @else if $value == right {
border-radius: 0 $radius $radius 0;
} @else if $value == start {
border-start-start-radius: $radius;
border-end-start-radius: $radius;
} @else if $value == end {
border-start-end-radius: $radius;
border-end-end-radius: $radius;
} @else {
border-radius: $value;
}
+2 -2
View File
@@ -8,7 +8,7 @@
font-size: 1.6rem;
font-weight: bold;
line-height: 140%;
text-align: right;
text-align: end;
}
.single-subtitle {
@@ -16,7 +16,7 @@
font-size: 1.2rem;
font-weight: normal;
line-height: 100%;
text-align: right;
text-align: end;
}
.group-title {
+6 -5
View File
@@ -12,7 +12,7 @@
.card-item {
font-size: 0.875rem;
text-align: left;
text-align: start;
width: 45%;
display: flex;
align-items: flex-start;
@@ -37,8 +37,8 @@
}
.more-post {
text-align: right;
padding-right: 1rem;
text-align: end;
padding-inline-end: 1rem;
}
}
@@ -53,7 +53,8 @@
justify-content: space-between;
align-items: center;
box-sizing: border-box;
margin: 0.25rem 0 0.25rem 1.5rem;
margin-block: 0.25rem;
margin-inline: 1.5rem 0;
}
.archive-item-link {
@@ -65,7 +66,7 @@
}
.archive-item-date {
text-align: right;
text-align: end;
color: fi-var(global-font-secondary-color);
white-space: nowrap;
font-variant-numeric: tabular-nums lining-nums;
+6 -2
View File
@@ -111,7 +111,7 @@
position: absolute;
width: 100%;
height: 100%;
left: 0;
inset-inline-start: 0;
top: 0;
object-fit: cover;
}
@@ -152,7 +152,11 @@
.post-tag:not(:last-child)::after {
content: ',';
margin-right: 0.25rem;
margin-inline-end: 0.25rem;
[dir="rtl"] & {
scale: -1 1;
}
}
}
}
+11 -3
View File
@@ -16,7 +16,7 @@
&:has(.collection-nav-item:nth-child(2))::before {
content: '';
position: absolute;
left: 50%;
inset-inline-start: 50%;
bottom: 0.75rem;
width: 1px;
height: 2rem;
@@ -55,6 +55,10 @@
i {
flex-shrink: 0;
[dir="rtl"] & {
scale: -1 1;
}
}
span {
@@ -65,7 +69,7 @@
}
&[rel='next'] {
text-align: right;
text-align: end;
}
&[rel='prev']:hover {
@@ -158,7 +162,7 @@
.collection-item > span::before {
content: '|';
font-weight: 600;
margin-right: 0.5em;
margin-inline-end: 0.5em;
position: relative;
bottom: 2px;
color: fi-var(single-link-color);
@@ -181,6 +185,10 @@
gap: 0.5em;
background-color: light-dark(color.adjust($global-background-color, $lightness: -5%), color.adjust($global-background-color-dark, $lightness: 5%));
[dir="rtl"] & i {
scale: -1 1;
}
a.collection-nav-item {
padding-inline: 2px;
@include border-radius(full);
+12 -10
View File
@@ -18,7 +18,7 @@
.post-info-mod {
font-size: 0.8em;
color: fi-var(global-font-secondary-color);
color: fi-var(global-font-secondary-color);
@include link(false, false);
}
@@ -38,8 +38,7 @@
>span:not(:first-child)::before {
content: '|';
margin-left: 0.25rem;
margin-right: 0.25rem;
margin-inline: 0.25rem;
color: fi-var(global-font-secondary-color);
}
}
@@ -71,16 +70,15 @@
.post-tags {
max-width: 65%;
* {
display: inline;
}
@include link(true, true);
.post-tag:not(:last-child)::after {
content: ',';
margin-right: 0.25rem;
margin-inline-end: 0.25rem;
[dir="rtl"] & {
scale: -1 1;
}
}
}
@@ -96,8 +94,12 @@
font-weight: 600;
transition: all 0.3s ease-out;
[dir="rtl"] & i {
scale: -1 1;
}
&[rel='next'] {
text-align: right;
text-align: end;
}
&[rel='prev']:hover {
+1 -1
View File
@@ -59,7 +59,7 @@
.related-item > span::before {
content: '|';
font-weight: 600;
margin-right: 0.5em;
margin-inline-end: 0.5em;
position: relative;
bottom: 2px;
color: fi-var(single-link-color);
+21 -9
View File
@@ -21,29 +21,29 @@
ul {
margin: 0;
text-indent: -0.8em;
padding-left: 0.8em;
padding-inline-start: 0.8em;
list-style: none;
a:first-child::before {
content: '|';
font-weight: bolder;
margin-right: 0.5em;
margin-inline-end: 0.5em;
position: relative;
bottom: 2px;
color: fi-var(single-link-color);
}
ul {
padding-left: 1em;
padding-inline-start: 1em;
}
}
ol {
margin: 0;
padding-left: 2.25em;
padding-inline-start: 2.25em;
ol {
padding-left: 1.25em;
padding-inline-start: 1.25em;
}
li:has(> a:hover)::marker {
@@ -107,7 +107,7 @@
&::before {
content: '|';
font-weight: bolder;
margin-right: 0.5em;
margin-inline-end: 0.5em;
position: relative;
bottom: 2px;
color: fi-var(global-border-color);
@@ -121,6 +121,10 @@
&.toc-hidden i.toc-icon {
rotate: -90deg;
transition: rotate 0.2s ease;
[dir="rtl"] & {
rotate: 90deg;
}
}
.toc-content {
@@ -225,9 +229,9 @@
height: 100dvh;
max-width: 100%;
max-height: 100%;
margin-right: 0;
margin-inline-end: 0;
border: none;
border-left: 1px solid fi-var(global-border-color-light);
border-inline-start: 1px solid fi-var(global-border-color-light);
background-color: fi-var(global-background-color);
transition:
display 0.2s allow-discrete,
@@ -235,10 +239,14 @@
translate 0.2s,
opacity 0.2s 0.4s;
[dir="rtl"] & {
translate: -100vw 0;
}
.toc-close-btn {
position: absolute;
top: 1.25rem;
right: 1rem;
inset-inline-end: 1rem;
padding: 0.25rem;
color: fi-var(global-font-secondary-color);
transition: color 0.2s ease;
@@ -302,6 +310,10 @@
&[open] {
translate: 100vw 0;
[dir="rtl"] & {
translate: -100vw 0;
}
}
}
}
+8
View File
@@ -14,6 +14,10 @@
color: fi-var(global-font-secondary-color);
transition: all 0.2s ease;
[dir="rtl"] & {
scale: -1 1;
}
&:hover {
color: fi-var(global-font-color);
}
@@ -33,6 +37,10 @@
i.details-icon {
rotate: 90deg;
[dir="rtl"] & {
rotate: -90deg;
}
}
}
+2 -2
View File
@@ -3,7 +3,7 @@
.fixed-buttons {
position: fixed;
right: 1.5rem;
inset-inline-end: 1.5rem;
bottom: 1.5rem;
display: flex;
flex-direction: column;
@@ -49,7 +49,7 @@
svg {
position: absolute;
top: 0;
left: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
// Rotate to start from top
+1 -1
View File
@@ -5,7 +5,7 @@
background-position: center;
position: fixed;
top: 0;
left: 0;
inset-inline-start: 0;
width: 100%;
height: 100%;
@include z-index(hide);
+6 -7
View File
@@ -12,8 +12,7 @@ dialog.search-dialog {
// Anchor to top and center horizontally with fixed dimensions
// to prevent position jumps when results appear/disappear.
top: 15vh;
left: 50%;
margin: 0;
margin: 0 auto;
&::backdrop {
background-color: rgba(0, 0, 0, 0.25);
@@ -219,7 +218,7 @@ dialog.search-dialog {
.suggestion-heading-mark {
color: fi-var(global-font-tertiary-color);
margin-right: 0.125rem;
margin-inline-end: 0.125rem;
}
em {
@@ -255,7 +254,7 @@ dialog.search-dialog {
color: fi-var(global-font-tertiary-color);
i {
margin-right: 0.125rem;
margin-inline-end: 0.125rem;
}
}
@@ -370,7 +369,7 @@ dialog.search-dialog {
@include media('sm', 'up') {
opacity: 0;
translate: -50% 12px;
translate: 0 12px;
scale: 0.98;
transition:
display 0.2s allow-discrete,
@@ -381,7 +380,7 @@ dialog.search-dialog {
&[open] {
opacity: 1;
translate: -50% 0;
translate: 0 0;
scale: 1;
}
@@ -404,7 +403,7 @@ dialog.search-dialog {
}
&[open] {
translate: -50% 12px;
translate: 0 12px;
scale: 0.98;
}
}
+9 -8
View File
@@ -33,16 +33,17 @@
fill: fi-var(github-corner-fill);
}
&.left {
left: 0;
svg {
scale: -1 1;
}
&.start {
inset-inline-start: 0;
}
&.right {
right: 0;
&.end {
inset-inline-end: 0;
}
// Flip octocat to face the start side
:is([dir="ltr"] &.start, [dir="rtl"] &.end) svg {
scale: -1 1;
}
@include media('print') {