tailwind-preset-mantine 1.3.2 → 2.0.0-beta.2

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/README.md CHANGED
@@ -2,7 +2,16 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/tailwind-preset-mantine.svg)](https://www.npmjs.com/package/tailwind-preset-mantine)
4
4
 
5
- A Tailwind CSS preset for seamless integration with Mantine UI components.
5
+ A Tailwind CSS (v4) preset for seamless integration with Mantine UI (v7) components.
6
+
7
+ ## Compatibility
8
+
9
+ | Tailwind CSS Version | Mantine Version | Preset Version |
10
+ |---------------------|-----------------|----------------|
11
+ | v4 | v7 | v2 (current) |
12
+ | v3 | v7 | ([v1](https://github.com/songkeys/tailwind-preset-mantine/tree/v1))* |
13
+
14
+ *Note: you can still use v1 for Tailwind CSS via [`@config`](https://tailwindcss.com/docs/upgrade-guide#using-a-javascript-config-file) directive.
6
15
 
7
16
  ## Installation
8
17
 
@@ -14,144 +23,95 @@ npm install tailwind-preset-mantine
14
23
 
15
24
  ### Default mantine theme
16
25
 
17
- To use the preset in your Tailwind CSS configuration, add it to the `presets` array:
18
-
19
- ```ts
20
- // tailwind.config.ts
21
- import tailwindPresetMantine from 'tailwind-preset-mantine';
26
+ 1. All-in-one import (recommended)
22
27
 
23
- export default {
24
- presets: [
25
- tailwindPresetMantine(),
26
- ],
27
- };
28
- ```
29
-
30
- Now you can use tailwind with mantine's style applied:
28
+ To use the preset in your Tailwind CSS configuration, add it to the css file:
31
29
 
32
- ```tsx
33
- import { Button } from '@mantine/core';
34
-
35
- export default function Page() {
36
- // `bg-red-500` will be `background-color: var(--mantine-color-red-5)`
37
- // `text-white` will be `color: var(--mantine-color-white)`
38
- return <Button className="bg-red-500 text-white">Hello</Button>
39
- }
30
+ ```css
31
+ @import "tailwind-preset-mantine";
40
32
  ```
41
33
 
42
- ### Custom mantine theme
43
-
44
- If you have a custom mantine theme (https://mantine.dev/theming/theme-object/), you should pass it as an option to make custom colors and custom breakpoints available to tailwind.
34
+ 2. Manual import (advanced)
45
35
 
46
- Let's define your custom mantine `colors` and `breakpoints` first:
36
+ Note that you don't have to import tailwind or mantine styles, this preset will handle that for you. If you want to import it yourself, you can use the `./theme.css` file:
47
37
 
48
- ```tsx
49
- // src/theme.ts
50
- import {
51
- type MantineThemeColors,
52
- type MantineBreakpointsValues,
53
- } from "@mantine/core";
38
+ ```css
39
+ @layer theme, base, mantine, components, utilities;
40
+ @import "tailwindcss/theme.css" layer(theme);
41
+ @import "tailwindcss/preflight.css" layer(base);
42
+ @import "tailwindcss/utilities.css" layer(utilities);
54
43
 
55
- export const colors: MantineThemeColors = {
56
- // ...your custom colors
57
- }
58
- export const breakpoints: MantineBreakpointsValues = {
59
- // ...your custom breakpoints
60
- }
61
- ```
44
+ @import "@mantine/core/styles.layer.css";
62
45
 
63
- Pass your custom `colors` and `breakpoints` to `MantineProvider`:
64
-
65
- ```tsx
66
- // src/mantine-provider.tsx
67
- import {
68
- MantineProvider,
69
- mergeMantineTheme,
70
- DEFAULT_THEME,
71
- } from '@mantine/core';
72
- import { colors, breakpoints } from './theme';
73
-
74
- const theme = mergeMantineTheme(
75
- DEFAULT_THEME,
76
- createTheme({
77
- breakpoints,
78
- colors,
79
- }),
80
- );
81
-
82
- export default function MantineProvider({ children }: { children: React.ReactNode }) {
83
- return <MantineProvider theme={{ colors, breakpoints }}>{children}</MantineProvider>
84
- }
46
+ @import "tailwind-preset-mantine/theme.css"; /* <-- import the preset */
85
47
  ```
86
48
 
87
- Then pass them to `tailwind-preset-mantine`:
49
+ > What's `@layer`?
50
+ >
51
+ > Note that here we setup tailwind slightly different from [the official docs](https://arc.net/l/quote/eifghbsm). We use the [CSS `@layer` directive](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) to control the order of the css. This is because we want to make sure that the mantine styles doesn't get overridden by tailwind reset (tw_base). In this case, the order is `tw_base -> mantine -> tw_components -> tw_utilities`
88
52
 
89
- ```ts
90
- // tailwind.config.ts
91
- import tailwindPresetMantine from 'tailwind-preset-mantine'
92
- import { colors, breakpoints } from './src/theme';
53
+ ### Custom mantine theme
93
54
 
94
- export default {
95
- presets: [tailwindPresetMantine({
96
- mantineColors: colors,
97
- mantineBreakpoints: breakpoints
98
- })],
99
- };
55
+ If you have a custom mantine theme (<https://mantine.dev/theming/theme-object/>), you can create a theme file using `@mantine/core`'s `createTheme` function and generate the CSS using our CLI:
56
+
57
+ 1. Create a theme file (e.g., `theme.js`):
58
+
59
+ ```js
60
+ import { createTheme } from "@mantine/core";
61
+
62
+ const theme = createTheme({
63
+ colors: {
64
+ // your custom colors
65
+ "brand-blue": [
66
+ "#e6f7ff",
67
+ "#bae7ff",
68
+ "#91d5ff",
69
+ "#69c0ff",
70
+ "#40a9ff",
71
+ "#1890ff",
72
+ "#096dd9",
73
+ "#0050b3",
74
+ "#003a8c",
75
+ "#002766",
76
+ ],
77
+ },
78
+ breakpoints: {
79
+ // your custom breakpoints
80
+ xs: "360px",
81
+ sm: "480px",
82
+ md: "768px",
83
+ lg: "960px",
84
+ xl: "1200px",
85
+ },
86
+ // other theme customizations
87
+ });
88
+
89
+ export default theme;
100
90
  ```
101
91
 
102
- > Why separate the `colors` and `breakpoints` definition in a single file?
103
- >
104
- > Because if passing the whole `mantineTheme` object, the property [`mantineTheme.components`](https://mantine.dev/theming/theme-object/#components) might include (s)css modules, which could fail to resolve due to the absence of an (s)css loader when loading the Tailwind config file.
105
- >
106
- > If you have a better solution, please let me know in the [issue](https://github.com/songkeys/tailwind-preset-mantine/issues).
107
-
108
- ## Prevent style conflicts
92
+ 2. Generate the CSS using our CLI:
109
93
 
110
- You will encounter style conflicts when using mantine and tailwind together. (See this [tough discussion](https://github.com/orgs/mantinedev/discussions/1672).) To prevent this, you can follow the steps below:
94
+ ```bash
95
+ npx tailwind-preset-mantine theme.js -o theme.css
96
+ ```
111
97
 
112
- ### 1. global.css
98
+ Options:
99
+ - `-o, --output`: Output file name (default: "theme.css")
100
+ - `-w, --watch`: Watch for changes (coming soon)
113
101
 
114
- Change your global.css to use CSS layers to prevent style conflicts:
102
+ 3. Import the generated CSS file in your application:
115
103
 
116
104
  ```css
117
- @layer tw_base, mantine, tw_components, tw_utilities;
118
-
119
- /* import tailwind */
120
- @import "tailwindcss/base" layer(tw_base);
121
- @import "tailwindcss/components" layer(tw_components);
122
- @import "tailwindcss/utilities" layer(tw_utilities);
123
-
124
- /* import mantine */
125
- @import "@mantine/core/styles.layer.css";
126
- ```
127
-
128
- > What's `@layer`?
129
- >
130
- > Note that here we setup tailwind slightly different from [the official docs](https://arc.net/l/quote/eifghbsm). We use the [CSS `@layer` directive](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) to control the order of the css. This is because we want to make sure that the mantine styles doesn't get overridden by tailwind reset (tw_base). In this case, the order is `tw_base -> mantine -> tw_components -> tw_utilities`
131
-
132
- ### 2. postcss.config.js
133
-
134
- To make it work, you also need to change the postcss config like this:
135
-
136
- ```diff
137
- // postcss.config.js
138
- module.exports = {
139
- plugins: {
140
- 'postcss-import': {},
141
- 'postcss-preset-mantine': {},
142
- // for tailwind
143
- + autoprefixer: {},
144
- + 'tailwindcss/nesting': {},
145
- + tailwindcss: {},
146
- },
147
- }
105
+ @import "./theme.css";
148
106
  ```
149
107
 
150
108
  ## Minimal template
151
109
 
152
- Here's a minimal template that you can use to get started:
110
+ <!-- Here's a minimal template that you can use to get started:
111
+
112
+ <https://github.com/songkeys/next-app-mantine-tailwind-template> -->
153
113
 
154
- <https://github.com/songkeys/next-app-mantine-tailwind-template>
114
+ TODO
155
115
 
156
116
  ## License
157
117
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-preset-mantine",
3
- "version": "1.3.2",
3
+ "version": "2.0.0-beta.2",
4
4
  "description": "Integrate Mantine with Tailwind CSS",
5
5
  "keywords": [
6
6
  "mantine",
@@ -17,21 +17,31 @@
17
17
  },
18
18
  "license": "MIT",
19
19
  "author": "Songkeys",
20
- "main": "src/index.js",
21
- "types": "src/index.d.ts",
20
+ "main": "src/index.css",
21
+ "exports": {
22
+ ".": "./src/index.css",
23
+ "./theme.css": "./src/theme.css"
24
+ },
25
+ "bin": {
26
+ "tailwind-preset-mantine": "./src/cli.js"
27
+ },
22
28
  "devDependencies": {
23
29
  "@biomejs/biome": "^1.9.4",
24
- "@mantine/core": "^7.14.3",
25
- "bumpp": "^9.8.1",
26
- "tailwindcss": "^3.4.16"
30
+ "@mantine/core": "^7.16.2",
31
+ "bumpp": "^10.0.1"
27
32
  },
28
33
  "peerDependencies": {
29
34
  "@mantine/core": "^7",
30
- "tailwindcss": "^3"
35
+ "tailwindcss": "^4"
36
+ },
37
+ "type": "module",
38
+ "dependencies": {
39
+ "tsx": "^4.19.2"
31
40
  },
32
41
  "scripts": {
33
42
  "lint": "biome check .",
34
43
  "lint:fix": "biome check . --write",
35
- "release": "bumpp"
44
+ "release": "bumpp",
45
+ "generate": "node scripts/generate.js"
36
46
  }
37
47
  }
@@ -0,0 +1,16 @@
1
+ // this file is to generate the theme.css and index.css file for the preset
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+ import { generateDefaultImports, generateTheme } from "../src/generate.js";
6
+
7
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
+
9
+ const defaultImports = generateDefaultImports();
10
+ const theme = generateTheme();
11
+
12
+ fs.writeFileSync(path.join(__dirname, "../src/theme.css"), theme);
13
+ fs.writeFileSync(
14
+ path.join(__dirname, "../src/index.css"),
15
+ defaultImports + theme,
16
+ );
package/src/cli.js ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env -S npx tsx
2
+
3
+ import { writeFile } from "node:fs/promises";
4
+ import { resolve } from "node:path";
5
+ import { parseArgs } from "node:util";
6
+ import { generateTheme } from "./generate.js";
7
+
8
+ const pwd = process.cwd();
9
+
10
+ // Define CLI options
11
+ const options = {
12
+ output: {
13
+ type: "string",
14
+ short: "o",
15
+ default: "theme.css",
16
+ description: "Output file name",
17
+ },
18
+ watch: {
19
+ type: "boolean",
20
+ short: "w",
21
+ default: false,
22
+ description: "Watch for changes",
23
+ },
24
+ };
25
+
26
+ // Parse command line arguments
27
+ const { values, positionals } = parseArgs({ options, allowPositionals: true });
28
+
29
+ if (positionals.length === 0) {
30
+ console.error("Please provide a theme file path");
31
+ process.exit(1);
32
+ }
33
+
34
+ const inputFile = positionals[0];
35
+ const outputFile = values.output;
36
+
37
+ if (values.watch) {
38
+ console.log(`Watching ${inputFile} for changes...`);
39
+ // TODO: Implement file watching
40
+ }
41
+
42
+ try {
43
+ // Read the input theme file
44
+ const themePath = resolve(pwd, inputFile);
45
+
46
+ // Execute the theme file content to get the theme object
47
+ const themeModule = await import(themePath);
48
+ const theme = themeModule.default;
49
+
50
+ // Generate CSS from theme object
51
+ const css = generateTheme(theme);
52
+
53
+ // Write to output file
54
+ const outputPath = resolve(pwd, outputFile);
55
+ await writeFile(outputPath, css);
56
+
57
+ console.log(`Successfully generated ${outputFile}`);
58
+ } catch (error) {
59
+ console.error("Error generating theme:", error.message);
60
+ process.exit(1);
61
+ }
@@ -0,0 +1,189 @@
1
+ // for reference:
2
+ // https://github.com/mantinedev/mantine/blob/master/packages/%40mantine/core/src/core/MantineProvider/global.css
3
+ // https://tailwindcss.com/docs/theme#default-theme-variable-reference
4
+
5
+ import { DEFAULT_THEME } from "@mantine/core";
6
+
7
+ export function generateDefaultImports() {
8
+ return `
9
+ /** This file is autogenerated by the script. Do not edit it manually. */
10
+ @layer theme, base, mantine, components, utilities;
11
+ @import "tailwindcss/theme.css" layer(theme);
12
+ @import "tailwindcss/preflight.css" layer(base);
13
+ @import "tailwindcss/utilities.css" layer(utilities);
14
+
15
+ @import "@mantine/core/styles.layer.css";
16
+ `;
17
+ }
18
+
19
+ /**
20
+ * @param {import("@mantine/core").MantineTheme} theme
21
+ */
22
+ export function generateTheme(theme = DEFAULT_THEME) {
23
+ // check if the object is deeply equal to DEFAULT_THEME
24
+ const isDefault = JSON.stringify(theme) === JSON.stringify(DEFAULT_THEME);
25
+
26
+ return `
27
+ /** This file is autogenerated by the script. Do not edit it manually. */
28
+ ${isDefault ? '@custom-variant dark (&:where([data-mantine-color-scheme="dark"], [data-mantine-color-scheme="dark"] *));' : ""}
29
+
30
+ @theme {
31
+ ${
32
+ isDefault
33
+ ? `
34
+ /* font */
35
+ --font-sans: var(--mantine-font-family);
36
+ --font-mono: var(--mantine-font-family-monospace);
37
+ --font-headings: var(--mantine-font-family-headings);
38
+
39
+ /* colors - primary */
40
+ --color-primary-50: rgb(from var(--mantine-primary-color-0) r g b / <alpha-value>);
41
+ --color-primary-100: rgb(from var(--mantine-primary-color-1) r g b / <alpha-value>);
42
+ --color-primary-200: rgb(from var(--mantine-primary-color-2) r g b / <alpha-value>);
43
+ --color-primary-300: rgb(from var(--mantine-primary-color-3) r g b / <alpha-value>);
44
+ --color-primary-400: rgb(from var(--mantine-primary-color-4) r g b / <alpha-value>);
45
+ --color-primary-500: rgb(from var(--mantine-primary-color-5) r g b / <alpha-value>);
46
+ --color-primary-600: rgb(from var(--mantine-primary-color-6) r g b / <alpha-value>);
47
+ --color-primary-700: rgb(from var(--mantine-primary-color-7) r g b / <alpha-value>);
48
+ --color-primary-800: rgb(from var(--mantine-primary-color-8) r g b / <alpha-value>);
49
+ --color-primary-900: rgb(from var(--mantine-primary-color-9) r g b / <alpha-value>);
50
+ --color-primary: rgb(from var(--mantine-primary-color-filled) r g b / <alpha-value>);
51
+
52
+ /* colors - variant specific primary */
53
+ --color-primary-filled: rgb(from var(--mantine-primary-color-filled) r g b / <alpha-value>);
54
+ --color-primary-filled-hover: var(--mantine-primary-color-filled-hover);
55
+ --color-primary-light: var(--mantine-primary-color-light);
56
+ --color-primary-light-hover: var(--mantine-primary-color-light-hover);
57
+ --color-primary-light-color: rgb(from var(--mantine-primary-color-light-color) r g b / <alpha-value>);
58
+ --color-primary-outline: rgb(from var(--mantine-primary-color-outline) r g b / <alpha-value>);
59
+ --color-primary-outline-hover: var(--mantine-primary-color-outline-hover);
60
+
61
+ /* colors - others */
62
+ --color-white: rgb(from var(--mantine-color-white) r g b / <alpha-value>);
63
+ --color-black: rgb(from var(--mantine-color-black) r g b / <alpha-value>);
64
+ --color-body: rgb(from var(--mantine-color-text) r g b / <alpha-value>);
65
+ --color-error: rgb(from var(--mantine-color-error) r g b / <alpha-value>);
66
+ --color-placeholder: rgb(from var(--mantine-color-placeholder) r g b / <alpha-value>);
67
+ --color-anchor: rgb(from var(--mantine-color-anchor) r g b / <alpha-value>);
68
+ --color-default: rgb(from var(--mantine-color-default-color) r g b / <alpha-value>);
69
+
70
+ /* spacing */
71
+ --spacing-xs: var(--mantine-spacing-xs);
72
+ --spacing-sm: var(--mantine-spacing-sm);
73
+ --spacing-md: var(--mantine-spacing-md);
74
+ --spacing-lg: var(--mantine-spacing-lg);
75
+ --spacing-xl: var(--mantine-spacing-xl);
76
+ --spacing: var(--mantine-spacing-md);
77
+
78
+ /* container */
79
+ /* TODO: */
80
+
81
+ /* font size */
82
+ --text-xs: var(--mantine-font-size-xs);
83
+ --text-sm: var(--mantine-font-size-sm);
84
+ --text-md: var(--mantine-font-size-md);
85
+ --text-lg: var(--mantine-font-size-lg);
86
+ --text-xl: var(--mantine-font-size-xl);
87
+ --text-h1: var(--mantine-h1-font-size);
88
+ --text-h2: var(--mantine-h2-font-size);
89
+ --text-h3: var(--mantine-h3-font-size);
90
+ --text-h4: var(--mantine-h4-font-size);
91
+ --text-h5: var(--mantine-h5-font-size);
92
+ --text-h6: var(--mantine-h6-font-size);
93
+ --text-base: var(--mantine-font-size-md);
94
+
95
+ /* line height */
96
+ --text-xs--line-height: var(--mantine-line-height-xs);
97
+ --text-sm--line-height: var(--mantine-line-height-sm);
98
+ --text-md--line-height: var(--mantine-line-height-md);
99
+ --text-lg--line-height: var(--mantine-line-height-lg);
100
+ --text-xl--line-height: var(--mantine-line-height-xl);
101
+ --text-h1--line-height: var(--mantine-h1-line-height);
102
+ --text-h2--line-height: var(--mantine-h2-line-height);
103
+ --text-h3--line-height: var(--mantine-h3-line-height);
104
+ --text-h4--line-height: var(--mantine-h4-line-height);
105
+ --text-h5--line-height: var(--mantine-h5-line-height);
106
+ --text-h6--line-height: var(--mantine-h6-line-height);
107
+ --text-base--line-height: var(--mantine-line-height-md);
108
+ --text-heading--line-height: var(--mantine-heading-line-height);
109
+ --text-base--line-height: var(--mantine-line-height);
110
+
111
+ /* font weight */
112
+ --font-weight-h1: var(--mantine-h1-font-weight);
113
+ --font-weight-h2: var(--mantine-h2-font-weight);
114
+ --font-weight-h3: var(--mantine-h3-font-weight);
115
+ --font-weight-h4: var(--mantine-h4-font-weight);
116
+ --font-weight-h5: var(--mantine-h5-font-weight);
117
+ --font-weight-h6: var(--mantine-h6-font-weight);
118
+
119
+ /* border radius */
120
+ --radius-xs: var(--mantine-radius-xs);
121
+ --radius-sm: var(--mantine-radius-sm);
122
+ --radius-md: var(--mantine-radius-md);
123
+ --radius-lg: var(--mantine-radius-lg);
124
+ --radius-xl: var(--mantine-radius-xl);
125
+ --radius: var(--mantine-radius-default);
126
+
127
+ /* shadow */
128
+ --shadow-xs: var(--mantine-shadow-xs);
129
+ --shadow-sm: var(--mantine-shadow-sm);
130
+ --shadow-md: var(--mantine-shadow-md);
131
+ --shadow-lg: var(--mantine-shadow-lg);
132
+ --shadow-xl: var(--mantine-shadow-xl);
133
+ --shadow: var(--mantine-shadow-xs);
134
+
135
+ /* z-index */
136
+ --z-index-app: var(--mantine-z-index-app);
137
+ --z-index-modal: var(--mantine-z-index-modal);
138
+ --z-index-popover: var(--mantine-z-index-popover);
139
+ --z-index-overlay: var(--mantine-z-index-overlay);
140
+ --z-index-max: var(--mantine-z-index-max);
141
+ `.trimEnd()
142
+ : ""
143
+ }
144
+
145
+ /* colors - all */
146
+ ${Object.keys(theme.colors)
147
+ .map((key) =>
148
+ `
149
+ --color-${key}-50: rgb(from var(--mantine-color-${key}-0) r g b / <alpha-value>);
150
+ --color-${key}-100: rgb(from var(--mantine-color-${key}-1) r g b / <alpha-value>);
151
+ --color-${key}-200: rgb(from var(--mantine-color-${key}-2) r g b / <alpha-value>);
152
+ --color-${key}-300: rgb(from var(--mantine-color-${key}-3) r g b / <alpha-value>);
153
+ --color-${key}-400: rgb(from var(--mantine-color-${key}-4) r g b / <alpha-value>);
154
+ --color-${key}-500: rgb(from var(--mantine-color-${key}-5) r g b / <alpha-value>);
155
+ --color-${key}-600: rgb(from var(--mantine-color-${key}-6) r g b / <alpha-value>);
156
+ --color-${key}-700: rgb(from var(--mantine-color-${key}-7) r g b / <alpha-value>);
157
+ --color-${key}-800: rgb(from var(--mantine-color-${key}-8) r g b / <alpha-value>);
158
+ --color-${key}-900: rgb(from var(--mantine-color-${key}-9) r g b / <alpha-value>);
159
+ --color-${key}: rgb(from var(--mantine-color-${key}-filled) r g b / <alpha-value>);
160
+ `.trimEnd(),
161
+ )
162
+ .join("\n")}
163
+
164
+ /* colors - variant specific */
165
+ ${Object.keys(theme.colors)
166
+ .map((key) =>
167
+ `
168
+ --color-${key}-filled: rgb(from var(--mantine-color-${key}-filled) r g b / <alpha-value>);
169
+ --color-${key}-filled-hover: var(--mantine-color-${key}-filled-hover);
170
+ --color-${key}-light: var(--mantine-color-${key}-light);
171
+ --color-${key}-light-hover: var(--mantine-color-${key}-light-hover);
172
+ --color-${key}-light-color: rgb(from var(--mantine-color-${key}-light-color) r g b / <alpha-value>);
173
+ --color-${key}-outline: rgb(from var(--mantine-color-${key}-outline) r g b / <alpha-value>);
174
+ --color-${key}-outline-hover: var(--mantine-color-${key}-outline-hover);
175
+ `.trimEnd(),
176
+ )
177
+ .join("\n")}
178
+
179
+ /* breakpoints */
180
+ ${Object.entries(theme.breakpoints)
181
+ .map(([key, value]) =>
182
+ `
183
+ --breakpoint-${key}: ${value};
184
+ `.trimEnd(),
185
+ )
186
+ .join("\n")}
187
+ }
188
+ `;
189
+ }