keystone_ui 0.16.0 → 0.17.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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/keystone_ui/file_upload_controller.js +2 -4
  3. data/app/components/keystone/ui/accordion_component.rb +9 -9
  4. data/app/components/keystone/ui/bottom_nav_component.rb +1 -1
  5. data/app/components/keystone/ui/bottom_nav_item_component.rb +2 -2
  6. data/app/components/keystone/ui/bucket_component.rb +9 -9
  7. data/app/components/keystone/ui/bucket_series_component.rb +1 -1
  8. data/app/components/keystone/ui/card_link_component.rb +4 -4
  9. data/app/components/keystone/ui/chart_card_component.rb +2 -2
  10. data/app/components/keystone/ui/checkbox_row_component.rb +4 -4
  11. data/app/components/keystone/ui/code_component.rb +3 -3
  12. data/app/components/keystone/ui/color_picker_component.html.erb +1 -1
  13. data/app/components/keystone/ui/color_picker_component.rb +4 -2
  14. data/app/components/keystone/ui/column_picker_component.rb +4 -4
  15. data/app/components/keystone/ui/copy_button_component.rb +1 -1
  16. data/app/components/keystone/ui/cta_banner_component.rb +7 -7
  17. data/app/components/keystone/ui/data_table_component.html.erb +4 -4
  18. data/app/components/keystone/ui/data_table_component.rb +14 -10
  19. data/app/components/keystone/ui/disclosure_component.rb +4 -4
  20. data/app/components/keystone/ui/feature_grid_component.rb +13 -13
  21. data/app/components/keystone/ui/file_upload_component.rb +10 -10
  22. data/app/components/keystone/ui/form_component.rb +1 -1
  23. data/app/components/keystone/ui/form_field_component.rb +2 -2
  24. data/app/components/keystone/ui/form_page_component.rb +2 -2
  25. data/app/components/keystone/ui/funnel_component.rb +12 -12
  26. data/app/components/keystone/ui/grid_component.rb +3 -3
  27. data/app/components/keystone/ui/hero_component.rb +11 -11
  28. data/app/components/keystone/ui/mobile_actions_component.rb +2 -2
  29. data/app/components/keystone/ui/mobile_header_component.rb +4 -4
  30. data/app/components/keystone/ui/modal_component.rb +5 -5
  31. data/app/components/keystone/ui/multi_select_component.rb +4 -4
  32. data/app/components/keystone/ui/nav_dropdown_component.rb +4 -4
  33. data/app/components/keystone/ui/nav_item_component.rb +1 -1
  34. data/app/components/keystone/ui/navbar_component.rb +1 -1
  35. data/app/components/keystone/ui/option_card_component.rb +2 -2
  36. data/app/components/keystone/ui/panel_component.rb +3 -3
  37. data/app/components/keystone/ui/pipeline_component.rb +14 -14
  38. data/app/components/keystone/ui/progress_component.rb +3 -3
  39. data/app/components/keystone/ui/radio_card_component.rb +4 -4
  40. data/app/components/keystone/ui/settings_link_component.html.erb +1 -1
  41. data/app/components/keystone/ui/settings_link_component.rb +3 -2
  42. data/app/components/keystone/ui/show_page_component.rb +2 -2
  43. data/app/components/keystone/ui/stat_card_component.html.erb +3 -3
  44. data/app/components/keystone/ui/stat_card_component.rb +17 -15
  45. data/app/components/keystone/ui/swipe_deck_component.html.erb +6 -6
  46. data/app/components/keystone/ui/swipe_deck_component.rb +7 -1
  47. data/app/components/keystone/ui/tab_switcher_component.rb +3 -3
  48. data/app/components/keystone/ui/theme_toggle_component.rb +2 -2
  49. data/lib/keystone_ui/source_css.rb +0 -1
  50. data/lib/keystone_ui/version.rb +1 -1
  51. data/the_local/agents/keystone_ui-info.md +12 -0
  52. data/the_local/agents/keystone_ui-install.md +27 -2
  53. metadata +3 -4
  54. data/app/assets/tailwind/keystone_ui_engine/nav.css +0 -175
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: efab888e379841270a79e3d2410df8c4905eb0270f5e13091b2f7db40d96f0fc
4
- data.tar.gz: f5487f7756e4771a754d7bba15ccb009519ac0af076c4dc04dd28015586f9672
3
+ metadata.gz: 7e0dc7211df561f52f213d69e2733292b883fd7bb31cb6bc203ba581e90c5022
4
+ data.tar.gz: e95919dc9707abaae6d12837d193ace1bed9a16b8f5d00c0758f0f2a6c82cf23
5
5
  SHA512:
6
- metadata.gz: 4f0c8f0433e90eb500c28eb36201b69d141968a6c482db81e9ccb4fd3e0cf0e81ed202d8b6f8b1dae6cd2e8f325b1d92674aa1464c9029470a4d26082e92fd20
7
- data.tar.gz: 4e5c1a2317719013e90221c344248aecb5b88649722e968806af6b7d7001b994a5bf9cc9a6f05d16cc75384c66a04ff49b4702f21d20696d8516d6f65b354058
6
+ metadata.gz: 6f0ccf38449bfa1c327f0abfc4e4bf818f80859a90ff19a6a5f680b43ba6790de67502d218ba7cfba32a019ff1ee96c4ab0653ffaca5bfaa97b6beb226110d18
7
+ data.tar.gz: 6019b1917c3736e6323cf5c924be7e0a7e5a2d3686aa3d371bf520f548046e7a7bdf42dccc6afcc5664693d558c77482cf4f7061c05fc383e81e6effd48ecb7e
@@ -21,14 +21,12 @@ export default class extends Controller {
21
21
 
22
22
  dragOver(event) {
23
23
  event.preventDefault()
24
- this.dropZoneTarget.classList.add("border-accent-500", "bg-accent-50", "dark:bg-accent-900/10")
25
- this.dropZoneTarget.classList.remove("border-gray-300", "dark:border-zinc-600")
24
+ this.dropZoneTarget.classList.add("ks-file-upload-drop-zone-active")
26
25
  }
27
26
 
28
27
  dragLeave(event) {
29
28
  event.preventDefault()
30
- this.dropZoneTarget.classList.remove("border-accent-500", "bg-accent-50", "dark:bg-accent-900/10")
31
- this.dropZoneTarget.classList.add("border-gray-300", "dark:border-zinc-600")
29
+ this.dropZoneTarget.classList.remove("ks-file-upload-drop-zone-active")
32
30
  }
33
31
 
34
32
  drop(event) {
@@ -3,11 +3,11 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class AccordionComponent < ViewComponent::Base
6
- BASE_CLASSES = "flex flex-col gap-4"
7
- ITEM_LAYOUT_CLASSES = "rounded-xl border"
8
- BUTTON_LAYOUT_CLASSES = "flex w-full items-center justify-between px-6 py-4 text-left font-semibold transition"
9
- ANSWER_LAYOUT_CLASSES = "hidden px-6 pb-4 text-sm"
10
- ICON_LAYOUT_CLASSES = "shrink-0 transition-transform"
6
+ BASE_CLASSES = "ks-accordion flex flex-col"
7
+ ITEM_LAYOUT_CLASSES = "ks-accordion-item"
8
+ BUTTON_LAYOUT_CLASSES = "ks-accordion-button flex w-full items-center justify-between text-left transition"
9
+ ANSWER_LAYOUT_CLASSES = "ks-accordion-answer hidden text-sm"
10
+ ICON_LAYOUT_CLASSES = "ks-disclosure-icon shrink-0 transition-transform"
11
11
 
12
12
  CARET_ICON = <<~SVG.freeze
13
13
  <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="M19 9l-7 7-7-7" /></svg>
@@ -24,19 +24,19 @@ module Keystone
24
24
  end
25
25
 
26
26
  def item_classes
27
- "#{ITEM_LAYOUT_CLASSES} border-surface-200 dark:border-surface-700"
27
+ ITEM_LAYOUT_CLASSES
28
28
  end
29
29
 
30
30
  def button_classes
31
- "#{BUTTON_LAYOUT_CLASSES} text-surface-900 dark:text-white hover:text-accent-600 dark:hover:text-accent-400"
31
+ BUTTON_LAYOUT_CLASSES
32
32
  end
33
33
 
34
34
  def answer_classes
35
- "#{ANSWER_LAYOUT_CLASSES} text-surface-600 dark:text-surface-400"
35
+ ANSWER_LAYOUT_CLASSES
36
36
  end
37
37
 
38
38
  def icon_classes
39
- "#{ICON_LAYOUT_CLASSES} text-surface-400"
39
+ ICON_LAYOUT_CLASSES
40
40
  end
41
41
 
42
42
  def caret_icon
@@ -3,7 +3,7 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class BottomNavComponent < ViewComponent::Base
6
- NAV_CLASSES = "bottom-nav lg:hidden hotwire-native:hidden"
6
+ NAV_CLASSES = "ks-bottom-nav lg:hidden hotwire-native:hidden"
7
7
 
8
8
  def nav_classes
9
9
  NAV_CLASSES
@@ -12,9 +12,9 @@ module Keystone
12
12
  @active = active
13
13
  end
14
14
 
15
- ITEM_BASE = "bottom-nav-item"
15
+ ITEM_BASE = "ks-bottom-nav-item"
16
16
  ACTIVE_CLASS = "active"
17
- LABEL_CLASSES = "bottom-nav-label"
17
+ LABEL_CLASSES = "ks-bottom-nav-label"
18
18
 
19
19
  def item_classes
20
20
  @active ? "#{ITEM_BASE} #{ACTIVE_CLASS}" : ITEM_BASE
@@ -3,17 +3,17 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class BucketComponent < ViewComponent::Base
6
- CONTAINER_CLASSES = "flex w-24 flex-col items-center gap-1"
7
- LABEL_CLASSES = "text-center text-sm font-medium text-gray-700 dark:text-gray-300"
8
- GOAL_CLASSES = "text-xs tabular-nums text-gray-500 dark:text-gray-400"
9
- TANK_CLASSES = "flex h-40 w-full items-end overflow-hidden rounded-t-sm rounded-b-xl border-2 border-gray-300 bg-gray-50 dark:border-zinc-600 dark:bg-zinc-800"
10
- ACTUAL_CLASSES = "text-sm font-semibold tabular-nums text-gray-900 dark:text-white"
11
- PERCENT_CLASSES = "text-xs tabular-nums text-gray-500 dark:text-gray-400"
6
+ CONTAINER_CLASSES = "ks-bucket flex w-24 flex-col items-center"
7
+ LABEL_CLASSES = "ks-bucket-label text-center text-sm"
8
+ GOAL_CLASSES = "ks-bucket-goal text-xs tabular-nums"
9
+ TANK_CLASSES = "ks-bucket-tank flex h-40 w-full items-end overflow-hidden"
10
+ ACTUAL_CLASSES = "ks-bucket-actual text-sm tabular-nums"
11
+ PERCENT_CLASSES = "ks-bucket-percent text-xs tabular-nums"
12
12
  FILL_BASE_CLASSES = "w-full transition-all"
13
- WITHIN_GOAL_FILL_CLASSES = "bg-accent-500"
13
+ WITHIN_GOAL_FILL_CLASSES = "ks-bucket-fill"
14
14
  OVER_GOAL_FILL_CLASSES = {
15
- success: "bg-green-500",
16
- warning: "bg-amber-500"
15
+ success: "ks-bucket-fill-over",
16
+ warning: "ks-bucket-fill-over-warning"
17
17
  }.freeze
18
18
 
19
19
  attr_reader :goal, :actual, :label
@@ -3,7 +3,7 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class BucketSeriesComponent < ViewComponent::Base
6
- ROW_CLASSES = "flex flex-wrap justify-center gap-4 sm:justify-start"
6
+ ROW_CLASSES = "ks-bucket-series flex flex-wrap justify-center sm:justify-start"
7
7
 
8
8
  def initialize(buckets:)
9
9
  @buckets = buckets
@@ -3,9 +3,9 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class CardLinkComponent < ViewComponent::Base
6
- BASE_CLASSES = "block rounded-lg border border-gray-200 bg-white dark:border-zinc-700 dark:bg-zinc-900"
7
- SHADOW_CLASS = "shadow-sm"
8
- PADDING_CLASSES = { sm: "p-3", md: "p-4", lg: "p-6" }.freeze
6
+ BASE_CLASSES = "ks-link-card block"
7
+ SHADOW_CLASS = "ks-link-card-shadow"
8
+ PADDING_CLASSES = { sm: "ks-link-card-padding-sm", md: "ks-link-card-padding-md", lg: "ks-link-card-padding-lg" }.freeze
9
9
 
10
10
  attr_reader :href
11
11
 
@@ -16,7 +16,7 @@ module Keystone
16
16
  end
17
17
 
18
18
  def classes
19
- tokens = [ BASE_CLASSES, "hover:border-accent-500/50", PADDING_CLASSES.fetch(@padding) ]
19
+ tokens = [ BASE_CLASSES, PADDING_CLASSES.fetch(@padding) ]
20
20
  tokens << SHADOW_CLASS if @shadow
21
21
  tokens.join(" ")
22
22
  end
@@ -3,8 +3,8 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class ChartCardComponent < ViewComponent::Base
6
- CARD_CLASSES = "rounded-xl border border-gray-200 bg-white p-6 dark:border-zinc-700 dark:bg-zinc-800"
7
- TITLE_CLASSES = "text-sm font-medium text-gray-500 dark:text-gray-400 mb-4"
6
+ CARD_CLASSES = "ks-metric-card"
7
+ TITLE_CLASSES = "ks-chart-card-title text-sm"
8
8
 
9
9
  HEIGHT_CLASSES = {
10
10
  sm: "h-48",
@@ -3,10 +3,10 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class CheckboxRowComponent < ViewComponent::Base
6
- ROW_CLASSES = "flex items-start gap-3 py-3 cursor-pointer"
7
- INPUT_CLASSES = "mt-0.5 size-4 shrink-0 rounded border-surface-300 text-accent-600 checked:bg-accent-600 focus:ring-accent-500"
8
- LABEL_CLASSES = "block text-sm font-medium text-surface-900 dark:text-surface-100"
9
- HINT_CLASSES = "block mt-0.5 text-sm text-surface-500 dark:text-surface-400"
6
+ ROW_CLASSES = "ks-checkbox-row flex items-start cursor-pointer"
7
+ INPUT_CLASSES = "ks-checkbox-row-input size-4 shrink-0"
8
+ LABEL_CLASSES = "ks-checkbox-row-label block text-sm"
9
+ HINT_CLASSES = "ks-checkbox-row-hint block text-sm"
10
10
 
11
11
  attr_reader :name, :value, :label, :hint
12
12
 
@@ -3,9 +3,9 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class CodeComponent < ViewComponent::Base
6
- WRAPPER_CLASSES = "overflow-hidden rounded-lg border border-surface-200 dark:border-surface-700"
7
- CAPTION_CLASSES = "border-b border-surface-200 bg-surface-50 px-4 py-2 font-mono text-xs text-surface-500 dark:border-surface-700 dark:bg-surface-800 dark:text-surface-400"
8
- PRE_CLASSES = "overflow-x-auto bg-surface-900 p-4 font-mono text-sm leading-relaxed text-surface-100 dark:bg-black"
6
+ WRAPPER_CLASSES = "ks-code overflow-hidden"
7
+ CAPTION_CLASSES = "ks-code-caption font-mono text-xs"
8
+ PRE_CLASSES = "ks-code-block overflow-x-auto font-mono text-sm leading-relaxed"
9
9
 
10
10
  attr_reader :language, :caption
11
11
 
@@ -1,6 +1,6 @@
1
1
  <div class="relative inline-block" data-controller="<%= controller_name %>" data-color-picker-value-value="<%= value %>">
2
2
  <% if label %>
3
- <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1"><%= label %></label>
3
+ <label class="<%= LABEL_CLASSES %>"><%= label %></label>
4
4
  <% end %>
5
5
 
6
6
  <div class="flex items-center gap-2">
@@ -3,9 +3,11 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class ColorPickerComponent < ViewComponent::Base
6
- SWATCH_CLASSES = "w-10 h-10 rounded-lg border border-gray-300 dark:border-zinc-600 cursor-pointer"
6
+ SWATCH_CLASSES = "ks-color-swatch w-10 h-10 cursor-pointer"
7
7
 
8
- PANEL_CLASSES = "absolute z-50 mt-2 p-3 rounded-lg shadow-lg bg-white dark:bg-zinc-800 border border-gray-200 dark:border-zinc-700 hidden"
8
+ LABEL_CLASSES = "ks-color-picker-label ks-label"
9
+
10
+ PANEL_CLASSES = "ks-color-picker-panel absolute z-50 hidden"
9
11
 
10
12
  attr_reader :name, :value, :label
11
13
 
@@ -4,10 +4,10 @@ module Keystone
4
4
  module Ui
5
5
  class ColumnPickerComponent < ViewComponent::Base
6
6
  WRAPPER_CLASSES = "relative inline-block"
7
- TRIGGER_CLASSES = "inline-flex items-center gap-1 rounded-md border px-3 py-2 text-sm border-gray-300 bg-white text-gray-900 dark:border-zinc-700 dark:bg-zinc-900 dark:text-white"
8
- MENU_CLASSES = "absolute right-0 z-10 mt-1 w-56 rounded-md border border-gray-200 bg-white shadow-lg dark:border-zinc-700 dark:bg-zinc-900 hidden"
9
- OPTION_CLASSES = "flex items-center gap-2 px-3 py-2 text-sm text-gray-700 hover:bg-gray-50 dark:text-gray-300 dark:hover:bg-zinc-800 cursor-pointer"
10
- CHECKBOX_CLASSES = "rounded border-gray-300 text-accent-600 focus:ring-accent-500 dark:border-zinc-600"
7
+ TRIGGER_CLASSES = "ks-menu-trigger inline-flex items-center text-sm"
8
+ MENU_CLASSES = "ks-menu absolute right-0 z-10 w-56 hidden"
9
+ OPTION_CLASSES = "ks-menu-option flex items-center text-sm cursor-pointer"
10
+ CHECKBOX_CLASSES = "ks-menu-checkbox"
11
11
 
12
12
  COLUMNS_ICON = <<~SVG.freeze
13
13
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="w-4 h-4">
@@ -3,7 +3,7 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class CopyButtonComponent < ViewComponent::Base
6
- BUTTON_CLASSES = "inline-flex items-center gap-1.5 rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-medium text-gray-700 transition hover:bg-gray-50 dark:border-zinc-600 dark:bg-zinc-800 dark:text-gray-300 dark:hover:bg-zinc-700"
6
+ BUTTON_CLASSES = "ks-copy-button inline-flex items-center text-sm transition"
7
7
 
8
8
  COPY_ICON = <<~SVG.freeze
9
9
  <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" /></svg>
@@ -3,10 +3,10 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class CtaBannerComponent < ViewComponent::Base
6
- CARD_LAYOUT_CLASSES = "rounded-2xl border px-6 py-12 text-center lg:px-16 lg:py-16"
7
- TITLE_BASE_CLASSES = "mb-4 text-3xl font-bold tracking-tight sm:text-4xl"
8
- SUBTITLE_BASE_CLASSES = "mx-auto mb-8 max-w-2xl text-lg"
9
- ACTIONS_CLASSES = "flex flex-wrap justify-center gap-4"
6
+ CARD_LAYOUT_CLASSES = "ks-cta-banner text-center"
7
+ TITLE_BASE_CLASSES = "ks-cta-banner-title text-3xl tracking-tight sm:text-4xl"
8
+ SUBTITLE_BASE_CLASSES = "ks-cta-banner-subtitle mx-auto max-w-2xl text-lg"
9
+ ACTIONS_CLASSES = "ks-cta-banner-actions flex flex-wrap justify-center"
10
10
 
11
11
  attr_reader :title, :subtitle
12
12
 
@@ -16,15 +16,15 @@ module Keystone
16
16
  end
17
17
 
18
18
  def classes
19
- "#{CARD_LAYOUT_CLASSES} border-surface-200 dark:border-surface-700 bg-surface-50 dark:bg-surface-800"
19
+ CARD_LAYOUT_CLASSES
20
20
  end
21
21
 
22
22
  def title_classes
23
- "#{TITLE_BASE_CLASSES} text-surface-900 dark:text-white"
23
+ TITLE_BASE_CLASSES
24
24
  end
25
25
 
26
26
  def subtitle_classes
27
- "#{SUBTITLE_BASE_CLASSES} text-surface-500 dark:text-surface-400"
27
+ SUBTITLE_BASE_CLASSES
28
28
  end
29
29
 
30
30
  def subtitle?
@@ -1,6 +1,6 @@
1
- <div class="overflow-hidden rounded-lg border border-gray-200 shadow-sm dark:border-zinc-700 dark:shadow-none">
1
+ <div class="<%= Keystone::Ui::DataTableComponent::WRAPPER_CLASSES %>">
2
2
  <table class="relative min-w-full divide-y divide-gray-300 dark:divide-white/15">
3
- <thead class="bg-gray-50 dark:bg-gray-800/75">
3
+ <thead class="<%= Keystone::Ui::DataTableComponent::HEAD_CLASSES %>">
4
4
  <tr>
5
5
  <% header_cells.each do |cell| %>
6
6
  <th scope="<%= cell[:scope] %>" class="<%= cell[:classes] %>">
@@ -20,11 +20,11 @@
20
20
  <% end %>
21
21
  </tr>
22
22
  </thead>
23
- <tbody class="divide-y divide-gray-200 bg-white dark:divide-white/10 dark:bg-gray-800/50">
23
+ <tbody class="<%= Keystone::Ui::DataTableComponent::BODY_CLASSES %>">
24
24
  <% if empty? %>
25
25
  <% if @empty_message %>
26
26
  <tr>
27
- <td class="px-3 py-4 text-sm text-gray-500 dark:text-gray-400" colspan="<%= column_count %>">
27
+ <td class="<%= Keystone::Ui::DataTableComponent::EMPTY_CELL_CLASSES %>" colspan="<%= column_count %>">
28
28
  <%= @empty_message %>
29
29
  </td>
30
30
  </tr>
@@ -3,20 +3,24 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class DataTableComponent < ViewComponent::Base
6
- HEADER_CLASSES_FIRST = "py-3.5 pr-3 pl-6 text-left text-sm font-semibold text-gray-900 dark:text-gray-200"
7
- HEADER_CLASSES_MIDDLE = "px-3 py-3.5 text-left text-sm font-semibold text-gray-900 dark:text-gray-200"
8
- HEADER_CLASSES_LAST = "py-3.5 pr-6 pl-3"
9
-
10
- ROW_CLASSES_FIRST = "py-4 pr-3 pl-6 text-sm font-medium whitespace-nowrap text-gray-900 dark:text-white"
11
- ROW_CLASSES_MIDDLE = "px-3 py-4 text-sm whitespace-nowrap text-gray-500 dark:text-gray-400"
12
- ROW_CLASSES_LAST = "py-4 pr-6 pl-3 text-right text-sm font-medium whitespace-nowrap"
6
+ EMPTY_CELL_CLASSES = "ks-table-cell-middle text-sm"
7
+ BODY_CLASSES = "ks-table-body"
8
+ HEAD_CLASSES = "ks-table-head"
9
+ WRAPPER_CLASSES = "ks-table overflow-hidden"
10
+ HEADER_CLASSES_FIRST = "ks-table-header ks-table-header-first text-left text-sm"
11
+ HEADER_CLASSES_MIDDLE = "ks-table-header ks-table-header-middle text-left text-sm"
12
+ HEADER_CLASSES_LAST = "ks-table-header-last"
13
+
14
+ ROW_CLASSES_FIRST = "ks-table-cell-first text-sm whitespace-nowrap"
15
+ ROW_CLASSES_MIDDLE = "ks-table-cell-middle text-sm whitespace-nowrap"
16
+ ROW_CLASSES_LAST = "ks-table-cell-last text-right text-sm whitespace-nowrap"
13
17
 
14
18
  MOBILE_HIDDEN_CLASSES = "hidden sm:table-cell"
15
19
 
16
- SORT_LINK_CLASSES = "group inline-flex items-center gap-1"
20
+ SORT_LINK_CLASSES = "ks-table-sort-link group inline-flex items-center"
17
21
  SORT_ICON_CLASSES = "h-4 w-4 flex-shrink-0"
18
- SORT_ICON_ACTIVE = "text-gray-700 dark:text-gray-300"
19
- SORT_ICON_INACTIVE = "text-gray-400 dark:text-gray-500 invisible group-hover:visible"
22
+ SORT_ICON_ACTIVE = "ks-table-sort-icon-active"
23
+ SORT_ICON_INACTIVE = "ks-table-sort-icon invisible group-hover:visible"
20
24
 
21
25
  SORT_ASC_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 17a.75.75 0 0 1-.75-.75V5.612L5.29 9.77a.75.75 0 0 1-1.08-1.04l5.25-5.5a.75.75 0 0 1 1.08 0l5.25 5.5a.75.75 0 1 1-1.08 1.04l-3.96-4.158V16.25A.75.75 0 0 1 10 17Z" clip-rule="evenodd" /></svg>'
22
26
  SORT_DESC_ICON = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 3a.75.75 0 0 1 .75.75v10.638l3.96-4.158a.75.75 0 1 1 1.08 1.04l-5.25 5.5a.75.75 0 0 1-1.08 0l-5.25-5.5a.75.75 0 0 1 1.08-1.04l3.96 4.158V3.75A.75.75 0 0 1 10 3Z" clip-rule="evenodd" /></svg>'
@@ -3,10 +3,10 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class DisclosureComponent < ViewComponent::Base
6
- WRAPPER_CLASSES = "group rounded-xl border border-surface-200 dark:border-surface-700"
7
- SUMMARY_CLASSES = "flex cursor-pointer list-none items-center justify-between gap-4 px-6 py-4 font-semibold text-surface-900 [&::-webkit-details-marker]:hidden dark:text-white"
8
- ICON_CLASSES = "h-4 w-4 shrink-0 text-surface-400 transition-transform group-open:rotate-180"
9
- BODY_CLASSES = "px-6 pb-4 text-sm text-surface-600 dark:text-surface-400"
6
+ WRAPPER_CLASSES = "ks-disclosure group"
7
+ SUMMARY_CLASSES = "ks-disclosure-summary flex cursor-pointer list-none items-center justify-between [&::-webkit-details-marker]:hidden"
8
+ ICON_CLASSES = "ks-disclosure-icon h-4 w-4 shrink-0 transition-transform group-open:rotate-180"
9
+ BODY_CLASSES = "ks-disclosure-body text-sm"
10
10
 
11
11
  CARET_ICON = <<~SVG.freeze
12
12
  <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="M19 9l-7 7-7-7" /></svg>
@@ -3,13 +3,13 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class FeatureGridComponent < ViewComponent::Base
6
- GRID_CLASSES = "grid gap-6 sm:grid-cols-2 lg:grid-cols-3"
7
- TITLE_BASE_CLASSES = "mb-4 text-center text-3xl font-bold tracking-tight sm:text-4xl"
8
- SUBTITLE_BASE_CLASSES = "mx-auto mb-16 max-w-2xl text-center text-lg"
9
- CARD_LAYOUT_CLASSES = "rounded-xl border p-6 transition"
10
- ICON_BASE_CLASSES = "mb-4 flex size-10 items-center justify-center rounded-lg text-lg"
11
- CARD_TITLE_BASE_CLASSES = "mb-2 text-lg font-semibold"
12
- CARD_DESCRIPTION_BASE_CLASSES = "text-sm"
6
+ GRID_CLASSES = "ks-feature-grid grid sm:grid-cols-2 lg:grid-cols-3"
7
+ TITLE_BASE_CLASSES = "ks-feature-grid-title text-center text-3xl tracking-tight sm:text-4xl"
8
+ SUBTITLE_BASE_CLASSES = "ks-feature-grid-subtitle mx-auto max-w-2xl text-center text-lg"
9
+ CARD_LAYOUT_CLASSES = "ks-feature-card transition"
10
+ ICON_BASE_CLASSES = "ks-feature-card-icon flex size-10 items-center justify-center text-lg"
11
+ CARD_TITLE_BASE_CLASSES = "ks-feature-card-title text-lg"
12
+ CARD_DESCRIPTION_BASE_CLASSES = "ks-feature-card-description text-sm"
13
13
 
14
14
  attr_reader :title, :subtitle, :features
15
15
 
@@ -24,11 +24,11 @@ module Keystone
24
24
  end
25
25
 
26
26
  def title_classes
27
- "#{TITLE_BASE_CLASSES} text-surface-900 dark:text-white"
27
+ TITLE_BASE_CLASSES
28
28
  end
29
29
 
30
30
  def subtitle_classes
31
- "#{SUBTITLE_BASE_CLASSES} text-surface-500 dark:text-surface-400"
31
+ SUBTITLE_BASE_CLASSES
32
32
  end
33
33
 
34
34
  def subtitle?
@@ -36,19 +36,19 @@ module Keystone
36
36
  end
37
37
 
38
38
  def card_classes
39
- "#{CARD_LAYOUT_CLASSES} border-surface-200 dark:border-surface-700 bg-white dark:bg-surface-800 hover:border-accent-500/50 dark:hover:border-accent-500/50"
39
+ CARD_LAYOUT_CLASSES
40
40
  end
41
41
 
42
42
  def icon_classes
43
- "#{ICON_BASE_CLASSES} bg-accent-500/10 text-accent-600 dark:text-accent-400"
43
+ ICON_BASE_CLASSES
44
44
  end
45
45
 
46
46
  def card_title_classes
47
- "#{CARD_TITLE_BASE_CLASSES} text-surface-900 dark:text-white"
47
+ CARD_TITLE_BASE_CLASSES
48
48
  end
49
49
 
50
50
  def card_description_classes
51
- "#{CARD_DESCRIPTION_BASE_CLASSES} text-surface-500 dark:text-surface-400"
51
+ CARD_DESCRIPTION_BASE_CLASSES
52
52
  end
53
53
  end
54
54
  end
@@ -3,16 +3,16 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class FileUploadComponent < ViewComponent::Base
6
- WRAPPER_CLASSES = "space-y-1"
7
- LABEL_CLASSES = "block text-sm font-medium text-gray-700 dark:text-gray-300"
8
- DROP_ZONE_CLASSES = "mt-1 flex justify-center rounded-md border-2 border-dashed border-gray-300 px-6 py-8 cursor-pointer dark:border-zinc-600 transition-colors"
9
- DROP_ZONE_ACTIVE_CLASSES = "border-accent-500 bg-accent-50 dark:bg-accent-900/10"
10
- DROP_ZONE_INNER_CLASSES = "space-y-2 text-center"
11
- ICON_CLASSES = "mx-auto h-10 w-10 text-gray-400 dark:text-gray-500"
12
- PROMPT_CLASSES = "text-sm text-gray-600 dark:text-gray-400"
13
- BROWSE_CLASSES = "font-semibold text-accent-600 hover:text-accent-500 dark:text-accent-400 dark:hover:text-accent-300"
14
- HINT_CLASSES = "mt-1 text-xs text-gray-500 dark:text-gray-400"
15
- FILE_NAME_CLASSES = "mt-2 text-sm text-gray-700 dark:text-gray-300 truncate"
6
+ WRAPPER_CLASSES = "ks-file-upload"
7
+ LABEL_CLASSES = "ks-label block text-sm"
8
+ DROP_ZONE_CLASSES = "ks-file-upload-drop-zone flex justify-center cursor-pointer transition-colors"
9
+ DROP_ZONE_ACTIVE_CLASSES = "ks-file-upload-drop-zone-active"
10
+ DROP_ZONE_INNER_CLASSES = "ks-file-upload-inner text-center"
11
+ ICON_CLASSES = "ks-file-upload-icon mx-auto h-10 w-10"
12
+ PROMPT_CLASSES = "ks-file-upload-prompt text-sm"
13
+ BROWSE_CLASSES = "ks-file-upload-browse"
14
+ HINT_CLASSES = "ks-file-upload-hint text-xs"
15
+ FILE_NAME_CLASSES = "ks-file-upload-file-name text-sm truncate"
16
16
  FILE_INPUT_CLASSES = "sr-only"
17
17
 
18
18
  UPLOAD_ICON = <<~SVG.freeze
@@ -3,7 +3,7 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class FormComponent < ViewComponent::Base
6
- FORM_CLASSES = "space-y-6"
6
+ FORM_CLASSES = "ks-form"
7
7
 
8
8
  def initialize(action:, method: :post, multipart: false, data: nil)
9
9
  @action = action
@@ -3,13 +3,13 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class FormFieldComponent < ViewComponent::Base
6
- WRAPPER_CLASSES = "space-y-1"
6
+ WRAPPER_CLASSES = "ks-form-field"
7
7
  LABEL_CLASSES = "ks-label"
8
8
  REQUIRED_CLASSES = "ks-required"
9
9
  HINT_CLASSES = "ks-hint"
10
10
  ERROR_CLASSES = "ks-error"
11
11
  CHECKBOX_CLASSES = "ks-checkbox"
12
- CHECKBOX_WRAPPER_CLASSES = "flex items-center gap-2"
12
+ CHECKBOX_WRAPPER_CLASSES = "ks-form-field-checkbox flex items-center"
13
13
 
14
14
  def initialize(attribute:, label: nil, type: :text, required: false, hint: nil, placeholder: nil, min: nil, max: nil, step: nil, value: nil, options: [], errors: [], include_blank: nil, disabled: false)
15
15
  @attribute = attribute
@@ -4,8 +4,8 @@ module Keystone
4
4
  module Ui
5
5
  class FormPageComponent < ViewComponent::Base
6
6
  DESKTOP_WRAPPER_CLASSES = "hidden md:block"
7
- TITLE_CLASSES = "text-2xl font-semibold text-gray-900 dark:text-white"
8
- SUBTITLE_CLASSES = "mt-1 text-sm text-gray-500 dark:text-gray-400"
7
+ TITLE_CLASSES = "ks-page-title text-2xl"
8
+ SUBTITLE_CLASSES = "ks-page-header-subtitle text-sm"
9
9
 
10
10
  def initialize(title:, back_url:, subtitle: nil)
11
11
  @title = title
@@ -5,19 +5,19 @@ module Keystone
5
5
  class FunnelComponent < ViewComponent::Base
6
6
  Layer = Struct.new(:label, :value, :width_percent, :conversion_percent, :color_classes, keyword_init: true)
7
7
 
8
- CONTAINER_CLASSES = "space-y-2"
9
- LAYER_CLASSES = "space-y-1"
10
- ROW_CLASSES = "flex items-baseline justify-between gap-3"
11
- LABEL_CLASSES = "text-sm font-medium text-surface-700 truncate dark:text-surface-300"
12
- VALUE_CLASSES = "text-sm font-semibold text-surface-900 tabular-nums dark:text-white"
13
- BAR_CLASSES = "h-8 rounded-md transition-all"
14
- TRANSITION_CLASSES = "py-1 text-center text-xs text-surface-500 dark:text-surface-400"
8
+ CONTAINER_CLASSES = "ks-funnel"
9
+ LAYER_CLASSES = "ks-funnel-layer"
10
+ ROW_CLASSES = "ks-funnel-row flex items-baseline justify-between"
11
+ LABEL_CLASSES = "ks-funnel-label text-sm truncate"
12
+ VALUE_CLASSES = "ks-funnel-value text-sm tabular-nums"
13
+ BAR_CLASSES = "ks-funnel-bar h-8 transition-all"
14
+ TRANSITION_CLASSES = "ks-funnel-transition text-center text-xs"
15
15
  STEP_COLOR_CLASSES = {
16
- accent: "bg-accent-500",
17
- sky: "bg-sky-500",
18
- violet: "bg-violet-500",
19
- amber: "bg-amber-500",
20
- rose: "bg-rose-500"
16
+ accent: "ks-funnel-bar-accent",
17
+ sky: "ks-funnel-bar-sky",
18
+ violet: "ks-funnel-bar-violet",
19
+ amber: "ks-funnel-bar-amber",
20
+ rose: "ks-funnel-bar-rose"
21
21
  }.freeze
22
22
 
23
23
  attr_reader :steps
@@ -3,9 +3,9 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class GridComponent < ViewComponent::Base
6
- GAP_CLASSES = { sm: "gap-3", md: "gap-4", lg: "gap-6", xl: "gap-8" }.freeze
7
- GAP_X_CLASSES = { sm: "gap-x-3", md: "gap-x-4", lg: "gap-x-6", xl: "gap-x-8" }.freeze
8
- GAP_Y_CLASSES = { sm: "gap-y-3", md: "gap-y-4", lg: "gap-y-6", xl: "gap-y-8" }.freeze
6
+ GAP_CLASSES = { sm: "ks-grid-gap-sm", md: "ks-grid-gap-md", lg: "ks-grid-gap-lg", xl: "ks-grid-gap-xl" }.freeze
7
+ GAP_X_CLASSES = { sm: "ks-grid-gap-x-sm", md: "ks-grid-gap-x-md", lg: "ks-grid-gap-x-lg", xl: "ks-grid-gap-x-xl" }.freeze
8
+ GAP_Y_CLASSES = { sm: "ks-grid-gap-y-sm", md: "ks-grid-gap-y-md", lg: "ks-grid-gap-y-lg", xl: "ks-grid-gap-y-xl" }.freeze
9
9
  COL_CLASSES = {
10
10
  default: { 1 => "grid-cols-1", 2 => "grid-cols-2", 3 => "grid-cols-3", 4 => "grid-cols-4", 5 => "grid-cols-5", 6 => "grid-cols-6", 7 => "grid-cols-7", 8 => "grid-cols-8", 9 => "grid-cols-9", 10 => "grid-cols-10", 11 => "grid-cols-11", 12 => "grid-cols-12" }.freeze,
11
11
  sm: { 1 => "sm:grid-cols-1", 2 => "sm:grid-cols-2", 3 => "sm:grid-cols-3", 4 => "sm:grid-cols-4", 5 => "sm:grid-cols-5", 6 => "sm:grid-cols-6", 7 => "sm:grid-cols-7", 8 => "sm:grid-cols-8", 9 => "sm:grid-cols-9", 10 => "sm:grid-cols-10", 11 => "sm:grid-cols-11", 12 => "sm:grid-cols-12" }.freeze,
@@ -3,19 +3,19 @@
3
3
  module Keystone
4
4
  module Ui
5
5
  class HeroComponent < ViewComponent::Base
6
- WRAPPER_CLASSES = "relative min-h-screen pt-24"
7
- INNER_CLASSES = "mx-auto max-w-6xl px-6 py-24 lg:py-32"
6
+ WRAPPER_CLASSES = "ks-hero relative min-h-screen"
7
+ INNER_CLASSES = "ks-hero-inner mx-auto max-w-6xl"
8
8
 
9
- CONTENT_COLUMN_CLASSES = "flex flex-col gap-8"
9
+ CONTENT_COLUMN_CLASSES = "ks-hero-content flex flex-col"
10
10
  CENTERED_COLUMN_CLASSES = "items-center"
11
11
 
12
- SPLIT_CLASSES = "grid gap-12 lg:grid-cols-2 lg:gap-16 items-center"
12
+ SPLIT_CLASSES = "ks-hero-split grid lg:grid-cols-2 items-center"
13
13
  CENTERED_CLASSES = "flex flex-col items-center text-center"
14
14
 
15
- TITLE_BASE_CLASSES = "text-4xl font-bold tracking-tight sm:text-5xl lg:text-6xl"
16
- SUBTITLE_BASE_CLASSES = "max-w-lg text-lg"
17
- BADGE_BASE_CLASSES = "inline-flex w-fit items-center gap-2 rounded-full border px-4 py-1.5 text-sm"
18
- ACTIONS_CLASSES = "flex flex-wrap gap-4"
15
+ TITLE_BASE_CLASSES = "ks-hero-title text-4xl tracking-tight sm:text-5xl lg:text-6xl"
16
+ SUBTITLE_BASE_CLASSES = "ks-hero-subtitle max-w-lg text-lg"
17
+ BADGE_BASE_CLASSES = "ks-hero-badge inline-flex w-fit items-center text-sm"
18
+ ACTIONS_CLASSES = "ks-hero-actions flex flex-wrap"
19
19
 
20
20
  renders_one :aside
21
21
 
@@ -47,11 +47,11 @@ module Keystone
47
47
  end
48
48
 
49
49
  def title_classes
50
- "#{TITLE_BASE_CLASSES} text-surface-900 dark:text-white"
50
+ TITLE_BASE_CLASSES
51
51
  end
52
52
 
53
53
  def subtitle_classes
54
- "#{SUBTITLE_BASE_CLASSES} text-surface-500 dark:text-surface-400"
54
+ SUBTITLE_BASE_CLASSES
55
55
  end
56
56
 
57
57
  def subtitle?
@@ -59,7 +59,7 @@ module Keystone
59
59
  end
60
60
 
61
61
  def badge_classes
62
- "#{BADGE_BASE_CLASSES} border-accent-500/20 bg-accent-500/10 text-accent-600 dark:text-accent-400"
62
+ BADGE_BASE_CLASSES
63
63
  end
64
64
 
65
65
  def badge?
@@ -10,8 +10,8 @@ module Keystone
10
10
  SVG
11
11
 
12
12
  WRAPPER_CLASSES = "relative lg:hidden"
13
- BUTTON_CLASSES = "text-gray-500 dark:text-gray-400"
14
- DROPDOWN_CLASSES = "hidden absolute right-0 z-50 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black/5 dark:bg-zinc-800 dark:ring-white/10"
13
+ BUTTON_CLASSES = "ks-action-menu-button"
14
+ DROPDOWN_CLASSES = "ks-action-menu hidden absolute right-0 z-50 w-48 origin-top-right"
15
15
 
16
16
  def wrapper_data
17
17
  { controller: "dropdown" }