JSPM

@netoum/themex

1.0.1
  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 4
  • Score
    100M100P100Q32088F
  • License ISC

A flexible and unstyled theming system that supports multiple theme attributes with persistent storage and automatic UI synchronization.

Package Exports

  • @netoum/themex
  • @netoum/themex/dist/index.esm.js
  • @netoum/themex/dist/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@netoum/themex) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Logo

Themex (@netoum/themex)

Flexible, accessible and unstyled theming system that supports multiple theme attributes with persistent storage and automatic UI synchronization.

Features

  • 🎨 Multiple theme attributes support (color schemes, modes, layouts, etc.)
  • 💾 Automatic localStorage persistence
  • 🔄 UI state synchronization across controls
  • 🎯 Data attribute-based targeting
  • 📱 Support for various control types (select, button, checkbox, radio and range)
  • 🔌 Zero dependencies
  • 📦 CommonJS & ESM support

Installation

npm install @netoum/themex

Quick Start

import { Themex } from '@netoum/themex';

const options = [
  {
    key: 'theme',
    default: 'gray',
    values: ['gray', 'red']
  },
  {
    key: 'mode',
    default: 'light',
    values: ['light', 'dark']
  },
  {
    key: 'density',
    default: 'compact',
    values: ['compact', 'wide']
  },
    {
    key: 'size',
    default: '2',
    values: ['1', '2', '3']
  }
];

new Themex(options);

Data Attributes

  • data-${key}: Applied to HTML document (for ex: data-mode="dark")
  • data-themex-key: Identifies the theme attribute to modify
  • data-themex-value: Specifies the value to apply

State Attributes

  • aria-current: Applied to Button Set controls to indicate current selection
  • aria-pressed: Applied to Button Toggle controls to indicate current selection
  • data-selected: Applied to Select Options controls to indicate current selection

HTML Controls

Themex works with various HTML controls:

Button Set

You must add "set" to each button The selected button will have "aria-current="true" attribute

<button data-themex-key="mode" data-themex-value="light" set>
  Light
</button>
<button data-themex-key="mode" data-themex-value="dark" set>
  Dark
</button>

<div role="button" data-themex-key="mode" data-themex-value="light" set>
  Light
</div>
<div role="button" data-themex-key="mode" data-themex-value="dark" set>
  Dark
</div>
button[aria-current="true"] {
  background-color: var(--color-primary-contrast);
  color:  var(--color-primary);
}

div[role="button"][aria-current="true"] {
  background-color: var(--color-primary-contrast);
  color:  var(--color-primary);
}

Button Toggle

You must add "toggle" to each button The selected button will have "aria-pressed="true" attribute

<button data-themex-key="mode" data-themex-value="light" toggle>
  Light
</button>
<button data-themex-key="mode" data-themex-value="dark" toggle>
  Dark
</button>

<div role="button" data-themex-key="mode" data-themex-value="light" toggle>
  Light
</div>
<div role="button" data-themex-key="mode" data-themex-value="dark" toggle>
  Dark
</div>
button[aria-pressed="true"] {
  display: hidden
}

div[role="button"][aria-pressed="true"] {
  display: hidden
}

Select Dropdowns

By default Select do not have a common way to track the selected option on all browser, so we add "data-selected="true" attribute for styling

<select data-themex-key="theme">
    <option value="gray">Gray</option>
    <option value="red">Red</option>
</select>
option[data-selected="true"] {
  background-color: var(--color-primary-contrast);
  color:  var(--color-primary);
}

Switches/Checkbox Toggle

You must select 2 values, the first one being the value selectd when the checkob is checked, the second beign the fallback when the checkbox is unchecked

<label>
  Wide
</label>
  <input type="checkbox" 
         data-themex-key="density" 
         data-themex-value="wide,compact">

Radio

      <label>
        Gray Theme
      </label>
      <input type="radio" name="theme-radio" data-themex-key="theme" data-themex-value="gray">
      <label>
        Red Theme
      </label>
      <input type="radio" name="theme-radio" data-themex-key="theme" data-themex-value="red">

CSS Usage

:root {
    /* Theme */
    --color-primary: var(--theme-color-primary);
    --color-primary-contrast: var(--theme-color-primary-contrast);

    /* Theme/Mode */
    --color-body: var(--theme-color-body);
    --color-body-contrast: var(--theme-color-body-contrast);

    /* Density */
    --spacing: var(--density-spacing);

    /* Base */
    --color-gray-1: #f6f6f6;
    --color-gray-2: #e2e2e2;
    --color-gray-3: #8b8b8b;
    --color-gray-4: #6f6f6f;
    --color-gray-5: #3e3e3e;
    --color-gray-6: #222222;
    --color-red-1: #fff8f6;
    --color-red-2: #ffddd8;
    --color-red-3: #ff4647;
    --color-red-4: #e0002b;
    --color-red-5: #830014;
    --color-red-6: #530003;
}

/* Theme variations */

[data-theme="gray"] {
  --theme-color-primary: var(--color-gray-2);
  --theme-color-primary-contrast: var(--color-gray-6);
}


[data-theme="red"] {
  --theme-color-primary: var(--color-red-2);
  --theme-color-primary-contrast: var(--color-red-6);
}

/* Theme/Mode variations */

[data-theme="gray"][data-mode="light"] {
--theme-color-body: var(--color-gray-2);
--theme-color-body-contrast: var(--color-gray-6);
}


[data-theme="gray"][data-mode="dark"] {
--theme-color-body: var(--color-gray-6);
--theme-color-body-contrast: var(--color-gray-2);

}

[data-theme="red"][data-mode="light"] {
--theme-color-body: var(--color-red-2);
--theme-color-body-contrast: var(--color-red-6);
}


[data-theme="red"][data-mode="dark"] {
--theme-color-body: var(--color-red-6);
--theme-color-body-contrast: var(--color-red-2);

}


/* Density variations */
[data-density="compact"] {
--spacing: 0.5rem;
--font-size: 0.875rem;
}

[data-density="wide"] {
--spacing: 1rem;
--font-size: 1rem;
}

/* See it in action */
body {
  background-color: var(--theme-color-body);
  color: var(--theme-color-body-contrast);
  padding: var(--spacing); 
  font-size: var(--font-size); 
}

button[aria-current="true"] {
  text-decoration: underline;
}

Examples

You will find some Themex examples with Vite and Eleventy using more complex theming and referencing. Some example also uses the System mode for Light/Dark mode

License

MIT

Open source by Netoum

The whole project, including the examples are fully open source and brought to you by Netoum.com