Patterns
Right to left
The viewer sits at the end of <body>, outside your layout. When it opens, it copies the trigger's direction and the nearest lang onto itself, so a gallery inside dir="rtl" gets a right-to-left viewer even on a left-to-right page. There is no option to set.
Loading the live example…
rtl.tsx
import { itemLabel } from "@ogdakke/fluidbox";
import { Fluidbox } from "@ogdakke/fluidbox/react";
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic, photos } from "./data";
export function Rtl() {
return (
// The viewer takes dir and lang from the trigger's surroundings.
<div dir="rtl" lang="ar">
<Fluidbox.Root items={photos} labels={arabic}>
<div className="pattern-grid">
{photos.map((photo) => (
<Fluidbox.Trigger
key={photo.src}
item={photo}
className="pattern-thumb"
>
<img src={photo.src} alt={itemLabel(photo)} />
</Fluidbox.Trigger>
))}
</div>
<Fluidbox.Filmstrip />
</Fluidbox.Root>
</div>
);
}Rtl.vue
<script setup lang="ts">
import { itemLabel } from "@ogdakke/fluidbox";
import { Fluidbox } from "@ogdakke/fluidbox/vue";
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic, photos } from "./data";
</script>
<template>
<!-- The viewer takes dir and lang from the trigger's surroundings. -->
<div dir="rtl" lang="ar">
<Fluidbox.Root :items="photos" :labels="arabic">
<div class="pattern-grid">
<Fluidbox.Trigger
v-for="photo in photos"
:key="photo.id"
:item="photo"
class="pattern-thumb"
>
<img :src="photo.src" :alt="itemLabel(photo)" />
</Fluidbox.Trigger>
</div>
<Fluidbox.Filmstrip />
</Fluidbox.Root>
</div>
</template>rtl.tsx
import { For } from "solid-js";
import { itemLabel } from "@ogdakke/fluidbox";
import { Fluidbox } from "@ogdakke/fluidbox/solid";
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic, photos } from "./data";
export function Rtl() {
return (
// The viewer takes dir and lang from the trigger's surroundings.
<div dir="rtl" lang="ar">
<Fluidbox.Root items={photos} labels={arabic}>
<div class="pattern-grid">
<For each={photos}>
{(photo) => (
<Fluidbox.Trigger item={photo} class="pattern-thumb">
<img src={photo.src} alt={itemLabel(photo)} />
</Fluidbox.Trigger>
)}
</For>
</div>
<Fluidbox.Filmstrip />
</Fluidbox.Root>
</div>
);
}rtl.ts
import { Component } from "@angular/core";
import { itemLabel } from "@ogdakke/fluidbox";
import { FluidboxModule } from "@ogdakke/fluidbox/angular";
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic, photos } from "./data";
@Component({
selector: "pattern-rtl",
standalone: true,
imports: [FluidboxModule],
template: `
<!-- The viewer takes dir and lang from the trigger's surroundings. -->
<div dir="rtl" lang="ar">
<div fluidboxRoot [items]="photos" [labels]="labels" class="pattern-grid">
@for (photo of photos; track photo.id) {
<button [fluidboxTrigger]="photo" class="pattern-thumb">
<img [src]="photo.src" [alt]="label(photo)" />
</button>
}
<ng-container fluidboxFilmstrip />
</div>
</div>
`,
})
export class Rtl {
readonly photos = photos;
readonly labels = arabic;
readonly label = itemLabel;
}rtl.html
<!-- The viewer takes dir and lang from the trigger's surroundings. -->
<div dir="rtl" lang="ar">
<fluidbox-gallery class="pattern-grid">
<fluidbox-item item-id="photo-aurora">
<button slot="trigger" type="button" class="pattern-thumb">
<img src="/art/aurora.svg" alt="Aurora over the tundra" />
</button>
<template slot="content">
<img src="/art/aurora.svg" alt="Aurora over the tundra" width="1100" height="1650" />
</template>
</fluidbox-item>
<fluidbox-item item-id="photo-ridge">
<button slot="trigger" type="button" class="pattern-thumb">
<img src="/art/ridge.svg" alt="Night ridge" />
</button>
<template slot="content">
<img src="/art/ridge.svg" alt="Night ridge" width="1200" height="1500" />
</template>
</fluidbox-item>
<fluidbox-item item-id="photo-fjord">
<button slot="trigger" type="button" class="pattern-thumb">
<img src="/art/fjord.svg" alt="Fjord in the blue hour" />
</button>
<template slot="content">
<img src="/art/fjord.svg" alt="Fjord in the blue hour" width="1200" height="1600" />
</template>
</fluidbox-item>
<fluidbox-item item-id="photo-lagoon">
<button slot="trigger" type="button" class="pattern-thumb">
<img src="/art/lagoon.svg" alt="Lagoon after sunset" />
</button>
<template slot="content">
<img src="/art/lagoon.svg" alt="Lagoon after sunset" width="1800" height="1200" />
</template>
</fluidbox-item>
<fluidbox-filmstrip></fluidbox-filmstrip>
</fluidbox-gallery>
</div>rtl.ts
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic } from "./data";
export function rtl(root: HTMLElement) {
root.querySelector("fluidbox-gallery")!.labels = arabic;
}rtl.ts
import { createFluidbox, itemLabel } from "@ogdakke/fluidbox";
import "@ogdakke/fluidbox/filmstrip";
import "@ogdakke/fluidbox/filmstrip.css";
import { arabic, photos } from "./data";
export function mountRtl(root: HTMLElement) {
const fluidbox = createFluidbox({ items: photos, labels: arabic, filmstrip: true });
// The viewer takes dir and lang from the trigger's surroundings.
const section = Object.assign(document.createElement("div"), { dir: "rtl", lang: "ar" });
const grid = document.createElement("div");
grid.className = "pattern-grid";
photos.forEach((photo, index) => {
const button = document.createElement("button");
button.type = "button";
button.className = "pattern-thumb";
button.append(Object.assign(new Image(), { src: photo.src, alt: itemLabel(photo) }));
grid.append(button);
fluidbox.bind(button, index);
});
section.append(grid);
root.append(section);
return () => {
fluidbox.destroy();
section.remove();
};
}- Forward is to the left. ArrowLeft and a swipe to the left go to the next item, Next sits on the left, and Close takes the top-left corner. The filmstrip starts on the right.
labelstranslates every word the viewer shows or announces. The example'sarabiclabels are in the example data.positionis a function, so it can format numbers for the language.langon the viewer makes a screen reader read the labels in that language.- Languages and direction covers what flips, what doesn't, and wiring labels to an i18n library.