Metadata-Version: 2.4
Name: datasette-themes
Version: 0.1
Summary: Pick a Datasette theme from the hamburger menu
License: Apache-2.0
Project-URL: Homepage, https://github.com/koaning/datasette-themes
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Requires-Dist: datasette
Provides-Extra: test
Requires-Dist: pytest; extra == "test"
Requires-Dist: pytest-asyncio; extra == "test"

# datasette-themes

A [Datasette](https://datasette.io/) plugin to make theming slightly easier. Lets a visitor 
pick one from the hamburger (navigation) menu and gives them a preview interface.

Features: 

- **Off by default** — Datasette looks exactly as it normally does until a visitor
  picks a theme.
- **Live preview** — you can see which theme works best for you
- **Theme per User** — the chosen theme is remembered in a cookie and
  injected server-side on first paint via the `extra_css_urls` hook.
- **Full restyles** — each theme can change typography, spacing, radii,
  shadows, tables, facets, etc. 

## Bundled themes

| Theme | Description |
|-------|-------------|
| Vercel | Taking some hints from Vercel-like pages |
| Dark | A modern dark theme. |
| Solarized | Variation of Solarized Dark palette. |
| Sepia | An "aged paper" light theme with a serif reading feel. |
| RollerCoaster | RollerCoaster Tycoon themed. Inspired by [koaning/rct-css](https://github.com/koaning/rct-css). |

## Installation

```bash
datasette install datasette-themes
```

## Usage

Open Datasette, click the hamburger menu (top right) and choose **Themes**. On the
picker page:

- Click a theme name to **preview** it — the page and the embedded table restyle,
  without changing your saved choice.
- Click **Use "…"** to save that theme in a cookie so it applies across the whole
  site and future visits (in this browser).
- Click **Reset to default** to clear the cookie and return to Datasette's stock look.

### Configuring the preview table

By default the picker embeds the first table of the first database. To point it at a
specific table, set `preview_table` in the plugin config:

```json
{
  "plugins": {
    "datasette-themes": {
      "preview_table": "aom_units/units"
    }
  }
}
```

## Try the demo locally

The repo includes a demo that loads real sample databases (Age of Mythology units
with inline images, earthquakes, Everest climbs, student sleep/GPA) and runs the
plugin alongside [`datasette-render-images`](https://datasette.io/plugins/datasette-render-images):

```bash
make dev          # builds the demo databases if needed, then serves on :8123
```

Then open <http://localhost:8123/-/themes>. Inside Conductor, the **Run** button is
wired to the same command via `.conductor/settings.toml`.

The demo databases are rebuilt from the public instance at `datasette.exe.xyz` (raw
`.db` downloads are disabled there, so `demo/build.py` reconstructs them from the
CSV/SQL API and re-fetches the unit icon image blobs). They are gitignored; rebuild
with:

```bash
make data
```

## Adding your own themes

You don't need to touch the plugin's internals to add a theme. Serve a CSS file from
your Datasette (e.g. `datasette --static static:./static`) and register it under the
`themes` plugin config — each entry maps a theme id to a `label` and stylesheet `url`:

```json
{
  "plugins": {
    "datasette-themes": {
      "themes": {
        "corp": { "label": "Corp Brand", "url": "/static/corp.css" }
      }
    }
  }
}
```

Your theme then shows up in the picker (with live preview) and behaves exactly like a
bundled one. Root-relative `url`s are resolved against Datasette's `base_url`; absolute
`https://…` URLs are used as-is.

### Showing only your own themes

Use `bundled_themes` to control which shipped themes are offered: `true` (default) shows
all of them, `false` hides them all, and a list is an allowlist (e.g. `["dark", "rct"]`).
To show **only** your own, hide the bundled ones and register your own:

```json
{
  "plugins": {
    "datasette-themes": {
      "bundled_themes": false,
      "themes": {
        "corp": { "label": "Corp Brand", "url": "/static/corp.css" }
      }
    }
  }
}
```

A hidden or unregistered theme can't be applied, even via an old cookie or a
`?_theme_preview=` link.

### Editing the bundled themes from source

If you're hacking on the plugin itself, the bundled themes are plain CSS files under
`datasette_themes/static/`, registered in the `THEMES` dict in
`datasette_themes/__init__.py`. Datasette serves them with no cache headers, so on an
editable install you can edit a `.css` file and just refresh the browser.

## How it works

| Hook | Role |
|------|------|
| `extra_css_urls` | Injects the active theme's CSS URL (from the `?_theme_preview=` query param, else the `ds_theme` cookie). Returns nothing when no theme is selected. |
| `menu_links` | Adds the **Themes** item to the hamburger menu. |
| `register_routes` | `/-/themes` (picker page) and `/-/themes/set` (saves the cookie and redirects back). |

CSS files are served by Datasette's built-in plugin static handling at
`/-/static-plugins/datasette_themes/<file>.css`.

## Development

```bash
make test         # uv run --with-editable '.[test]' --with pytest-asyncio pytest
```

## Credits

The RollerCoaster theme's pixel font is **Departure Mono** (bundled under
`datasette_themes/static/`, see the included license) and the aesthetic is adapted
from [rct-css](https://github.com/koaning/rct-css).
