odt-ui-rails 2.0.1 → 2.2.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,126 @@
1
+ /*
2
+ * odt_ui/theme.css
3
+ *
4
+ * Tailwind CSS v4 @theme configuration for ODT Design Tokens.
5
+ *
6
+ * Usage in application.tailwind.css / application.css:
7
+ * @import "tailwindcss";
8
+ * @import "odt_ui/tokens.css";
9
+ * @import "odt_ui/styles.css";
10
+ * @import "odt_ui/theme.css";
11
+ */
12
+
13
+ @theme {
14
+ /* Primary Colors */
15
+ --color-primary-0: hsl(240 78.3% 100%);
16
+ --color-primary-50: hsl(240 78.3% 95%);
17
+ --color-primary-100: hsl(240 78.3% 90%);
18
+ --color-primary-200: hsl(240 78.3% 85%);
19
+ --color-primary-300: hsl(240 78.3% 80%);
20
+ --color-primary-400: hsl(240 78.3% 75%);
21
+ --color-primary-500: hsl(240 78.3% 65%);
22
+ --color-primary-600: hsl(240 78.3% 60%);
23
+ --color-primary-700: hsl(240 78.3% 55%);
24
+ --color-primary-800: hsl(240 78.3% 45%);
25
+ --color-primary-900: hsl(240 78.3% 34.3%);
26
+
27
+ /* Secondary Colors */
28
+ --color-secondary-0: hsl(47 100% 100%);
29
+ --color-secondary-50: hsl(47 100% 95%);
30
+ --color-secondary-100: hsl(47 100% 85%);
31
+ --color-secondary-200: hsl(47 100% 80%);
32
+ --color-secondary-300: hsl(47 100% 75%);
33
+ --color-secondary-400: hsl(47 100% 70%);
34
+ --color-secondary-500: hsl(47 100% 65%);
35
+ --color-secondary-600: hsl(47 100% 60%);
36
+ --color-secondary-700: hsl(47 100% 55%);
37
+ --color-secondary-800: hsl(47 100% 50%);
38
+ --color-secondary-900: hsl(47 100% 45%);
39
+
40
+ /* Neutral Palette */
41
+ --color-neutral-0: hsl(0 0% 100%);
42
+ --color-neutral-50: hsl(240 10% 98%);
43
+ --color-neutral-100: hsl(240 10% 96%);
44
+ --color-neutral-200: hsl(240 9% 90%);
45
+ --color-neutral-300: hsl(240 8% 82%);
46
+ --color-neutral-400: hsl(240 8% 64%);
47
+ --color-neutral-500: hsl(240 7% 46%);
48
+ --color-neutral-600: hsl(240 7% 32%);
49
+ --color-neutral-700: hsl(240 8% 25%);
50
+ --color-neutral-800: hsl(240 10% 15%);
51
+ --color-neutral-900: hsl(240 12% 9%);
52
+ --color-neutral-950: hsl(240 14% 4%);
53
+
54
+ /* Semantic Colors */
55
+ --color-success: hsl(142 71% 45%);
56
+ --color-success-subtle: hsl(142 71% 96%);
57
+ --color-warning: hsl(38 92% 50%);
58
+ --color-warning-subtle: hsl(38 92% 96%);
59
+ --color-danger: hsl(0 84% 60%);
60
+ --color-danger-subtle: hsl(0 84% 97%);
61
+ --color-info: hsl(217 91% 60%);
62
+ --color-info-subtle: hsl(217 91% 97%);
63
+
64
+ /* Surfaces & Backgrounds */
65
+ --color-surface-base: hsl(0 0% 100%);
66
+ --color-surface: hsl(0 0% 100%);
67
+ --color-surface-muted: hsl(240 10% 98%);
68
+ --color-surface-subtle: hsl(240 10% 96%);
69
+ --color-surface-elevated: hsl(240 10% 98%);
70
+ --color-surface-primary: hsl(240 78.3% 65%);
71
+ --color-surface-secondary: hsl(47 100% 65%);
72
+ --color-surface-success: hsl(142 71% 96%);
73
+ --color-surface-warning: hsl(38 92% 96%);
74
+ --color-surface-danger: hsl(0 84% 97%);
75
+ --color-surface-info: hsl(217 91% 97%);
76
+
77
+ /* Foregrounds */
78
+ --color-fg-strong: hsl(240 10% 15%);
79
+ --color-fg: hsl(240 8% 25%);
80
+ --color-fg-muted: hsl(240 7% 46%);
81
+ --color-fg-subtle: hsl(240 8% 64%);
82
+ --color-fg-disabled: hsl(240 8% 82%);
83
+
84
+ --color-fg-inverse-strong: hsl(0 0% 100%);
85
+ --color-fg-inverse: hsl(240 10% 98%);
86
+ --color-fg-inverse-muted: hsl(240 10% 96%);
87
+ --color-fg-inverse-subtle: hsl(240 8% 82%);
88
+ --color-fg-inverse-disabled: hsl(240 8% 64%);
89
+
90
+ --color-fg-primary: hsl(240 78.3% 34.3%);
91
+ --color-fg-secondary: hsl(47 100% 45%);
92
+
93
+ --color-fg-success: hsl(142 71% 45%);
94
+ --color-fg-warning: hsl(38 92% 50%);
95
+ --color-fg-danger: hsl(0 84% 60%);
96
+ --color-fg-info: hsl(217 91% 60%);
97
+
98
+ --color-ring: hsl(240 78.3% 65%);
99
+
100
+ /* Lines & Borders */
101
+ --color-line: hsl(240 9% 90%);
102
+ --color-line-muted: hsl(240 10% 96%);
103
+ --color-line-strong: hsl(240 8% 82%);
104
+ --color-line-primary: hsl(240 78.3% 65%);
105
+ --color-line-success: hsl(142 71% 45%);
106
+ --color-line-warning: hsl(38 92% 50%);
107
+ --color-line-danger: hsl(0 84% 60%);
108
+
109
+ /* Radius */
110
+ --radius-xs: 0.125rem;
111
+ --radius-sm: 0.25rem;
112
+ --radius-md: 0.375rem;
113
+ --radius-lg: 0.5rem;
114
+ --radius-xl: 0.75rem;
115
+ --radius-2xl: 1rem;
116
+ --radius-3xl: 1.5rem;
117
+ --radius-4xl: 2rem;
118
+ --radius-full: 9999px;
119
+
120
+ /* Shadows */
121
+ --color-shadow: hsl(240 78.3% 70%);
122
+ --shadow-card: 0 8px 26px hsl(240 78.3% 70% / 0.10);
123
+ --shadow-dropdown: 0 8px 24px hsl(240 78.3% 70% / 0.12);
124
+ --shadow-modal: 0 16px 40px hsl(240 78.3% 70% / 0.16);
125
+ --shadow-popover: 0 24px 64px hsl(240 78.3% 70% / 0.20);
126
+ }
@@ -86,16 +86,44 @@
86
86
  --color-fg-danger: var(--color-danger);
87
87
  --color-fg-info: var(--color-info);
88
88
 
89
+ /* ==========================================================================
90
+ * Button & Solid Controls Foreground (Text & Icon on Solid Controls)
91
+ * ========================================================================== */
92
+ --color-btn-primary-fg: hsl(0 0% 100%);
93
+ --color-btn-secondary-fg: hsl(224 25% 6%);
94
+ --color-btn-surface-fg: var(--color-fg-strong);
95
+ --color-btn-muted-fg: var(--color-fg);
96
+ --color-btn-inverse-fg: var(--color-surface);
97
+ --color-btn-success-fg: hsl(0 0% 100%);
98
+ --color-btn-warning-fg: var(--color-fg-strong);
99
+ --color-btn-danger-fg: hsl(0 0% 100%);
100
+ --color-btn-info-fg: hsl(0 0% 100%);
101
+
102
+ /* Badge Foreground */
103
+ --color-badge-primary-fg: var(--color-btn-primary-fg);
104
+ --color-badge-secondary-fg: var(--color-btn-secondary-fg);
105
+ --color-badge-success-fg: var(--color-btn-success-fg);
106
+ --color-badge-warning-fg: var(--color-btn-warning-fg);
107
+ --color-badge-danger-fg: var(--color-btn-danger-fg);
108
+ --color-badge-info-fg: var(--color-btn-info-fg);
109
+ --color-badge-neutral-fg: var(--color-neutral-0);
110
+
111
+ /* Control (Checkbox / Radio / Switch) Tokens */
112
+ --color-control-checked-fg: hsl(0 0% 100%);
113
+ --color-control-checked-dark-fg: hsl(224 25% 6%);
114
+ --color-switch-thumb: var(--color-neutral-0);
115
+
89
116
  /* ==========================================================================
90
117
  * Focus Ring
91
118
  * ========================================================================== */
92
- --color-ring: var(--color-primary-500);
119
+ --color-ring: var(--color-primary-300);
93
120
  }
94
121
 
95
122
  :root {
96
123
  /* ==========================================================================
97
124
  * Surfaces & Backgrounds
98
125
  * ========================================================================== */
126
+ --color-surface-base: var(--color-surface);
99
127
  --color-surface: var(--color-neutral-0);
100
128
  --color-surface-muted: var(--color-neutral-50);
101
129
  --color-surface-subtle: var(--color-neutral-100);
@@ -253,50 +281,165 @@
253
281
  :root[data-theme="dark"],
254
282
  [data-theme="dark"],
255
283
  .dark {
256
- /* Foreground Hierarchy (Auto Swapped to Inverse for Dark Theme) */
257
- --color-fg-strong: var(--color-neutral-0);
258
- --color-fg: var(--color-neutral-100);
259
- --color-fg-muted: var(--color-neutral-400);
260
- --color-fg-subtle: var(--color-neutral-500);
261
- --color-fg-disabled: var(--color-neutral-600);
262
-
263
- /* Brand Foregrounds on Dark */
264
- --color-fg-primary: var(--color-primary-400);
265
- --color-fg-secondary: var(--color-secondary-400);
266
-
267
- /* Surfaces on Dark */
268
- --color-surface: var(--color-neutral-900);
269
- --color-surface-elevated: var(--color-neutral-800);
270
- --color-surface-muted: var(--color-neutral-950);
271
- --color-surface-subtle: var(--color-neutral-850, hsl(240 10% 15%));
272
-
273
- /* Lines & Borders on Dark */
274
- --color-line: var(--color-neutral-800);
275
- --color-line-muted: var(--color-neutral-850, hsl(240 10% 12%));
276
- --color-line-strong: var(--color-neutral-700);
277
-
278
- /* Shadows on Dark */
279
- --color-shadow: hsl(240 12% 4%);
280
- --shadow-card: 0 8px 26px rgba(0, 0, 0, 0.45);
281
- --shadow-dropdown: 0 8px 24px rgba(0, 0, 0, 0.55);
282
- --shadow-modal: 0 16px 40px rgba(0, 0, 0, 0.70);
283
- --shadow-popover: 0 24px 64px rgba(0, 0, 0, 0.85);
284
-
285
- /* Overlays on Dark */
286
- --color-overlay-light: rgba(255, 255, 255, 0.1);
287
- --color-overlay-dark: rgba(0, 0, 0, 0.7);
288
-
289
- /* Frosted Glass on Dark */
290
- --frosted-surface-bg: rgba(24, 24, 38, 0.65);
291
- --frosted-surface-border: rgba(255, 255, 255, 0.12);
292
- --frosted-muted-bg: rgba(11, 11, 20, 0.65);
293
- --frosted-muted-border: rgba(255, 255, 255, 0.08);
294
- --frosted-subtle-bg: rgba(36, 36, 52, 0.65);
295
- --frosted-subtle-border: rgba(255, 255, 255, 0.15);
296
- --frosted-gradient-primary: linear-gradient(to bottom right, rgba(79, 70, 229, 0.25), rgba(24, 24, 38, 0.75));
297
- --frosted-gradient-secondary: linear-gradient(to bottom right, rgba(234, 179, 8, 0.2), rgba(24, 24, 38, 0.75));
298
-
299
- /* Card Gradients on Dark */
300
- --gradient-card: linear-gradient(to bottom, hsl(240 78.3% 20% / 0.4), var(--color-neutral-900));
284
+ /* ==========================================================================
285
+ * Primary Brand Colors (Dark Scale)
286
+ * ========================================================================== */
287
+ --color-primary-0: hsl(240 78.3% 10%);
288
+ --color-primary-50: hsla(240, 78.3%, 65%, 0.18);
289
+ --color-primary-100: hsla(240, 78.3%, 65%, 0.28);
290
+ --color-primary-200: hsl(240 78.3% 34.3%);
291
+ --color-primary-300: hsl(240 78.3% 45%);
292
+ --color-primary-400: hsl(240 78.3% 55%);
293
+ --color-primary-500: hsl(240 78.3% 65%);
294
+ --color-primary-600: hsl(240 78.3% 72%);
295
+ --color-primary-700: hsl(240 78.3% 80%);
296
+ --color-primary-800: hsl(240 78.3% 88%);
297
+ --color-primary-900: hsl(240 78.3% 96%);
298
+
299
+ /* ==========================================================================
300
+ * Secondary Brand Colors (Dark Scale)
301
+ * ========================================================================== */
302
+ --color-secondary-0: hsl(47 100% 10%);
303
+ --color-secondary-50: hsla(47, 100%, 60%, 0.16);
304
+ --color-secondary-100: hsla(47, 100%, 60%, 0.25);
305
+ --color-secondary-200: hsl(47 100% 30%);
306
+ --color-secondary-300: hsl(47 100% 40%);
307
+ --color-secondary-400: hsl(47 100% 50%);
308
+ --color-secondary-500: hsl(47 100% 60%);
309
+ --color-secondary-600: hsl(47 100% 68%);
310
+ --color-secondary-700: hsl(47 100% 75%);
311
+ --color-secondary-800: hsl(47 100% 82%);
312
+ --color-secondary-900: hsl(47 100% 90%);
313
+
314
+ /* ==========================================================================
315
+ * Neutral Palette (Dark Scale)
316
+ * ========================================================================== */
317
+ --color-neutral-0: hsl(224 25% 6%);
318
+ --color-neutral-50: hsl(224 20% 10%);
319
+ --color-neutral-100: hsl(224 16% 15%);
320
+ --color-neutral-200: hsl(224 14% 18%);
321
+ --color-neutral-300: hsl(224 14% 26%);
322
+ --color-neutral-400: hsl(215 14% 48%);
323
+ --color-neutral-500: hsl(215 16% 62%);
324
+ --color-neutral-600: hsl(215 18% 74%);
325
+ --color-neutral-700: hsl(215 20% 84%);
326
+ --color-neutral-800: hsl(215 22% 92%);
327
+ --color-neutral-900: hsl(215 24% 97%);
328
+ --color-neutral-950: hsl(0 0% 100%);
329
+
330
+ /* ==========================================================================
331
+ * Semantic Colors
332
+ * ========================================================================== */
333
+ --color-success: hsl(142 71% 45%);
334
+ --color-warning: hsl(38 92% 58%);
335
+ --color-danger: hsl(0 78% 64%);
336
+ --color-info: hsl(217 91% 64%);
337
+
338
+ /* Semantic surface tint */
339
+ --color-surface-success: hsl(152 68% 12%);
340
+ --color-surface-warning: hsl(38 92% 13%);
341
+ --color-surface-danger: hsl(0 78% 14%);
342
+ --color-surface-info: hsl(217 91% 14%);
343
+
344
+ /* ==========================================================================
345
+ * Surfaces & Backgrounds
346
+ * ========================================================================== */
347
+ --color-surface-base: var(--color-surface-elevated);
348
+ --color-surface: var(--color-neutral-0);
349
+ --color-surface-elevated: var(--color-neutral-50);
350
+ --color-surface-muted: hsl(224 22% 8%);
351
+ --color-surface-subtle: var(--color-neutral-100);
352
+ --color-surface-primary: var(--color-primary-500);
353
+ --color-surface-secondary: var(--color-secondary-500);
354
+
355
+ /* ==========================================================================
356
+ * Foreground (Text & Icon)
357
+ * ========================================================================== */
358
+ --color-fg-strong: var(--color-neutral-900);
359
+ --color-fg: var(--color-neutral-700);
360
+ --color-fg-muted: var(--color-neutral-500);
361
+ --color-fg-subtle: var(--color-neutral-400);
362
+ --color-fg-disabled: hsl(215 12% 32%);
363
+
364
+ /* Inverse */
365
+ --color-fg-inverse-strong: var(--color-neutral-0);
366
+ --color-fg-inverse: var(--color-neutral-50);
367
+ --color-fg-inverse-muted: var(--color-neutral-100);
368
+ --color-fg-inverse-subtle: var(--color-neutral-300);
369
+ --color-fg-inverse-disabled: var(--color-neutral-400);
370
+
371
+ /* Brand Foreground */
372
+ --color-fg-primary: var(--color-primary-600);
373
+ --color-fg-secondary: var(--color-secondary-600);
374
+
375
+ /* Semantic Foreground */
376
+ --color-fg-success: var(--color-success);
377
+ --color-fg-warning: var(--color-warning);
378
+ --color-fg-danger: var(--color-danger);
379
+ --color-fg-info: var(--color-info);
380
+
381
+ /* Focus Ring */
382
+ --color-ring: hsl(240, 42%, 39%);
383
+
384
+ /* ==========================================================================
385
+ * Borders & Lines
386
+ * ========================================================================== */
387
+ --color-line: var(--color-neutral-200);
388
+ --color-line-muted: var(--color-neutral-100);
389
+ --color-line-strong: hsl(224, 44%, 27%);
390
+
391
+ --color-line-primary: var(--color-primary-500);
392
+ --color-line-success: var(--color-success);
393
+ --color-line-warning: var(--color-warning);
394
+ --color-line-danger: var(--color-danger);
395
+
396
+ /* ==========================================================================
397
+ * Shadows & Depth Elevations
398
+ * ========================================================================== */
399
+ --color-shadow: hsl(0 0% 0%);
400
+
401
+ --shadow-card: 0 8px 26px hsl(0 0% 0% / 0.50);
402
+ --shadow-dropdown: 0 8px 24px hsl(0 0% 0% / 0.60);
403
+ --shadow-modal: 0 16px 40px hsl(0 0% 0% / 0.70);
404
+ --shadow-popover: 0 24px 64px hsl(0 0% 0% / 0.80);
405
+
406
+ /* ==========================================================================
407
+ * Gradients
408
+ * ========================================================================== */
409
+ --gradient-subtle: linear-gradient(to top right, var(--color-primary-50), var(--color-primary-0) 60%, var(--color-secondary-50));
410
+ --gradient-hero-primary: var(--gradient-subtle);
411
+
412
+ /* Vibrant accent gradient */
413
+ --gradient-vibrant: linear-gradient(to top right, var(--color-primary-200), var(--color-primary-50) 50%, var(--color-secondary-100));
414
+ --gradient-hero-vibrant: var(--gradient-vibrant);
415
+
416
+ /* Card surface gradients */
417
+ --gradient-card: linear-gradient(to bottom, hsla(240, 78.3%, 65%, 0.25), var(--color-neutral-50));
418
+ --gradient-primary-to-white: linear-gradient(to bottom, var(--color-primary-50), var(--color-surface));
419
+ --gradient-secondary-to-white: linear-gradient(to bottom, var(--color-secondary-50), var(--color-surface));
420
+ --gradient-primary-h: linear-gradient(to right, var(--color-primary-50), var(--color-surface));
421
+ --gradient-secondary-h: linear-gradient(to right, var(--color-secondary-50), var(--color-surface));
422
+
423
+ /* ==========================================================================
424
+ * Button & Solid Controls Foreground
425
+ * ========================================================================== */
426
+ --color-btn-surface-fg: var(--color-fg-strong);
427
+ --color-btn-muted-fg: var(--color-fg);
428
+ --color-btn-inverse-fg: var(--color-surface);
429
+ --color-btn-warning-fg: hsl(224 25% 6%);
430
+ --color-badge-neutral-fg: var(--color-neutral-0);
431
+ --color-switch-thumb: hsl(0 0% 100%);
432
+
433
+ /* ==========================================================================
434
+ * Frosted Glass Tokens
435
+ * ========================================================================== */
436
+ --frosted-surface-bg: hsl(224 25% 6% / 0.60);
437
+ --frosted-surface-border: hsl(224 14% 26% / 0.70);
438
+ --frosted-muted-bg: hsl(224 22% 8% / 0.60);
439
+ --frosted-muted-border: hsl(224 22% 8% / 0.70);
440
+ --frosted-subtle-bg: hsl(224 16% 15% / 0.60);
441
+ --frosted-subtle-border: hsl(224 16% 15% / 0.70);
442
+ --frosted-gradient-primary: linear-gradient(to bottom right, hsla(240, 78.3%, 65%, 0.18), hsl(224 25% 6% / 0.60));
443
+ --frosted-gradient-secondary: linear-gradient(to bottom right, hsla(47, 100%, 60%, 0.16), hsl(224 25% 6% / 0.60));
301
444
  }
302
445
 
@@ -5,10 +5,11 @@ require "rails/generators/base"
5
5
  module Odt
6
6
  module Generators
7
7
  class InstallGenerator < Rails::Generators::Base
8
- desc "Configures ODT UI stylesheets for Rails application"
8
+ desc "Configures ODT UI standalone stylesheets, Tailwind theme, and RBS type signatures for Rails application"
9
9
 
10
10
  def inject_stylesheets
11
11
  css_candidates = [
12
+ "app/assets/tailwind/application.css",
12
13
  "app/assets/stylesheets/application.tailwind.css",
13
14
  "app/assets/stylesheets/application.css",
14
15
  "app/assets/stylesheets/application.scss"
@@ -17,13 +18,53 @@ module Odt
17
18
  target_css = css_candidates.find { |file| File.exist?(file) }
18
19
 
19
20
  if target_css
20
- imports = %(\n/* ODT Design Tokens & Component Styles */\n@import "odt_ui.css";\n)
21
+ existing_content = File.read(target_css)
22
+
23
+ if existing_content.include?("odt_ui")
24
+ say "ODT UI stylesheet imports already present in #{target_css}", :yellow
25
+ return
26
+ end
27
+
28
+ is_tailwind = target_css.include?("tailwind") || existing_content.include?("@import \"tailwindcss\"") || existing_content.include?("@import 'tailwindcss'")
29
+
30
+ imports = if is_tailwind
31
+ <<~CSS
32
+
33
+ /* ==========================================================================
34
+ * ODT Lightweight UI - Design Tokens, Standalone Styles & Tailwind Theme
35
+ * ========================================================================== */
36
+ @import "odt_ui/tokens.css";
37
+ @import "odt_ui/styles.css";
38
+ @import "odt_ui/theme.css";
39
+ CSS
40
+ else
41
+ <<~CSS
42
+
43
+ /* ==========================================================================
44
+ * ODT Lightweight UI - Design Tokens & Standalone Component Styles
45
+ * ========================================================================== */
46
+ @import "odt_ui/tokens.css";
47
+ @import "odt_ui/styles.css";
48
+ CSS
49
+ end
50
+
21
51
  append_to_file target_css, imports
22
- say "Added ODT CSS imports to #{target_css}", :green
52
+ say "Added ODT UI CSS imports to #{target_css}", :green
23
53
  else
24
- say "Please add @import \"odt_ui.css\"; to your application stylesheet.", :yellow
54
+ say "No standard application stylesheet found.", :yellow
55
+ say "Please add the following to your application stylesheet or layout:", :yellow
56
+ say %( @import "odt_ui/tokens.css";\n @import "odt_ui/styles.css";\n), :cyan
25
57
  end
26
58
  end
59
+
60
+ def copy_rbs_signature
61
+ source = File.expand_path("../../../../../sig/odt_ui.rbs", __dir__)
62
+ return unless File.exist?(source)
63
+
64
+ empty_directory "sig"
65
+ copy_file source, "sig/odt_ui.rbs"
66
+ say "Copied sig/odt_ui.rbs for Ruby LSP / Solargraph support", :green
67
+ end
27
68
  end
28
69
  end
29
70
  end