@marwes-ui/presets 0.0.4 → 1.0.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.
Files changed (47) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +271 -47
  3. package/dist/chunk-2JNIKK66.js +21 -0
  4. package/dist/chunk-2JNIKK66.js.map +1 -0
  5. package/dist/firstEdition/index.d.ts +3 -3
  6. package/dist/firstEdition/index.js +1 -1
  7. package/dist/index.d.ts +2 -2
  8. package/dist/index.js +1 -1
  9. package/package.json +15 -9
  10. package/src/firstEdition/accordion.css +140 -0
  11. package/src/firstEdition/avatar.css +204 -0
  12. package/src/firstEdition/badge.css +139 -0
  13. package/src/firstEdition/button.css +219 -0
  14. package/src/firstEdition/card.css +136 -0
  15. package/src/firstEdition/checkbox.css +214 -0
  16. package/src/firstEdition/dialog.css +149 -0
  17. package/src/firstEdition/divider.css +37 -0
  18. package/src/firstEdition/icon.css +72 -0
  19. package/src/firstEdition/index.ts +19 -0
  20. package/src/firstEdition/input-otp.css +107 -0
  21. package/src/firstEdition/input.css +73 -0
  22. package/src/firstEdition/molecules/accordion-field.css +46 -0
  23. package/src/firstEdition/molecules/checkbox-field.css +53 -0
  24. package/src/firstEdition/molecules/checkbox-group-field.css +67 -0
  25. package/src/firstEdition/molecules/dialog-modal.css +34 -0
  26. package/src/firstEdition/molecules/input-field.css +260 -0
  27. package/src/firstEdition/molecules/radio-group-field.css +59 -0
  28. package/src/firstEdition/molecules/slider-field.css +83 -0
  29. package/src/firstEdition/molecules/switch-field.css +37 -0
  30. package/src/firstEdition/molecules/tab-group.css +26 -0
  31. package/src/firstEdition/molecules/toast-container.css +45 -0
  32. package/src/firstEdition/radio.css +121 -0
  33. package/src/firstEdition/rich-text.css +134 -0
  34. package/src/firstEdition/select.css +337 -0
  35. package/src/firstEdition/slider.css +228 -0
  36. package/src/firstEdition/spacing.css +6 -0
  37. package/src/firstEdition/spinner.css +94 -0
  38. package/src/firstEdition/styles.css +27 -0
  39. package/src/firstEdition/switch.css +156 -0
  40. package/src/firstEdition/tab.css +81 -0
  41. package/src/firstEdition/textarea.css +63 -0
  42. package/src/firstEdition/toast.css +318 -0
  43. package/src/firstEdition/tokens.css +35 -0
  44. package/src/firstEdition/tooltip.css +112 -0
  45. package/src/firstEdition/typography.css +33 -0
  46. package/dist/chunk-UJIVT75P.js +0 -26
  47. package/dist/chunk-UJIVT75P.js.map +0 -1
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 Niklas Westman
3
+ Copyright (c) 2026 Niklas Westman, Martino Ognissanti and contributors
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -1,68 +1,292 @@
1
- # @marwes-ui/presets
1
+ <div align="center">
2
2
 
3
- Design presets for Marwes. Presets define theme defaults and static CSS for component classnames.
3
+ <img alt="Marwes Design System" src="https://raw.githubusercontent.com/niklas-westman/marwes/main/.github/assets/banner-light.png" width="100%" style="border-radius: 40px;">
4
4
 
5
- ## Responsibilities
6
- - Provide preset objects (currently `firstEdition`).
7
- - Provide static CSS for `.mw-*` classnames.
8
- - Map semantic theme values to visual styles with CSS variables.
5
+ <br>
6
+ <br>
9
7
 
10
- ## Non-Responsibilities
11
- - No component logic.
12
- - No framework rendering.
13
- - No runtime CSS-in-JS.
8
+ # Marwes Design System - Presets
9
+
10
+ **Static default CSS and preset theme exports for Marwes React and Vue apps.**
11
+
12
+ Static `.mw-*` CSS • CSS variables • Default Marwes visuals • No runtime CSS-in-JS
13
+
14
+ [Documentation](https://github.com/niklas-westman/marwes/tree/main/docs) • [Storybook](https://d3hobet9plpuvm.cloudfront.net/storybook-react/latest/) • [GitHub](https://github.com/niklas-westman/marwes)
15
+
16
+ </div>
17
+
18
+ ---
19
+
20
+ ## Why Use It
21
+
22
+ Most apps install `@marwes-ui/react` or `@marwes-ui/vue`, and those adapters load the default preset automatically. Install presets directly when you need the standalone CSS path, the explicit `firstEditionTheme` object, or preset CSS in a custom adapter.
23
+
24
+ Presets gives Marwes its default visual layer:
25
+
26
+ - default component CSS
27
+ - theme-variable driven colors, radius, focus, typography, density, and state styling
28
+ - stable `.mw-*` class styling for every shipped component family
29
+ - no CSS-in-JS runtime
30
+ - CSS that follows the same core recipes used by React and Vue
31
+
32
+ ## Package Map
33
+
34
+ Presets are the static visual layer, not the normal app entry point.
35
+
36
+ | Package | Use it when |
37
+ | --- | --- |
38
+ | `@marwes-ui/react` | You are building a React app. |
39
+ | `@marwes-ui/vue` | You are building a Vue app. |
40
+ | `@marwes-ui/core` | You need framework-agnostic recipes, theme utilities, accessibility contracts, or adapter/tooling APIs. |
41
+ | `@marwes-ui/presets` | You need standalone preset CSS or preset theme exports. |
42
+
43
+ This package gives humans and AI agents a predictable CSS contract: `.mw-*` classes consume `--mw-*` variables generated by the provider, while adapters stay thin.
44
+
45
+ ## Install
46
+
47
+ ```bash
48
+ pnpm add @marwes-ui/presets
49
+ ```
50
+
51
+ ## Normal App Setup
52
+
53
+ React and Vue apps normally import only the adapter:
14
54
 
15
- ## Install and Use
16
55
  ```tsx
17
- import { MarwesProvider } from "@marwes-ui/react";
18
- import { firstEdition } from "@marwes-ui/presets";
19
- import "@marwes-ui/presets/firstEdition/styles.css";
56
+ import { Button, ButtonVariant, MarwesProvider } from "@marwes-ui/react"
20
57
 
21
- <MarwesProvider preset={firstEdition}>
58
+ export function App() {
59
+ return (
60
+ <MarwesProvider>
61
+ <Button variant={ButtonVariant.primary}>Save</Button>
62
+ </MarwesProvider>
63
+ )
64
+ }
65
+ ```
66
+
67
+ ## Direct CSS Import
68
+
69
+ Use the direct CSS path for custom adapters, static prototypes, or tooling that needs the preset without the React/Vue entry.
70
+
71
+ ```ts
72
+ import "@marwes-ui/presets/firstEdition/styles.css"
73
+ ```
74
+
75
+ ## Available Styled Families
76
+
77
+ The default preset styles these Marwes families today:
78
+
79
+ - Accordion and accordion fields
80
+ - Avatar and avatar groups
81
+ - Badge and contextual badge variants
82
+ - Button and purpose button variants
83
+ - Card variants
84
+ - Checkbox, checkbox fields, and checkbox groups
85
+ - Dialog and dialog modal
86
+ - Divider
87
+ - Icon
88
+ - Input, textarea, select, rich text, OTP, and field variants
89
+ - Paragraph and heading typography
90
+ - Radio and radio groups
91
+ - Slider and slider fields
92
+ - Spacing and spacer primitives
93
+ - Spinner variants
94
+ - Switch and switch fields
95
+ - Tab groups and panels
96
+ - Toast and toast container
97
+ - Tooltip and tooltip groups
98
+
99
+ ## Custom Theme With Preset CSS
100
+
101
+ Preset CSS consumes provider-generated `--mw-*` variables. Marwes is designed to look great from the beginning: map an existing design library or graphical profile into a partial `ThemeInput`, override only the tokens your product owns, pass it to `MarwesProvider`, and the preset follows it.
102
+
103
+ ```tsx
104
+ import { MarwesProvider, mwAvailableFonts, type ThemeInput } from "@marwes-ui/react"
105
+
106
+ const brandTheme = {
107
+ color: {
108
+ primary: "#2457FF",
109
+ danger: "#D90429",
110
+ success: "#15803D",
111
+ warning: "#D97706",
112
+ background: "#F8FAFC",
113
+ surface: "#FFFFFF",
114
+ surfaceElevated: "#FFFFFF",
115
+ text: "#111827",
116
+ textMuted: "#4B5563",
117
+ border: "#D1D5DB",
118
+ focus: "#2457FF",
119
+ },
120
+ font: {
121
+ primary: mwAvailableFonts.Poppins,
122
+ secondary: mwAvailableFonts.Lora,
123
+ },
124
+ ui: {
125
+ radius: 10,
126
+ density: "comfortable",
127
+ },
128
+ } satisfies ThemeInput
129
+
130
+ <MarwesProvider theme={brandTheme}>
22
131
  <App />
23
- </MarwesProvider>;
132
+ </MarwesProvider>
24
133
  ```
25
134
 
26
- ## firstEdition
27
- Preset definition:
28
- - `src/firstEdition/index.ts`
135
+ ## Light And Dark Mode
29
136
 
30
- Main stylesheet:
31
- - `src/firstEdition/styles.css`
137
+ The preset CSS already contains the light and dark visual rules. In React and Vue apps, use `ThemeMode.light` and `ThemeMode.dark` instead of string literals, then let `MarwesProvider` own the active mode and toggle it with the adapter hook:
32
138
 
33
- Imported component styles:
34
- - `button.css`
35
- - `input.css`
36
- - `checkbox.css`
37
- - `icon.css`
38
- - `typography.css`
39
- - `molecules/checkbox-field.css`
139
+ ```tsx
140
+ import { Button, ButtonVariant, MarwesProvider, ThemeMode, useThemeMode } from "@marwes-ui/react"
141
+
142
+ function ThemeToggle() {
143
+ const { mode, toggleMode } = useThemeMode()
144
+
145
+ return (
146
+ <Button variant={ButtonVariant.secondary} onClick={toggleMode}>
147
+ Use {mode === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark} mode
148
+ </Button>
149
+ )
150
+ }
151
+
152
+ export function App() {
153
+ return (
154
+ <MarwesProvider defaultMode={ThemeMode.light}>
155
+ <ThemeToggle />
156
+ <AppShell />
157
+ </MarwesProvider>
158
+ )
159
+ }
160
+ ```
161
+
162
+ When the mode changes, the provider updates the preset's `--mw-*` variables and root class. Preset selectors such as `.mw-theme--dark .mw-btn` then pick up the correct dark-mode component states without any extra CSS in the app.
163
+
164
+ You do not need a `themeByMode` map for the normal toggle. With no `theme` prop, Marwes uses its default light and dark palettes. With shared brand overrides, pass the same partial `theme` object and the provider still swaps every omitted token by mode.
165
+
166
+ Use a `themeByMode` map only when your product wants different brand overrides in light and dark mode, such as a different primary color or surface color per mode:
167
+
168
+ ```tsx
169
+ import { useState } from "react"
170
+ import {
171
+ Button,
172
+ ButtonVariant,
173
+ MarwesProvider,
174
+ ThemeMode,
175
+ type ThemeInput,
176
+ useThemeMode,
177
+ } from "@marwes-ui/react"
178
+
179
+ const themeByMode = {
180
+ [ThemeMode.light]: { color: { primary: "#2457FF", background: "#F8FAFC", text: "#111827" } },
181
+ [ThemeMode.dark]: { color: { primary: "#8BA2FF", background: "#0B1020", text: "#F8FAFC" } },
182
+ } satisfies Record<ThemeMode, ThemeInput>
183
+
184
+ function ThemeToggle() {
185
+ const { mode, toggleMode } = useThemeMode()
186
+
187
+ return (
188
+ <Button variant={ButtonVariant.secondary} onClick={toggleMode}>
189
+ Use {mode === ThemeMode.dark ? ThemeMode.light : ThemeMode.dark} mode
190
+ </Button>
191
+ )
192
+ }
193
+
194
+ export function App() {
195
+ const [mode, setMode] = useState<ThemeMode>(ThemeMode.light)
196
+
197
+ return (
198
+ <MarwesProvider mode={mode} theme={themeByMode[mode]} onModeChange={setMode}>
199
+ <ThemeToggle />
200
+ <AppShell />
201
+ </MarwesProvider>
202
+ )
203
+ }
204
+ ```
205
+
206
+ ## firstEditionTheme
207
+
208
+ `firstEditionTheme` remains exported for explicit or advanced use. React and Vue providers already use the same baseline by default, so normal app code does not need to pass it.
209
+
210
+ ```ts
211
+ import { firstEditionTheme } from "@marwes-ui/presets"
212
+ ```
213
+
214
+ ## CSS Contract
40
215
 
41
- ## Contract with Core
42
216
  Core recipes emit:
43
- - stable classes such as `mw-btn`, `mw-input`, `mw-checkbox`
44
- - CSS vars such as `--mw-primary`, `--mw-radius`
217
+ - stable classes such as `.mw-btn`, `.mw-input`, `.mw-checkbox`, `.mw-card`
218
+ - component-scoped vars where needed
219
+ - semantic theme variables such as `--mw-color-primary-base`, `--mw-color-text`, and `--mw-ui-radius`
220
+ - fixed spacing variables such as `--mw-spacing-sp-24`
45
221
 
46
- Presets must style those classes/vars consistently and should not require adapter-specific hacks.
222
+ Preset CSS must style those classes and variables consistently without adapter-specific hacks.
47
223
 
48
- ## CSS Conventions
49
- - Keep prefix `--mw-*` for variables.
50
- - Keep classname prefix `.mw-*`.
51
- - Prefer semantic vars from core (`--mw-primary`, `--mw-text`, `--mw-surface`) over hardcoded colors.
52
- - Keep focus-visible and disabled states explicit in CSS.
224
+ Plain CSS can use those variables anywhere under `MarwesProvider`:
53
225
 
54
- ## Figma Mapping
55
- When syncing design changes from Figma, follow:
56
- - `../../docs/FIGMA_TO_MARWES.md`
226
+ ```css
227
+ .project-panel {
228
+ padding: var(--mw-spacing-sp-24);
229
+ color: var(--mw-color-text);
230
+ background: var(--mw-color-surface);
231
+ border: 1px solid var(--mw-color-border);
232
+ border-radius: var(--mw-ui-radius);
233
+ }
234
+ ```
57
235
 
58
- This ensures token names and state variants map predictably into preset CSS.
236
+ JavaScript styling layers should import token helpers from `@marwes-ui/core`, `@marwes-ui/react`, or `@marwes-ui/vue` instead of duplicating `var(...)` strings.
237
+
238
+ Use the helper that matches the job:
239
+
240
+ - `mwThemeVars` returns CSS `var(...)` references for app-owned CSS-in-JS, style objects, vanilla-extract, and config files.
241
+ - `mwThemeVarNames` returns raw custom property names for assigning overrides or inspecting the preset CSS contract.
242
+ - `mwVar()` wraps custom or advanced `--mw-*` names with optional fallback support.
243
+ - `mwStyledTheme` mirrors `mwThemeVars` as a plain theme object for styled-components and Emotion integrations.
244
+
245
+ ```ts
246
+ import { mwThemeVarNames, mwThemeVars, mwVar } from "@marwes-ui/core"
247
+
248
+ const panelStyle = {
249
+ padding: mwThemeVars.spacing.sp24,
250
+ color: mwThemeVars.color.text,
251
+ outlineColor: mwVar("--mw-color-focus", "#2457FF"),
252
+ }
253
+
254
+ const localOverride = {
255
+ [mwThemeVarNames.color.focus]: "#FF00AA",
256
+ }
257
+ ```
258
+
259
+ These helpers exist so preset CSS, adapter components, and custom application styles all follow the same provider-generated variables. That enables custom layouts and third-party styling systems to stay visually aligned with the default preset without depending on React, Vue, styled-components, or Emotion.
260
+
261
+ ## Accessible Styling Contract
262
+
263
+ Presets make the semantic contract visible without replacing it. Core and the adapters own roles, labels, state, and ARIA wiring; preset CSS owns the visual states that users need to perceive.
264
+
265
+ That means the default CSS includes styling for:
266
+
267
+ - visible focus states on interactive controls
268
+ - disabled, invalid, selected, expanded, checked, and busy states
269
+ - theme-driven text and background colors with contrast-aware defaults
270
+ - component classes that match the same recipes used by React and Vue
271
+
272
+ Example: an invalid input field is accessible because the adapter applies `aria-invalid` and `aria-describedby`; the preset then makes that same invalid state visually obvious through `.mw-input-field--invalid` and related input classes.
273
+
274
+ ## Package Boundaries
275
+
276
+ - `@marwes-ui/core` owns recipes, semantic metadata, and theme resolution.
277
+ - `@marwes-ui/presets` owns static default CSS.
278
+ - `@marwes-ui/react` and `@marwes-ui/vue` load this preset by default and render components.
59
279
 
60
280
  ## Scripts
61
- - `pnpm --filter @marwes-ui/presets dev`
62
- - `pnpm --filter @marwes-ui/presets build`
63
- - `pnpm --filter @marwes-ui/presets typecheck`
281
+
282
+ ```bash
283
+ pnpm --filter @marwes-ui/presets build
284
+ pnpm --filter @marwes-ui/presets typecheck
285
+ pnpm --filter @marwes-ui/presets test
286
+ ```
64
287
 
65
288
  ## Related Docs
66
- - `../../docs/PROJECT.md`
67
- - `../../docs/ARCHITECTURE.md`
68
- - `../../docs/ENGINEERING.md`
289
+
290
+ - [Docs index](https://github.com/niklas-westman/marwes/tree/main/docs)
291
+ - [Architecture](https://github.com/niklas-westman/marwes/blob/main/docs/reference/architecture.md)
292
+ - [Figma to Marwes](https://github.com/niklas-westman/marwes/blob/main/docs/guides/figma-to-marwes.md)
@@ -0,0 +1,21 @@
1
+ import '@fontsource/instrument-sans/400.css';
2
+ import '@fontsource/instrument-sans/500.css';
3
+ import '@fontsource/instrument-sans/600.css';
4
+
5
+ // src/firstEdition/index.ts
6
+ var firstEditionTheme = {
7
+ color: {
8
+ primary: {
9
+ base: "#2F31FC",
10
+ label: "#FFFFFF",
11
+ labelDisabled: "rgba(255,255,255,0.5)"
12
+ },
13
+ success: "#00875A"
14
+ },
15
+ font: { primary: "'Instrument Sans', Inter, system-ui, sans-serif" },
16
+ ui: { radius: 4, density: "comfortable" }
17
+ };
18
+
19
+ export { firstEditionTheme };
20
+ //# sourceMappingURL=chunk-2JNIKK66.js.map
21
+ //# sourceMappingURL=chunk-2JNIKK66.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/firstEdition/index.ts"],"names":[],"mappings":";;;;;AAOO,IAAM,iBAAA,GAAgC;AAAA,EAC3C,KAAA,EAAO;AAAA,IACL,OAAA,EAAS;AAAA,MACP,IAAA,EAAM,SAAA;AAAA,MACN,KAAA,EAAO,SAAA;AAAA,MACP,aAAA,EAAe;AAAA,KACjB;AAAA,IACA,OAAA,EAAS;AAAA,GACX;AAAA,EACA,IAAA,EAAM,EAAE,OAAA,EAAS,iDAAA,EAAkD;AAAA,EACnE,EAAA,EAAI,EAAE,MAAA,EAAQ,CAAA,EAAG,SAAS,aAAA;AAC5B","file":"chunk-2JNIKK66.js","sourcesContent":["import type { ThemeInput } from \"@marwes-ui/core\"\nimport \"@fontsource/instrument-sans/400.css\"\nimport \"@fontsource/instrument-sans/500.css\"\nimport \"@fontsource/instrument-sans/600.css\"\n\n// Explicit ThemeInput for consumers that still want to import the preset object.\n// MarwesProvider uses the same first edition baseline when no theme is provided.\nexport const firstEditionTheme: ThemeInput = {\n color: {\n primary: {\n base: \"#2F31FC\",\n label: \"#FFFFFF\",\n labelDisabled: \"rgba(255,255,255,0.5)\",\n },\n success: \"#00875A\",\n },\n font: { primary: \"'Instrument Sans', Inter, system-ui, sans-serif\" },\n ui: { radius: 4, density: \"comfortable\" },\n}\n"]}
@@ -1,5 +1,5 @@
1
- import { Preset } from '@marwes-ui/core';
1
+ import { ThemeInput } from '@marwes-ui/core';
2
2
 
3
- declare const firstEdition: Preset;
3
+ declare const firstEditionTheme: ThemeInput;
4
4
 
5
- export { firstEdition };
5
+ export { firstEditionTheme };
@@ -1,3 +1,3 @@
1
- export { firstEdition } from '../chunk-UJIVT75P.js';
1
+ export { firstEditionTheme } from '../chunk-2JNIKK66.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export { firstEdition } from './firstEdition/index.js';
2
- export { Preset } from '@marwes-ui/core';
1
+ export { firstEditionTheme } from './firstEdition/index.js';
2
+ export { ThemeInput } from '@marwes-ui/core';
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { firstEdition } from './chunk-UJIVT75P.js';
1
+ export { firstEditionTheme } from './chunk-2JNIKK66.js';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@marwes-ui/presets",
3
- "version": "0.0.4",
3
+ "version": "1.0.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
7
+ "license": "MIT",
7
8
  "private": false,
8
9
  "type": "module",
9
- "sideEffects": false,
10
+ "sideEffects": [
11
+ "*.css",
12
+ "**/*.css"
13
+ ],
10
14
  "main": "./dist/index.js",
11
15
  "types": "./dist/index.d.ts",
12
16
  "exports": {
@@ -22,22 +26,24 @@
22
26
  },
23
27
  "files": [
24
28
  "dist",
25
- "src/firstEdition/styles.css"
29
+ "src/firstEdition"
26
30
  ],
27
31
  "dependencies": {
28
- "@fontsource/instrument-sans": "^5.2.8",
29
- "@marwes-ui/core": "0.0.4"
32
+ "@fontsource/instrument-sans": "5.2.8",
33
+ "@marwes-ui/core": "1.0.1"
30
34
  },
31
35
  "devDependencies": {
32
- "rimraf": "^6.0.0",
33
- "tsup": "^8.0.0",
34
- "typescript": "^5.4.0"
36
+ "rimraf": "6.1.2",
37
+ "tsup": "8.5.1",
38
+ "typescript": "5.9.3",
39
+ "vitest": "4.0.18"
35
40
  },
36
41
  "scripts": {
37
42
  "dev": "tsup --watch",
38
43
  "build": "tsup",
39
44
  "typecheck": "tsc -p tsconfig.json --noEmit",
40
- "test": "echo \"No tests in @marwes-ui/presets\"",
45
+ "test:typecheck": "tsc -p tsconfig.test.json --noEmit",
46
+ "test": "vitest run",
41
47
  "clean": "rimraf dist",
42
48
  "lint": "biome lint .",
43
49
  "format": "biome format --write ."
@@ -0,0 +1,140 @@
1
+ /*
2
+ * Accordion Component Styles
3
+ * Validated against the latest live Figma sync:
4
+ * - .figma/marwes/components/accordion.json
5
+ * - .figma/marwes/pages/-accordion/-accordion_1364-11755.json
6
+ * - .figma/marwes/pages/-accordion/-accordion-dark_2276-47132.json
7
+ *
8
+ * Light state colors:
9
+ * default surface #ffffff
10
+ * hover surface #f3f4f6
11
+ * pressed surface #e5e7eb
12
+ * border #e5e7eb
13
+ * focus border #2f31fc
14
+ * title #141414
15
+ * icon/content #595959
16
+ * disabled text #737373
17
+ *
18
+ * Dark state colors:
19
+ * default surface #2e2e2e
20
+ * hover surface #595959
21
+ * pressed surface #737373
22
+ * border #474747
23
+ * focus border #5859fc
24
+ * title #f9fafb
25
+ * icon/content #a3a3a3
26
+ * disabled text #595959
27
+ */
28
+
29
+ .mw-accordion {
30
+ --mw-accordion-title: var(--mw-color-text);
31
+ --mw-accordion-icon: var(--mw-color-text-muted);
32
+ --mw-accordion-content: var(--mw-color-text-muted);
33
+ --mw-accordion-surface: var(--mw-color-surface-elevated);
34
+ --mw-accordion-surface-hover: var(--mw-color-surface-subtle);
35
+ --mw-accordion-surface-pressed: var(--mw-color-border-subtle);
36
+ --mw-accordion-border: var(--mw-color-border-subtle);
37
+ --mw-accordion-focus-border: var(--mw-color-focus, #2f31fc);
38
+ --mw-accordion-title-disabled: var(--mw-color-text-disabled);
39
+ --mw-accordion-icon-disabled: var(--mw-color-text-disabled);
40
+ --mw-accordion-content-disabled: var(--mw-color-text-disabled);
41
+
42
+ width: 100%;
43
+ background: var(--mw-accordion-surface);
44
+ border: 1px solid var(--mw-accordion-border);
45
+ border-radius: var(--mw-ui-radius, 6px);
46
+ overflow: hidden;
47
+ transition: background-color 150ms ease, border-color 150ms ease;
48
+ }
49
+
50
+ .mw-accordion__trigger {
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: space-between;
54
+ width: 100%;
55
+ padding: 16px;
56
+ border: none;
57
+ background: transparent;
58
+ cursor: pointer;
59
+ text-align: left;
60
+ gap: 8px;
61
+ }
62
+
63
+ .mw-accordion__title {
64
+ flex: 1;
65
+ font-family: var(--mw-font-primary, inherit);
66
+ font-size: var(--mw-density-font-size, 14px);
67
+ font-weight: 500;
68
+ line-height: 16px;
69
+ color: var(--mw-accordion-title);
70
+ }
71
+
72
+ .mw-accordion__icon {
73
+ display: inline-block;
74
+ flex-shrink: 0;
75
+ width: 16px;
76
+ height: 16px;
77
+ background-color: var(--mw-accordion-icon);
78
+ mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolyline fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' points='6 9 12 15 18 9'/%3E%3C/svg%3E");
79
+ -webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpolyline fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round' points='6 9 12 15 18 9'/%3E%3C/svg%3E");
80
+ mask-repeat: no-repeat;
81
+ mask-position: center;
82
+ mask-size: contain;
83
+ -webkit-mask-repeat: no-repeat;
84
+ -webkit-mask-position: center;
85
+ -webkit-mask-size: contain;
86
+ transition: transform 200ms ease;
87
+ }
88
+
89
+ .mw-accordion--open .mw-accordion__icon {
90
+ transform: rotate(180deg);
91
+ }
92
+
93
+ .mw-accordion:not(.mw-accordion--disabled):hover {
94
+ background: var(--mw-accordion-surface-hover);
95
+ }
96
+
97
+ .mw-accordion:not(.mw-accordion--disabled) .mw-accordion__trigger:active,
98
+ .mw-accordion:not(.mw-accordion--disabled) .mw-accordion__trigger:active + .mw-accordion__panel {
99
+ background: var(--mw-accordion-surface-pressed);
100
+ }
101
+
102
+ .mw-accordion:focus-within {
103
+ border-color: var(--mw-accordion-focus-border);
104
+ }
105
+
106
+ .mw-accordion__trigger:focus-visible {
107
+ outline: none;
108
+ }
109
+
110
+ .mw-accordion__content {
111
+ padding: 0 16px 16px;
112
+ font-family: var(--mw-font-primary, inherit);
113
+ font-size: var(--mw-density-font-size, 14px);
114
+ line-height: 20px;
115
+ color: var(--mw-accordion-content);
116
+ }
117
+
118
+ .mw-accordion--disabled {
119
+ --mw-accordion-title: var(--mw-accordion-title-disabled);
120
+ --mw-accordion-icon: var(--mw-accordion-icon-disabled);
121
+ --mw-accordion-content: var(--mw-accordion-content-disabled);
122
+ }
123
+
124
+ .mw-accordion--disabled .mw-accordion__trigger {
125
+ cursor: not-allowed;
126
+ }
127
+
128
+ .mw-theme--dark .mw-accordion {
129
+ --mw-accordion-title: var(--mw-color-text);
130
+ --mw-accordion-icon: var(--mw-color-text-muted);
131
+ --mw-accordion-content: var(--mw-color-text-muted);
132
+ --mw-accordion-surface: var(--mw-color-surface-elevated);
133
+ --mw-accordion-surface-hover: var(--mw-color-surface-subtle);
134
+ --mw-accordion-surface-pressed: var(--mw-color-border);
135
+ --mw-accordion-border: var(--mw-color-border-subtle);
136
+ --mw-accordion-focus-border: var(--mw-color-focus, #5859fc);
137
+ --mw-accordion-title-disabled: var(--mw-color-text-disabled);
138
+ --mw-accordion-icon-disabled: var(--mw-color-text-disabled);
139
+ --mw-accordion-content-disabled: var(--mw-color-text-disabled);
140
+ }