Skip to content

Commit

Permalink
feature(rtl-support): add rtl support for baklava components (#920)
Browse files Browse the repository at this point in the history
  • Loading branch information
erbilnas authored Oct 14, 2024
1 parent 7f66431 commit 163f188
Show file tree
Hide file tree
Showing 34 changed files with 305 additions and 124 deletions.
10 changes: 10 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ The Baklava library has an automated release flow, and our release versions and

In every push to a PR, we are running automated visual regression tests to be sure we are not breaking any components visual output accidentally. When you are done with your changes and created a PR, if you have some changes that effects visual output of any components, then our automated flow will notice this and block PR for a design review. Design reviews are done by designers involved in project. If the changes are intentional, they will be approved, and once the PR is merged, the new designs will serve as references for upcoming PRs. If there are no visual changes, this step will pass automatically, and there will be no need for a review from a designer.

### Should be RTL-Aware

Baklava components support Right-to-Left (RTL) text direction, which is crucial for languages written from right to left. When developing or modifying components, ensure proper RTL support by following these guidelines:

1. Use the `--bl-text-x-direction` CSS custom property for transformations and directional styling.
2. Utilize CSS logical properties (e.g., `inline-start`, `inline-end`, `margin-inline-start`) instead of directional properties.
3. Use `inset` with logical values for positioning.

For a comprehensive guide on RTL support and detailed examples, please refer to our [Right-to-Left (RTL) documentation](/docs/documentation-right-to-left-rtl--documentation).

### Enough approvals to merge

Every PR should be reviewed and approved by at least one of the core contributors. Please add needed information to PR description to help making review process quicker and easier.
85 changes: 85 additions & 0 deletions docs/rtl-support.stories.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import { Meta } from '@storybook/blocks';

<Meta title="Documentation/Right-to-Left (RTL)" />

# Right-to-Left (RTL)

Baklava components support Right-to-Left (RTL) text direction, which is essential for languages that are written from right to left, such as Arabic, Hebrew, and Persian. To enable RTL support in your application using Baklava components, you need to set the `dir` attribute on the `<html>` tag in your project.

## Enabling Right-to-Left (RTL)

To enable Right-to-Left (RTL), add the `dir="rtl"` attribute to your HTML tag. Here's how you can do it:

1. In your HTML file, locate the opening `<html>` tag.
2. Add the `dir="rtl"` attribute to the tag.

```html
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RTL Example</title>
</head>

<body>
<!-- Your content here -->
</body>
</html>
```


## Guidelines for Contributors

When developing or modifying Baklava components, it's crucial to ensure proper RTL support. This includes being aware of RTL text and its implications on layout and styling. For a comprehensive guide on building RTL-aware web applications and websites, refer to [this article](https://hacks.mozilla.org/2015/09/building-rtl-aware-web-apps-and-websites-part-1/). Here are some guidelines to follow:

1. Use the `--bl-text-x-direction` CSS custom property:
This property helps determine whether the element is in RTL or LTR. You can use it in your CSS like this:


```css
.my-component {
transform: scaleX(var(--bl-text-x-direction));
box-shadow: calc(8px * var(--bl-text-x-direction)) 0 16px 0 rgb(39 49 66 / 10%);
}
```
###

2. Utilize CSS logical properties:
Instead of using directional properties like `left`, `right`, `margin-left`, etc., use their logical counterparts. This ensures that your components adapt correctly to both LTR and RTL layouts. Here are some examples:

- Use `inline-start` and `inline-end` instead of `left` and `right`
- Use `block-start` and `block-end` instead of `top` and `bottom`
- Use `margin-inline-start` and `margin-inline-end` instead of `margin-left` and `margin-right`
- Use `padding-inline-start` and `padding-inline-end` instead of `padding-left` and `padding-right`
- Use `border-inline-start` and `border-inline-end` instead of `border-left` and `border-right`

###

```css
.my-component {
margin-inline-start: 1rem;
padding-inline-end: 0.5rem;
border-inline-start: 1px solid #ccc;
}
```

###

For more information on CSS logical properties and values, please refer to the [MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_logical_properties_and_values).

###

3. Use `inset` for positioning:
When using absolute or relative positioning, use the `inset` property with logical values:

```css
.positioned-element {
position: absolute;
inset-inline-start: 0;
inset-block-start: 0;
}
```

By following these guidelines, you'll ensure that Baklava components work seamlessly in both LTR and RTL layouts, providing a consistent user experience across different language settings.

2 changes: 1 addition & 1 deletion playground/template.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ <h1>Baklava Playground</h1>

<bl-button>Baklava is ready</bl-button>
</body>
</html>
</html>
6 changes: 3 additions & 3 deletions src/components/alert/bl-alert.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
box-shadow: inset 0 0 0 1px var(--main-color);
border-radius: var(--bl-border-radius-l);
padding: calc(var(--padding) / 2) var(--padding);
padding-right: calc(var(--padding) / 2);
padding-inline-end: calc(var(--padding) / 2);
}

.description {
Expand All @@ -33,14 +33,14 @@

.content {
display: flex;
margin-right: var(--bl-size-2xs);
margin-inline-end: var(--bl-size-2xs);
flex: 20 1 70%;
padding: calc(var(--padding) / 2) 0;
}

.icon {
padding: calc(var(--padding) / 2) 0;
margin-right: var(--bl-size-2xs);
margin-inline-end: var(--bl-size-2xs);
color: var(--main-color);
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/checkbox-group/checkbox/bl-checkbox.css
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ input[type="checkbox"] {

.required-suffix {
color: var(--bl-color-danger);
margin-left: calc(var(--bl-size-2xs) * -1);
margin-inline-start: calc(var(--bl-size-2xs) * -1);
}

.dirty.invalid .check-mark {
Expand Down
4 changes: 2 additions & 2 deletions src/components/dialog/bl-dialog.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
.dialog-polyfill {
display: none;
position: fixed;
left: 0;
inset-inline-start: 0;
top: 0;
width: 100vw;
height: 100vh;
Expand All @@ -59,7 +59,7 @@ header {
}

header bl-button {
margin-left: auto;
margin-inline-start: auto;
}

header h2 {
Expand Down
10 changes: 3 additions & 7 deletions src/components/drawer/bl-drawer.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,19 @@
position: fixed;
display: flex;
top: 0;
right: -100%;
bottom: 0;
inset-inline-end: 0;
width: var(--bl-drawer-current-width, 424px);
padding: var(--bl-size-xl);
padding-top: max(env(safe-area-inset-top), var(--bl-size-xl));
padding-right: max(env(safe-area-inset-right), var(--bl-size-xl));
padding-inline-end: max(env(safe-area-inset-right), var(--bl-size-xl));
padding-bottom: max(env(safe-area-inset-bottom), var(--bl-size-xl));
background: var(--bl-color-neutral-full);
box-shadow: var(--bl-size-xs) 0 var(--bl-size-2xl) rgba(0 0 0 / 50%);
transition: right var(--bl-drawer-animation-duration, 0.25s);
z-index: var(--bl-index-sticky);
}

:host([open]) .drawer {
right: 0;
}

iframe {
height: 100%;
width: 100%;
Expand All @@ -45,7 +41,7 @@ header {
header .header-buttons {
display: flex;
gap: var(--bl-size-xl);
margin-left: auto;
margin-inline-start: auto;
}

header h2 {
Expand Down
3 changes: 1 addition & 2 deletions src/components/drawer/bl-drawer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { PropertyValues } from "lit";
import { CSSResultGroup, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { event, EventDispatcher } from "../../utilities/event";
import { styleToPixelConverter } from "../../utilities/style-to-px.converter";
Expand Down
18 changes: 11 additions & 7 deletions src/components/input/bl-input.css
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,14 @@ label {
transition: all ease-in 0.1s;
font: var(--input-font);
top: var(--padding-vertical);
left: var(--bl-input-padding-start, var(--padding-horizontal));
right: var(--bl-input-padding-end, var(--padding-horizontal));
inset-inline-start: var(--bl-input-padding-start, var(--padding-horizontal));
inset-inline-end: var(--bl-input-padding-end, var(--padding-horizontal));
pointer-events: none;
color: var(--bl-color-neutral-light);
}

.has-icon label {
right: calc(
inset-inline-end: calc(
var(--bl-input-padding-end, var(--padding-horizontal)) + var(--icon-size) +
var(--padding-vertical)
);
Expand Down Expand Up @@ -147,7 +147,7 @@ input::-webkit-credentials-auto-fill-button {
}

:where(.wrapper:focus-within, .wrapper.has-value) input {
padding-left: var(--label-padding);
padding-inline-start: var(--label-padding);
}

input:disabled {
Expand Down Expand Up @@ -189,7 +189,7 @@ input:-webkit-autofill {
flex-basis: var(--icon-size);
align-self: center;
height: var(--icon-size);
margin-right: var(--label-padding);
margin-inline-end: var(--label-padding);
}

bl-icon:not(.reveal-icon),
Expand Down Expand Up @@ -263,8 +263,12 @@ bl-icon[name="eye_on"] {
:host(:not([label-fixed])) :focus-within label,
:host(:not([label-fixed])) .has-value label {
top: 0;
left: calc(var(--bl-input-padding-start, var(--padding-horizontal)) - var(--label-padding));
right: calc(var(--bl-input-padding-end, var(--padding-horizontal)) - var(--label-padding));
inset-inline-start: calc(
var(--bl-input-padding-start, var(--padding-horizontal)) - var(--label-padding)
);
inset-inline-end: calc(
var(--bl-input-padding-end, var(--padding-horizontal)) - var(--label-padding)
);
transform: translateY(-50%);
font: var(--bl-font-caption);
color: var(--bl-color-neutral-dark);
Expand Down
15 changes: 14 additions & 1 deletion src/components/notification/bl-notification.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
flex-direction: column-reverse;
position: fixed;
top: 0;
right: 0;
inset-inline-end: 0;
max-width: var(--bl-notification-width);
margin: var(--margin);
width: calc(100% - var(--margin) * 2);
Expand All @@ -32,6 +32,10 @@
touch-action: none;
}

:host(:has([dir="rtl"])) .notification {
animation: slide-in-left var(--bl-notification-animation-duration) ease;
}

.notification[data-slide="top"] {
animation: slide-in-top var(--bl-notification-animation-duration) ease;
}
Expand Down Expand Up @@ -75,6 +79,15 @@
}
}

@keyframes slide-in-left {
from {
transform: translateX(var(--travel-distance, -10px));
height: 0;
opacity: 0;
margin: 0;
}
}

@keyframes slide-out-right {
to {
transform: translateX(var(--travel-distance, 10px));
Expand Down
4 changes: 2 additions & 2 deletions src/components/notification/card/bl-notification-card.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@

.duration {
position: absolute;
left: 0;
right: 0;
inset-inline-start: 0;
inset-inline-end: 0;
bottom: 0;
height: var(--bl-size-2xs);
width: 100%;
Expand Down
4 changes: 4 additions & 0 deletions src/components/pagination/bl-pagination.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
align-items: center;
}

:host([dir="rtl"]) .page-container :is(bl-button.next, bl-button.previous) {
transform: rotate(180deg);
}

.page-list {
display: flex;
align-items: center;
Expand Down
5 changes: 4 additions & 1 deletion src/components/pagination/bl-pagination.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { CSSResultGroup, html, LitElement, TemplateResult, PropertyValues } from "lit";
import { CSSResultGroup, html, LitElement, PropertyValues, TemplateResult } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { localized, msg } from "@lit/localize";
import { setDirectionProperty } from "../../utilities/direction";
import { event, EventDispatcher } from "../../utilities/event";
import "../button/bl-button";
import "../input/bl-input";
Expand Down Expand Up @@ -103,6 +104,8 @@ export default class BlPagination extends LitElement {
setTimeout(() => {
window?.addEventListener("resize", () => this._paginate());
});

setDirectionProperty(this);
}

disconnectedCallback() {
Expand Down
2 changes: 1 addition & 1 deletion src/components/popover/bl-popover.css
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
transform: rotate(var(--arrow-rotation));
border: var(--border-size) solid var(--border-color);
border-bottom: none;
border-right: none;
border-inline-end: none;
}

.popover[data-placement*="bottom"] .arrow {
Expand Down
10 changes: 5 additions & 5 deletions src/components/popover/bl-popover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import { CSSResultGroup, html, LitElement, TemplateResult } from "lit";
import { customElement, property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import {
arrow,
autoUpdate,
computePosition,
flip,
shift,
offset,
arrow,
inline,
autoUpdate,
size,
Middleware,
MiddlewareState,
offset,
shift,
size,
} from "@floating-ui/dom";
import { getTarget } from "../../utilities/elements";
import { event, EventDispatcher } from "../../utilities/event";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
height: var(--height);
border-radius: var(--radius);
width: 100%;
transform: scaleX(var(--bl-text-x-direction));
}

.progress-indicator::before {
Expand Down
Loading

0 comments on commit 163f188

Please sign in to comment.