@dsfrkit/config 0.1.0
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 +99 -0
- package/dist/index.d.mts +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +245 -0
- package/dist/index.mjs +214 -0
- package/package.json +48 -0
- package/src/index.ts +256 -0
- package/src/plugin.test.ts +43 -0
package/README.md
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# @dsfrkit/config
|
|
2
|
+
|
|
3
|
+
Preset Tailwind CSS pour le Système de Design de l'État français (DSFR).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add -D @dsfrkit/config tailwindcss
|
|
9
|
+
pnpm add @dsfrkit/tokens
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
> Note: `@dsfrkit/config` déclare `@dsfrkit/tokens` en tant que peerDependency — installez `@dsfrkit/tokens` dans votre projet pour pouvoir importer `@dsfrkit/tokens/theme.css`.
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
### Configuration Tailwind
|
|
17
|
+
|
|
18
|
+
Ajoutez le preset dans votre `tailwind.config.js` :
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
import dsfrPreset from '@dsfrkit/config'
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
presets: [dsfrPreset],
|
|
25
|
+
content: [
|
|
26
|
+
'./src/**/*.{js,jsx,ts,tsx}',
|
|
27
|
+
],
|
|
28
|
+
// Vos personnalisations ici
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Utilisation des classes
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
// Couleurs DSFR
|
|
36
|
+
<button className="bg-blue-france-main text-white">
|
|
37
|
+
Bouton principal
|
|
38
|
+
</button>
|
|
39
|
+
|
|
40
|
+
<div className="bg-error-main text-white">
|
|
41
|
+
Message d'erreur
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
// Typographie Marianne
|
|
45
|
+
<h1 className="font-marianne text-4xl font-bold">
|
|
46
|
+
Titre principal
|
|
47
|
+
</h1>
|
|
48
|
+
|
|
49
|
+
// Container DSFR
|
|
50
|
+
<div className="fr-container">
|
|
51
|
+
<div className="fr-grid-row">
|
|
52
|
+
<div className="fr-col">
|
|
53
|
+
Contenu
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
// Utilities de décision
|
|
59
|
+
<p className="text-decision-default">Texte par défaut</p>
|
|
60
|
+
<div className="bg-decision-disabled">Arrière-plan désactivé</div>
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Couleurs disponibles
|
|
64
|
+
|
|
65
|
+
- `blue-france-*` - Bleu France (couleur principale)
|
|
66
|
+
- `red-marianne-*` - Rouge Marianne
|
|
67
|
+
- `grey-*` - Échelle de gris complète
|
|
68
|
+
- `info-*` - Couleurs d'information
|
|
69
|
+
- `success-*` - Couleurs de succès
|
|
70
|
+
- `warning-*` - Couleurs d'avertissement
|
|
71
|
+
- `error-*` - Couleurs d'erreur
|
|
72
|
+
|
|
73
|
+
## Typographie
|
|
74
|
+
|
|
75
|
+
### Polices Marianne et Spectral
|
|
76
|
+
|
|
77
|
+
Importez les polices officielles DSFR dans votre CSS principal :
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
/* src/index.css */
|
|
81
|
+
@import '@dsfrkit/config/fonts.css';
|
|
82
|
+
|
|
83
|
+
@tailwind base;
|
|
84
|
+
@tailwind components;
|
|
85
|
+
@tailwind utilities;
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Les polices sont chargées depuis le CDN officiel DSFR avec `font-display: swap` pour de meilleures performances.
|
|
90
|
+
|
|
91
|
+
- **Police principale** : Marianne (`font-marianne`)
|
|
92
|
+
- Regular (400)
|
|
93
|
+
- Medium (500)
|
|
94
|
+
- Bold (700)
|
|
95
|
+
- Italic variants
|
|
96
|
+
|
|
97
|
+
- **Police serif** : Spectral (`font-spectral`)
|
|
98
|
+
- Regular (400)
|
|
99
|
+
- ExtraBold (800)
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { borderRadius, boxShadow, colors, screens, spacing, typography } from '@dsfrkit/tokens';
|
|
2
|
+
import { Config } from 'tailwindcss';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Preset Tailwind CSS pour le DSFR
|
|
6
|
+
* Étend la configuration Tailwind avec les tokens du design system
|
|
7
|
+
* Supporte le mode clair/sombre via CSS variables
|
|
8
|
+
*
|
|
9
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/couleurs-palette
|
|
10
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/typographie
|
|
11
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/espacement
|
|
12
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/grille-et-points-de-rupture
|
|
13
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/systeme-d-ombres-et-d-elevation
|
|
14
|
+
*/
|
|
15
|
+
declare const dsfrPreset: Partial<Config>;
|
|
16
|
+
|
|
17
|
+
export { dsfrPreset as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { borderRadius, boxShadow, colors, screens, spacing, typography } from '@dsfrkit/tokens';
|
|
2
|
+
import { Config } from 'tailwindcss';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Preset Tailwind CSS pour le DSFR
|
|
6
|
+
* Étend la configuration Tailwind avec les tokens du design system
|
|
7
|
+
* Supporte le mode clair/sombre via CSS variables
|
|
8
|
+
*
|
|
9
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/couleurs-palette
|
|
10
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/typographie
|
|
11
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/espacement
|
|
12
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/grille-et-points-de-rupture
|
|
13
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/systeme-d-ombres-et-d-elevation
|
|
14
|
+
*/
|
|
15
|
+
declare const dsfrPreset: Partial<Config>;
|
|
16
|
+
|
|
17
|
+
export { dsfrPreset as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var tokens = require('@dsfrkit/tokens');
|
|
6
|
+
var plugin = require('tailwindcss/plugin');
|
|
7
|
+
|
|
8
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
+
|
|
10
|
+
var plugin__default = /*#__PURE__*/_interopDefault(plugin);
|
|
11
|
+
|
|
12
|
+
// src/index.ts
|
|
13
|
+
var toMutableArray = (arr) => [...arr];
|
|
14
|
+
var toMutableFontSize = (fontSize) => {
|
|
15
|
+
const result = {};
|
|
16
|
+
for (const [key, value] of Object.entries(fontSize)) {
|
|
17
|
+
result[key] = [
|
|
18
|
+
value[0],
|
|
19
|
+
{ lineHeight: value[1].lineHeight }
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
return result;
|
|
23
|
+
};
|
|
24
|
+
var dsfrPreset = {
|
|
25
|
+
// Mode sombre via classe 'dark' sur <html>, data-theme="dark" ou data-fr-theme="dark" (DSFR natif)
|
|
26
|
+
darkMode: ["selector", '&:is(.dark, [data-theme="dark"], [data-fr-theme="dark"])'],
|
|
27
|
+
theme: {
|
|
28
|
+
// Breakpoints DSFR (surcharge complète)
|
|
29
|
+
screens: tokens.screens,
|
|
30
|
+
extend: {
|
|
31
|
+
colors: {
|
|
32
|
+
// Couleurs principales (statiques)
|
|
33
|
+
"blue-france": tokens.colors["blue-france"],
|
|
34
|
+
"red-marianne": tokens.colors["red-marianne"],
|
|
35
|
+
// Couleurs sémantiques via CSS variables (thème-aware)
|
|
36
|
+
info: tokens.cssVariables.info,
|
|
37
|
+
success: tokens.cssVariables.success,
|
|
38
|
+
warning: tokens.cssVariables.warning,
|
|
39
|
+
error: tokens.cssVariables.destructive,
|
|
40
|
+
destructive: tokens.cssVariables.destructive,
|
|
41
|
+
grey: tokens.colors.grey,
|
|
42
|
+
// Palette illustrative DSFR
|
|
43
|
+
"green-tilleul-verveine": tokens.colors["green-tilleul-verveine"],
|
|
44
|
+
"green-bourgeon": tokens.colors["green-bourgeon"],
|
|
45
|
+
"green-emeraude": tokens.colors["green-emeraude"],
|
|
46
|
+
"green-menthe": tokens.colors["green-menthe"],
|
|
47
|
+
"green-archipel": tokens.colors["green-archipel"],
|
|
48
|
+
"blue-ecume": tokens.colors["blue-ecume"],
|
|
49
|
+
"blue-cumulus": tokens.colors["blue-cumulus"],
|
|
50
|
+
"purple-glycine": tokens.colors["purple-glycine"],
|
|
51
|
+
"pink-macaron": tokens.colors["pink-macaron"],
|
|
52
|
+
"pink-tuile": tokens.colors["pink-tuile"],
|
|
53
|
+
"yellow-tournesol": tokens.colors["yellow-tournesol"],
|
|
54
|
+
"yellow-moutarde": tokens.colors["yellow-moutarde"],
|
|
55
|
+
"orange-terre-battue": tokens.colors["orange-terre-battue"],
|
|
56
|
+
"brown-cafe-creme": tokens.colors["brown-cafe-creme"],
|
|
57
|
+
"brown-caramel": tokens.colors["brown-caramel"],
|
|
58
|
+
"brown-opera": tokens.colors["brown-opera"],
|
|
59
|
+
"beige-gris-galet": tokens.colors["beige-gris-galet"],
|
|
60
|
+
background: tokens.cssVariables.background,
|
|
61
|
+
foreground: tokens.cssVariables.foreground,
|
|
62
|
+
border: tokens.cssVariables.border.DEFAULT,
|
|
63
|
+
"border-contrast": tokens.cssVariables.border.contrast,
|
|
64
|
+
"border-active": tokens.cssVariables.border.active,
|
|
65
|
+
primary: tokens.cssVariables.primary,
|
|
66
|
+
secondary: tokens.cssVariables.secondary,
|
|
67
|
+
muted: {
|
|
68
|
+
DEFAULT: tokens.cssVariables.background.alt,
|
|
69
|
+
foreground: tokens.cssVariables.foreground.muted
|
|
70
|
+
},
|
|
71
|
+
accent: {
|
|
72
|
+
DEFAULT: tokens.cssVariables.background.contrast,
|
|
73
|
+
foreground: tokens.cssVariables.foreground.DEFAULT
|
|
74
|
+
},
|
|
75
|
+
ring: tokens.cssVariables.focus.DEFAULT,
|
|
76
|
+
card: tokens.cssVariables.card,
|
|
77
|
+
popover: tokens.cssVariables.popover,
|
|
78
|
+
input: tokens.cssVariables.input
|
|
79
|
+
},
|
|
80
|
+
fontFamily: {
|
|
81
|
+
sans: toMutableArray(tokens.typography.fontFamily.marianne),
|
|
82
|
+
serif: toMutableArray(tokens.typography.fontFamily.spectral),
|
|
83
|
+
marianne: toMutableArray(tokens.typography.fontFamily.marianne),
|
|
84
|
+
spectral: toMutableArray(tokens.typography.fontFamily.spectral)
|
|
85
|
+
},
|
|
86
|
+
fontSize: toMutableFontSize(tokens.typography.fontSize),
|
|
87
|
+
fontWeight: tokens.typography.fontWeight,
|
|
88
|
+
lineHeight: tokens.typography.lineHeight,
|
|
89
|
+
spacing: tokens.spacing,
|
|
90
|
+
borderRadius: tokens.borderRadius,
|
|
91
|
+
boxShadow: tokens.boxShadow,
|
|
92
|
+
// Container pour suivre les breakpoints DSFR
|
|
93
|
+
container: {
|
|
94
|
+
center: true,
|
|
95
|
+
padding: {
|
|
96
|
+
DEFAULT: "1rem",
|
|
97
|
+
sm: "2rem",
|
|
98
|
+
lg: "4rem",
|
|
99
|
+
xl: "5rem"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
// Outline DSFR pour le focus
|
|
103
|
+
outlineOffset: {
|
|
104
|
+
focus: "2px"
|
|
105
|
+
},
|
|
106
|
+
outlineWidth: {
|
|
107
|
+
focus: "2px"
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
plugins: [
|
|
112
|
+
plugin__default.default(({ addBase, addComponents, addUtilities, theme }) => {
|
|
113
|
+
addBase({
|
|
114
|
+
// Focus visible DSFR — outline 2px + offset 2px
|
|
115
|
+
"*:focus-visible": {
|
|
116
|
+
outline: `2px solid ${theme("colors.ring")}`,
|
|
117
|
+
outlineOffset: "2px"
|
|
118
|
+
},
|
|
119
|
+
// Suppression du focus visible pour les clics souris
|
|
120
|
+
"*:focus:not(:focus-visible)": {
|
|
121
|
+
outline: "none"
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
addComponents({
|
|
125
|
+
".fr-container": {
|
|
126
|
+
width: "100%",
|
|
127
|
+
marginLeft: "auto",
|
|
128
|
+
marginRight: "auto",
|
|
129
|
+
paddingLeft: theme("spacing.4"),
|
|
130
|
+
paddingRight: theme("spacing.4"),
|
|
131
|
+
"@screen sm": {
|
|
132
|
+
maxWidth: "540px"
|
|
133
|
+
},
|
|
134
|
+
"@screen md": {
|
|
135
|
+
maxWidth: "720px"
|
|
136
|
+
},
|
|
137
|
+
"@screen lg": {
|
|
138
|
+
maxWidth: "960px"
|
|
139
|
+
},
|
|
140
|
+
"@screen xl": {
|
|
141
|
+
maxWidth: "1140px"
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
".fr-grid-row": {
|
|
145
|
+
display: "flex",
|
|
146
|
+
flexWrap: "wrap",
|
|
147
|
+
marginLeft: `-${theme("spacing.2")}`,
|
|
148
|
+
marginRight: `-${theme("spacing.2")}`
|
|
149
|
+
},
|
|
150
|
+
".fr-col": {
|
|
151
|
+
flex: "0 0 100%",
|
|
152
|
+
maxWidth: "100%",
|
|
153
|
+
paddingLeft: theme("spacing.2"),
|
|
154
|
+
paddingRight: theme("spacing.2")
|
|
155
|
+
},
|
|
156
|
+
/* Utilitaires globaux DSFR (liens, boutons, textes) */
|
|
157
|
+
".fr-link": {
|
|
158
|
+
color: theme("colors.primary.DEFAULT"),
|
|
159
|
+
textDecoration: "underline",
|
|
160
|
+
textDecorationSkipInk: "auto",
|
|
161
|
+
"&:hover": {
|
|
162
|
+
color: theme("colors.primary.hover")
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
".fr-btn": {
|
|
166
|
+
display: "inline-flex",
|
|
167
|
+
alignItems: "center",
|
|
168
|
+
justifyContent: "center",
|
|
169
|
+
gap: theme("spacing.2"),
|
|
170
|
+
fontWeight: theme("fontWeight.medium"),
|
|
171
|
+
transitionProperty: "color, background-color, border-color, box-shadow",
|
|
172
|
+
transitionTimingFunction: "ease-in-out",
|
|
173
|
+
transitionDuration: "200ms",
|
|
174
|
+
cursor: "pointer",
|
|
175
|
+
borderRadius: "0",
|
|
176
|
+
"&:disabled": {
|
|
177
|
+
cursor: "not-allowed",
|
|
178
|
+
opacity: "0.6"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
".fr-text": {
|
|
182
|
+
color: theme("colors.foreground.DEFAULT")
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
addUtilities({
|
|
186
|
+
".text-decision-default": {
|
|
187
|
+
color: tokens.colors.decision.text.default.grey
|
|
188
|
+
},
|
|
189
|
+
".text-decision-disabled": {
|
|
190
|
+
color: tokens.colors.decision.text.disabled.grey
|
|
191
|
+
},
|
|
192
|
+
".bg-decision-default": {
|
|
193
|
+
backgroundColor: tokens.colors.decision.background.default.grey
|
|
194
|
+
},
|
|
195
|
+
".bg-decision-disabled": {
|
|
196
|
+
backgroundColor: tokens.colors.decision.background.disabled.grey
|
|
197
|
+
},
|
|
198
|
+
/* Text / border helpers (DSFR fundamentals) */
|
|
199
|
+
".text-default": { color: theme("colors.foreground.DEFAULT") },
|
|
200
|
+
".text-muted": { color: theme("colors.foreground.muted") },
|
|
201
|
+
".text-inverted": { color: theme("colors.foreground.inverted") },
|
|
202
|
+
".border-default": { borderColor: theme("colors.border") },
|
|
203
|
+
".border-contrast": { borderColor: theme("colors.border-contrast") },
|
|
204
|
+
".border-active": { borderColor: theme("colors.border-active") },
|
|
205
|
+
/* Élévation DSFR */
|
|
206
|
+
".elevation-raised": { boxShadow: theme("boxShadow.raised") },
|
|
207
|
+
".elevation-overlap": { boxShadow: theme("boxShadow.overlap") },
|
|
208
|
+
".elevation-sticky": { boxShadow: theme("boxShadow.sticky") },
|
|
209
|
+
".elevation-lifted": { boxShadow: theme("boxShadow.lifted") },
|
|
210
|
+
/* Focus DSFR */
|
|
211
|
+
".focus-dsfr": {
|
|
212
|
+
outline: `2px solid ${theme("colors.ring")}`,
|
|
213
|
+
outlineOffset: "2px"
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
})
|
|
217
|
+
]
|
|
218
|
+
};
|
|
219
|
+
var index_default = dsfrPreset;
|
|
220
|
+
|
|
221
|
+
Object.defineProperty(exports, "borderRadius", {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
get: function () { return tokens.borderRadius; }
|
|
224
|
+
});
|
|
225
|
+
Object.defineProperty(exports, "boxShadow", {
|
|
226
|
+
enumerable: true,
|
|
227
|
+
get: function () { return tokens.boxShadow; }
|
|
228
|
+
});
|
|
229
|
+
Object.defineProperty(exports, "colors", {
|
|
230
|
+
enumerable: true,
|
|
231
|
+
get: function () { return tokens.colors; }
|
|
232
|
+
});
|
|
233
|
+
Object.defineProperty(exports, "screens", {
|
|
234
|
+
enumerable: true,
|
|
235
|
+
get: function () { return tokens.screens; }
|
|
236
|
+
});
|
|
237
|
+
Object.defineProperty(exports, "spacing", {
|
|
238
|
+
enumerable: true,
|
|
239
|
+
get: function () { return tokens.spacing; }
|
|
240
|
+
});
|
|
241
|
+
Object.defineProperty(exports, "typography", {
|
|
242
|
+
enumerable: true,
|
|
243
|
+
get: function () { return tokens.typography; }
|
|
244
|
+
});
|
|
245
|
+
exports.default = index_default;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { colors, typography, cssVariables, boxShadow, borderRadius, spacing, screens } from '@dsfrkit/tokens';
|
|
2
|
+
export { borderRadius, boxShadow, colors, screens, spacing, typography } from '@dsfrkit/tokens';
|
|
3
|
+
import plugin from 'tailwindcss/plugin';
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
var toMutableArray = (arr) => [...arr];
|
|
7
|
+
var toMutableFontSize = (fontSize) => {
|
|
8
|
+
const result = {};
|
|
9
|
+
for (const [key, value] of Object.entries(fontSize)) {
|
|
10
|
+
result[key] = [
|
|
11
|
+
value[0],
|
|
12
|
+
{ lineHeight: value[1].lineHeight }
|
|
13
|
+
];
|
|
14
|
+
}
|
|
15
|
+
return result;
|
|
16
|
+
};
|
|
17
|
+
var dsfrPreset = {
|
|
18
|
+
// Mode sombre via classe 'dark' sur <html>, data-theme="dark" ou data-fr-theme="dark" (DSFR natif)
|
|
19
|
+
darkMode: ["selector", '&:is(.dark, [data-theme="dark"], [data-fr-theme="dark"])'],
|
|
20
|
+
theme: {
|
|
21
|
+
// Breakpoints DSFR (surcharge complète)
|
|
22
|
+
screens,
|
|
23
|
+
extend: {
|
|
24
|
+
colors: {
|
|
25
|
+
// Couleurs principales (statiques)
|
|
26
|
+
"blue-france": colors["blue-france"],
|
|
27
|
+
"red-marianne": colors["red-marianne"],
|
|
28
|
+
// Couleurs sémantiques via CSS variables (thème-aware)
|
|
29
|
+
info: cssVariables.info,
|
|
30
|
+
success: cssVariables.success,
|
|
31
|
+
warning: cssVariables.warning,
|
|
32
|
+
error: cssVariables.destructive,
|
|
33
|
+
destructive: cssVariables.destructive,
|
|
34
|
+
grey: colors.grey,
|
|
35
|
+
// Palette illustrative DSFR
|
|
36
|
+
"green-tilleul-verveine": colors["green-tilleul-verveine"],
|
|
37
|
+
"green-bourgeon": colors["green-bourgeon"],
|
|
38
|
+
"green-emeraude": colors["green-emeraude"],
|
|
39
|
+
"green-menthe": colors["green-menthe"],
|
|
40
|
+
"green-archipel": colors["green-archipel"],
|
|
41
|
+
"blue-ecume": colors["blue-ecume"],
|
|
42
|
+
"blue-cumulus": colors["blue-cumulus"],
|
|
43
|
+
"purple-glycine": colors["purple-glycine"],
|
|
44
|
+
"pink-macaron": colors["pink-macaron"],
|
|
45
|
+
"pink-tuile": colors["pink-tuile"],
|
|
46
|
+
"yellow-tournesol": colors["yellow-tournesol"],
|
|
47
|
+
"yellow-moutarde": colors["yellow-moutarde"],
|
|
48
|
+
"orange-terre-battue": colors["orange-terre-battue"],
|
|
49
|
+
"brown-cafe-creme": colors["brown-cafe-creme"],
|
|
50
|
+
"brown-caramel": colors["brown-caramel"],
|
|
51
|
+
"brown-opera": colors["brown-opera"],
|
|
52
|
+
"beige-gris-galet": colors["beige-gris-galet"],
|
|
53
|
+
background: cssVariables.background,
|
|
54
|
+
foreground: cssVariables.foreground,
|
|
55
|
+
border: cssVariables.border.DEFAULT,
|
|
56
|
+
"border-contrast": cssVariables.border.contrast,
|
|
57
|
+
"border-active": cssVariables.border.active,
|
|
58
|
+
primary: cssVariables.primary,
|
|
59
|
+
secondary: cssVariables.secondary,
|
|
60
|
+
muted: {
|
|
61
|
+
DEFAULT: cssVariables.background.alt,
|
|
62
|
+
foreground: cssVariables.foreground.muted
|
|
63
|
+
},
|
|
64
|
+
accent: {
|
|
65
|
+
DEFAULT: cssVariables.background.contrast,
|
|
66
|
+
foreground: cssVariables.foreground.DEFAULT
|
|
67
|
+
},
|
|
68
|
+
ring: cssVariables.focus.DEFAULT,
|
|
69
|
+
card: cssVariables.card,
|
|
70
|
+
popover: cssVariables.popover,
|
|
71
|
+
input: cssVariables.input
|
|
72
|
+
},
|
|
73
|
+
fontFamily: {
|
|
74
|
+
sans: toMutableArray(typography.fontFamily.marianne),
|
|
75
|
+
serif: toMutableArray(typography.fontFamily.spectral),
|
|
76
|
+
marianne: toMutableArray(typography.fontFamily.marianne),
|
|
77
|
+
spectral: toMutableArray(typography.fontFamily.spectral)
|
|
78
|
+
},
|
|
79
|
+
fontSize: toMutableFontSize(typography.fontSize),
|
|
80
|
+
fontWeight: typography.fontWeight,
|
|
81
|
+
lineHeight: typography.lineHeight,
|
|
82
|
+
spacing,
|
|
83
|
+
borderRadius,
|
|
84
|
+
boxShadow,
|
|
85
|
+
// Container pour suivre les breakpoints DSFR
|
|
86
|
+
container: {
|
|
87
|
+
center: true,
|
|
88
|
+
padding: {
|
|
89
|
+
DEFAULT: "1rem",
|
|
90
|
+
sm: "2rem",
|
|
91
|
+
lg: "4rem",
|
|
92
|
+
xl: "5rem"
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
// Outline DSFR pour le focus
|
|
96
|
+
outlineOffset: {
|
|
97
|
+
focus: "2px"
|
|
98
|
+
},
|
|
99
|
+
outlineWidth: {
|
|
100
|
+
focus: "2px"
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
plugins: [
|
|
105
|
+
plugin(({ addBase, addComponents, addUtilities, theme }) => {
|
|
106
|
+
addBase({
|
|
107
|
+
// Focus visible DSFR — outline 2px + offset 2px
|
|
108
|
+
"*:focus-visible": {
|
|
109
|
+
outline: `2px solid ${theme("colors.ring")}`,
|
|
110
|
+
outlineOffset: "2px"
|
|
111
|
+
},
|
|
112
|
+
// Suppression du focus visible pour les clics souris
|
|
113
|
+
"*:focus:not(:focus-visible)": {
|
|
114
|
+
outline: "none"
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
addComponents({
|
|
118
|
+
".fr-container": {
|
|
119
|
+
width: "100%",
|
|
120
|
+
marginLeft: "auto",
|
|
121
|
+
marginRight: "auto",
|
|
122
|
+
paddingLeft: theme("spacing.4"),
|
|
123
|
+
paddingRight: theme("spacing.4"),
|
|
124
|
+
"@screen sm": {
|
|
125
|
+
maxWidth: "540px"
|
|
126
|
+
},
|
|
127
|
+
"@screen md": {
|
|
128
|
+
maxWidth: "720px"
|
|
129
|
+
},
|
|
130
|
+
"@screen lg": {
|
|
131
|
+
maxWidth: "960px"
|
|
132
|
+
},
|
|
133
|
+
"@screen xl": {
|
|
134
|
+
maxWidth: "1140px"
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
".fr-grid-row": {
|
|
138
|
+
display: "flex",
|
|
139
|
+
flexWrap: "wrap",
|
|
140
|
+
marginLeft: `-${theme("spacing.2")}`,
|
|
141
|
+
marginRight: `-${theme("spacing.2")}`
|
|
142
|
+
},
|
|
143
|
+
".fr-col": {
|
|
144
|
+
flex: "0 0 100%",
|
|
145
|
+
maxWidth: "100%",
|
|
146
|
+
paddingLeft: theme("spacing.2"),
|
|
147
|
+
paddingRight: theme("spacing.2")
|
|
148
|
+
},
|
|
149
|
+
/* Utilitaires globaux DSFR (liens, boutons, textes) */
|
|
150
|
+
".fr-link": {
|
|
151
|
+
color: theme("colors.primary.DEFAULT"),
|
|
152
|
+
textDecoration: "underline",
|
|
153
|
+
textDecorationSkipInk: "auto",
|
|
154
|
+
"&:hover": {
|
|
155
|
+
color: theme("colors.primary.hover")
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
".fr-btn": {
|
|
159
|
+
display: "inline-flex",
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
justifyContent: "center",
|
|
162
|
+
gap: theme("spacing.2"),
|
|
163
|
+
fontWeight: theme("fontWeight.medium"),
|
|
164
|
+
transitionProperty: "color, background-color, border-color, box-shadow",
|
|
165
|
+
transitionTimingFunction: "ease-in-out",
|
|
166
|
+
transitionDuration: "200ms",
|
|
167
|
+
cursor: "pointer",
|
|
168
|
+
borderRadius: "0",
|
|
169
|
+
"&:disabled": {
|
|
170
|
+
cursor: "not-allowed",
|
|
171
|
+
opacity: "0.6"
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
".fr-text": {
|
|
175
|
+
color: theme("colors.foreground.DEFAULT")
|
|
176
|
+
}
|
|
177
|
+
});
|
|
178
|
+
addUtilities({
|
|
179
|
+
".text-decision-default": {
|
|
180
|
+
color: colors.decision.text.default.grey
|
|
181
|
+
},
|
|
182
|
+
".text-decision-disabled": {
|
|
183
|
+
color: colors.decision.text.disabled.grey
|
|
184
|
+
},
|
|
185
|
+
".bg-decision-default": {
|
|
186
|
+
backgroundColor: colors.decision.background.default.grey
|
|
187
|
+
},
|
|
188
|
+
".bg-decision-disabled": {
|
|
189
|
+
backgroundColor: colors.decision.background.disabled.grey
|
|
190
|
+
},
|
|
191
|
+
/* Text / border helpers (DSFR fundamentals) */
|
|
192
|
+
".text-default": { color: theme("colors.foreground.DEFAULT") },
|
|
193
|
+
".text-muted": { color: theme("colors.foreground.muted") },
|
|
194
|
+
".text-inverted": { color: theme("colors.foreground.inverted") },
|
|
195
|
+
".border-default": { borderColor: theme("colors.border") },
|
|
196
|
+
".border-contrast": { borderColor: theme("colors.border-contrast") },
|
|
197
|
+
".border-active": { borderColor: theme("colors.border-active") },
|
|
198
|
+
/* Élévation DSFR */
|
|
199
|
+
".elevation-raised": { boxShadow: theme("boxShadow.raised") },
|
|
200
|
+
".elevation-overlap": { boxShadow: theme("boxShadow.overlap") },
|
|
201
|
+
".elevation-sticky": { boxShadow: theme("boxShadow.sticky") },
|
|
202
|
+
".elevation-lifted": { boxShadow: theme("boxShadow.lifted") },
|
|
203
|
+
/* Focus DSFR */
|
|
204
|
+
".focus-dsfr": {
|
|
205
|
+
outline: `2px solid ${theme("colors.ring")}`,
|
|
206
|
+
outlineOffset: "2px"
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
})
|
|
210
|
+
]
|
|
211
|
+
};
|
|
212
|
+
var index_default = dsfrPreset;
|
|
213
|
+
|
|
214
|
+
export { index_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsfrkit/config",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Preset Tailwind CSS pour le Système de Design de l'État français (DSFR)",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsup",
|
|
21
|
+
"dev": "tsup --watch",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"test:watch": "vitest",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"clean": "rm -rf dist"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"dsfr",
|
|
29
|
+
"tailwindcss",
|
|
30
|
+
"preset",
|
|
31
|
+
"design-system",
|
|
32
|
+
"france"
|
|
33
|
+
],
|
|
34
|
+
"license": "ETALAB-2.0",
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"@dsfrkit/tokens": "workspace:*",
|
|
40
|
+
"tailwindcss": ">=3.4.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@dsfrkit/tokens": "workspace:*",
|
|
44
|
+
"tailwindcss": "^3.4.17",
|
|
45
|
+
"tsup": "^8.3.5",
|
|
46
|
+
"typescript": "^5.7.2"
|
|
47
|
+
}
|
|
48
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import {
|
|
2
|
+
borderRadius,
|
|
3
|
+
boxShadow,
|
|
4
|
+
colors,
|
|
5
|
+
cssVariables,
|
|
6
|
+
screens,
|
|
7
|
+
spacing,
|
|
8
|
+
typography,
|
|
9
|
+
} from '@dsfrkit/tokens'
|
|
10
|
+
import type { Config } from 'tailwindcss'
|
|
11
|
+
import plugin from 'tailwindcss/plugin'
|
|
12
|
+
|
|
13
|
+
// Convertit les tableaux readonly en tableaux mutables pour Tailwind
|
|
14
|
+
const toMutableArray = (arr: readonly string[]): string[] => [...arr]
|
|
15
|
+
|
|
16
|
+
// Convertit fontSize readonly en format mutable
|
|
17
|
+
const toMutableFontSize = (fontSize: typeof typography.fontSize) => {
|
|
18
|
+
const result: Record<string, [string, { lineHeight: string }]> = {}
|
|
19
|
+
for (const [key, value] of Object.entries(fontSize)) {
|
|
20
|
+
result[key] = [
|
|
21
|
+
value[0] as string,
|
|
22
|
+
{ lineHeight: (value[1] as { lineHeight: string }).lineHeight },
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
return result
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Preset Tailwind CSS pour le DSFR
|
|
30
|
+
* Étend la configuration Tailwind avec les tokens du design system
|
|
31
|
+
* Supporte le mode clair/sombre via CSS variables
|
|
32
|
+
*
|
|
33
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/couleurs-palette
|
|
34
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/typographie
|
|
35
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/espacement
|
|
36
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/grille-et-points-de-rupture
|
|
37
|
+
* @see https://www.systeme-de-design.gouv.fr/fondamentaux/systeme-d-ombres-et-d-elevation
|
|
38
|
+
*/
|
|
39
|
+
const dsfrPreset: Partial<Config> = {
|
|
40
|
+
// Mode sombre via classe 'dark' sur <html>, data-theme="dark" ou data-fr-theme="dark" (DSFR natif)
|
|
41
|
+
darkMode: ['selector', '&:is(.dark, [data-theme="dark"], [data-fr-theme="dark"])'],
|
|
42
|
+
theme: {
|
|
43
|
+
// Breakpoints DSFR (surcharge complète)
|
|
44
|
+
screens,
|
|
45
|
+
|
|
46
|
+
extend: {
|
|
47
|
+
colors: {
|
|
48
|
+
// Couleurs principales (statiques)
|
|
49
|
+
'blue-france': colors['blue-france'],
|
|
50
|
+
'red-marianne': colors['red-marianne'],
|
|
51
|
+
|
|
52
|
+
// Couleurs sémantiques via CSS variables (thème-aware)
|
|
53
|
+
info: cssVariables.info,
|
|
54
|
+
success: cssVariables.success,
|
|
55
|
+
warning: cssVariables.warning,
|
|
56
|
+
error: cssVariables.destructive,
|
|
57
|
+
destructive: cssVariables.destructive,
|
|
58
|
+
grey: colors.grey,
|
|
59
|
+
// Palette illustrative DSFR
|
|
60
|
+
'green-tilleul-verveine': colors['green-tilleul-verveine'],
|
|
61
|
+
'green-bourgeon': colors['green-bourgeon'],
|
|
62
|
+
'green-emeraude': colors['green-emeraude'],
|
|
63
|
+
'green-menthe': colors['green-menthe'],
|
|
64
|
+
'green-archipel': colors['green-archipel'],
|
|
65
|
+
'blue-ecume': colors['blue-ecume'],
|
|
66
|
+
'blue-cumulus': colors['blue-cumulus'],
|
|
67
|
+
'purple-glycine': colors['purple-glycine'],
|
|
68
|
+
'pink-macaron': colors['pink-macaron'],
|
|
69
|
+
'pink-tuile': colors['pink-tuile'],
|
|
70
|
+
'yellow-tournesol': colors['yellow-tournesol'],
|
|
71
|
+
'yellow-moutarde': colors['yellow-moutarde'],
|
|
72
|
+
'orange-terre-battue': colors['orange-terre-battue'],
|
|
73
|
+
'brown-cafe-creme': colors['brown-cafe-creme'],
|
|
74
|
+
'brown-caramel': colors['brown-caramel'],
|
|
75
|
+
'brown-opera': colors['brown-opera'],
|
|
76
|
+
'beige-gris-galet': colors['beige-gris-galet'],
|
|
77
|
+
|
|
78
|
+
background: cssVariables.background,
|
|
79
|
+
foreground: cssVariables.foreground,
|
|
80
|
+
border: cssVariables.border.DEFAULT,
|
|
81
|
+
'border-contrast': cssVariables.border.contrast,
|
|
82
|
+
'border-active': cssVariables.border.active,
|
|
83
|
+
primary: cssVariables.primary,
|
|
84
|
+
secondary: cssVariables.secondary,
|
|
85
|
+
muted: {
|
|
86
|
+
DEFAULT: cssVariables.background.alt,
|
|
87
|
+
foreground: cssVariables.foreground.muted,
|
|
88
|
+
},
|
|
89
|
+
accent: {
|
|
90
|
+
DEFAULT: cssVariables.background.contrast,
|
|
91
|
+
foreground: cssVariables.foreground.DEFAULT,
|
|
92
|
+
},
|
|
93
|
+
ring: cssVariables.focus.DEFAULT,
|
|
94
|
+
card: cssVariables.card,
|
|
95
|
+
popover: cssVariables.popover,
|
|
96
|
+
input: cssVariables.input,
|
|
97
|
+
},
|
|
98
|
+
|
|
99
|
+
fontFamily: {
|
|
100
|
+
sans: toMutableArray(typography.fontFamily.marianne),
|
|
101
|
+
serif: toMutableArray(typography.fontFamily.spectral),
|
|
102
|
+
marianne: toMutableArray(typography.fontFamily.marianne),
|
|
103
|
+
spectral: toMutableArray(typography.fontFamily.spectral),
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
fontSize: toMutableFontSize(typography.fontSize),
|
|
107
|
+
fontWeight: typography.fontWeight,
|
|
108
|
+
lineHeight: typography.lineHeight,
|
|
109
|
+
|
|
110
|
+
spacing,
|
|
111
|
+
borderRadius,
|
|
112
|
+
boxShadow,
|
|
113
|
+
|
|
114
|
+
// Container pour suivre les breakpoints DSFR
|
|
115
|
+
container: {
|
|
116
|
+
center: true,
|
|
117
|
+
padding: {
|
|
118
|
+
DEFAULT: '1rem',
|
|
119
|
+
sm: '2rem',
|
|
120
|
+
lg: '4rem',
|
|
121
|
+
xl: '5rem',
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
|
|
125
|
+
// Outline DSFR pour le focus
|
|
126
|
+
outlineOffset: {
|
|
127
|
+
focus: '2px',
|
|
128
|
+
},
|
|
129
|
+
outlineWidth: {
|
|
130
|
+
focus: '2px',
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
plugins: [
|
|
136
|
+
plugin(({ addBase, addComponents, addUtilities, theme }) => {
|
|
137
|
+
// Styles de base DSFR
|
|
138
|
+
addBase({
|
|
139
|
+
// Focus visible DSFR — outline 2px + offset 2px
|
|
140
|
+
'*:focus-visible': {
|
|
141
|
+
outline: `2px solid ${theme('colors.ring')}`,
|
|
142
|
+
outlineOffset: '2px',
|
|
143
|
+
},
|
|
144
|
+
// Suppression du focus visible pour les clics souris
|
|
145
|
+
'*:focus:not(:focus-visible)': {
|
|
146
|
+
outline: 'none',
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Composants utilitaires DSFR
|
|
151
|
+
addComponents({
|
|
152
|
+
'.fr-container': {
|
|
153
|
+
width: '100%',
|
|
154
|
+
marginLeft: 'auto',
|
|
155
|
+
marginRight: 'auto',
|
|
156
|
+
paddingLeft: theme('spacing.4'),
|
|
157
|
+
paddingRight: theme('spacing.4'),
|
|
158
|
+
'@screen sm': {
|
|
159
|
+
maxWidth: '540px',
|
|
160
|
+
},
|
|
161
|
+
'@screen md': {
|
|
162
|
+
maxWidth: '720px',
|
|
163
|
+
},
|
|
164
|
+
'@screen lg': {
|
|
165
|
+
maxWidth: '960px',
|
|
166
|
+
},
|
|
167
|
+
'@screen xl': {
|
|
168
|
+
maxWidth: '1140px',
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
'.fr-grid-row': {
|
|
172
|
+
display: 'flex',
|
|
173
|
+
flexWrap: 'wrap',
|
|
174
|
+
marginLeft: `-${theme('spacing.2')}`,
|
|
175
|
+
marginRight: `-${theme('spacing.2')}`,
|
|
176
|
+
},
|
|
177
|
+
'.fr-col': {
|
|
178
|
+
flex: '0 0 100%',
|
|
179
|
+
maxWidth: '100%',
|
|
180
|
+
paddingLeft: theme('spacing.2'),
|
|
181
|
+
paddingRight: theme('spacing.2'),
|
|
182
|
+
},
|
|
183
|
+
/* Utilitaires globaux DSFR (liens, boutons, textes) */
|
|
184
|
+
'.fr-link': {
|
|
185
|
+
color: theme('colors.primary.DEFAULT'),
|
|
186
|
+
textDecoration: 'underline',
|
|
187
|
+
textDecorationSkipInk: 'auto',
|
|
188
|
+
'&:hover': {
|
|
189
|
+
color: theme('colors.primary.hover'),
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
'.fr-btn': {
|
|
193
|
+
display: 'inline-flex',
|
|
194
|
+
alignItems: 'center',
|
|
195
|
+
justifyContent: 'center',
|
|
196
|
+
gap: theme('spacing.2'),
|
|
197
|
+
fontWeight: theme('fontWeight.medium'),
|
|
198
|
+
transitionProperty: 'color, background-color, border-color, box-shadow',
|
|
199
|
+
transitionTimingFunction: 'ease-in-out',
|
|
200
|
+
transitionDuration: '200ms',
|
|
201
|
+
cursor: 'pointer',
|
|
202
|
+
borderRadius: '0',
|
|
203
|
+
'&:disabled': {
|
|
204
|
+
cursor: 'not-allowed',
|
|
205
|
+
opacity: '0.6',
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
'.fr-text': {
|
|
209
|
+
color: theme('colors.foreground.DEFAULT'),
|
|
210
|
+
},
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
// Utilities pour les couleurs de décision DSFR
|
|
214
|
+
addUtilities({
|
|
215
|
+
'.text-decision-default': {
|
|
216
|
+
color: colors.decision.text.default.grey,
|
|
217
|
+
},
|
|
218
|
+
'.text-decision-disabled': {
|
|
219
|
+
color: colors.decision.text.disabled.grey,
|
|
220
|
+
},
|
|
221
|
+
'.bg-decision-default': {
|
|
222
|
+
backgroundColor: colors.decision.background.default.grey,
|
|
223
|
+
},
|
|
224
|
+
'.bg-decision-disabled': {
|
|
225
|
+
backgroundColor: colors.decision.background.disabled.grey,
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
/* Text / border helpers (DSFR fundamentals) */
|
|
229
|
+
'.text-default': { color: theme('colors.foreground.DEFAULT') },
|
|
230
|
+
'.text-muted': { color: theme('colors.foreground.muted') },
|
|
231
|
+
'.text-inverted': { color: theme('colors.foreground.inverted') },
|
|
232
|
+
|
|
233
|
+
'.border-default': { borderColor: theme('colors.border') },
|
|
234
|
+
'.border-contrast': { borderColor: theme('colors.border-contrast') },
|
|
235
|
+
'.border-active': { borderColor: theme('colors.border-active') },
|
|
236
|
+
|
|
237
|
+
/* Élévation DSFR */
|
|
238
|
+
'.elevation-raised': { boxShadow: theme('boxShadow.raised') },
|
|
239
|
+
'.elevation-overlap': { boxShadow: theme('boxShadow.overlap') },
|
|
240
|
+
'.elevation-sticky': { boxShadow: theme('boxShadow.sticky') },
|
|
241
|
+
'.elevation-lifted': { boxShadow: theme('boxShadow.lifted') },
|
|
242
|
+
|
|
243
|
+
/* Focus DSFR */
|
|
244
|
+
'.focus-dsfr': {
|
|
245
|
+
outline: `2px solid ${theme('colors.ring')}`,
|
|
246
|
+
outlineOffset: '2px',
|
|
247
|
+
},
|
|
248
|
+
})
|
|
249
|
+
}),
|
|
250
|
+
],
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export default dsfrPreset
|
|
254
|
+
|
|
255
|
+
// Export individuel pour usage avancé
|
|
256
|
+
export { borderRadius, boxShadow, colors, screens, spacing, typography }
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import dsfrPreset, { colors, spacing, typography } from './index'
|
|
3
|
+
|
|
4
|
+
describe('DSFR Tailwind Preset', () => {
|
|
5
|
+
it('should export preset configuration object', () => {
|
|
6
|
+
expect(dsfrPreset).toBeDefined()
|
|
7
|
+
expect(dsfrPreset.theme).toBeDefined()
|
|
8
|
+
expect(dsfrPreset.plugins).toBeDefined()
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('should map core DSFR colors to the Tailwind extend theme', () => {
|
|
12
|
+
const extendColors = dsfrPreset.theme?.extend?.colors as any
|
|
13
|
+
expect(extendColors).toBeDefined()
|
|
14
|
+
|
|
15
|
+
// Check direct static assignments
|
|
16
|
+
expect(extendColors['blue-france']).toEqual(colors['blue-france'])
|
|
17
|
+
expect(extendColors['red-marianne']).toEqual(colors['red-marianne'])
|
|
18
|
+
|
|
19
|
+
// Check semantic variables assignments
|
|
20
|
+
expect(extendColors.primary).toBeDefined()
|
|
21
|
+
expect(extendColors.background).toBeDefined()
|
|
22
|
+
expect(extendColors.foreground).toBeDefined()
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('should map typography and spacing', () => {
|
|
26
|
+
const extendTheme = dsfrPreset.theme?.extend as any
|
|
27
|
+
expect(extendTheme.fontFamily.marianne).toBeDefined()
|
|
28
|
+
expect(extendTheme.spacing).toEqual(spacing)
|
|
29
|
+
expect(extendTheme.fontWeight).toEqual(typography.fontWeight)
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
it('should contain the DSFR container configuration', () => {
|
|
33
|
+
const container = dsfrPreset.theme?.extend?.container as any
|
|
34
|
+
expect(container).toBeDefined()
|
|
35
|
+
expect(container.center).toBe(true)
|
|
36
|
+
expect(container.padding).toBeDefined()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('should inject plugins', () => {
|
|
40
|
+
expect(Array.isArray(dsfrPreset.plugins)).toBe(true)
|
|
41
|
+
expect(dsfrPreset.plugins?.length).toBeGreaterThan(0)
|
|
42
|
+
})
|
|
43
|
+
})
|