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);