studio-engine 0.5.10 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '0817243bffbcd834fd5a3d8f593a420b12d8fba691c48337b68e6661ebbe5d7c'
4
- data.tar.gz: 5328f4a61db1c6c8965a0291bf0573a1e71b9e83b29e8eafe0a974b5208a0487
3
+ metadata.gz: e0dff947db7bda136b0fcca271b86347449fa0d5f259c102ba5fe50e8e29dea8
4
+ data.tar.gz: 898fb4de879042127da3c85ee072603a8cf4d02125037d13d16793ecc8579e17
5
5
  SHA512:
6
- metadata.gz: 642c7e82c5576ed3565091922473f6da39d3ab5388d5affb5d6c4a7dda9be7f037dda006e5ead66f61ba711701ad0fbd7cb0038227d102e7fc962a22c0fb888d
7
- data.tar.gz: 8457efd67516bc2bcb42bc440cf6ff628c9153be16d0064bb8d3998f21d4c9a4f96e6b15a6978c08d8aa97d0f965a94a368f1a5df734589d4a08b61af60a2e7b
6
+ metadata.gz: 91f96cfc96d999ef6ea31aa7d427fb903c538da72470768891dd1e3667d7e5380bf8f931089c24548b9ad844b4c7815e0a9167231dd989c36fd674f04391e831
7
+ data.tar.gz: dc439df4fc3125f2a98c1511606008f74df5dc869c98a72ca0c4fe6a8ba4e082d093d5093de211e9b6534e280140cb35a6ba31952dc40b667e5fbe5de1b04552
data/CHANGELOG.md CHANGED
@@ -1,9 +1,22 @@
1
1
  # Changelog
2
2
 
3
- The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — `MAJOR.MINOR.PATCH`. Consumer Rails apps install the released RubyGems package with `gem "studio-engine", "~> 0.5"`; bumping the gem version and updating consumer lockfiles is a release.
3
+ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html) — `MAJOR.MINOR.PATCH`. Consumer Rails apps install the released RubyGems package with `gem "studio-engine", "~> 0.6"`; bumping the gem version and updating consumer lockfiles is a release.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## v0.6.1 (2026-06-18)
8
+
9
+ ### Added
10
+ - **`components/emoji_swap` UI primitive** plus shared CSS for nav/sidebar
11
+ emoji hover and focus transitions, including reduced-motion fallback and
12
+ aliases for the existing `nav-emoji-*` class names.
13
+
14
+ ## v0.6.0 (2026-06-16)
15
+
16
+ ### Changed
17
+ - Require `tailwindcss-rails ~> 4.5` so Studio apps can move onto the
18
+ Tailwind CSS v4 build chain together.
19
+
7
20
  ## v0.5.10 (2026-06-15)
8
21
 
9
22
  ### Added
data/README.md CHANGED
@@ -8,10 +8,10 @@ Shared Rails engine for McRitchie apps. Provides authentication, error handling,
8
8
 
9
9
  ```ruby
10
10
  # Gemfile — install from RubyGems (recommended)
11
- gem "studio-engine", "~> 0.5"
11
+ gem "studio-engine", "~> 0.6"
12
12
  ```
13
13
 
14
- Then `bundle install`. The current release is **v0.5.10**; see [`CHANGELOG.md`](./CHANGELOG.md) for the history.
14
+ Then `bundle install`. The current release is **v0.6.1**; see [`CHANGELOG.md`](./CHANGELOG.md) for the history.
15
15
 
16
16
  > Published to RubyGems as of v0.4.0 (2026-05-17). New installs should use the RubyGems form, which the consumer Rails apps (`mcritchie-studio`, `turf-monster`) already use.
17
17
 
@@ -20,6 +20,7 @@ Then `bundle install`. The current release is **v0.5.10**; see [`CHANGELOG.md`](
20
20
  - **Authentication**: Passwordless magic-link auth, optional password auth, Google OAuth via OmniAuth, Solana wallet sign-in, and optional one-way SSO patterns
21
21
  - **Error handling**: `Studio::ErrorHandling` concern with `rescue_and_log`, `ErrorLog` model with `capture!`, error log viewer at `/error_logs`
22
22
  - **Theme system**: Dynamic CSS custom properties generated from 7 role colors (primary, dark, light, success, accent, warning, danger). Dark/light mode toggle. Admin theme editor at `/admin/theme`.
23
+ - **UI primitives**: Shared component partials and CSS primitives such as `components/emoji_swap` for nav/sidebar emoji hover transitions.
23
24
  - **Operator tooling**: Shared `studio/banners/environment` banner with Dev Mode + email connector controls, `studio/banners/impersonation`, and an opt-in `Studio::Impersonation` concern for Act As session conventions.
24
25
  - **Sluggable concern**: `before_save :set_slug` with `to_param` for human-readable URLs
25
26
  - **ThemeSetting model**: Per-app DB overrides with fallback to config defaults
@@ -111,6 +112,19 @@ audit log, enter/exit controller actions, and any app-specific safeguards such
111
112
  as binding session-token checks to `true_user` or disabling wallet-only
112
113
  privileges while impersonating.
113
114
 
115
+ ## UI Primitives
116
+
117
+ Render `components/emoji_swap` inside a link or button with the `group` class to
118
+ slide between two emoji on hover and keyboard focus. The CSS ships through
119
+ `studio_theme_css_tag`, including a reduced-motion fade fallback.
120
+
121
+ ```erb
122
+ <%= link_to root_path, class: "group inline-flex items-center gap-2" do %>
123
+ <%= render "components/emoji_swap", base: "📊", hover: "✨" %>
124
+ <span>Dashboard</span>
125
+ <% end %>
126
+ ```
127
+
114
128
  ## Overriding Views
115
129
 
116
130
  This is a non-isolated engine -- app views at the same path automatically override engine views. For example, placing `app/views/sessions/new.html.erb` in the consuming app replaces the engine's login page.
@@ -10,6 +10,6 @@ module StudioThemeHelper
10
10
  Studio::ThemeResolver.new(colors).to_css
11
11
  end
12
12
 
13
- tag.style(css.html_safe, nonce: content_security_policy_nonce)
13
+ tag.style("#{css}\n#{Studio::UiPrimitives.css}".html_safe, nonce: content_security_policy_nonce)
14
14
  end
15
15
  end
@@ -0,0 +1,17 @@
1
+ <%# locals: (base:, hover:, aria_label: nil, class_name: nil) %>
2
+ <%
3
+ wrapper_classes = ["studio-emoji-swap", "flex-shrink-0", local_assigns[:class_name]].compact_blank.join(" ")
4
+ attrs = { class: wrapper_classes }
5
+
6
+ if local_assigns[:aria_label].present?
7
+ attrs[:role] = "img"
8
+ attrs["aria-label"] = aria_label
9
+ else
10
+ attrs["aria-hidden"] = "true"
11
+ end
12
+ %>
13
+
14
+ <%= tag.span(**attrs) do %>
15
+ <span class="studio-emoji-swap-base" aria-hidden="true"><%= base %></span>
16
+ <span class="studio-emoji-swap-hover" aria-hidden="true"><%= hover %></span>
17
+ <% end %>
@@ -0,0 +1,91 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Studio
4
+ module UiPrimitives
5
+ EMOJI_SWAP_CSS = <<~CSS
6
+ .studio-emoji-swap,
7
+ .nav-emoji-swap {
8
+ position: relative;
9
+ display: inline-flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ vertical-align: middle;
13
+ width: 1.5rem;
14
+ height: 1.25rem;
15
+ overflow: hidden;
16
+ }
17
+
18
+ .studio-emoji-swap > span,
19
+ .nav-emoji-swap > span {
20
+ position: absolute;
21
+ inset: 0;
22
+ display: inline-flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ transition: transform 240ms cubic-bezier(0.34, 1.2, 0.5, 1), opacity 180ms ease;
26
+ }
27
+
28
+ .studio-emoji-swap-base,
29
+ .nav-emoji-base {
30
+ transform: translateX(0);
31
+ opacity: 1;
32
+ }
33
+
34
+ .studio-emoji-swap-hover,
35
+ .nav-emoji-hover {
36
+ transform: translateX(-110%);
37
+ opacity: 0;
38
+ }
39
+
40
+ .group:hover .studio-emoji-swap-base,
41
+ .group:focus-visible .studio-emoji-swap-base,
42
+ .group:focus-within .studio-emoji-swap-base,
43
+ .group:hover .nav-emoji-base,
44
+ .group:focus-visible .nav-emoji-base,
45
+ .group:focus-within .nav-emoji-base {
46
+ transform: translateX(110%);
47
+ opacity: 0;
48
+ }
49
+
50
+ .group:hover .studio-emoji-swap-hover,
51
+ .group:focus-visible .studio-emoji-swap-hover,
52
+ .group:focus-within .studio-emoji-swap-hover,
53
+ .group:hover .nav-emoji-hover,
54
+ .group:focus-visible .nav-emoji-hover,
55
+ .group:focus-within .nav-emoji-hover {
56
+ transform: translateX(0);
57
+ opacity: 1;
58
+ }
59
+
60
+ @media (prefers-reduced-motion: reduce) {
61
+ .studio-emoji-swap > span,
62
+ .nav-emoji-swap > span {
63
+ transition: opacity 120ms ease;
64
+ }
65
+
66
+ .studio-emoji-swap-base,
67
+ .studio-emoji-swap-hover,
68
+ .nav-emoji-base,
69
+ .nav-emoji-hover,
70
+ .group:hover .studio-emoji-swap-base,
71
+ .group:focus-visible .studio-emoji-swap-base,
72
+ .group:focus-within .studio-emoji-swap-base,
73
+ .group:hover .studio-emoji-swap-hover,
74
+ .group:focus-visible .studio-emoji-swap-hover,
75
+ .group:focus-within .studio-emoji-swap-hover,
76
+ .group:hover .nav-emoji-base,
77
+ .group:focus-visible .nav-emoji-base,
78
+ .group:focus-within .nav-emoji-base,
79
+ .group:hover .nav-emoji-hover,
80
+ .group:focus-visible .nav-emoji-hover,
81
+ .group:focus-within .nav-emoji-hover {
82
+ transform: none;
83
+ }
84
+ }
85
+ CSS
86
+
87
+ def self.css
88
+ EMOJI_SWAP_CSS
89
+ end
90
+ end
91
+ end
@@ -1,3 +1,3 @@
1
1
  module Studio
2
- VERSION = "0.5.10"
2
+ VERSION = "0.6.1"
3
3
  end
data/lib/studio.rb CHANGED
@@ -2,6 +2,7 @@ require "studio/version"
2
2
  require "studio/engine"
3
3
  require "studio/color_scale"
4
4
  require "studio/theme_resolver"
5
+ require "studio/ui_primitives"
5
6
  require "studio/username_generator"
6
7
  require "studio/s3"
7
8
  require "studio/image_cache"
@@ -22,7 +22,7 @@ Gem::Specification.new do |spec|
22
22
  spec.require_paths = ["lib"]
23
23
 
24
24
  spec.add_dependency "rails", ">= 7.0", "< 8.0"
25
- spec.add_dependency "tailwindcss-rails", "~> 2.7"
25
+ spec.add_dependency "tailwindcss-rails", "~> 4.5"
26
26
  spec.add_dependency "faker", ">= 2.0", "< 4.0"
27
27
  spec.add_dependency "solid_queue", ">= 1.0", "< 2.0"
28
28
  spec.add_dependency "aws-sdk-s3", "~> 1.218"
metadata CHANGED
@@ -1,13 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: studio-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.10
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex McRitchie
8
+ autorequire:
8
9
  bindir: bin
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2026-06-18 00:00:00.000000000 Z
11
12
  dependencies:
12
13
  - !ruby/object:Gem::Dependency
13
14
  name: rails
@@ -35,14 +36,14 @@ dependencies:
35
36
  requirements:
36
37
  - - "~>"
37
38
  - !ruby/object:Gem::Version
38
- version: '2.7'
39
+ version: '4.5'
39
40
  type: :runtime
40
41
  prerelease: false
41
42
  version_requirements: !ruby/object:Gem::Requirement
42
43
  requirements:
43
44
  - - "~>"
44
45
  - !ruby/object:Gem::Version
45
- version: '2.7'
46
+ version: '4.5'
46
47
  - !ruby/object:Gem::Dependency
47
48
  name: faker
48
49
  requirement: !ruby/object:Gem::Requirement
@@ -176,6 +177,7 @@ files:
176
177
  - app/views/components/_badge.html.erb
177
178
  - app/views/components/_card.html.erb
178
179
  - app/views/components/_copy_button.html.erb
180
+ - app/views/components/_emoji_swap.html.erb
179
181
  - app/views/components/_empty_state.html.erb
180
182
  - app/views/components/_google_logo.html.erb
181
183
  - app/views/components/_input.html.erb
@@ -229,6 +231,7 @@ files:
229
231
  - lib/studio/mail_transport.rb
230
232
  - lib/studio/s3.rb
231
233
  - lib/studio/theme_resolver.rb
234
+ - lib/studio/ui_primitives.rb
232
235
  - lib/studio/username_generator.rb
233
236
  - lib/studio/version.rb
234
237
  - lib/tasks/studio_email.rake
@@ -243,6 +246,7 @@ metadata:
243
246
  source_code_uri: https://github.com/amcritchie/studio-engine/tree/main
244
247
  bug_tracker_uri: https://github.com/amcritchie/studio-engine/issues
245
248
  changelog_uri: https://github.com/amcritchie/studio-engine/blob/main/CHANGELOG.md
249
+ post_install_message:
246
250
  rdoc_options: []
247
251
  require_paths:
248
252
  - lib
@@ -257,7 +261,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
257
261
  - !ruby/object:Gem::Version
258
262
  version: '0'
259
263
  requirements: []
260
- rubygems_version: 4.0.9
264
+ rubygems_version: 3.5.11
265
+ signing_key:
261
266
  specification_version: 4
262
267
  summary: Shared Rails engine providing auth, SSO, error logging, theming, and S3-backed
263
268
  image caching