baldur 0.1.7 → 0.2.3

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/README.md +78 -376
  4. data/TODO.md +53 -5
  5. data/app/assets/javascripts/baldur/controllers/confirmation_controller.js +23 -0
  6. data/app/assets/stylesheets/baldur/application/components/auth-page.css +7 -0
  7. data/app/assets/stylesheets/baldur/application/components/confirmation.css +11 -0
  8. data/app/assets/stylesheets/baldur/application/components/sidebar.css +234 -0
  9. data/app/assets/stylesheets/baldur.css +1 -0
  10. data/app/assets/tailwind/baldur/engine.css +2 -2
  11. data/app/helpers/baldur/marketing_helper.rb +71 -69
  12. data/app/helpers/baldur/optional/auth_page_helper.rb +4 -2
  13. data/app/helpers/baldur/optional/google_auth_helper.rb +2 -2
  14. data/app/helpers/baldur/optional/panel_secondary_helper.rb +3 -2
  15. data/app/helpers/baldur/ui_helper.rb +159 -121
  16. data/app/helpers/baldur/ui_helper_feedback.rb +38 -36
  17. data/app/helpers/baldur/ui_helper_forms.rb +81 -76
  18. data/app/helpers/baldur/ui_helper_sidebar.rb +6 -5
  19. data/app/helpers/baldur/ui_helper_unavailable.rb +17 -15
  20. data/app/views/baldur/components/_confirmation_modal.html.erb +99 -0
  21. data/app/views/baldur/components/_modal_host.html.erb +10 -0
  22. data/app/views/baldur/components/_sidebar.html.erb +30 -30
  23. data/app/views/baldur/components/_theme_toggle.html.erb +23 -0
  24. data/app/views/baldur/optional/_auth_page.html.erb +6 -0
  25. data/baldur.gemspec +23 -23
  26. data/config/importmap.rb +2 -2
  27. data/lib/baldur/configuration.rb +6 -6
  28. data/lib/baldur/engine.rb +3 -3
  29. data/lib/baldur/version.rb +1 -1
  30. data/lib/baldur.rb +5 -5
  31. data/lib/generators/baldur/install/install_generator.rb +20 -19
  32. data/lib/generators/baldur/install/templates/baldur_initializer.rb +7 -7
  33. data/lib/generators/baldur/install/templates/theme.css +32 -6
  34. data/lib/generators/baldur/install_google_auth/install_google_auth_generator.rb +2 -2
  35. data/lib/generators/baldur/install_panel_right/install_panel_right_generator.rb +2 -2
  36. data/lib/generators/baldur/install_panel_secondary/install_panel_secondary_generator.rb +3 -3
  37. data/script/verify_host_install +59 -31
  38. data/test/confirmation_modal_helper_test.rb +241 -0
  39. data/test/csp_rendering_test.rb +21 -21
  40. data/test/engine_css_test.rb +36 -0
  41. data/test/fixtures/shared/_brand_lockup.html.erb +1 -0
  42. data/test/gemspec_test.rb +7 -5
  43. data/test/install_generator_test.rb +25 -21
  44. data/test/install_panel_secondary_generator_test.rb +12 -9
  45. data/test/marketing_helper_test.rb +7 -7
  46. data/test/run_all.rb +1 -1
  47. data/test/sidebar_helper_test.rb +16 -16
  48. data/test/test_helper.rb +14 -14
  49. data/test/theme_toggle_helper_test.rb +119 -0
  50. data/test/tmp/install_generator/app/assets/stylesheets/theme.css +32 -6
  51. data/test/tmp/install_generator/app/javascript/controllers/confirmation_controller.js +1 -0
  52. data/test/tmp/install_generator/config/initializers/baldur.rb +7 -7
  53. metadata +20 -8
@@ -0,0 +1,23 @@
1
+ <%
2
+ aria_label = local_assigns[:aria_label] || "Toggle theme"
3
+ extra_classes = local_assigns[:classes]
4
+ toggle_classes = ["switch", "theme-toggle"].tap do |classes|
5
+ classes << extra_classes if extra_classes.present?
6
+ end.join(" ")
7
+ %>
8
+ <label class="<%= toggle_classes %>">
9
+ <input type="checkbox"
10
+ data-theme-target="toggle"
11
+ data-theme-toggle
12
+ aria-label="<%= aria_label %>" />
13
+ <span class="switch__track">
14
+ <span class="switch__icon switch__icon--sun" aria-hidden="true"><%= ui_icon("sun", class_name: "h-4 w-4") %></span>
15
+ <span class="switch__icon switch__icon--moon" aria-hidden="true"><%= ui_icon("moon", class_name: "h-4 w-4") %></span>
16
+ <span class="switch__thumb"></span>
17
+ </span>
18
+ <span class="icon-button theme-toggle__compact" aria-hidden="true" data-action="click->theme#toggle">
19
+ <span class="theme-toggle__compact-icon theme-toggle__compact-icon--sun"><%= ui_icon("sun", class_name: "h-5 w-5") %></span>
20
+ <span class="theme-toggle__compact-icon theme-toggle__compact-icon--moon"><%= ui_icon("moon", class_name: "h-5 w-5") %></span>
21
+ </span>
22
+ <span class="sr-only"><%= aria_label %></span>
23
+ </label>
@@ -6,6 +6,12 @@
6
6
 
7
7
  <div class="<%= auth_shell_classes %>">
8
8
  <div class="auth-page__container">
9
+ <% if local_assigns[:top_rail].present? %>
10
+ <div class="auth-page__top-rail">
11
+ <%= local_assigns[:top_rail] %>
12
+ </div>
13
+ <% end %>
14
+
9
15
  <div class="auth-page__brand">
10
16
  <%= link_to resolved_brand_path, class: "inline-flex items-center justify-center no-underline" do %>
11
17
  <%= render "shared/brand_lockup",
data/baldur.gemspec CHANGED
@@ -1,36 +1,36 @@
1
- require_relative "lib/baldur/version"
1
+ require_relative 'lib/baldur/version'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
- spec.name = "baldur"
4
+ spec.name = 'baldur'
5
5
  spec.version = Baldur::VERSION
6
- spec.authors = [ "Varun Murkar" ]
7
- spec.summary = "Reusable Rails UI engine for same-stack application interfaces"
8
- spec.description = "Baldur packages reusable Rails view helpers, components, styles, and Stimulus controllers."
9
- spec.homepage = "https://github.com/varunmurkar/baldur"
10
- spec.license = "MIT"
6
+ spec.authors = ['Varun Murkar']
7
+ spec.summary = 'Batteries-included Rails UI engine for the importmap, Stimulus, Tailwind stack'
8
+ spec.description = 'Baldur helps Rails teams ship polished UI faster with install generators, reusable ui_* helpers, Tailwind components, and Stimulus wiring for apps using Propshaft, importmap-rails, stimulus-rails, and tailwindcss-rails.'
9
+ spec.homepage = 'https://github.com/varunmurkar/baldur'
10
+ spec.license = 'MIT'
11
11
  spec.metadata = {
12
- "source_code_uri" => "https://github.com/varunmurkar/baldur",
13
- "bug_tracker_uri" => "https://github.com/varunmurkar/baldur/issues",
14
- "changelog_uri" => "https://github.com/varunmurkar/baldur/releases",
15
- "rubygems_mfa_required" => "true"
12
+ 'source_code_uri' => 'https://github.com/varunmurkar/baldur',
13
+ 'bug_tracker_uri' => 'https://github.com/varunmurkar/baldur/issues',
14
+ 'changelog_uri' => 'https://github.com/varunmurkar/baldur/releases',
15
+ 'rubygems_mfa_required' => 'true'
16
16
  }
17
17
 
18
18
  spec.files = Dir.chdir(__dir__) do
19
19
  Dir[
20
- "{app,config,lib,script,test}/**/*",
21
- "README.md",
22
- "TODO.md",
23
- "LICENSE",
24
- "SECURITY.md",
25
- "baldur.gemspec",
26
- "Gemfile"
20
+ '{app,config,lib,script,test}/**/*',
21
+ 'README.md',
22
+ 'TODO.md',
23
+ 'LICENSE',
24
+ 'SECURITY.md',
25
+ 'baldur.gemspec',
26
+ 'Gemfile'
27
27
  ].select { |path| File.file?(path) }
28
28
  end
29
29
 
30
- spec.required_ruby_version = ">= 3.3.0"
30
+ spec.required_ruby_version = '>= 3.3.0'
31
31
 
32
- spec.add_dependency "importmap-rails"
33
- spec.add_dependency "lucide-rails"
34
- spec.add_dependency "rails", ">= 8.1.0"
35
- spec.add_dependency "tailwindcss-rails", ">= 4.4.0"
32
+ spec.add_dependency 'importmap-rails'
33
+ spec.add_dependency 'lucide-rails'
34
+ spec.add_dependency 'rails', '>= 7.0.0'
35
+ spec.add_dependency 'tailwindcss-rails', '>= 4.3.0'
36
36
  end
data/config/importmap.rb CHANGED
@@ -1,2 +1,2 @@
1
- pin_all_from File.expand_path("../app/assets/javascripts/baldur/controllers", __dir__), under: "baldur/controllers"
2
- pin_all_from File.expand_path("../app/assets/javascripts/baldur/lib", __dir__), under: "baldur/lib"
1
+ pin_all_from File.expand_path('../app/assets/javascripts/baldur/controllers', __dir__), under: 'baldur/controllers'
2
+ pin_all_from File.expand_path('../app/assets/javascripts/baldur/lib', __dir__), under: 'baldur/lib'
@@ -10,15 +10,15 @@ module Baldur
10
10
  def initialize
11
11
  @warning_dependency_resolver = ->(_warning_keys) { [] }
12
12
  @dependency_dataset_name_resolver = ->(dataset_key) { dataset_key.to_s.humanize }
13
- @unavailable_fallback_message = "Missing metric or raw data required to compute this value."
13
+ @unavailable_fallback_message = 'Missing metric or raw data required to compute this value.'
14
14
  @marketing_brand = {
15
- name: "Brand",
16
- wordmark: "Brand",
17
- logo_src: "/icon.png",
18
- logo_alt: "Brand logo"
15
+ name: 'Brand',
16
+ wordmark: 'Brand',
17
+ logo_src: '/icon.png',
18
+ logo_alt: 'Brand logo'
19
19
  }
20
20
  @default_google_sign_in_path = nil
21
- @theme_storage_key = "baldur.theme"
21
+ @theme_storage_key = 'baldur.theme'
22
22
  end
23
23
  end
24
24
  end
data/lib/baldur/engine.rb CHANGED
@@ -2,9 +2,9 @@ module Baldur
2
2
  class Engine < ::Rails::Engine
3
3
  isolate_namespace Baldur
4
4
 
5
- initializer "baldur.importmap", before: "importmap" do |app|
6
- app.config.importmap.paths << Engine.root.join("config/importmap.rb")
7
- app.config.importmap.cache_sweepers << Engine.root.join("app/assets/javascripts")
5
+ initializer 'baldur.importmap', before: 'importmap' do |app|
6
+ app.config.importmap.paths << Engine.root.join('config/importmap.rb')
7
+ app.config.importmap.cache_sweepers << Engine.root.join('app/assets/javascripts')
8
8
  end
9
9
  end
10
10
  end
@@ -1,3 +1,3 @@
1
1
  module Baldur
2
- VERSION = "0.1.7".freeze
2
+ VERSION = '0.2.3'.freeze
3
3
  end
data/lib/baldur.rb CHANGED
@@ -1,9 +1,9 @@
1
- require "rails"
2
- require "lucide-rails"
1
+ require 'rails'
2
+ require 'lucide-rails'
3
3
 
4
- require_relative "baldur/version"
5
- require_relative "baldur/configuration"
6
- require_relative "baldur/engine"
4
+ require_relative 'baldur/version'
5
+ require_relative 'baldur/configuration'
6
+ require_relative 'baldur/engine'
7
7
 
8
8
  module Baldur
9
9
  class << self
@@ -1,12 +1,13 @@
1
- require "rails/generators"
1
+ require 'rails/generators'
2
2
 
3
3
  module Baldur
4
4
  module Generators
5
5
  class InstallGenerator < Rails::Generators::Base
6
- source_root File.expand_path("templates", __dir__)
6
+ source_root File.expand_path('templates', __dir__)
7
7
 
8
8
  CORE_CONTROLLERS = %w[
9
9
  accordion
10
+ confirmation
10
11
  date_field
11
12
  details_menu
12
13
  form_submit
@@ -34,19 +35,19 @@ module Baldur
34
35
  ].freeze
35
36
 
36
37
  def create_ui_helper
37
- template "ui_helper.rb", "app/helpers/ui_helper.rb"
38
+ template 'ui_helper.rb', 'app/helpers/ui_helper.rb'
38
39
  end
39
40
 
40
41
  def create_initializer
41
- template "baldur_initializer.rb", "config/initializers/baldur.rb"
42
+ template 'baldur_initializer.rb', 'config/initializers/baldur.rb'
42
43
  end
43
44
 
44
45
  def create_theme_override
45
- template "theme.css", "app/assets/stylesheets/theme.css"
46
+ template 'theme.css', 'app/assets/stylesheets/theme.css'
46
47
  end
47
48
 
48
49
  def create_fonts_override
49
- template "fonts.css", "app/assets/stylesheets/fonts.css"
50
+ template 'fonts.css', 'app/assets/stylesheets/fonts.css'
50
51
  end
51
52
 
52
53
  def create_controller_shims
@@ -68,9 +69,9 @@ module Baldur
68
69
  def add_stylesheet_import
69
70
  return unless File.exist?(tailwind_entrypoint_path)
70
71
 
71
- append_unique_line tailwind_entrypoint_path, "@import \"../stylesheets/fonts.css\";"
72
- append_unique_line tailwind_entrypoint_path, "@import \"../builds/tailwind/baldur.css\";"
73
- append_unique_line tailwind_entrypoint_path, "@import \"../stylesheets/theme.css\";"
72
+ append_unique_line tailwind_entrypoint_path, '@import "../stylesheets/fonts.css";'
73
+ append_unique_line tailwind_entrypoint_path, '@import "../builds/tailwind/baldur.css";'
74
+ append_unique_line tailwind_entrypoint_path, '@import "../stylesheets/theme.css";'
74
75
  ensure_stylesheet_import_order
75
76
  end
76
77
 
@@ -82,19 +83,19 @@ module Baldur
82
83
 
83
84
  def ensure_stylesheet_import_order
84
85
  source = File.read(tailwind_entrypoint_path)
85
- fonts_import = "@import \"../stylesheets/fonts.css\";"
86
- tailwind_import = "@import \"tailwindcss\";"
87
- baldur_import = "@import \"../builds/tailwind/baldur.css\";"
88
- theme_import = "@import \"../stylesheets/theme.css\";"
86
+ fonts_import = '@import "../stylesheets/fonts.css";'
87
+ tailwind_import = '@import "tailwindcss";'
88
+ baldur_import = '@import "../builds/tailwind/baldur.css";'
89
+ theme_import = '@import "../stylesheets/theme.css";'
89
90
  normalized = source.lines.reject { |line| line.strip == fonts_import }.join
90
91
  normalized = if normalized.include?(tailwind_import)
91
- normalized.sub("#{tailwind_import}\n", "#{fonts_import}\n#{tailwind_import}\n")
92
- else
93
- "#{fonts_import}\n#{normalized}"
94
- end
92
+ normalized.sub("#{tailwind_import}\n", "#{fonts_import}\n#{tailwind_import}\n")
93
+ else
94
+ "#{fonts_import}\n#{normalized}"
95
+ end
95
96
 
96
97
  if normalized.include?(baldur_import) && normalized.include?(theme_import) &&
97
- normalized.index(baldur_import) > normalized.index(theme_import)
98
+ normalized.index(baldur_import) > normalized.index(theme_import)
98
99
  normalized = normalized.lines.reject { |line| line.strip == theme_import }.join
99
100
  normalized = normalized.sub("#{baldur_import}\n", "#{baldur_import}\n#{theme_import}\n")
100
101
  end
@@ -107,7 +108,7 @@ module Baldur
107
108
  end
108
109
 
109
110
  def tailwind_entrypoint
110
- "app/assets/tailwind/application.css"
111
+ 'app/assets/tailwind/application.css'
111
112
  end
112
113
  end
113
114
  end
@@ -1,13 +1,13 @@
1
- require "baldur"
1
+ require 'baldur'
2
2
 
3
3
  Baldur.configure do |config|
4
- config.unavailable_fallback_message = "Missing metric or raw data required to compute this value."
5
- config.theme_storage_key = "baldur.theme"
4
+ config.unavailable_fallback_message = 'Missing metric or raw data required to compute this value.'
5
+ config.theme_storage_key = 'baldur.theme'
6
6
  config.marketing_brand = {
7
- name: "Your Brand",
8
- wordmark: "Your Brand",
9
- logo_src: "/icon.png",
10
- logo_alt: "Your Brand logo"
7
+ name: 'Your Brand',
8
+ wordmark: 'Your Brand',
9
+ logo_src: '/icon.png',
10
+ logo_alt: 'Your Brand logo'
11
11
  }
12
12
 
13
13
  # Supply host-specific lookups when using unavailable dependency helpers.
@@ -1,12 +1,36 @@
1
1
  /*
2
2
  * Host theme overrides.
3
3
  *
4
- * Override only the base palette inputs below. Baldur remains the source of
5
- * truth for semantic tokens, light/dark role mapping, and component styling.
6
- * Use `fonts.css` to load font files, then map those loaded families to the
7
- * font tokens below.
4
+ * ── Brand inputs ─────────────────────────────────────────
5
+ * Override the four base palette tokens to rebrand. Baldur
6
+ * derives all semantic and role tokens from these inputs;
7
+ * do NOT override the semantic outputs directly.
8
8
  *
9
- * Example:
9
+ * --_primary-base primary actions / CTA
10
+ * --_secondary-base sidebar, nav, subdued surfaces
11
+ * --_accent-base highlights, badges, tags
12
+ * --_neutral-base surfaces, text, borders
13
+ *
14
+ * Values are oklch(). To pick a color, convert to oklch and
15
+ * paste the three channels (L C H) — no parens needed:
16
+ *
17
+ * --_primary-base: oklch(0.68 0.16 27);
18
+ *
19
+ * ── Semantic tokens ──────────────────────────────────────
20
+ * Baldur owns all --color-* semantic tokens (e.g. --color-primary,
21
+ * --color-surface, --color-on-surface). They adapt between
22
+ * light/dark automatically. Do not override them here.
23
+ *
24
+ * ── Font mapping ─────────────────────────────────────────
25
+ * Load web fonts in fonts.css, then map the loaded families
26
+ * to the tokens below. Baldur uses --font-body as the default
27
+ * family for body, heading, and UI text unless overridden.
28
+ *
29
+ * --font-body body copy
30
+ * --font-heading headings (falls back to --font-body)
31
+ * --font-ui buttons, labels, form text (falls back to --font-body)
32
+ *
33
+ * ── Example ──────────────────────────────────────────────
10
34
  * :root {
11
35
  * --_primary-base: oklch(0.68 0.16 27);
12
36
  * --_secondary-base: oklch(0.30 0.04 195);
@@ -15,6 +39,8 @@
15
39
  * --font-body: "Geist", "Inter", "Segoe UI", "Helvetica Neue", Arial, system-ui, -apple-system, sans-serif;
16
40
  * --font-heading: var(--font-body);
17
41
  * --font-ui: var(--font-body);
42
+ * --font-family: var(--font-body);
43
+ * --font-sans: var(--font-body);
18
44
  * }
19
45
  */
20
46
 
@@ -24,4 +50,4 @@
24
50
  --font-ui: var(--font-body);
25
51
  --font-family: var(--font-body);
26
52
  --font-sans: var(--font-body);
27
- }
53
+ }
@@ -1,10 +1,10 @@
1
- require "rails/generators"
1
+ require 'rails/generators'
2
2
 
3
3
  module Baldur
4
4
  module Generators
5
5
  class InstallGoogleAuthGenerator < Rails::Generators::Base
6
6
  def create_helper
7
- create_file "app/helpers/google_auth_helper.rb", <<~RUBY
7
+ create_file 'app/helpers/google_auth_helper.rb', <<~RUBY
8
8
  module GoogleAuthHelper
9
9
  include Baldur::Optional::GoogleAuthHelper
10
10
  end
@@ -1,5 +1,5 @@
1
- require "rails/generators"
2
- require_relative "../install_panel_secondary/install_panel_secondary_generator"
1
+ require 'rails/generators'
2
+ require_relative '../install_panel_secondary/install_panel_secondary_generator'
3
3
 
4
4
  module Baldur
5
5
  module Generators
@@ -1,10 +1,10 @@
1
- require "rails/generators"
1
+ require 'rails/generators'
2
2
 
3
3
  module Baldur
4
4
  module Generators
5
5
  class InstallPanelSecondaryGenerator < Rails::Generators::Base
6
6
  def create_helper
7
- create_file "app/helpers/panel_secondary_helper.rb", <<~RUBY
7
+ create_file 'app/helpers/panel_secondary_helper.rb', <<~RUBY
8
8
  module PanelSecondaryHelper
9
9
  include Baldur::Optional::PanelSecondaryHelper
10
10
  end
@@ -12,7 +12,7 @@ module Baldur
12
12
  end
13
13
 
14
14
  def create_controller_shim
15
- create_file "app/javascript/controllers/panel_secondary_controller.js", <<~JS
15
+ create_file 'app/javascript/controllers/panel_secondary_controller.js', <<~JS
16
16
  export { default } from "baldur/controllers/panel_secondary_controller"
17
17
  JS
18
18
  end
@@ -1,24 +1,26 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- ENV["RAILS_ENV"] ||= "development"
4
+ ENV['RAILS_ENV'] ||= 'development'
5
5
 
6
- require File.expand_path("../../../config/environment", __dir__)
6
+ require File.expand_path('../../../config/environment', __dir__)
7
7
 
8
8
  def assert!(message)
9
9
  raise message unless yield
10
10
  end
11
11
 
12
12
  def tailwind_entrypoint
13
- Rails.root.join("app/assets/tailwind/application.css")
13
+ Rails.root.join('app/assets/tailwind/application.css')
14
14
  end
15
15
 
16
- puts "Baldur host install smoke check"
16
+ puts 'Baldur host install smoke check'
17
17
  puts "Rails root: #{Rails.root}"
18
18
  puts "Baldur root: #{Baldur::Engine.root}"
19
19
 
20
- assert!("Expected Baldur importmap path to be registered") do
21
- Rails.application.config.importmap.paths.any? { |path| path.to_s.end_with?("/config/importmap.rb") && path.to_s.include?("/baldur/") }
20
+ assert!('Expected Baldur importmap path to be registered') do
21
+ Rails.application.config.importmap.paths.any? do |path|
22
+ path.to_s.end_with?('/config/importmap.rb') && path.to_s.include?('/baldur/')
23
+ end
22
24
  end
23
25
 
24
26
  %w[
@@ -33,34 +35,34 @@ end
33
35
  assert!("Missing generated shim: #{relative_path}") { path.exist? }
34
36
  end
35
37
 
36
- assert!("Expected ui_button helper to be available") do
38
+ assert!('Expected ui_button helper to be available') do
37
39
  ApplicationController.helpers.respond_to?(:ui_button)
38
40
  end
39
41
 
40
- button_html = ApplicationController.helpers.ui_button(label: "Verify", href: "/")
41
- assert!("ui_button did not render expected markup") do
42
- button_html.include?("button") || button_html.include?("<a")
42
+ button_html = ApplicationController.helpers.ui_button(label: 'Verify', href: '/')
43
+ assert!('ui_button did not render expected markup') do
44
+ button_html.include?('button') || button_html.include?('<a')
43
45
  end
44
46
 
45
- modal_html = ApplicationController.helpers.ui_modal(id: "verify-modal", title: "Verify") { "Body".html_safe }
46
- assert!("ui_modal did not render expected markup") do
47
- modal_html.include?("dialog") || modal_html.include?("modal")
47
+ modal_html = ApplicationController.helpers.ui_modal(id: 'verify-modal', title: 'Verify') { 'Body'.html_safe }
48
+ assert!('ui_modal did not render expected markup') do
49
+ modal_html.include?('dialog') || modal_html.include?('modal')
48
50
  end
49
- assert!("ui_modal did not render body content") do
50
- modal_html.include?("Body")
51
+ assert!('ui_modal did not render body content') do
52
+ modal_html.include?('Body')
51
53
  end
52
54
 
53
- card_html = ApplicationController.helpers.ui_card(title: "Verify", body: "Card body")
54
- assert!("ui_card did not render body content") do
55
- card_html.include?("Card body")
55
+ card_html = ApplicationController.helpers.ui_card(title: 'Verify', body: 'Card body')
56
+ assert!('ui_card did not render body content') do
57
+ card_html.include?('Card body')
56
58
  end
57
59
 
58
60
  top_nav_html = ApplicationController.helpers.ui_marketing_top_nav(
59
- links: [ { label: "Pricing", href: "/pricing", class: "nav-link" } ],
60
- primary_action: { label: "Verify", href: "/", variant: :primary }
61
+ links: [{ label: 'Pricing', href: '/pricing', class: 'nav-link' }],
62
+ primary_action: { label: 'Verify', href: '/', variant: :primary }
61
63
  )
62
- assert!("ui_marketing_top_nav did not render expected markup") do
63
- top_nav_html.include?("marketing-top-nav") && top_nav_html.include?("Pricing")
64
+ assert!('ui_marketing_top_nav did not render expected markup') do
65
+ top_nav_html.include?('marketing-top-nav') && top_nav_html.include?('Pricing')
64
66
  end
65
67
 
66
68
  assert!("Expected Tailwind entrypoint at #{tailwind_entrypoint}") do
@@ -77,35 +79,61 @@ tailwind_source = tailwind_entrypoint.read
77
79
  assert!("Missing Tailwind integration line: #{line}") { tailwind_source.include?(line) }
78
80
  end
79
81
 
80
- host_fonts = Rails.root.join("app/assets/stylesheets/fonts.css")
82
+ host_fonts = Rails.root.join('app/assets/stylesheets/fonts.css')
81
83
  assert!("Expected host font override scaffold at #{host_fonts}") do
82
84
  host_fonts.exist?
83
85
  end
84
86
 
85
- host_theme = Rails.root.join("app/assets/stylesheets/theme.css")
87
+ host_theme = Rails.root.join('app/assets/stylesheets/theme.css')
86
88
  assert!("Expected host theme override scaffold at #{host_theme}") do
87
89
  host_theme.exist?
88
90
  end
89
91
 
90
- assert!("Expected host fonts import before Tailwind in the entrypoint") do
92
+ assert!('Expected host fonts import before Tailwind in the entrypoint') do
91
93
  tailwind_source.index('@import "../stylesheets/fonts.css";') <
92
94
  tailwind_source.index('@import "tailwindcss";')
93
95
  end
94
96
 
95
- assert!("Expected host theme override import after the Baldur import") do
97
+ assert!('Expected host theme override import after the Baldur import') do
96
98
  tailwind_source.index('@import "../builds/tailwind/baldur.css";') <
97
99
  tailwind_source.index('@import "../stylesheets/theme.css";')
98
100
  end
99
101
 
100
- assert!("Expected Tailwind entrypoint to stop hard-coding Geist font imports") do
102
+ assert!('Expected Tailwind entrypoint to stop hard-coding Geist font imports') do
101
103
  !tailwind_source.include?('family=Geist:wght@100..900')
102
104
  end
103
105
 
106
+ engine_css = Baldur::Engine.root.join('app/assets/tailwind/baldur/engine.css')
107
+ if engine_css.exist?
108
+ engine_source = engine_css.read
109
+ %w[helpers views].each do |dir|
110
+ assert!("Expected @source for #{dir} with correct depth (../../../#{dir}) in engine.css") do
111
+ engine_source.include?("@source \"../../../#{dir}\"")
112
+ end
113
+ end
114
+ end
115
+
104
116
  if ApplicationController.helpers.respond_to?(:ui_panel_secondary)
105
- panel_html = ApplicationController.helpers.ui_panel_secondary(id: "verify-panel", title: "Panel", trigger_label: "Open") { "Body".html_safe }
106
- assert!("ui_panel_secondary did not render expected markup") do
107
- panel_html.include?("panel-secondary")
117
+ panel_html = ApplicationController.helpers.ui_panel_secondary(id: 'verify-panel', title: 'Panel',
118
+ trigger_label: 'Open') do
119
+ 'Body'.html_safe
120
+ end
121
+ assert!('ui_panel_secondary did not render expected markup') do
122
+ panel_html.include?('panel-secondary')
123
+ end
124
+ end
125
+
126
+ compiled_css_path = Rails.root.join('app/assets/builds/tailwind/application.css')
127
+ if compiled_css_path.exist?
128
+ compiled_css = compiled_css_path.read
129
+ %w[px-6 py-4 uppercase tracking-wide font-semibold].each do |utility|
130
+ assert!("Expected Baldur utility .#{utility} in compiled CSS — engine @source paths may be misconfigured") do
131
+ compiled_css.include?(".#{utility}")
132
+ end
108
133
  end
134
+ else
135
+ warn "WARNING: Compiled Tailwind CSS not found at #{compiled_css_path}; skipping utility-class checks."
136
+ warn 'Run `bundle exec rails tailwindcss:build` then re-run this check.'
109
137
  end
110
138
 
111
- puts "Smoke check passed"
139
+ puts 'Smoke check passed'