Skip to content

useDirection ​

The one thing that writes dir and lang on <html>. Direction follows the language, until you pin it.

Open in demo

Import ​

ts
import { useDirection } from '@core/i18n/useDirection'

Signature ​

ts
function useDirection(): {
  setDirection: (mode: DirectionMode) => void
  currentDirection: Readonly<Ref<Direction>>
}

Direction is 'ltr' | 'rtl'. DirectionMode is Direction | 'auto'.

Returns ​

MemberTypeDescription
setDirection(mode: DirectionMode) => void'auto' re-derives from the locale. 'ltr' or 'rtl' pins until the next call.
currentDirectionReadonly<Ref<Direction>>What dir currently is. Never 'auto' — that is a mode, not a direction.

Example ​

vue
<script setup lang="ts">
import { useDirection } from '@core/i18n/useDirection'

const MODES = ['auto', 'ltr', 'rtl'] as const

const { setDirection, currentDirection } = useDirection()
</script>

<template>
  <div class="flex flex-wrap items-center gap-2">
    <button
      v-for="mode in MODES"
      :key="mode"
      type="button"
      @click="setDirection(mode)"
    >
      {{ mode }}
    </button>
    <span>Rendering {{ currentDirection }}</span>
  </div>
</template>

Notes ​

  • Two paths reach dir. A watcher on the active locale re-derives it while the mode is 'auto', and setDirection('ltr' | 'rtl') pins it. The right-to-left locales are ar, he, fa and ur.
  • A pin is released by a language switch, because setLocale calls setDirection('auto'). That is what makes "preview the RTL layout" a preview: pick Arabic, or pin rtl, and the next language change puts it back.
  • lang is not pinned. The watcher mirrors the active locale onto <html lang> unconditionally, so an override changes the direction only, never the document's language. Screen readers and hyphenation keep reading the right one.
  • The watcher is immediate, so dir and lang are correct on the first paint rather than one tick later.
  • Both writers no-op without a document.