Skip to main content
AutoLog provides a comprehensive theming system built on Material UI Joy with support for light/dark modes, brand colors, and custom typography.

Theme Architecture

The theming system consists of:
  • Color Schemes - Light, Dark, and System modes
  • Brand Colors - 10 pre-configured color palettes
  • Typography - 4 font options with live preview
  • Theme Persistence - Settings saved to localStorage

Color Schemes

AutoLog supports three color scheme modes:

Light Mode

Clean, bright interface optimized for daylight viewing

Dark Mode

Reduced eye strain for low-light environments

System Mode

Automatically matches your operating system preference

Implementing Color Scheme Toggle

Use the useColorScheme hook from Material UI Joy:
ColorSchemeToggle.jsx
import { useColorScheme } from "@mui/joy/styles";
import IconButton from "@mui/joy/IconButton";
import DarkModeRoundedIcon from "@mui/icons-material/DarkModeRounded";
import LightModeIcon from "@mui/icons-material/LightMode";

export default function ColorSchemeToggle() {
  const { mode, setMode } = useColorScheme();

  return (
    <IconButton
      variant="outlined"
      color="neutral"
      onClick={() => {
        setMode(mode === "light" ? "dark" : "light");
      }}
    >
      {mode === "light" ? <DarkModeRoundedIcon /> : <LightModeIcon />}
    </IconButton>
  );
}

Mode Detection

import { useColorScheme } from "@mui/joy/styles";

const { mode, systemMode } = useColorScheme();
// mode: "light" | "dark" | "system"
// systemMode: actual resolved mode when "system" is selected

Brand Colors

AutoLog includes 10 professionally designed brand color palettes:
BrandPrimary ColorName
Default#0B6BCBAzul Tecnasa
Indigo#6366f1Índigo
Forest#10b981Bosque
Orange#f97316Naranja
Teams#6264A7Teams
Rose#e11d48Rose Red
Purple#a855f7Deep Purple
Cyan#06b6d4Cyan Sky
Slate#64748bSlate Grey
Neon#d946efCyberpunk

Theme Context

The AppThemeProvider manages theme state:
AppThemeContext.jsx
import { createContext, useContext, useState, useEffect } from "react";
import { CssVarsProvider } from "@mui/joy";
import { createAppTheme } from "../theme/createAppTheme";

const AppThemeCtx = createContext(null);

export function AppThemeProvider({ children }) {
  const [brand, setBrand] = useState(getLS("ui:brand", "default"));
  const [font, setFont] = useState(getLS("ui:font", "Poppins, sans-serif"));

  const theme = useMemo(() => createAppTheme({ brand, font }), [brand, font]);

  return (
    <AppThemeCtx.Provider value={{ brand, setBrand, font, setFont }}>
      <CssVarsProvider
        theme={theme}
        defaultMode="light"
        modeStorageKey="ui:mode"
        disableTransitionOnChange
      >
        {children}
      </CssVarsProvider>
    </AppThemeCtx.Provider>
  );
}

export const useAppTheme = () => useContext(AppThemeCtx);

Using Custom Brand Colors

import { useAppTheme } from "@/context/AppThemeContext";

export default function BrandColorSelector() {
  const { brand, setBrand } = useAppTheme();

  return (
    <select value={brand} onChange={(e) => setBrand(e.target.value)}>
      <option value="default">Azul Tecnasa</option>
      <option value="indigo">Índigo</option>
      <option value="forest">Bosque</option>
      <option value="orange">Naranja</option>
    </select>
  );
}

Theme Creation

The createAppTheme function generates a Material UI Joy theme:
createAppTheme.js
import { extendTheme } from "@mui/joy/styles";

const BRANDS = {
  default: { primary: "#0B6BCB", name: "Azul Tecnasa" },
  indigo: { primary: "#6366f1", name: "Índigo" },
  forest: { primary: "#10b981", name: "Bosque" },
  // ... more brands
};

export const createAppTheme = ({ brand = "default", font = "Poppins" }) => {
  const selectedBrand = BRANDS[brand] || BRANDS.default;
  const color = selectedBrand.primary;

  return extendTheme({
    fontFamily: {
      body: font,
      display: font,
      code: "monospace",
    },
    colorSchemes: {
      light: {
        palette: generatePalette(color),
      },
      dark: {
        palette: generatePalette(color),
      },
    },
  });
};

Typography

AutoLog supports 4 font families:
1

Poppins (Default)

Modern, geometric sans-serif font with excellent readability
2

Inter

Optimized for user interfaces with precise letter spacing
3

Roboto

Google’s Material Design font, clean and professional
4

Fira Code

Monospace font with programming ligatures

Font Configuration

const FONTS = [
  { value: "Poppins, sans-serif", label: "Poppins" },
  { value: "Inter, ui-sans-serif, system-ui, sans-serif", label: "Inter" },
  { value: "Roboto, system-ui, sans-serif", label: "Roboto" },
  { value: "'Fira Code', monospace", label: "Fira Code" },
];

Changing Fonts

import { useAppTheme } from "@/context/AppThemeContext";

export default function FontSelector() {
  const { font, setFont } = useAppTheme();

  const handleFontChange = async (newFont) => {
    setFont(newFont);
    // Font changes require page reload
    window.location.reload();
  };

  return (
    <Select value={font} onChange={(_, value) => handleFontChange(value)}>
      <Option value="Poppins, sans-serif">Poppins</Option>
      <Option value="Inter, ui-sans-serif, system-ui, sans-serif">Inter</Option>
      <Option value="Roboto, system-ui, sans-serif">Roboto</Option>
    </Select>
  );
}
Font changes require a page reload to take effect. This ensures all components properly load the new font family.

Appearance Settings

The Settings page (src/pages/Settings/sections/Apariencia.jsx) provides a UI for customizing appearance:
const { mode, setMode } = useColorScheme();
const { t } = useTranslation();

const handleModeChange = async (event) => {
  const newMode = event.target.value;
  setMode(newMode);
  await onSave({ mode: newMode });
};

return (
  <RadioGroup value={mode || "light"} onChange={handleModeChange}>
    <Radio value="system" label={t("settings.appearance.theme.system")} />
    <Radio value="dark" label={t("settings.appearance.theme.dark")} />
    <Radio value="light" label={t("settings.appearance.theme.light")} />
  </RadioGroup>
);

Storage Keys

Theme settings are persisted in localStorage:
KeyValueDescription
ui:mode"light" | "dark" | "system"Color scheme mode
ui:brand"default" | "indigo" | …Selected brand color
ui:font"Poppins, sans-serif" | …Font family

Accessing Stored Preferences

const getLS = (key, defaultValue) => {
  try {
    const value = localStorage.getItem(key);
    return value ?? defaultValue;
  } catch {
    return defaultValue;
  }
};

const setLS = (key, value) => {
  try {
    localStorage.setItem(key, value);
  } catch {}
};

const currentBrand = getLS("ui:brand", "default");
const currentMode = getLS("ui:mode", "light");

Custom CSS Variables

The theme system exposes CSS variables for custom styling:
:root {
  --app-font: Poppins, sans-serif;
  --joy-palette-primary-main: #0B6BCB;
  --joy-palette-primary-mainChannel: 11 107 203;
}

Using CSS Variables

<Box
  sx={{
    fontFamily: "var(--app-font)",
    color: "var(--joy-palette-primary-main)",
    backgroundColor: "rgba(var(--joy-palette-primary-mainChannel) / 0.15)",
  }}
>
  Themed content
</Box>

Dark Mode Synchronization

AutoLog includes a TailwindDarkSync component to sync dark mode with Tailwind CSS:
TailwindDarkSync.jsx
import { useColorScheme } from "@mui/joy/styles";
import { useEffect } from "react";

export default function TailwindDarkSync() {
  const { mode, systemMode } = useColorScheme();
  const resolvedMode = mode === "system" ? systemMode : mode;

  useEffect(() => {
    if (resolvedMode === "dark") {
      document.documentElement.classList.add("dark");
    } else {
      document.documentElement.classList.remove("dark");
    }
  }, [resolvedMode]);

  return null;
}
Include TailwindDarkSync inside your theme provider to automatically sync dark mode with Tailwind’s dark mode classes.

Best Practices

  • Always use theme tokens instead of hardcoded colors
  • Test your UI in both light and dark modes
  • Provide fallback values for localStorage access
  • Use useColorScheme for mode-aware components
  • Reload the page after font changes for consistency

Build docs developers (and LLMs) love