studio-engine 0.105.0.rc1 → 0.106.0.rc1

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: b8d6d2e7f0fd6764c079a422a705446c36254603f9c49c2f7999d5ee31ce9ea3
4
- data.tar.gz: eecf186eda2510ddc315ed69346b1d26de64104f0ee01ef8420bbeddc6d87a75
3
+ metadata.gz: a988ae9e78ea6355954e11d8698fc41f69ea88bd91e4d86c21932625081e4aae
4
+ data.tar.gz: d8fdbcc944fc672efe43802dea5f4e16b6f14d7950cc731fe8d7b72b69cee8b0
5
5
  SHA512:
6
- metadata.gz: 8f6b2847809ddf9520d659809f9be964314e784c096ab8caa459862635464cb416a5fbd729c3c16eb8b10bda96efafddc92ce0d6ab64c5c338e0c44074a66a1e
7
- data.tar.gz: d64c2f5daadeafb668d574e32ea8db2ee5f6e50136ce9efd34d62526ee5be505c558933d1e253142bff5d42632bba39dc8337f9ed09c338cbfebfb2f8dc5346f
6
+ metadata.gz: 78ec459d2b0357d17e186dc0d878a2feaa14228855e62fbbe2e9eee000f3a7061c147a277f28851658028697a26959056ac5e4f13ef48dbdb46840135cec125e
7
+ data.tar.gz: e25bf874a2f3560b3e164ac9d05532052567361aa9220a3c49cf232af7001ee3fbaddedb70a24f0f73873cfc2d936d9561a256e6fbed7f16f256a81fe219bc85
data/CHANGELOG.md CHANGED
@@ -4,6 +4,24 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.106.0 — 2026-10-14
8
+
9
+ ### Changed
10
+
11
+ - **The navbar names the signed-in user by first name.** With
12
+ `Studio.navbar_user_name` unset, the user nav (and anything else calling
13
+ `Studio.navbar_user_name_for`) prints the user's `first_name`, else the first
14
+ word of `name`, else `display_name` whole, as before. A host that configures
15
+ the setting is unchanged. A user nav with no second row now centres its icon
16
+ column, so the gear and theme toggle sit level with the name rather than at
17
+ the top of the bar.
18
+ - **A host can make the name and avatar open the link sidebar.** Define the
19
+ view helper `studio_account_opens_sidebar?` as true and the account link
20
+ carries the sidebar's toggle attributes (`data-profile-image-toggle`,
21
+ `aria-controls`), so `studio/link_sidebar` opens the sidebar on click; the
22
+ link keeps its href for a click before that script loads. Without the helper
23
+ the link is unchanged.
24
+
7
25
  ## 0.105.0 — 2026-10-13
8
26
 
9
27
  ### Added
data/README.md CHANGED
@@ -624,13 +624,13 @@ end
624
624
 
625
625
  ### Navbar identity — `Studio.navbar_user_name` and `Studio.sign_in_label`
626
626
 
627
- Two words the navbar says about the viewer. Both defaults render the navbar
628
- byte-identical to before, so an app that sets neither sees no change. Rules:
629
- `lib/studio/navbar_identity.rb`.
627
+ Two words the navbar says about the viewer. The name defaults to the user's
628
+ first name: the `first_name` column, else the first word of `name`, else
629
+ `display_name` whole. Rules: `lib/studio/navbar_identity.rb`.
630
630
 
631
631
  ```ruby
632
632
  Studio.configure do |config|
633
- # The signed-in name in components/_user_nav. nil (the default) is display_name.
633
+ # The signed-in name in components/_user_nav. nil (the default) is the first name.
634
634
  config.navbar_user_name = :player_name # a method on the user
635
635
  # config.navbar_user_name = ->(user, view) { user.player_name } # or a callable
636
636
 
@@ -78,8 +78,10 @@
78
78
  defaults to min-width auto, and without it this column refuses to
79
79
  shrink below balance + icons. On a 320px phone with a balance the
80
80
  reserved column is 147px, and a column that will not give pushed the
81
- avatar 17px past the screen edge (e2e/header_phone_width.spec.js). %>
82
- <div class="flex-1 min-w-0">
81
+ avatar 17px past the screen edge (e2e/header_phone_width.spec.js).
82
+ It is a centred flex column, so with no second row the icons sit level
83
+ with the name and avatar rather than at the top of the bar. %>
84
+ <div class="flex-1 min-w-0 flex flex-col justify-center" data-nav-tools>
83
85
  <%# Div 1 (Bigger): balance + icons. %>
84
86
  <div class="flex items-center gap-2 leading-none" :style="'padding: 0 6px;' + ($store.devMode ? 'background: cornflowerblue;' : '')">
85
87
  <%= studio_nav_slot.call(balance_slot, balance_html) %>
@@ -207,8 +209,22 @@
207
209
  column beside it is what gives way. So the name cannot truncate by
208
210
  flex shrinking: from md up its box carries a max width instead, and
209
211
  the name ellipsizes inside it. The avatar is aria-hidden: the name is
210
- the link's accessible name. %>
212
+ the link's accessible name.
213
+
214
+ A host whose link sidebar heads with the profile can make the link open
215
+ the sidebar instead, by defining studio_account_opens_sidebar? as true
216
+ (a view helper; the engine defines none, so every other host keeps the
217
+ link). The link then carries the sidebar's toggle attributes and
218
+ studio/link_sidebar claims its click; the href stays, so a click before
219
+ that script loads still reaches the account page. %>
211
220
  <% account_classes = "group flex items-center gap-2 flex-shrink-0" %>
221
+ <% account_toggle =
222
+ if studio_nav_destination && respond_to?(:studio_account_opens_sidebar?) && studio_account_opens_sidebar?
223
+ { "data-profile-image-toggle": "", "aria-controls": "studio-link-sidebar studio-link-sidebar-mobile",
224
+ "aria-haspopup": "dialog", ":aria-expanded": "$store.sidebars && $store.sidebars.linkTreeOpen ? 'true' : 'false'" }
225
+ else
226
+ {}
227
+ end %>
212
228
  <% account_inner = capture do %>
213
229
  <span class="sr-only md:not-sr-only md:max-w-40"><span class="block truncate text-right text-heading font-semibold text-base leading-none transition<%= " group-hover:text-primary" if studio_nav_destination %>" data-nav-name><%= Studio.navbar_user_name_for(current_user, self) %></span></span>
214
230
  <span class="flex-shrink-0 flex items-center" aria-hidden="true">
@@ -216,7 +232,7 @@
216
232
  </span>
217
233
  <% end %>
218
234
  <% if studio_nav_destination %>
219
- <%= link_to account_inner, studio_nav_destination, class: "#{account_classes} hover:opacity-80 transition", "data-nav-account": "", "x-bind:style": "$store.devMode && 'background: lightgreen'" %>
235
+ <%= link_to account_inner, studio_nav_destination, class: "#{account_classes} hover:opacity-80 transition", "data-nav-account": "", "x-bind:style": "$store.devMode && 'background: lightgreen'", **account_toggle %>
220
236
  <% else %>
221
237
  <span class="<%= account_classes %>" data-nav-account x-bind:style="$store.devMode && 'background: lightgreen'"><%= account_inner %></span>
222
238
  <% end %>
@@ -7,7 +7,8 @@
7
7
  #
8
8
  # Studio.navbar_user_name is one of:
9
9
  #
10
- # nil the default: user.display_name, as before
10
+ # nil the default: the user's first name (first_name, else
11
+ # the first word of name), else user.display_name
11
12
  # :player_name a method called on the user ("player_name" works too)
12
13
  # ->(user, view) { ... } a callable; a one-argument callable gets the user only
13
14
  #
@@ -32,7 +33,7 @@ module Studio
32
33
 
33
34
  def user_name(user, view = nil, config: Studio.navbar_user_name)
34
35
  fallback = user.display_name # outside the rescue: the default path is not ours to swallow
35
- return fallback if config.nil?
36
+ return first_name(user) || fallback if config.nil?
36
37
 
37
38
  begin
38
39
  text = plain_text(configured_name(config, user, view))
@@ -62,6 +63,16 @@ module Studio
62
63
  @reported_lock.synchronize { @reported.clear }
63
64
  end
64
65
 
66
+ # The default name: the first_name column, else the first word of name; nil
67
+ # when the host has neither, and the caller prints display_name. display_name
68
+ # itself is never split: a host may build it from a username or an email.
69
+ def first_name(user)
70
+ given = plain_text(user.first_name) if user.respond_to?(:first_name)
71
+ return given unless given.to_s.empty?
72
+
73
+ plain_text(user.name).split.first if user.respond_to?(:name)
74
+ end
75
+
65
76
  def configured_name(config, user, view)
66
77
  return user.public_send(config.to_sym) unless config.respond_to?(:call)
67
78
 
@@ -1,3 +1,3 @@
1
1
  module Studio
2
- VERSION = "0.105.0.rc1"
2
+ VERSION = "0.106.0.rc1"
3
3
  end
data/lib/studio.rb CHANGED
@@ -223,7 +223,7 @@ module Studio
223
223
 
224
224
  # ---- Navbar identity ----
225
225
  # The name the signed-in user nav prints, and the signed-out button's label.
226
- # Both defaults render the navbar byte-identical to before. The engine has no
226
+ # The name defaults to the user's first name. The engine has no
227
227
  # I18n catalogue, so the label is plain config rather than a locale key.
228
228
  # The label also words the engine's auth pages (lib/studio/auth_labels.rb).
229
229
  # Rules: lib/studio/navbar_identity.rb.
@@ -232,7 +232,8 @@ module Studio
232
232
  # config.navbar_user_name = ->(user, view) { user.player_name } # or a callable
233
233
  # config.sign_in_label = "Sign in"
234
234
  #
235
- # nil means user.display_name. A method or callable that raises, or answers
235
+ # nil means the first name (first_name, else the first word of name), else
236
+ # user.display_name. A method or callable that raises, or answers
236
237
  # blank, falls back to display_name; a raise is reported once, never a 500.
237
238
  mattr_reader :navbar_user_name, default: nil
238
239
 
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.105.0.rc1
4
+ version: 0.106.0.rc1
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-10-13 00:00:00.000000000 Z
11
+ date: 2026-10-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails