@sckyzo/cosmos-theme 0.3.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,26 @@ All notable changes to `@sckyzo/cosmos-theme` are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.4.1](https://github.com/SckyzO/cosmos/compare/@sckyzo/cosmos-theme@0.4.0...@sckyzo/cosmos-theme@0.4.1) (2026-10-31)
9
+
10
+
11
+ ### Miscellaneous Chores
12
+
13
+ * **@sckyzo/cosmos-theme:** Synchronize cosmos versions
14
+
15
+ ## [0.4.0](https://github.com/SckyzO/cosmos/compare/@sckyzo/cosmos-theme@0.3.0...@sckyzo/cosmos-theme@0.4.0) (2026-10-30)
16
+
17
+
18
+ ### Features
19
+
20
+ * **react:** add density to appearance settings and a compact DataTable ([000d1c2](https://github.com/SckyzO/cosmos/commit/000d1c211c4a4bfffd22e1b119558d0e0cb57235))
21
+ * **theme:** add 20px and 24px row padding tokens ([e4acd79](https://github.com/SckyzO/cosmos/commit/e4acd79ac1cc8e47551e1b2d82efe032c7ed95fa))
22
+ * **theme:** add a 4px row padding token ([4886cf3](https://github.com/SckyzO/cosmos/commit/4886cf3c65edbdef99ee88a4f9dc822ae8ea3000))
23
+ * **theme:** add a 5px row token that stops at 4px ([842804d](https://github.com/SckyzO/cosmos/commit/842804d10ab958a7c3f083ebd842597ffb16bd78))
24
+ * **theme:** add data-density and its spacing tokens ([070f74a](https://github.com/SckyzO/cosmos/commit/070f74a8135fe3564b4609a8a53755fc9e12d002))
25
+ * **theme:** follow the nearest dir attribute in the rtl variant ([6e25a80](https://github.com/SckyzO/cosmos/commit/6e25a800d64c3c3208c1d0eea940fe60980842d3))
26
+ * **theme:** rescale every corner with data-radius ([2bdea86](https://github.com/SckyzO/cosmos/commit/2bdea865a341d3052e9a1fe10a1c7875f6793f9f))
27
+
8
28
  ## [0.3.0](https://github.com/SckyzO/cosmos/compare/@sckyzo/cosmos-theme@0.2.0...@sckyzo/cosmos-theme@0.3.0) (2026-10-27)
9
29
 
10
30
 
package/README.md CHANGED
@@ -2,23 +2,30 @@
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/@sckyzo/cosmos-theme)](https://www.npmjs.com/package/@sckyzo/cosmos-theme)
4
4
 
5
- Cosmos design tokens — CSS only.
5
+ Cosmos design tokens, CSS only: a Tailwind 4 `@theme` block, four themes, twelve accents, six
6
+ fonts, and text size, density and corner radius settings. It is what `@sckyzo/cosmos-react` and
7
+ `@sckyzo/cosmos-charts` are styled with, and it works on its own in any framework.
6
8
 
7
- Provides CSS files consumable by any framework:
9
+ | Import | Purpose |
10
+ | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
11
+ | `@sckyzo/cosmos-theme/tailwind` | Tailwind 4 `@theme` block (palette, fonts, shadows, brand colors), the `dark:` and `rtl:` variants, the focus utilities |
12
+ | `@sckyzo/cosmos-theme/vars` | The CSS custom properties (bg, text, border, accent), the themes and the accents |
13
+ | `@sckyzo/cosmos-theme/fonts` | `@fontsource` font imports (Outfit + JetBrains Mono) |
14
+ | `@sckyzo/cosmos-theme/fonts/<name>` | One variable font for `data-font`: `inter`, `plex`, `montserrat`, `open-sans` |
8
15
 
9
- | Import | Purpose |
10
- | ----------------------------------- | ------------------------------------------------------------------------------ |
11
- | `@sckyzo/cosmos-theme/tailwind` | Tailwind 4 `@theme` block (palette, fonts, shadows, brand colors) |
12
- | `@sckyzo/cosmos-theme/vars` | Universal CSS custom properties (bg, text, border, accent), themes and accents |
13
- | `@sckyzo/cosmos-theme/fonts` | `@fontsource` font imports (Outfit + JetBrains Mono) |
14
- | `@sckyzo/cosmos-theme/fonts/<name>` | One variable font for `data-font`: `inter`, `plex`, `montserrat`, `open-sans` |
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install @sckyzo/cosmos-theme
20
+ ```
21
+
22
+ The three Cosmos packages share one version number: install the same version of each.
15
23
 
16
24
  ## Usage
17
25
 
18
26
  ### With Tailwind 4 (recommended for React apps)
19
27
 
20
- Import order matters: `tailwindcss` comes first, then the Cosmos tokens, then
21
- the vars.
28
+ Import order matters: `tailwindcss` comes first, then the Cosmos tokens, then the vars.
22
29
 
23
30
  ```css
24
31
  /* src/index.css */
@@ -28,9 +35,7 @@ the vars.
28
35
  @import '@sckyzo/cosmos-theme/fonts';
29
36
  ```
30
37
 
31
- Pairing this with `@sckyzo/cosmos-react`? You also need an `@source` line so
32
- Tailwind scans the components — see the
33
- [cosmos-react README](../react#set-up-the-styles).
38
+ With `@sckyzo/cosmos-react`, also add an `@source` line so Tailwind scans the components: see [Getting started](https://github.com/SckyzO/cosmos/blob/main/docs/getting-started.md#set-up-the-styles).
34
39
 
35
40
  ### Without Tailwind (e.g. Docusaurus)
36
41
 
@@ -40,114 +45,22 @@ Tailwind scans the components — see the
40
45
  /* Then reference vars: var(--color-brand-500), var(--color-bg-base), etc. */
41
46
  ```
42
47
 
43
- ## Themes & accents
44
-
45
- Two independent settings, both on the `<html>` element:
48
+ ### Set the appearance
46
49
 
47
- - **Theme**: one class, and only one at a time.
48
-
49
- | Theme | Class | Look |
50
- | ----------- | ------------ | -------------------------------------------- |
51
- | `light` | _(none)_ | Cool gray, the default |
52
- | `sand` | `.sand` | Warm beige light theme |
53
- | `dark` | `.dark` | Neutral black/gray, softened (no pure black) |
54
- | `deep-blue` | `.deep-blue` | Navy dark theme |
55
-
56
- `.dark` and `.deep-blue` both enable Tailwind's `dark:` variant.
57
-
58
- - **Accent**: a `data-accent` attribute that swaps the whole `--color-brand-*`
59
- scale (and with it `--color-accent` and the focus ring). Leave it off for
60
- `blue`. The others are `indigo`, `violet`, `purple`, `rose`, `teal`, `cyan`,
61
- `graphite`, `red`, `orange`, `amber`, `green`.
50
+ The theme is one class on `<html>`; the accent, the font, the text size, the density and the corner
51
+ radius are `data-accent`, `data-font`, `data-text-size`, `data-density` and `data-radius` attributes,
52
+ and the reading direction is the native `dir`.
62
53
 
63
54
  ```html
64
55
  <html class="sand" data-accent="teal"></html>
65
56
  ```
66
57
 
67
- `red`, `orange`, `amber` and `green` look like the status colors (error,
68
- warning, success): a red primary button reads as a destructive action. Offer
69
- them last in any picker, after the others.
70
-
71
- Every theme × accent pair meets WCAG AA for body text, links and white text on
72
- the accent. `pnpm --filter @sckyzo/cosmos-theme test` runs the contrast check
73
- (`scripts/check-contrast.mjs`) against the CSS files.
74
-
75
- ## Focus indicator
76
-
77
- Four Tailwind utilities, shipped with `@sckyzo/cosmos-theme/tailwind`, give
78
- every control the same keyboard focus look: a **solid accent indicator** plus
79
- the `--shadow-focus-ring` halo (12% of the accent). The halo alone is too faint
80
- to count: the solid part is what reaches 3:1 against the surface (WCAG 1.4.11;
81
- `brand-500` is checked on every theme × accent pair by `pnpm test`).
82
-
83
- | Utility | Paints | For |
84
- | --------------------------- | --------------------------- | --------------------------------------------------------------------- |
85
- | `focus-indicator` | 2px `brand-500` ring + halo | buttons, links, toggles, tabs, menu items, cards… |
86
- | `field-focus` | `brand-500` border + halo | text inputs, textarea, select and their wrappers |
87
- | `field-focus-error` | `red-500` border + red halo | the same fields in error (`--shadow-focus-ring-error`) |
88
- | `focus-indicator-on-accent` | 2px white ring, no halo | a control filled with `brand-500`, where the accent ring would vanish |
89
-
90
- They hold no state: put the variant that fits in front of them.
91
-
92
- ```html
93
- <button class="focus-visible:focus-indicator">Save</button>
94
- <input class="focus:field-focus border border-gray-200" />
95
- <div class="focus-within:field-focus border border-gray-200"><input /></div>
96
- <!-- a control drawn by a sibling of a visually hidden input -->
97
- <input type="checkbox" class="peer sr-only" />
98
- <span class="peer-focus-visible:focus-indicator"></span>
99
- ```
100
-
101
- There is no ring offset. Add `ring-inset` where an ancestor clips with
102
- `overflow-hidden`, or a neighbour covers the outer ring. The utilities use
103
- `outline-hidden`, so the indicator survives forced-colors mode, where box
104
- shadows are not painted.
105
-
106
- ## Fonts & text size
107
-
108
- Two more settings on `<html>`, both optional:
109
-
110
- - **Font**: a `data-font` attribute that swaps `--font-sans`. Leave it off for
111
- Outfit. The others are `inter`, `plex` (IBM Plex Sans), `montserrat`,
112
- `open-sans`, and `system`, the platform's UI font. Each one loads from its own
113
- subpath, so import only the fonts you offer; `system` loads nothing. The mono
114
- font stays JetBrains Mono.
115
-
116
- ```css
117
- @import '@sckyzo/cosmos-theme/fonts'; /* Outfit + JetBrains Mono */
118
- @import '@sckyzo/cosmos-theme/fonts/inter';
119
- ```
120
-
121
- - **Text size**: a `data-text-size` attribute, `sm`, `lg` or `xl`, that scales
122
- every `text-*` size to 93.75%, 112.5% or 125%. Leave it off for 100%. Only the
123
- text grows: spacing keeps its `rem` values, so layouts keep their density.
124
- Sizes written in pixels, such as `text-[13px]`, don't scale; the `text-*`
125
- scale includes `text-2xs` (11px) and `text-3xs` (10px) for small labels.
126
-
127
- ```html
128
- <html class="sand" data-accent="teal" data-font="inter" data-text-size="lg"></html>
129
- ```
130
-
131
- Both attributes also work on an element below `<html>`, for one part of a page.
132
-
133
- ## Tokens
134
-
135
- See [`css/tailwind-tokens.css`](css/tailwind-tokens.css) for the full source.
136
-
137
- The brand palette, the status colors and the semantic colors are always in the CSS (`@theme static`): Tailwind
138
- only emits a theme variable that a utility uses, and the charts read these as plain `var(--color-…)`.
139
-
140
- Categories:
58
+ ## Documentation
141
59
 
142
- - **Brand palette** : `--color-brand-25` to `--color-brand-950`
143
- - **Chart series** : `--color-chart-2` to `--color-chart-8`, the series colors after the accent (the first series is `--color-brand-500`). Each accent lists its own seven, skipping the hues that look like it
144
- - **Semantic colors** : `--color-success-*`, `--color-error-*`, `--color-warning-*`
145
- - **Status** : `--color-status-{ok,warn,crit,unknown}`
146
- - **Typography** : `--font-sans` (Outfit), `--font-mono` (JetBrains Mono), `--text-2xs` (11px), `--text-3xs` (10px)
147
- - **Shadows** : `--shadow-card`, `--shadow-card-hover`, `--shadow-focus-ring` and `--shadow-focus-ring-error` (the focus halos)
148
- - **Layout vars** (theme-aware): `--color-bg-{base,panel,elevated}`, `--color-text-{base,primary,secondary,muted}`, `--color-border`, `--color-accent`
149
- - **Code highlighting** (theme-aware): `--color-code-foreground` and `--color-code-token-*` (keyword, string, comment, constant, function, parameter, string-expression, punctuation, link, inserted, deleted, changed). The names match Shiki's CSS variables theme with `variablePrefix: '--color-code-'`. Each one keeps 4.5:1 on CodeBlock's background in all four themes (checked by `pnpm test`).
60
+ - [Appearance](https://github.com/SckyzO/cosmos/blob/main/docs/guides/appearance.md): every theme, accent, font, text size, density and radius.
61
+ - [Tokens and focus](https://github.com/SckyzO/cosmos/blob/main/docs/guides/tokens.md): the design tokens and the focus utilities.
62
+ - [Getting started](https://github.com/SckyzO/cosmos/blob/main/docs/getting-started.md).
150
63
 
151
64
  ## License
152
65
 
153
- MIT — see [LICENSE](../../LICENSE).
66
+ MIT, see [LICENSE](https://github.com/SckyzO/cosmos/blob/main/LICENSE).
package/css/css-vars.css CHANGED
@@ -500,6 +500,111 @@
500
500
  }
501
501
  }
502
502
 
503
+ /* ── Density ───────────────────────────────────────────────────────────────
504
+ * data-density moves the vertical rhythm only: the height of controls
505
+ * (--spacing-ctrl-*), the vertical padding of rows (--spacing-row-*) and of
506
+ * table cells (--spacing-cell-*). Panel padding, gaps and the horizontal
507
+ * padding stay. compact takes 4px off a control (the smallest, 28px, stays at
508
+ * 24px, the WCAG 2.5.8 floor) and 2px off each side of a row; comfortable adds
509
+ * as much. No attribute keeps today's values; 'default' is the same, spelled
510
+ * out so a part of the page (a DataTable) can opt out of its parent's density.
511
+ *
512
+ * Declared again here for the same reason as the text sizes: a custom property
513
+ * resolves var() on the element that declares it, so the tokens are rebuilt
514
+ * on every element that carries the attribute. */
515
+ [data-density] {
516
+ --spacing-ctrl-28: calc(1.75rem + var(--cosmos-density-control, 0rem));
517
+ --spacing-ctrl-32: calc(2rem + var(--cosmos-density-control, 0rem));
518
+ --spacing-ctrl-36: calc(2.25rem + var(--cosmos-density-control, 0rem));
519
+ --spacing-ctrl-40: calc(2.5rem + var(--cosmos-density-control, 0rem));
520
+ --spacing-ctrl-44: calc(2.75rem + var(--cosmos-density-control, 0rem));
521
+ --spacing-ctrl-48: calc(3rem + var(--cosmos-density-control, 0rem));
522
+ --spacing-row-4: calc(0.25rem + var(--cosmos-density-row, 0rem));
523
+ /* 5px rows are 26px sidebar rows of 16px text: compact stops at 4px, the 24px floor. */
524
+ --spacing-row-5: max(0.25rem, calc(0.3125rem + var(--cosmos-density-row, 0rem)));
525
+ --spacing-row-6: calc(0.375rem + var(--cosmos-density-row, 0rem));
526
+ --spacing-row-8: calc(0.5rem + var(--cosmos-density-row, 0rem));
527
+ --spacing-row-10: calc(0.625rem + var(--cosmos-density-row, 0rem));
528
+ --spacing-row-12: calc(0.75rem + var(--cosmos-density-row, 0rem));
529
+ --spacing-row-14: calc(0.875rem + var(--cosmos-density-row, 0rem));
530
+ --spacing-row-16: calc(1rem + var(--cosmos-density-row, 0rem));
531
+ --spacing-row-20: calc(1.25rem + var(--cosmos-density-row, 0rem));
532
+ --spacing-row-24: calc(1.5rem + var(--cosmos-density-row, 0rem));
533
+ --spacing-cell-head: calc(0.75rem + var(--cosmos-density-cell-head, 0rem));
534
+ --spacing-cell-body: calc(0.875rem + var(--cosmos-density-cell-body, 0rem));
535
+ }
536
+
537
+ [data-density='default'] {
538
+ --cosmos-density-control: 0rem;
539
+ --cosmos-density-row: 0rem;
540
+ --cosmos-density-cell-head: 0rem;
541
+ --cosmos-density-cell-body: 0rem;
542
+ --cosmos-density-virtual-cell: calc(48em / 14);
543
+ }
544
+
545
+ [data-density='compact'] {
546
+ --cosmos-density-control: -0.25rem;
547
+ --cosmos-density-row: -0.125rem;
548
+ --cosmos-density-cell-head: -0.25rem;
549
+ --cosmos-density-cell-body: -0.25rem;
550
+ --cosmos-density-virtual-cell: calc(40em / 14);
551
+ }
552
+
553
+ [data-density='comfortable'] {
554
+ --cosmos-density-control: 0.25rem;
555
+ --cosmos-density-row: 0.125rem;
556
+ --cosmos-density-cell-head: 0.25rem;
557
+ --cosmos-density-cell-body: 0.375rem;
558
+ --cosmos-density-virtual-cell: calc(60em / 14);
559
+ }
560
+
561
+ /* ── Radius ────────────────────────────────────────────────────────────────
562
+ * data-radius rescales Tailwind's own --radius-* tokens, the ones rounded-sm
563
+ * to rounded-4xl read, so every corner of a component follows. none squares
564
+ * them all to 2px (a scale cannot get there from 4px to 32px), sm halves
565
+ * them, lg takes them one and a half times. No attribute keeps today's
566
+ * values; 'default' is the same, spelled out so a part of the page can opt
567
+ * out of its parent's radius. rounded-full and rounded-none are literals and
568
+ * never move: avatars, dots, switches, badges and pill buttons stay round.
569
+ *
570
+ * Declared again here for the same reason as the text sizes and the density:
571
+ * a custom property resolves var() on the element that declares it, so the
572
+ * tokens are rebuilt on every element that carries the attribute. The values
573
+ * are Tailwind's (theme.css); check-contrast.mjs fails if one goes missing. */
574
+ [data-radius] {
575
+ --radius-xs: calc(0.125rem * var(--cosmos-radius-scale, 1));
576
+ --radius-sm: calc(0.25rem * var(--cosmos-radius-scale, 1));
577
+ --radius-md: calc(0.375rem * var(--cosmos-radius-scale, 1));
578
+ --radius-lg: calc(0.5rem * var(--cosmos-radius-scale, 1));
579
+ --radius-xl: calc(0.75rem * var(--cosmos-radius-scale, 1));
580
+ --radius-2xl: calc(1rem * var(--cosmos-radius-scale, 1));
581
+ --radius-3xl: calc(1.5rem * var(--cosmos-radius-scale, 1));
582
+ --radius-4xl: calc(2rem * var(--cosmos-radius-scale, 1));
583
+ }
584
+
585
+ [data-radius='default'] {
586
+ --cosmos-radius-scale: 1;
587
+ }
588
+
589
+ [data-radius='sm'] {
590
+ --cosmos-radius-scale: 0.5;
591
+ }
592
+
593
+ [data-radius='lg'] {
594
+ --cosmos-radius-scale: 1.5;
595
+ }
596
+
597
+ [data-radius='none'] {
598
+ --radius-xs: 2px;
599
+ --radius-sm: 2px;
600
+ --radius-md: 2px;
601
+ --radius-lg: 2px;
602
+ --radius-xl: 2px;
603
+ --radius-2xl: 2px;
604
+ --radius-3xl: 2px;
605
+ --radius-4xl: 2px;
606
+ }
607
+
503
608
  /* Smooth theme switching transition — opt-in via .cosmos-bg-transition class
504
609
  on the app shell (not body, to avoid transitioning every DOM element). */
505
610
  .cosmos-bg-transition {
@@ -16,6 +16,15 @@
16
16
  `focus:border-brand-500`, so form controls lost their focus border in the dark themes. */
17
17
  @custom-variant dark (&:where(.dark, .dark *, .deep-blue, .deep-blue *));
18
18
 
19
+ /* Tailwind rtl variant: the nearest `dir` attribute. Not `:dir(rtl)`: Tailwind's build lowers
20
+ it to a list of `:lang()` for its browser targets, which a page that only sets `dir` never
21
+ matches (the dev server skips that step, so only a build shows it). Tailwind's default adds
22
+ `[dir="rtl"] *`, which also holds in a `dir="ltr"` island inside a right-to-left page (a code
23
+ sample, a phone number field) and would flip its icons: the `:not()` leaves the island out.
24
+ Not followed: `dir="auto"`, and a `dir="rtl"` nested in such an island.
25
+ `tests/e2e/specs/rtl-variant.spec.ts` checks it in the static build. */
26
+ @custom-variant rtl (&:where([dir="rtl"], [dir="rtl"] *):not(:where([dir="rtl"] [dir="ltr"], [dir="rtl"] [dir="ltr"] *)));
27
+
19
28
  /* The colors the charts read as plain CSS variables (var(--color-brand-500),
20
29
  * var(--color-status-warn)…), with no utility behind them. Tailwind only emits
21
30
  * a theme variable that a utility uses, so these are `static`: always in the
@@ -72,6 +81,32 @@
72
81
  --text-2xs: 0.6875rem;
73
82
  --text-3xs: 0.625rem;
74
83
 
84
+ /* ── Density ────────────────────────────────────────────────────────────── */
85
+ /* The vertical rhythm that data-density moves (css-vars.css redefines these
86
+ under the attribute): the height of a control, named by its default
87
+ height in px (h-ctrl-36 is h-9), and the vertical padding of a row, named
88
+ the same way (py-row-8 is py-2). A table cell has its own two. The
89
+ horizontal padding and the gaps stay where they are. Without the
90
+ attribute these are the values the components always had. */
91
+ --spacing-ctrl-28: 1.75rem;
92
+ --spacing-ctrl-32: 2rem;
93
+ --spacing-ctrl-36: 2.25rem;
94
+ --spacing-ctrl-40: 2.5rem;
95
+ --spacing-ctrl-44: 2.75rem;
96
+ --spacing-ctrl-48: 3rem;
97
+ --spacing-row-4: 0.25rem;
98
+ --spacing-row-5: 0.3125rem;
99
+ --spacing-row-6: 0.375rem;
100
+ --spacing-row-8: 0.5rem;
101
+ --spacing-row-10: 0.625rem;
102
+ --spacing-row-12: 0.75rem;
103
+ --spacing-row-14: 0.875rem;
104
+ --spacing-row-16: 1rem;
105
+ --spacing-row-20: 1.25rem;
106
+ --spacing-row-24: 1.5rem;
107
+ --spacing-cell-head: 0.75rem;
108
+ --spacing-cell-body: 0.875rem;
109
+
75
110
  /* ── Card shadows — work on both light and dark backgrounds ────────────── */
76
111
  --shadow-card: 0 1px 3px rgb(0 0 0 / 40%), 0 1px 2px rgb(0 0 0 / 30%);
77
112
  --shadow-card-hover: 0 10px 25px rgb(0 0 0 / 50%), 0 4px 6px rgb(0 0 0 / 20%);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sckyzo/cosmos-theme",
3
- "version": "0.3.0",
3
+ "version": "0.4.1",
4
4
  "description": "Tailwind 4 theme and design tokens for the Cosmos design system — palette, typography, radii and CSS variables for its light, sand, dark and deep-blue themes.",
5
5
  "license": "MIT",
6
6
  "author": "SckyzO",