Skip to main content

Theme options

A small kit for building custom theme options pages that read and write from wp/v2/settings. Three pieces work together:

  • ThemeOptionsPage — the page shell with a header, save button, and a Toaster for success/error feedback.
  • useThemeOptions — hook that loads, holds, and saves the settings via apiFetch.
  • EsThemeOptionsContext — React context that exposes the hook's return value to any child component.

Based on the WordPress developer blog post How to use WordPress React components for plugin pages.

ThemeOptionsPage

The page shell. Renders the header (title + save button), exposes the settings via context, and mounts a Sonner Toaster for the save feedback toasts.

import { ThemeOptionsPage, EsThemeOptionsContext } from '@eightshift/frontend-libs-tailwind/scripts';
import { useContext } from '@wordpress/element';
import { InputField } from '@eightshift/ui-components';

const ContactFields = () => {
const { settings, updateSettings } = useContext(EsThemeOptionsContext);

return (
<>
<InputField
label='Contact email'
value={settings?.contactEmail ?? ''}
onChange={(v) => updateSettings({ contactEmail: v })}
/>
</>
);
};

const App = () => (
<ThemeOptionsPage
title={__('Site options', 'my-theme')}
settingName='my-theme-options'
>
<ContactFields />
</ThemeOptionsPage>
);

Highlighted props

PropTypeDescription
titlestringPage heading. Defaults to "Theme options".
settingNamestringWordPress option key to read/write. Defaults to eightshift-theme-options. The value must be a JSON-encoded string in the database.
childrenJSX.ElementThe page body — typically a tree of OptionsPanel / ContainerPanel components that read from EsThemeOptionsContext.
Note

The option referenced by settingName must be registered on the PHP side with show_in_rest: true so it's exposed via /wp/v2/settings. The value is stored as a JSON-encoded string — useThemeOptions handles the encoding and decoding for you.

useThemeOptions

The hook that powers ThemeOptionsPage. Use it directly if you want to build a custom shell.

import { useThemeOptions } from '@eightshift/frontend-libs-tailwind/scripts';

const { settings, setSettings, updateSettings, saveSettings, isLoading } = useThemeOptions('my-theme-options');
ReturnedTypeDescription
settingsobject | undefinedThe decoded option value. undefined while loading.
setSettings(next) => voidReplaces the whole settings object.
updateSettings(partial) => voidShallow-merges partial into the current settings. The usual way to update one field.
saveSettings() => Promise<void>Persists the current settings via apiFetch. Shows a success/error toast.
isLoadingbooleantrue while a save is in flight.

EsThemeOptionsContext

A standard React context that exposes the value returned by useThemeOptions. Use it from any child component of ThemeOptionsPage to read or update settings without prop-drilling.

import { useContext } from '@wordpress/element';
import { EsThemeOptionsContext } from '@eightshift/frontend-libs-tailwind/scripts';

const { settings, updateSettings } = useContext(EsThemeOptionsContext);