Theme data
Every field of the theme object that useTheme and useTwilight().theme return, with real values from a live store.
Read this when you need the merchant's brand colours, font or theme settings in a component, and you want to know exactly what the object holds.
The theme object is what the store's store/settings response calls theme. The engine loads it once, puts it in the provider at the root of the app, and hands it to your components in two ways.
| You call | You get | Use it when |
|---|---|---|
useTheme() | A small result: color, font, settings, isRTL | You need colours, the font or your settings. The common case. |
useTwilight().theme | The whole theme object | You need a field useTheme leaves out: name, mode, profile, assets, customization, twilight. |
The text direction of the current language is a separate thing: see useTranslation.
Read a setting and a colour
import { useTheme } from '@salla.sa/twilight-theme-engine/hooks/useTheme';
export function PromoBar({ children }: { children: React.ReactNode }) {
const { color, settings } = useTheme();
// `!== false`: a store that never saved the setting has no value, and that should mean "on".
if (settings.header_is_sticky === false) return null;
return <div style={{ background: color.primary, color: color.reverse_text }}>{children}</div>;
}The same values through the provider:
import { useTwilight } from '@salla.sa/twilight-theme-engine/providers';
const { theme } = useTwilight();
theme.mode; // 'live'
theme.settings.header_is_sticky; // trueThe full object
This is the real theme of the public demo store (1510890315), trimmed. Search it, or click a key to copy its path.
Fields
The tables are generated from Theme in @salla.sa/twilight-theme-engine/types. color, font and settings get their own tables.
| Field | Type | Description |
|---|---|---|
id? | number | Theme id. Not sent by the settings API (absent on the demo store); treat as optional. |
name | string | Theme name. The engine adds it to <body> as the class salla-<name>. |
profile? | { id: number; name: string | null; } | The merchant's theme profile (the saved set of choices). |
mode | string | 'preview' while the merchant previews a draft (the engine adds the body class preview-mode), otherwise 'live'. |
is_rtl | boolean | Whether the theme reads right to left. |
color | ThemeColor | Brand colors of the theme. |
settings | ThemeSettings | Merchant values for the theme's settings. |
assets? | string | URL template of the theme's published files; :path stands for the file path. |
bundle_assets? | string | URL template of component bundles (:bundle, :component). |
customization? | { css?: string | null; js?: string | null; } | The merchant's custom CSS and JS, as a URL or inline code. The engine loads them for you. |
side_menu_enabled? | boolean | null | Whether the merchant turned on the side menu. |
twilight? | { version?: string | null; } | Platform-pinned twilight SDK release, served from the production CDN. |
font? | ThemeFont | The selected font. Can be missing. |
components? | unknown[] | Not typed and empty on the demo store. Home blocks do not come from here. |
isDark? | boolean | null | Sent by the platform, usually null. Use color.is_dark instead. |
translations_hash? | string | Hash of current translations for cache invalidation |
profile
| Field | Type | Description |
|---|---|---|
id | number | Profile id. |
name | string | null | Profile name, or null. |
color
| Field | Type | Description |
|---|---|---|
primary | string | Primary brand color. |
text | string | Text color chosen for the theme. |
is_dark | boolean | Dark color scheme. The engine adds color-mode-dark or color-mode-light to <body>. |
reverse_primary | string | The reverse counterpart of the primary color. |
reverse_text | string | Text color to put on top of primary. |
settings
| Field | Type | Description |
|---|---|---|
font? | ThemeFont | The selected font. |
imageZoom? | boolean | Zoom on the product gallery. |
show_tags? | boolean | Show product tags. |
store_color? | string | Brand color value. Platform-managed. |
is_custom_js? | boolean | Whether the merchant has custom JS. Platform-managed. |
is_custom_css? | boolean | Whether the merchant has custom CSS. Platform-managed. |
homepage_type? | string | Kind of home page. Platform-managed. |
theme_version? | string | Installed theme version. Platform-managed. |
footer_is_dark? | boolean | Dark footer. Adds footer-is-dark or footer-is-light to <body>. |
topnav_is_dark? | boolean | Dark top bar. Adds the body class topnav-is-dark. |
use_sar_symbol? | boolean | Show the Saudi riyal symbol instead of the currency code. |
important_links? | boolean | Show the important-links block. Platform-managed. |
store_font_type? | string | Font type of the store. Platform-managed. |
footer_menu_type? | string | Footer menu variant. Platform-managed. |
header_is_sticky? | boolean | Keep the main menu at the top while scrolling. |
product_show_breadcrumbs? | boolean | Breadcrumb trail on the product page (default on). |
product_index_show_breadcrumbs? | boolean | Breadcrumb trail on product list pages (default on). |
notify_when_available_in_card? | boolean | Out-of-stock cards offer "notify me when available" (default on). |
header_menu_type? | string | Header menu variant. Platform-managed. |
header_layout? | "default" | "lite" | Header layout variant of the reference theme. |
footer_layout? | "centered" | "columns" | Footer layout variant of the reference theme. |
product_card_img_ratio? | string | { value?: string; }[] | Product card image ratio. Either shape can arrive. |
default_font_name? | string | Name of the default font. Platform-managed. |
sticky_add_to_cart? | boolean | Sticky add-to-cart bar on mobile. Adds is-sticky-product-bar to <body>. |
customization_js_ver? | number | null | Version of the merchant's custom JS, or null. Platform-managed. |
customization_css_ver? | number | null | Version of the merchant's custom CSS, or null. Platform-managed. |
translations_hash? | string | Hash of current translations (also sent at theme.translations_hash). |
is_more_button_enabled? | boolean | The "All" button on home blocks. |
slider_background_size? | "contain" | "cover" | How product gallery images fit their frame. |
vertical_fixed_products? | boolean | Show products in a vertical fixed layout. |
is_custom_widgets_enabled? | boolean | Custom widgets are enabled. |
squar_photo_bg_image_size? | "contain" | "cover" | How images fit in the square-photos block. |
is_show_more_detail_enabled? | boolean | Show the "more details" control. |
is_breadcrumbs_enabled? | boolean | Breadcrumbs on or off. |
placeholder? | string | Image the SDK's product cards show when a product has none. |
enable_add_product_toast? | boolean | Show a toast after adding to the cart. |
enable_more_menu? | boolean | Show the "More" menu. |
settings.font
| Field | Type | Description |
|---|---|---|
id? | number | Font id. |
name | string | Font family name. |
path? | string | Relative path of the stylesheet that loads the font. |
url? | string | Stylesheet URL that loads the font. |
type? | string | number | Source of the font. theme.font sends a string, theme.settings.font a number. |
family_name? | string | CSS family name. Present on settings.font, not on theme.font. |
customization
| Field | Type | Description |
|---|---|---|
css? | string | null | Custom CSS, or null. |
js? | string | null | Custom JS, or null. |
twilight
| Field | Type | Description |
|---|---|---|
version? | string | null | The pinned SDK version, or null. |
font
Same fields as settings.font.
settings holds every merchant-editable value, flat, keyed by the id you declared in twilight.json. The engine types only the keys the reference theme uses. A store's settings can hold more keys than the type lists, so read only the keys you declared.
Settings the engine reads itself (footer_is_dark, footer_layout, topnav_is_dark, sticky_add_to_cart, slider_background_size, header_is_sticky) work even when your theme never reads them.
Features and home blocks
features(such as"mega-menu","fonts") are declared intwilight.jsonfor the dashboard. They are not part of the runtime theme object: you cannot read them fromuseTheme.- Home blocks are loaded by the home route, not read from the theme. A block's values reach your component as a
dataprop. See Add a home block.
How CSS gets its values
When the page mounts in the browser, the engine copies the theme onto the root element as CSS variables, so styles need no JavaScript:
| Variable | Value |
|---|---|
--color-primary | color.primary |
--color-primary-dark, --color-primary-light | primary darkened or lightened by 15% |
--color-title, --color-secondary | color.primary |
--color-primary-reverse, --color-text-reverse, --color-reverse-text | color.reverse_text |
--color-reverse-primary | color.reverse_primary |
--color-text | Always #222222, not color.text |
--font-main, --font-light, --font-regular | font.name |
--font-medium, --font-bold | font.name plus -Medium or -Bold |
See Styling.
From twilight.json to a value
You declare a setting once in twilight.json (Settings guide). The merchant picks a value in the dashboard, and the key appears in theme.settings under the same id.
{ "id": "header_is_sticky", "type": "boolean", "format": "switch", "value": true }settings.header_is_sticky; // true (a plain boolean)static entries (titles, lines, descriptions) only decorate the dashboard and have no runtime value. Entries typed collection and variable-list belong to home block fields.
Common tasks
A boolean that defaults to on:
const sticky = useTheme().settings.header_is_sticky !== false;A dropdown value, from a string or [{ value }]:
function dropdownValue(raw: unknown): string | undefined {
const first = Array.isArray(raw) ? raw[0] : raw;
return typeof first === 'string' ? first : (first as { value?: string } | undefined)?.value;
}
const fit = dropdownValue(settings.slider_background_size) ?? 'cover';A colour in an inline style, with readable text on top:
const { color } = useTheme();
<button style={{ background: color.primary, color: color.reverse_text }}>Buy</button>;The font name, safely:
const { font } = useTheme();
const family = font?.name ?? 'inherit';Direction:
const { isRTL } = useTheme();
<div dir={isRTL ? 'rtl' : 'ltr'} />;Gotchas
- Value shapes differ per widget. A switch is a boolean, a dropdown is the chosen
value. Check the shape before using it. - A dropdown can be a string or
[{ value }].product_card_img_ratiois typed to allow both. Normalise with a helper like the one above. - Settings can be
undefined. Until the merchant saves, a key may be missing. Test!== falsefor "on by default". fontis optional, andsettings.fontis a different object (withfamily_name).useTheme().fontis thefontfield.- CSS variables are set in the browser. The engine writes them when the page mounts, so on the server render they are not there yet. The theme object itself is available on the server and the client.
--color-textis#222222, notcolor.text. Readcolor.textfrom the hook when you need it.isRTLis the theme's direction. UseuseTranslationfor the direction of the current language.
Next
- Settings guide: declare settings in
twilight.json. useTheme: the hook's API.- Store data: the store object next to the theme.
- Styling: use the colours and fonts in CSS.