Skip to content
Meeko
Type to search the guides and the API reference. Open it from any page with / or Ctrl K; move with the arrow keys and open a result with Enter.
Get started

Contents

On this page

useThemeToggle

Public state for a custom theme selector compatible with SSR, hydration and forms without JavaScript.

composable Since 1.8.0 @meekojs/meeko/framework Source code
ts
import { useThemeToggle } from "@meekojs/meeko/framework";

useThemeToggle() provides the state used by UIThemeToggle from @meekojs/ui. You can build a selector that preserves the SSR theme during hydration.

Usage#

Enable theme: true in meeko.config.ts and call the composable in a component's script:

ts
import { useThemeToggle } from '@meekojs/meeko/framework'

const toggle = useThemeToggle()

Type#

ts
function useThemeToggle(): ThemeToggleState

ThemeToggleState

ts
interface ThemeToggleState<
  Name extends string = ThemeName,
  Choice extends string = ThemeChoice,
> {
  readonly theme: ThemeState<Name, Choice>;
  readonly choices: readonly Choice[];
  readonly system: ThemeToggleSystem<Name> | undefined;
  readonly known: ReadonlySignal<boolean>;
  readonly interactive: ReadonlySignal<boolean>;
}

ThemeToggleSystem

ts
interface ThemeToggleSystem<Name extends string = ThemeName> {
	readonly light: Name
	readonly dark: Name
}

Parameters#

It takes no parameters. It reads the themes from the framework configuration.

Return value#

A ThemeToggleState<Name, Choice>, with names inferred from the configuration:

Property Type Description
theme ThemeState<Name, Choice> State from useTheme(), with set(choice) to change it in the browser.
choices readonly Choice[] Choices in order, including "system" if enabled.
system ThemeToggleSystem<Name> | undefined The light and dark names resolved by system mode.
known ReadonlySignal<boolean> The choice is known: a cookie in SSR or completed hydration in the browser.
interactive ReadonlySignal<boolean> Handlers are responding; false in SSR and during hydration.

Examples#

ts
import { computed } from '@meekojs/meeko'
import { useThemeToggle } from '@meekojs/meeko/framework'

const toggle = useThemeToggle()
const label = computed(() => (toggle.known.value ? `Theme: ${toggle.theme.theme.value}` : 'Cambiar tema'))

The custom theme selector includes a complete form with POST /_meeko/theme, theme and return, which switches through theme.set(choice) when interactive.value is true.

To avoid icon jumps, render all icons with data-meeko-theme-icon and let the <head> rule show the one for the choice. While known.value is false, announce a neutral action (“Change theme”).

Common mistakes#

Call it without configuring the theme#

Incorrectts
// meeko.config.ts no activa theme
const toggle = useThemeToggle()
Correctts
// meeko.config.ts
export default defineMeekoConfig({ theme: true })

Without theme in meeko.config.ts, or outside a Meeko application, it throws MEEK111. Enable theme: true and call it while a component's script is running.

Change the theme during SSR#

Incorrectts
const toggle = useThemeToggle()
toggle.theme.set('dark') // setup also runs on the server
Correctts
import { useThemeToggle } from '@meekojs/meeko/framework'

const toggle = useThemeToggle()
const chooseDark = (): void => {
	if (toggle.interactive.value) toggle.theme.set('dark')
}

theme.set() only changes the theme in the browser. In SSR, use the read-only state and preserve native form submission; do not call set during setup.

Notes#

  • known and interactive are read-only signals: read .value in the binding that uses them.
  • The form works without JavaScript with a server adapter. The static adapter requires JavaScript.
  • The cookie, script, <head> icon rule and POST /_meeko/theme remain in core; they do not require UI.
  • <MeekoThemeToggle> is deprecated since 1.8 and will be removed in 2.0. For a ready-made selector, enable the UI module and use <UIThemeToggle>.

Was this page helpful?

Add a comment

It is sent when you choose “Yes” or “No”. Only the page, your answer and the comment are stored: no cookies and no personal data.

0 of 2000 characters

Edit on GitHub: docs/en/reference/composables/usethemetoggle.md