keystone_ui 0.6.0 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3461e5f2648165cab0fbea2244fe15dbf42c2bf1da5a96f5ebfdfe89b7a2278c
4
- data.tar.gz: c39d95798511ddbe58a61144a98fca8b2070475c3850e83b7016a73627c439ce
3
+ metadata.gz: 794dd244d2cfac2f3389a4e4405e8e127c759fb310aac4c9e00b55c6c4501be7
4
+ data.tar.gz: 7ebebe2b82a82e423dd2ab440c5c804192355a9aab7f00ffffaf513f05c902de
5
5
  SHA512:
6
- metadata.gz: 2a0eb208c6a668bf2d2e62ae1d5a996f04b4c8cae8b5f014287cc066a4840195b24756b7efe5a44ef1b3aa2cec367c32129361897f2aa8dbeff09ee786a8ba5f
7
- data.tar.gz: 5d596e9a799b189775af38d413afc945fea87828d90517cd21930c80a6efa9a222faa32d8401c4d8bfe8f4d5bc03f32f1e4bb8dfb5f8691aa570e8322d4340bd
6
+ metadata.gz: e214dca626bc889d34fb68f322d0fd311a118b017e2ede2092d433df032c41163e2469ac67fe305b78164692cbaf3a73b25691c9cbc34686446f70d971767443
7
+ data.tar.gz: 811a7d3124b5d8b090239c38c0fd8b9dbfa74c225f92f1385d0f1ec0125a55d0b2234636a25b3d7d9010af37d23f91ba261e3d8154e2ef68ff5ff14e0041dfe3
data/MIT-LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tyler Schneider
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -5,18 +5,16 @@
5
5
  <button type="button" class="<%= info_button_classes %>" data-action="click->stat-card-info#toggle" aria-label="Show metric details">
6
6
  <%= info_icon.html_safe %>
7
7
  </button>
8
+ <div class="<%= disclosure_classes %>" data-stat-card-info-target="panel">
9
+ <% if definition %><p><span class="font-medium text-gray-700 dark:text-gray-300">Captures:</span> <%= definition %></p><% end %>
10
+ <% if calculation %><p><span class="font-medium text-gray-700 dark:text-gray-300">Calc:</span> <%= calculation %></p><% end %>
11
+ </div>
8
12
  <% end %>
9
13
  </div>
10
14
  <p class="<%= value_classes %>">
11
- <%= value %><% if suffix? %><span class="<%= suffix_classes %>"> <%= suffix %></span><% end %>
15
+ <% if link? %><a href="<%= href %>" class="<%= value_link_classes %>"><%= value %></a><% else %><%= value %><% end %><% if suffix? %><span class="<%= suffix_classes %>"> <%= suffix %></span><% end %>
12
16
  </p>
13
17
  <% if change? %>
14
18
  <p class="mt-1 text-sm font-medium <%= change_classes %>"><%= change_label %></p>
15
19
  <% end %>
16
- <% if info? %>
17
- <div class="<%= disclosure_classes %>" data-stat-card-info-target="panel">
18
- <% if definition %><p><span class="font-medium text-gray-700 dark:text-gray-300">Captures:</span> <%= definition %></p><% end %>
19
- <% if calculation %><p><span class="font-medium text-gray-700 dark:text-gray-300">Calc:</span> <%= calculation %></p><% end %>
20
- </div>
21
- <% end %>
22
20
  </div>
@@ -3,12 +3,13 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class StatCardComponent < ViewComponent::Base
6
- CARD_CLASSES = "rounded-xl border border-gray-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-800"
6
+ CARD_CLASSES = "relative rounded-xl border border-gray-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-800"
7
7
  LABEL_CLASSES = "text-sm font-medium text-gray-500 dark:text-gray-400"
8
8
  VALUE_BASE_CLASSES = "mt-1 text-3xl font-bold"
9
9
  SUFFIX_CLASSES = "text-lg text-gray-500 dark:text-gray-400"
10
- DISCLOSURE_CLASSES = "hidden mt-4 space-y-1 border-t border-gray-200 pt-3 text-sm text-gray-600 dark:border-zinc-700 dark:text-gray-400"
11
- INFO_BUTTON_CLASSES = "shrink-0 text-gray-400 transition hover:text-accent-600 dark:hover:text-accent-400"
10
+ DISCLOSURE_CLASSES = "hidden peer-hover:block peer-focus-visible:block absolute inset-x-0 top-full z-10 mt-2 space-y-1 rounded-lg border border-gray-200 bg-white p-3 text-sm text-gray-600 shadow-lg dark:border-zinc-700 dark:bg-zinc-800 dark:text-gray-400"
11
+ VALUE_LINK_CLASSES = "hover:underline focus:outline-none focus-visible:underline"
12
+ INFO_BUTTON_CLASSES = "peer shrink-0 text-gray-400 transition hover:text-accent-600 dark:hover:text-accent-400"
12
13
 
13
14
  INFO_ICON = <<~SVG.freeze
14
15
  <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
@@ -22,9 +23,9 @@ module Keystone
22
23
  info: "text-accent-600 dark:text-accent-400"
23
24
  }.freeze
24
25
 
25
- attr_reader :label, :value, :suffix, :definition, :calculation, :change
26
+ attr_reader :label, :value, :suffix, :definition, :calculation, :change, :href
26
27
 
27
- def initialize(label:, value:, variant: :neutral, suffix: nil, definition: nil, calculation: nil, change: nil)
28
+ def initialize(label:, value:, variant: :neutral, suffix: nil, definition: nil, calculation: nil, change: nil, href: nil)
28
29
  @label = label
29
30
  @value = value
30
31
  @variant = variant
@@ -32,6 +33,7 @@ module Keystone
32
33
  @definition = definition
33
34
  @calculation = calculation
34
35
  @change = change
36
+ @href = href
35
37
  end
36
38
 
37
39
  def classes
@@ -62,6 +64,14 @@ module Keystone
62
64
  !@change.nil?
63
65
  end
64
66
 
67
+ def link?
68
+ !@href.nil?
69
+ end
70
+
71
+ def value_link_classes
72
+ VALUE_LINK_CLASSES
73
+ end
74
+
65
75
  def change_label
66
76
  formatted = "#{format("%.1f", @change.abs)}%"
67
77
  return formatted if @change.zero?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module KeystoneUi
4
- VERSION = "0.6.0"
4
+ VERSION = "0.7.0"
5
5
  end
@@ -157,11 +157,14 @@ one raises at render time.
157
157
  close control.
158
158
  - `ui_progress(value:, max:, label: nil)` — a labeled progress bar. The percent
159
159
  is `value / max`, rounded and clamped at 100.
160
- - `ui_stat_card(label:, value:, variant: :neutral, suffix: nil, definition: nil, calculation: nil, change: nil)`
160
+ - `ui_stat_card(label:, value:, variant: :neutral, suffix: nil, definition: nil, calculation: nil, change: nil, href: nil)`
161
161
  — a single metric tile. `variant:` `:neutral` `:success` `:danger` `:warning`
162
162
  `:info` colors the value. `change:` is a signed number rendered as `▲ 4.2%` in
163
- green when positive, `▼` in red when negative, plain when zero. Passing
164
- `definition:` and/or `calculation:` adds an info button that reveals them.
163
+ green when positive, `▼` in red when negative, plain when zero. `href:` makes
164
+ the value a link to its drill-down screen; only the value is linked, never the
165
+ whole card. Passing `definition:` and/or `calculation:` adds an info button
166
+ whose details show in a panel floating below the card while the button is
167
+ hovered or focused, and tapping the button toggles it.
165
168
  - `ui_copy_button(text:, label: "Copy", success_message: "Copied!", error_message: "Failed!")`
166
169
  — copies `text:` to the clipboard.
167
170
  - `ui_code(language: nil, caption: nil)` — takes a block holding the code. The
@@ -242,7 +245,8 @@ one raises at render time.
242
245
  5. Fill the body with the leaf helpers from the Interface above. Reach for the
243
246
  most specific one that fits — `ui_form_field` over `ui_input`,
244
247
  `ui_data_table` over a hand-built `<table>`, `ui_stat_card` over a panel with
245
- text in it.
248
+ text in it. To make a stat card clickable, pass `href:` — never wrap it in
249
+ `ui_card_link`, because a tap on the info button would then follow the link.
246
250
 
247
251
  6. For a table, decide how columns are declared. Use `{ key: "Label" }` hashes
248
252
  when every column is plain. Switch the whole set to `Keystone::Ui::Column`
@@ -105,6 +105,7 @@ sources:
105
105
  - app/components/keystone/ui/settings_link_component.rb
106
106
  - app/components/keystone/ui/show_page_component.rb
107
107
  - app/components/keystone/ui/stat_card_component.rb
108
+ - app/components/keystone/ui/stat_card_component.html.erb
108
109
  - app/components/keystone/ui/swipe_deck_component.rb
109
110
  - app/components/keystone/ui/tab_switcher_component.rb
110
111
  - app/components/keystone/ui/textarea_component.rb
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keystone_ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tyler Schneider
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-07-31 00:00:00.000000000 Z
11
+ date: 2026-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: view_component
@@ -37,6 +37,7 @@ executables: []
37
37
  extensions: []
38
38
  extra_rdoc_files: []
39
39
  files:
40
+ - MIT-LICENSE
40
41
  - app/assets/javascripts/keystone_ui/accordion_controller.js
41
42
  - app/assets/javascripts/keystone_ui/auto_submit_controller.js
42
43
  - app/assets/javascripts/keystone_ui/chartjs.js