studio-engine 0.6.0 → 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: e9e4f490c1b36a67d00f603bee9cf9849fd36103fff17a6e348ed98b138f4987
4
- data.tar.gz: 5003c6176d386ae82f129b749bd9d914a65e258b40587ff82ec3d7a5c2c3509f
3
+ metadata.gz: e0dff947db7bda136b0fcca271b86347449fa0d5f259c102ba5fe50e8e29dea8
4
+ data.tar.gz: 898fb4de879042127da3c85ee072603a8cf4d02125037d13d16793ecc8579e17
5
5
  SHA512:
6
- metadata.gz: 0ea8405b0e80d57f6d69df6a96dfdb835859e581076b9182d01a88a7b0517f63210835265ce4691549ee0f5c52444cbb504f97e173af4b27a46d99c17c51838c
7
- data.tar.gz: '080e131c86404755936a99ae1e41f10a143a32b7401170639ad0251bac7d787c5308bc9cb818db92446576f73b368764c7eef9570764651a015ef295c8e64856'
6
+ metadata.gz: 91f96cfc96d999ef6ea31aa7d427fb903c538da72470768891dd1e3667d7e5380bf8f931089c24548b9ad844b4c7815e0a9167231dd989c36fd674f04391e831
7
+ data.tar.gz: dc439df4fc3125f2a98c1511606008f74df5dc869c98a72ca0c4fe6a8ba4e082d093d5093de211e9b6534e280140cb35a6ba31952dc40b667e5fbe5de1b04552
data/CHANGELOG.md CHANGED
@@ -4,6 +4,13 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
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
+
7
14
  ## v0.6.0 (2026-06-16)
8
15
 
9
16
  ### Changed
data/README.md CHANGED
@@ -11,7 +11,7 @@ Shared Rails engine for McRitchie apps. Provides authentication, error handling,
11
11
  gem "studio-engine", "~> 0.6"
12
12
  ```
13
13
 
14
- Then `bundle install`. The current release is **v0.6.0**; 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.6.0**; 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.6.0"
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"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: studio-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex McRitchie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-16 00:00:00.000000000 Z
11
+ date: 2026-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -177,6 +177,7 @@ files:
177
177
  - app/views/components/_badge.html.erb
178
178
  - app/views/components/_card.html.erb
179
179
  - app/views/components/_copy_button.html.erb
180
+ - app/views/components/_emoji_swap.html.erb
180
181
  - app/views/components/_empty_state.html.erb
181
182
  - app/views/components/_google_logo.html.erb
182
183
  - app/views/components/_input.html.erb
@@ -230,6 +231,7 @@ files:
230
231
  - lib/studio/mail_transport.rb
231
232
  - lib/studio/s3.rb
232
233
  - lib/studio/theme_resolver.rb
234
+ - lib/studio/ui_primitives.rb
233
235
  - lib/studio/username_generator.rb
234
236
  - lib/studio/version.rb
235
237
  - lib/tasks/studio_email.rake