All files / core/blong-browser/src/components/ThemeSwitcher ThemeSwitcher.tsx

100% Statements 12/12
100% Branches 11/11
100% Functions 3/3
100% Lines 11/11

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73                                                            12x 12x 12x   12x   11x 11x 12x 12x   12x                 1x                             1x              
import './ThemeSwitcher.css';
 
import {useText} from '../../hooks/useText.js';
import {Button, Dropdown} from '../../primereact/index.js';
import {useTheme, type PaletteType} from '../Theme/Theme.js';
import {THEME_GROUPS} from '../Theme/themeRegistry.js';
 
export interface IThemeSwitcherProps {
    /** Extra class name for the wrapper. */
    className?: string;
}
 
/**
 * ThemeSwitcher — the theme selector shown in the portal menubar, to the left
 * of the language switcher.
 *
 * A dropdown picks the theme family (Light/Dark variants of a family share one
 * entry; Glass/Wood are standalone). When the selected theme provides both a
 * light and a dark variant, a single borderless sun/moon icon button appears
 * next to the dropdown to flip between them. The icon shows the mode the button
 * switches **to**: a moon while light mode is active, a sun while dark mode is
 * active.
 *
 * The choice is written to `appStore.setTheme` (persisted to localStorage) and
 * applied by the `<Theme>` provider. Render it inside `<Theme>` so `useTheme()`
 * has the effective theme.
 *
 * Renders nothing when `IThemeConfig.switcher` is `false`.
 */
export function ThemeSwitcher({className = ''}: IThemeSwitcherProps) {
    const {optionId, palette, paletteToggle, switcher, selectTheme, selectPalette} = useTheme();
    const toLightLabel = useText('Switch to light mode');
    const toDarkLabel = useText('Switch to dark mode');
 
    if (!switcher) return null;
 
    const isDark = palette === 'dark';
    const nextPalette: PaletteType = isDark ? 'light' : 'dark';
    const modeLabel = isDark ? toLightLabel : toDarkLabel;
    const modeIcon = isDark ? 'pi pi-sun' : 'pi pi-moon';
 
    return (
        <div className={['blong-theme-switcher', className].filter(Boolean).join(' ')}>
            <Dropdown
                value={optionId}
                options={THEME_GROUPS}
                optionLabel="label"
                optionValue="id"
                optionGroupLabel="label"
                optionGroupChildren="items"
                onChange={e => selectTheme(e.value as string)}
                className="blong-theme-switcher__select"
                panelClassName="blong-theme-switcher__panel"
                aria-label="Theme"
            />
            {paletteToggle ? (
                <Button
                    type="button"
                    icon={modeIcon}
                    text
                    rounded
                    severity="secondary"
                    tooltip={modeLabel}
                    tooltipOptions={{position: 'bottom'}}
                    aria-label={modeLabel}
                    onClick={() => selectPalette(nextPalette)}
                    className="blong-theme-switcher__mode"
                />
            ) : null}
        </div>
    );
}