@ibis-design/css 0.9.0 → 1.0.0-alpha.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.
@@ -0,0 +1,314 @@
1
+ /* Navigation shell layout — import via @ibis-design/css/components/navShell.css */
2
+
3
+ /* NavDrawer */
4
+
5
+ .ib-nav-drawer {
6
+ display: flex;
7
+ flex-direction: column;
8
+ align-items: stretch;
9
+ width: 360px;
10
+ height: 100%;
11
+ min-height: 0;
12
+ padding: var(--spacing-4) var(--spacing-3);
13
+ background-color: var(--color-surface-default);
14
+ border-right: var(--border-width-thin) solid var(--border-color-subtle);
15
+ border-bottom-right-radius: var(--border-radius-xl);
16
+ box-shadow: var(--shadow-nav);
17
+ box-sizing: border-box;
18
+ }
19
+
20
+ .ib-nav-drawer__header {
21
+ display: flex;
22
+ align-items: flex-start;
23
+ justify-content: space-between;
24
+ flex-shrink: 0;
25
+ gap: var(--spacing-2);
26
+ margin-bottom: var(--spacing-6);
27
+ }
28
+
29
+ .ib-nav-drawer__logo {
30
+ display: flex;
31
+ align-items: center;
32
+ flex: 1 1 auto;
33
+ min-width: 0;
34
+ }
35
+
36
+ .ib-nav-drawer__logo-placeholder {
37
+ width: 40px;
38
+ height: 40px;
39
+ border-radius: var(--border-radius-full);
40
+ background: var(--gradient-brand-primary);
41
+ display: flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ color: var(--color-text-inverse);
45
+ font-family: var(--font-family-heading);
46
+ font-weight: var(--font-weight-bold);
47
+ font-size: var(--font-size-body-lg);
48
+ }
49
+
50
+ .ib-nav-drawer-logo-image {
51
+ height: 48px;
52
+ width: auto;
53
+ object-fit: contain;
54
+ }
55
+
56
+ .ib-nav-drawer__toggle {
57
+ display: flex;
58
+ flex-shrink: 0;
59
+ align-items: flex-start;
60
+ }
61
+
62
+ .ib-nav-drawer__content {
63
+ display: flex;
64
+ flex-direction: column;
65
+ justify-content: space-between;
66
+ flex: 1 1 auto;
67
+ min-height: 0;
68
+ }
69
+
70
+ .ib-nav-drawer__section-label {
71
+ margin: 0 0 var(--spacing-2);
72
+ padding: 0 var(--spacing-2);
73
+ font-family: var(--font-family-sans);
74
+ font-size: var(--font-size-body-sm);
75
+ font-weight: var(--font-weight-medium);
76
+ color: var(--color-text-muted);
77
+ }
78
+
79
+ .ib-nav-drawer__body {
80
+ display: flex;
81
+ flex-direction: column;
82
+ flex-shrink: 0;
83
+ gap: var(--spacing-2);
84
+ }
85
+
86
+ .ib-nav-drawer__footer {
87
+ display: flex;
88
+ flex-direction: column;
89
+ flex-shrink: 0;
90
+ gap: var(--spacing-1);
91
+ border-top: var(--border-width-thin) solid var(--border-color-subtle);
92
+ padding-top: var(--spacing-4);
93
+ margin-top: var(--spacing-4);
94
+ }
95
+
96
+ .ib-nav-drawer__footer-label {
97
+ margin: 0;
98
+ padding: 0 var(--spacing-2);
99
+ font-family: var(--font-family-sans);
100
+ font-size: var(--font-size-body-sm);
101
+ font-weight: var(--font-weight-medium);
102
+ color: var(--color-text-muted);
103
+ }
104
+
105
+ .ib-nav-drawer__footer-actions {
106
+ display: flex;
107
+ flex-direction: column;
108
+ gap: var(--spacing-2);
109
+ }
110
+
111
+ .ib-nav-drawer__meta {
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: var(--spacing-1);
115
+ padding: var(--spacing-3) var(--spacing-2) 0;
116
+ font-family: var(--font-family-sans);
117
+ font-size: var(--font-size-body-xs);
118
+ font-weight: var(--font-weight-normal);
119
+ color: var(--color-text-muted);
120
+ line-height: 1.4;
121
+ }
122
+
123
+ /* NavRail */
124
+
125
+ .ib-nav-rail {
126
+ display: flex;
127
+ flex-direction: column;
128
+ align-items: center;
129
+ width: 72px;
130
+ height: 100%;
131
+ min-height: 0;
132
+ padding: var(--spacing-4) 0;
133
+ background-color: var(--color-surface-default);
134
+ border-right: var(--border-width-thin) solid var(--border-color-subtle);
135
+ border-bottom-right-radius: var(--border-radius-xl);
136
+ box-shadow: var(--shadow-nav);
137
+ box-sizing: border-box;
138
+ overflow: visible;
139
+ }
140
+
141
+ .ib-nav-rail__header {
142
+ position: relative;
143
+ display: flex;
144
+ flex-direction: column;
145
+ align-items: center;
146
+ flex-shrink: 0;
147
+ width: 100%;
148
+ margin-bottom: var(--spacing-4);
149
+ overflow: visible;
150
+ }
151
+
152
+ .ib-nav-rail__logo {
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: center;
156
+ width: 100%;
157
+ }
158
+
159
+ .ib-nav-rail__logo-placeholder {
160
+ width: 40px;
161
+ height: 40px;
162
+ border-radius: var(--border-radius-full);
163
+ background: var(--gradient-brand-primary);
164
+ display: flex;
165
+ align-items: center;
166
+ justify-content: center;
167
+ color: var(--color-text-inverse);
168
+ font-family: var(--font-family-heading);
169
+ font-weight: var(--font-weight-bold);
170
+ font-size: var(--font-size-body-lg);
171
+ }
172
+
173
+ .ib-nav-rail-logo-image {
174
+ width: 40px;
175
+ height: 40px;
176
+ object-fit: contain;
177
+ }
178
+
179
+ .ib-nav-rail__toggle {
180
+ position: absolute;
181
+ top: 50%;
182
+ right: 0;
183
+ transform: translate(50%, -50%);
184
+ z-index: var(--z-index-overlay);
185
+ }
186
+
187
+ .ib-nav-rail__body {
188
+ display: flex;
189
+ flex-direction: column;
190
+ align-items: center;
191
+ flex: 1 1 auto;
192
+ min-height: 0;
193
+ width: 100%;
194
+ gap: var(--spacing-1);
195
+ padding: 0 var(--spacing-2);
196
+ box-sizing: border-box;
197
+ }
198
+
199
+ .ib-nav-rail__footer {
200
+ display: flex;
201
+ flex-direction: column;
202
+ align-items: center;
203
+ flex-shrink: 0;
204
+ width: 100%;
205
+ gap: var(--spacing-1);
206
+ margin-top: auto;
207
+ padding: var(--spacing-2) var(--spacing-2) 0;
208
+ box-sizing: border-box;
209
+ border-top: var(--border-width-thin) solid var(--border-color-subtle);
210
+ }
211
+
212
+ /* NavBottom */
213
+
214
+ .ib-nav-bottom {
215
+ display: flex;
216
+ flex-direction: row;
217
+ align-items: flex-end;
218
+ justify-content: space-around;
219
+ position: fixed;
220
+ bottom: 0;
221
+ inset-inline: 0;
222
+ z-index: var(--z-index-sticky);
223
+ padding: var(--spacing-2) var(--spacing-4);
224
+ padding-bottom: calc(var(--spacing-2) + env(safe-area-inset-bottom, 0px));
225
+ gap: var(--spacing-1);
226
+ background-color: var(--color-surface-default);
227
+ border-top: var(--border-width-thin) solid var(--border-color-default);
228
+ box-shadow: var(--shadow-elevation-md);
229
+ box-sizing: border-box;
230
+ }
231
+
232
+ /* Toggle Button */
233
+
234
+ .ib-nav-shell-toggle {
235
+ all: unset;
236
+ box-sizing: border-box;
237
+ display: inline-flex;
238
+ align-items: center;
239
+ justify-content: center;
240
+ padding: var(--spacing-1);
241
+ border-radius: var(--border-radius-md);
242
+ color: var(--color-text-muted);
243
+ cursor: pointer;
244
+ background: transparent;
245
+ border: none;
246
+ outline: none;
247
+ transition:
248
+ background-color var(--transition-duration-fast) var(--transition-timing-default),
249
+ color var(--transition-duration-fast) var(--transition-timing-default);
250
+ }
251
+
252
+ .ib-nav-shell-toggle:hover {
253
+ background-color: var(--color-interactive-neutral-bg-hover);
254
+ color: var(--color-text-primary);
255
+ }
256
+
257
+ .ib-nav-shell-toggle svg {
258
+ width: 20px;
259
+ height: 20px;
260
+ display: block;
261
+ overflow: visible;
262
+ }
263
+
264
+ .ib-nav-shell-toggle svg path {
265
+ stroke: currentColor;
266
+ }
267
+
268
+ /* Icon Animations */
269
+
270
+ .ib-nav-rail-icon {
271
+ display: flex;
272
+ align-items: center;
273
+ justify-content: center;
274
+ transition: transform var(--transition-duration-normal) var(--transition-timing-default);
275
+ transform: scale(1);
276
+ }
277
+
278
+ .ib-nav-rail-icon--selected {
279
+ transform: scale(1.15);
280
+ }
281
+
282
+ .ib-nav-drawer-icon {
283
+ display: flex;
284
+ align-items: center;
285
+ justify-content: center;
286
+ transition: transform var(--transition-duration-normal) var(--transition-timing-default);
287
+ transform: scale(1);
288
+ }
289
+
290
+ .ib-nav-drawer-icon--selected {
291
+ transform: scale(1.15);
292
+ }
293
+
294
+ .ib-nav-bottom-icon {
295
+ display: flex;
296
+ align-items: center;
297
+ justify-content: center;
298
+ transition: transform var(--transition-duration-normal) var(--transition-timing-default);
299
+ transform: scale(1);
300
+ }
301
+
302
+ .ib-nav-bottom-icon--selected {
303
+ transform: scale(1.15);
304
+ }
305
+
306
+ /* Sign Out Button */
307
+
308
+ .ib-nav-signout:not(:disabled):hover {
309
+ background-color: color-mix(
310
+ in srgb,
311
+ var(--color-status-error) calc(var(--opacity-5) * 100%),
312
+ transparent
313
+ );
314
+ }
@@ -0,0 +1,52 @@
1
+ /* Top bar — import via @ibis-design/css/components/topBar.css */
2
+
3
+ .ib-top-bar {
4
+ position: relative;
5
+ width: 100%;
6
+ height: 96px;
7
+ display: flex;
8
+ flex-direction: row;
9
+ align-items: center;
10
+ justify-content: space-between;
11
+ background-color: var(--color-surface-default);
12
+ border-bottom: var(--border-width-thin) solid var(--border-color-subtle);
13
+ box-shadow: 0 1px 8px 0 var(--shadow-color-black-soft);
14
+ z-index: var(--z-index-sticky);
15
+ box-sizing: border-box;
16
+ padding: 0 var(--spacing-6);
17
+ gap: var(--spacing-4);
18
+ flex-shrink: 0;
19
+ }
20
+
21
+ .ib-top-bar__left {
22
+ display: flex;
23
+ flex-direction: row;
24
+ align-items: center;
25
+ gap: var(--spacing-3);
26
+ flex-shrink: 0;
27
+ }
28
+
29
+ .ib-top-bar__title {
30
+ font-family: var(--font-family-heading);
31
+ font-size: var(--font-size-heading-h4);
32
+ font-weight: var(--font-weight-bold);
33
+ color: var(--color-text-primary);
34
+ margin: 0;
35
+ }
36
+
37
+ .ib-top-bar__right {
38
+ display: flex;
39
+ flex-direction: row;
40
+ align-items: center;
41
+ gap: var(--spacing-3);
42
+ flex-shrink: 0;
43
+ }
44
+
45
+ .ib-top-bar__search {
46
+ width: 200px;
47
+ }
48
+
49
+ .ib-top-bar__search .ibis-input {
50
+ max-width: 100%;
51
+ width: 100%;
52
+ }
@@ -1,8 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly. Generated by @ibis-design/css build.
3
- * Set data-brand (ib | alc) and data-color-mode (light | dark) on <html>,
4
- * or use setTheme() from @ibis-design/css/theme.
5
- * :root holds global tokens; :root + [data-brand="ib"][data-color-mode="light"] is the default theme overlay.
3
+ * Set data-brand (ib | alc) and data-color-mode (light | dark) on <html>, or use setTheme() from @ibis-design/css/theme. :root holds global tokens; :root + [data-brand="ib"][data-color-mode="light"] is the default theme overlay.
6
4
  */
7
5
 
8
6
  /**
@@ -130,6 +128,7 @@
130
128
  --shadow-focus-default: 0 0 0 4px var(--shadow-color-black-soft);
131
129
  --shadow-focus-primary: 0 0 0 4px var(--shadow-color-brand-soft);
132
130
  --shadow-focus-error: 0 0 0 4px var(--shadow-color-black-medium);
131
+ --shadow-nav: 0 0 8px 0 var(--shadow-color-black-soft);
133
132
  }
134
133
 
135
134
  /**
@@ -189,7 +188,7 @@
189
188
  --font-size-heading-h1: 4.188rem;
190
189
  --font-size-heading-h2: 3.188rem;
191
190
  --font-size-heading-h3: 2.375rem;
192
- --font-size-heading-h4: 1.75rem;
191
+ --font-size-heading-h4: 1.750rem;
193
192
  --font-size-heading-h5: 1.312rem;
194
193
  --border-radius-none: 0;
195
194
  --border-radius-xs: 0.25rem;
@@ -306,7 +305,7 @@
306
305
  --font-size-heading-h1: 4.188rem;
307
306
  --font-size-heading-h2: 3.188rem;
308
307
  --font-size-heading-h3: 2.375rem;
309
- --font-size-heading-h4: 1.75rem;
308
+ --font-size-heading-h4: 1.750rem;
310
309
  --font-size-heading-h5: 1.312rem;
311
310
  --border-radius-none: 0;
312
311
  --border-radius-xs: 0.25rem;
@@ -218,7 +218,8 @@ module.exports = {
218
218
  default: "var(--shadow-focus-default)",
219
219
  primary: "var(--shadow-focus-primary)",
220
220
  error: "var(--shadow-focus-error)"
221
- }
221
+ },
222
+ nav: "var(--shadow-nav)"
222
223
  },
223
224
  color: {
224
225
  primary: {
package/package.json CHANGED
@@ -1,33 +1,34 @@
1
- {
2
- "name": "@ibis-design/css",
3
- "version": "0.9.0",
4
- "description": "Design tokens, CSS variables, and Tailwind preset for the IBIS design system.",
5
- "type": "module",
6
- "exports": {
7
- ".": "./dist/design-tokens.css",
8
- "./design-tokens.css": "./dist/design-tokens.css",
9
- "./tailwind.preset": "./dist/tailwind.preset.js",
10
- "./preset": "./dist/tailwind.preset.js",
11
- "./ibis-design.css": "./dist/design-tokens.css",
12
- "./alchemy-design.css": "./dist/design-tokens.css",
13
- "./ibis/tailwind.preset": "./dist/tailwind.preset.js",
14
- "./alchemy/tailwind.preset": "./dist/tailwind.preset.js",
15
- "./components/*": "./dist/components/*",
16
- "./tailwind.theme": "./dist/tailwind.theme.js",
17
- "./theme": "./src/lib/set-theme.ts"
18
- },
19
- "files": [
20
- "dist",
21
- "src/lib"
22
- ],
23
- "scripts": {
24
- "build": "tsx src/scripts/build.ts && tsx src/scripts/validate-themes.ts && tsx src/scripts/validate-component-tokens.ts",
25
- "validate": "tsx src/scripts/validate-themes.ts && tsx src/scripts/validate-component-tokens.ts",
26
- "prepublishOnly": "npm run build"
27
- },
28
- "devDependencies": {
29
- "sd-tailwindcss-transformer": "^2.2.1",
30
- "style-dictionary": "^5.4.1",
31
- "tsx": "^4.22.3"
32
- }
33
- }
1
+ {
2
+ "name": "@ibis-design/css",
3
+ "version": "1.0.0-alpha.0",
4
+ "description": "Design tokens, CSS variables, and Tailwind preset for the IBIS design system.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./dist/design-tokens.css",
8
+ "./design-tokens.css": "./dist/design-tokens.css",
9
+ "./bootstrap-overrides.css": "./dist/bootstrap-overrides.css",
10
+ "./tailwind.preset": "./dist/tailwind.preset.js",
11
+ "./preset": "./dist/tailwind.preset.js",
12
+ "./ibis-design.css": "./dist/design-tokens.css",
13
+ "./alchemy-design.css": "./dist/design-tokens.css",
14
+ "./ibis/tailwind.preset": "./dist/tailwind.preset.js",
15
+ "./alchemy/tailwind.preset": "./dist/tailwind.preset.js",
16
+ "./components/*": "./dist/components/*",
17
+ "./tailwind.theme": "./dist/tailwind.theme.js",
18
+ "./theme": "./src/lib/set-theme.ts"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "src/lib"
23
+ ],
24
+ "scripts": {
25
+ "build": "tsx src/scripts/build.ts && tsx src/scripts/validate-themes.ts && tsx src/scripts/validate-bootstrap-themes.ts && tsx src/scripts/validate-component-tokens.ts",
26
+ "validate": "tsx src/scripts/validate-themes.ts && tsx src/scripts/validate-bootstrap-themes.ts && tsx src/scripts/validate-component-tokens.ts",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "devDependencies": {
30
+ "sd-tailwindcss-transformer": "^2.2.1",
31
+ "style-dictionary": "^5.4.3",
32
+ "tsx": "^4.22.4"
33
+ }
34
+ }
@@ -0,0 +1,23 @@
1
+ import { BOOTSTRAP_VAR_MAP } from "../config/bootstrap-map.ts";
2
+ import { THEMES } from "./themes.ts";
3
+
4
+ /**
5
+ * Builds Bootstrap 5.3 override CSS that maps `--bs-*` vars to IBIS semantic tokens.
6
+ */
7
+ export const assembleBootstrapOverridesStylesheet = (): string => {
8
+ const blocks = THEMES.map((theme) => {
9
+ const lines = BOOTSTRAP_VAR_MAP.map(
10
+ ({ ibisVar, bootstrapVar }) => ` ${bootstrapVar}: var(${ibisVar});`,
11
+ );
12
+ return `${theme.cssSelector} {\n${lines.join("\n")}\n}`;
13
+ });
14
+
15
+ return `/**
16
+ * Do not edit directly. Generated by @ibis-design/css build.
17
+ * Load after Bootstrap CSS and @ibis-design/css design tokens.
18
+ * IBIS theme selectors set --bs-* vars from semantic --color-* / --font-* tokens.
19
+ */
20
+
21
+ ${blocks.join("\n\n")}
22
+ `;
23
+ };
@@ -1,8 +1,12 @@
1
1
  /**
2
2
  * @param blocks - Formatted CSS blocks from Style Dictionary (one per global/theme layer).
3
- * @returns Full design-tokens stylesheet with header comment.
3
+ * @param description - Optional header description line.
4
+ * @returns Full stylesheet with header comment.
4
5
  */
5
- export const assembleDesignTokensStylesheet = (blocks: string[]): string => {
6
+ export const assembleDesignTokensStylesheet = (
7
+ blocks: string[],
8
+ description = "Set data-brand (ib | alc) and data-color-mode (light | dark) on <html>, or use setTheme() from @ibis-design/css/theme. :root holds global tokens; :root + [data-brand=\"ib\"][data-color-mode=\"light\"] is the default theme overlay.",
9
+ ): string => {
6
10
  const body = blocks
7
11
  .map((block) => block.trim())
8
12
  .filter(Boolean)
@@ -10,9 +14,7 @@ export const assembleDesignTokensStylesheet = (blocks: string[]): string => {
10
14
 
11
15
  return `/**
12
16
  * Do not edit directly. Generated by @ibis-design/css build.
13
- * Set data-brand (ib | alc) and data-color-mode (light | dark) on <html>,
14
- * or use setTheme() from @ibis-design/css/theme.
15
- * :root holds global tokens; :root + [data-brand="ib"][data-color-mode="light"] is the default theme overlay.
17
+ * ${description}
16
18
  */
17
19
 
18
20
  ${body}
@@ -21,6 +21,8 @@ export {
21
21
  export type ThemeOptions = {
22
22
  brand?: BrandId;
23
23
  colorMode?: ColorModeId;
24
+ /** When true, also sets `data-bs-theme` on `<html>` for Bootstrap 5.3 components. */
25
+ syncBootstrapTheme?: boolean;
24
26
  };
25
27
 
26
28
  const isBrandId = (value: string): value is BrandId => value === "ib" || value === "alc";
@@ -44,6 +46,10 @@ export const setTheme = (options: ThemeOptions = {}): ThemeId => {
44
46
  root.dataset.brand = brand;
45
47
  root.dataset.colorMode = colorMode;
46
48
  delete root.dataset.theme;
49
+
50
+ if (options.syncBootstrapTheme) {
51
+ root.dataset.bsTheme = colorMode;
52
+ }
47
53
  }
48
54
 
49
55
  return toThemeId(brand, colorMode);