Skip to content

Commit 3006217

Browse files
committed
feat: finished themeable features
0 parents  commit 3006217

32 files changed

+6823
-0
lines changed

.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist

.eslintrc.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
extends: 'standard-with-typescript',
3+
parserOptions: {
4+
project: './tsconfig.json'
5+
},
6+
rules: {
7+
'@typescript-eslint/explicit-function-return-type': 0
8+
}
9+
}

.github/workflows/ci.yml

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Build
2+
# Avoid triggering two build on PR
3+
# https://github.community/t/how-to-trigger-an-action-on-push-or-pull-request-but-not-both/16662/2
4+
on:
5+
push:
6+
branches:
7+
- main
8+
pull_request:
9+
branches:
10+
- main
11+
12+
jobs:
13+
build-and-prerelease:
14+
runs-on: macos-latest
15+
steps:
16+
- uses: actions/checkout@v2
17+
- uses: actions/setup-node@v2
18+
with:
19+
node-version: '14'
20+
- uses: pnpm/[email protected]
21+
with:
22+
version: 6.0.2
23+
24+
- name: Install and Build 🔧
25+
run: |
26+
pnpm i
27+
pnpm run build
28+
(cd examples/tailwind && pnpm run build && cp -r dist/ ../../dist/tailwind)
29+
(cd examples/windi && pnpm run build && cp -r dist/ ../../dist/windi)
30+
31+
- name: Deploy 🚀
32+
uses: JamesIves/[email protected]
33+
with:
34+
branch: gh-pages # The branch the action should deploy to.
35+
folder: dist # The folder the action should deploy.
36+
git-config-name: 'github-actions[bot]'
37+
git-config-email: 'github-actions[bot]@users.noreply.github.com'

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
dist
3+
.pnpm-debug.log

.husky/commit-msg

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
pnpx commitlint --edit $1

.husky/pre-commit

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/sh
2+
. "$(dirname "$0")/_/husky.sh"
3+
4+
pnpx lint-staged

.stylelintrc.js

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module.exports = {
2+
extends: [
3+
'stylelint-config-standard'
4+
],
5+
ignoreFiles: [
6+
// avoid conflict with prettier
7+
'**/*.html'
8+
]
9+
}

.vscode/settings.json

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"cSpell.words": ["tailwindcss", "themeable", "vite", "windi", "windicss"], // Use eslint to format js/ts files
3+
"editor.codeActionsOnSave": {
4+
"source.fixAll.eslint": true,
5+
"source.fixAll.stylelint": true
6+
},
7+
// Disable css built-in lint
8+
"css.validate": false,
9+
"scss.validate": false,
10+
"less.validate": false,
11+
"stylelint.enable": true,
12+
"stylelint.validate": ["css", "less", "html", "vue"],
13+
// Use prettier to format files
14+
"editor.formatOnSave": true,
15+
// Since we use eslint to format js/ts files, so we have to disable prettier to avoid confilcts
16+
"[javascript]": {
17+
"editor.formatOnSave": false
18+
},
19+
"[javascriptreact]": {
20+
"editor.formatOnSave": false
21+
},
22+
"[typescript]": {
23+
"editor.formatOnSave": false
24+
},
25+
"[typescriptreact]": {
26+
"editor.formatOnSave": false
27+
},
28+
"editor.defaultFormatter": "esbenp.prettier-vscode",
29+
"editor.tabSize": 2
30+
}

LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2021-present upupming
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

+262
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,262 @@
1+
# tailwindcss-themeable
2+
3+
Multiple themes support for tailwindcss and windicss. Developing with one theme and it will work with multiple themes, all you need is just to define your default (for shade `500`) color values for your theme. We will generate all shades from `50` to `900` for you, following the built-in shade name convention of the [default color values](https://tailwindcss.com/docs/customizing-colors).
4+
5+
|Dracula (default theme), Demo Link|Material, Demo Link|
6+
|-------|--------|
7+
|![dracula](img/dracula.png)|![material](img/material.png)|
8+
9+
## Installation
10+
11+
```bash
12+
npm i tailwindcss-themeable
13+
```
14+
15+
## Usage
16+
17+
We define the color names following [the dracula contribute color palette](https://draculatheme.com/contribute).
18+
19+
CSS variables are generated from build time, and added to the corresponding scope for usage.
20+
21+
Configuration:
22+
23+
```ts
24+
// windi.config.ts or tailwind.config.js
25+
import { themeable } from 'tailwindcss-themeable'
26+
// or: const { themeable } = require('tailwindcss-themeable')
27+
28+
plugins: [
29+
themeable({
30+
themes: [
31+
{
32+
name: 'example-theme',
33+
palette: {
34+
background: '#282A36',
35+
foreground: '#F8F8F2',
36+
selection: '#44475A',
37+
comment: '#6272A4',
38+
cyan: '#8BE9FD',
39+
green: '#50FA7B',
40+
orange: '#FFB86C',
41+
pink: '#FF79C6',
42+
purple: '#BD93F9',
43+
red: '#FF5555',
44+
yellow: '#F1FA8C'
45+
}
46+
}
47+
]
48+
})
49+
]
50+
```
51+
52+
<details>
53+
54+
<summary>Generated CSS</summary>
55+
56+
```css
57+
.themeable-example-theme {
58+
--themeable-background-50: 121, 126, 156;
59+
--themeable-background-100: 110, 115, 147;
60+
--themeable-background-200: 92, 97, 124;
61+
--themeable-background-300: 75, 78, 101;
62+
--themeable-background-400: 57, 60, 77;
63+
--themeable-background-500: 40, 42, 54;
64+
--themeable-background-600: 16, 17, 22;
65+
--themeable-background-700: 0, 0, 0;
66+
--themeable-background-800: 0, 0, 0;
67+
--themeable-background-900: 0, 0, 0;
68+
--themeable-background: 40, 42, 54;
69+
--themeable-foreground-50: 255, 255, 255;
70+
--themeable-foreground-100: 255, 255, 255;
71+
--themeable-foreground-200: 255, 255, 255;
72+
--themeable-foreground-300: 255, 255, 255;
73+
--themeable-foreground-400: 255, 255, 255;
74+
--themeable-foreground-500: 248, 248, 242;
75+
--themeable-foreground-600: 228, 228, 206;
76+
--themeable-foreground-700: 209, 209, 169;
77+
--themeable-foreground-800: 189, 189, 133;
78+
--themeable-foreground-900: 169, 169, 96;
79+
--themeable-foreground: 248, 248, 242;
80+
--themeable-selection-50: 159, 162, 183;
81+
--themeable-selection-100: 147, 151, 174;
82+
--themeable-selection-200: 124, 129, 156;
83+
--themeable-selection-300: 103, 108, 136;
84+
--themeable-selection-400: 86, 89, 113;
85+
--themeable-selection-500: 68, 71, 90;
86+
--themeable-selection-600: 44, 46, 58;
87+
--themeable-selection-700: 20, 21, 26;
88+
--themeable-selection-800: 0, 0, 0;
89+
--themeable-selection-900: 0, 0, 0;
90+
--themeable-selection: 68, 71, 90;
91+
--themeable-comment-50: 214, 218, 231;
92+
--themeable-comment-100: 201, 207, 224;
93+
--themeable-comment-200: 175, 184, 209;
94+
--themeable-comment-300: 150, 160, 194;
95+
--themeable-comment-400: 124, 137, 179;
96+
--themeable-comment-500: 98, 114, 164;
97+
--themeable-comment-600: 76, 89, 130;
98+
--themeable-comment-700: 55, 65, 95;
99+
--themeable-comment-800: 34, 40, 59;
100+
--themeable-comment-900: 14, 16, 24;
101+
--themeable-comment: 98, 114, 164;
102+
--themeable-cyan-50: 255, 255, 255;
103+
--themeable-cyan-100: 255, 255, 255;
104+
--themeable-cyan-200: 255, 255, 255;
105+
--themeable-cyan-300: 219, 248, 254;
106+
--themeable-cyan-400: 179, 241, 254;
107+
--themeable-cyan-500: 139, 233, 253;
108+
--themeable-cyan-600: 84, 223, 252;
109+
--themeable-cyan-700: 29, 212, 251;
110+
--themeable-cyan-800: 4, 182, 220;
111+
--themeable-cyan-900: 3, 136, 165;
112+
--themeable-cyan: 139, 233, 253;
113+
--themeable-green-50: 255, 255, 255;
114+
--themeable-green-100: 239, 255, 243;
115+
--themeable-green-200: 199, 253, 213;
116+
--themeable-green-300: 159, 252, 183;
117+
--themeable-green-400: 120, 251, 153;
118+
--themeable-green-500: 80, 250, 123;
119+
--themeable-green-600: 25, 248, 82;
120+
--themeable-green-700: 6, 212, 58;
121+
--themeable-green-800: 4, 157, 43;
122+
--themeable-green-900: 3, 103, 28;
123+
--themeable-green: 80, 250, 123;
124+
--themeable-orange-50: 255, 255, 255;
125+
--themeable-orange-100: 255, 255, 255;
126+
--themeable-orange-200: 255, 243, 230;
127+
--themeable-orange-300: 255, 223, 190;
128+
--themeable-orange-400: 255, 204, 149;
129+
--themeable-orange-500: 255, 184, 108;
130+
--themeable-orange-600: 255, 157, 52;
131+
--themeable-orange-700: 251, 130, 0;
132+
--themeable-orange-800: 195, 101, 0;
133+
--themeable-orange-900: 139, 72, 0;
134+
--themeable-orange: 255, 184, 108;
135+
--themeable-pink-50: 255, 255, 255;
136+
--themeable-pink-100: 255, 255, 255;
137+
--themeable-pink-200: 255, 243, 250;
138+
--themeable-pink-300: 255, 203, 233;
139+
--themeable-pink-400: 255, 162, 215;
140+
--themeable-pink-500: 255, 121, 198;
141+
--themeable-pink-600: 255, 65, 174;
142+
--themeable-pink-700: 255, 9, 150;
143+
--themeable-pink-800: 208, 0, 119;
144+
--themeable-pink-900: 152, 0, 87;
145+
--themeable-pink: 255, 121, 198;
146+
--themeable-purple-50: 255, 255, 255;
147+
--themeable-purple-100: 255, 255, 255;
148+
--themeable-purple-200: 255, 255, 255;
149+
--themeable-purple-300: 236, 224, 253;
150+
--themeable-purple-400: 213, 186, 251;
151+
--themeable-purple-500: 189, 147, 249;
152+
--themeable-purple-600: 157, 94, 246;
153+
--themeable-purple-700: 124, 41, 243;
154+
--themeable-purple-800: 96, 12, 216;
155+
--themeable-purple-900: 72, 9, 163;
156+
--themeable-purple: 189, 147, 249;
157+
--themeable-red-50: 255, 255, 255;
158+
--themeable-red-100: 255, 248, 248;
159+
--themeable-red-200: 255, 207, 207;
160+
--themeable-red-300: 255, 167, 167;
161+
--themeable-red-400: 255, 126, 126;
162+
--themeable-red-500: 255, 85, 85;
163+
--themeable-red-600: 255, 29, 29;
164+
--themeable-red-700: 228, 0, 0;
165+
--themeable-red-800: 172, 0, 0;
166+
--themeable-red-900: 116, 0, 0;
167+
--themeable-red: 255, 85, 85;
168+
--themeable-yellow-50: 255, 255, 255;
169+
--themeable-yellow-100: 255, 255, 255;
170+
--themeable-yellow-200: 255, 255, 255;
171+
--themeable-yellow-300: 251, 253, 218;
172+
--themeable-yellow-400: 246, 252, 179;
173+
--themeable-yellow-500: 241, 250, 140;
174+
--themeable-yellow-600: 234, 248, 86;
175+
--themeable-yellow-700: 228, 245, 32;
176+
--themeable-yellow-800: 196, 212, 9;
177+
--themeable-yellow-900: 146, 159, 7;
178+
--themeable-yellow: 241, 250, 140;
179+
}
180+
```
181+
182+
</details>
183+
184+
Then you can wrap you HTML elements with `themeable-example-theme` class to use the `example` theme! All `text-themeable-*` class uses the CSS variable from the generated CSS of your configuration.
185+
186+
```html
187+
<div class="themeable-example-theme">
188+
<div class="text-themeable-foreground">
189+
Hello world!
190+
</div>
191+
</div>
192+
```
193+
194+
<hr>
195+
196+
You can specify all the shades of a color if you want:
197+
198+
```js
199+
themeable({
200+
themes: [
201+
{
202+
name: 'theme-example',
203+
palette: {
204+
background: {
205+
// Replace the hex color value with whatever your like
206+
'50': '#000000',
207+
'100': '#000000',
208+
'200': '#000000',
209+
'300': '#000000',
210+
'400': '#000000',
211+
'500': '#000000',
212+
'600': '#000000',
213+
'700': '#000000',
214+
'800': '#000000',
215+
'900': '#000000',
216+
DEFAULT: '#000000',
217+
}
218+
//...
219+
}
220+
]
221+
})
222+
```
223+
224+
Extra configurations:
225+
226+
```ts
227+
interface ThemeableOptions {
228+
/**
229+
* Support a list of theme definitions, the user should define the colors of the theme follow the contribute of Dracula theme.
230+
* See https://draculatheme.com/contribute#color-palette
231+
* @default []
232+
*/
233+
themes?: Theme[];
234+
/**
235+
* Prefix of the class to enable a theme, for example the container with class `${classPrefix}-dracula` will enable dracula theme in its children elements
236+
* @default `themeable`
237+
*/
238+
classPrefix?: string;
239+
/** The lighten step for auto generated shades smaller than the default `500` color
240+
* For example, if you passed `#50FA7B` as the `green` theme key, and `shadeLightenStep` is 8,
241+
* then we will use this color as the `DEFAULT` and shade `500` to generate all other shades of `green`,
242+
* for shade smaller than `500`, we will add the lightness up `shadeLightenStep` in per 100 gap.
243+
* Color `#50FA7B` converted to HSL is [135, 94, 64], so the shade `400` will be computed to [135, 94, 72]
244+
* @default 8
245+
*/
246+
shadeLightenStep?: number;
247+
/** Similar with `shadeLightenStep` but for shades larger than `500`
248+
* @default 11
249+
*/
250+
shadeDarkenStep?: number;
251+
/** When not specify any theme in HTML, the `defaultTheme` will be used
252+
* @default `dracula`
253+
*/
254+
defaultTheme?: string;
255+
}
256+
```
257+
258+
## Reference
259+
260+
1. https://github.com/dracula/tailwind
261+
2. https://github.com/anheric/tailwindshades
262+
3. [Theming Tailwind with CSS Variables](https://www.youtube.com/watch?v=MAtaT8BZEAo)

commitlint.config.js

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
extends: ['@commitlint/config-angular']
3+
}

0 commit comments

Comments
 (0)