feat: tsuki Firefox theme for Nova (157+)
Adaptive light/dark static theme generated from @tsuki/tokens, plus an optional userChrome.css layer (IBM Plex, tsuki radii, shu accent) that overrides Nova's design tokens. Self-hosted via AMO unlisted signing and Gitea releases. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
# @tsuki/firefox-theme
|
||||
|
||||
tsuki for Firefox 157+ (Nova). One adaptive theme: kami (paper) when your system is light, sumi (ink) when it's dark, with shu marking the active tab, loading state, and focused address bar.
|
||||
|
||||
Two layers:
|
||||
|
||||
- **Theme** (`tsuki-<version>.xpi`) — colors only. Signed by Mozilla, self-hosted on Gitea, updates automatically.
|
||||
- **userChrome.css** (optional) — what the theme API can't reach: IBM Plex Sans, tsuki corner radii (4/6/8px instead of Nova's 12–24px), and shu in place of Nova's violet for focus rings, links, and primary buttons.
|
||||
|
||||
Both are generated from [`@tsuki/tokens`](https://git.d-v.cc/tsuki/tokens). No hex values are written by hand.
|
||||
|
||||
## Install
|
||||
|
||||
### Theme
|
||||
|
||||
Download `tsuki-<version>.xpi` from the [latest release](https://git.d-v.cc/tsuki/firefox-theme/releases) and open it in Firefox. Firefox checks `updates.json` in this repo for new versions.
|
||||
|
||||
### userChrome.css
|
||||
|
||||
1. Open `about:config` and set `toolkit.legacyUserProfileCustomizations.stylesheets` to `true`.
|
||||
2. Open `about:support` and click **Open Folder** next to *Profile Folder*.
|
||||
3. Unzip `tsuki-userchrome-<version>.zip` from the release and copy the contents of its `userChrome/` folder into a `chrome/` folder in your profile, giving you `chrome/userChrome.css` and `chrome/tsuki-fonts/`.
|
||||
4. Restart Firefox.
|
||||
|
||||
If you already have a `userChrome.css`, paste tsuki's at the top of yours and keep the `tsuki-fonts/` folder next to it.
|
||||
|
||||
The overrides target Nova's design tokens (`--border-radius-*`, `--color-accent-primary`, `--focus-outline-color`), not element selectors, so they should survive most Firefox updates. Mozilla doesn't support userChrome.css, though, and a future release may rename these tokens.
|
||||
|
||||
## Design notes
|
||||
|
||||
- **No gradients.** Nova encourages gradient themes. tsuki doesn't use them, and the tests fail on any `gradient` or `images` in the output.
|
||||
- **Selected tab = toolbar.** Both are `kami-0` / `sumi-100`, so the active tab reads as one sheet with the toolbar. Separation comes from color, not shadow.
|
||||
- **Dead Nova keys are omitted:** `ntp_text`, `sidebar_highlight`, `sidebar_highlight_text`.
|
||||
- **Contrast is tested:** text pairs ≥ 4.5:1, icons and accent marks ≥ 3:1, in both modes.
|
||||
|
||||
To change a color, edit [`src/mapping.ts`](src/mapping.ts).
|
||||
|
||||
## Develop
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
pnpm build # dist/theme, dist/userChrome, updates.json
|
||||
pnpm test
|
||||
pnpm lint # web-ext lint (self-hosted rules)
|
||||
pnpm start # Firefox with the theme + userChrome, light
|
||||
pnpm start:dark # same, forced dark
|
||||
```
|
||||
|
||||
`pnpm start` uses a throwaway profile in `.preview-profile/`, not your own.
|
||||
|
||||
### Test checklist (Mozilla's for Nova)
|
||||
|
||||
Horizontal and vertical tabs · sidebar closed / open / expand-on-hover · compact density · private window · light and dark · hover states on tabs and toolbar buttons.
|
||||
|
||||
## Releasing
|
||||
|
||||
Release Firefox only installs Mozilla-signed add-ons, so "self-hosted" means signed through AMO's **unlisted** channel (not published on addons.mozilla.org), then distributed from Gitea.
|
||||
|
||||
One-time setup:
|
||||
|
||||
1. Create AMO API credentials at <https://addons.mozilla.org/developers/addon/api/key/>.
|
||||
2. Add repo secrets: `AMO_JWT_ISSUER`, `AMO_JWT_SECRET`, `NPM_TOKEN` (registry read), `RELEASE_TOKEN` (Gitea token with repo write).
|
||||
3. The repo must be public: Firefox fetches `updates.json` and the XPI without auth.
|
||||
|
||||
Cut a release:
|
||||
|
||||
```bash
|
||||
npm version <patch|minor|major> --no-git-tag-version
|
||||
pnpm build # regenerates updates.json for the new version
|
||||
git commit -am "release: vX.Y.Z"
|
||||
git tag vX.Y.Z
|
||||
git push --follow-tags
|
||||
```
|
||||
|
||||
CI verifies `updates.json` is committed for the tag, signs the XPI, and attaches it and the userChrome zip to a Gitea release.
|
||||
Reference in New Issue
Block a user