infotable 1.0.0 → 1.2.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -2
  3. data/app/assets/javascripts/infotable/controllers/drawer_controller.js +68 -42
  4. data/app/assets/javascripts/infotable/controllers/table_controller.js +127 -23
  5. data/app/assets/tailwind/infotable/engine.css +5 -0
  6. data/app/controllers/infotable/tables_controller.rb +17 -7
  7. data/app/helpers/infotable/tables_helper.rb +64 -2
  8. data/app/views/infotable/tables/_active_filters.html.erb +24 -0
  9. data/app/views/infotable/tables/_column_visibility.html.erb +11 -11
  10. data/app/views/infotable/tables/_filter_drawer.html.erb +4 -4
  11. data/app/views/infotable/tables/_next_page_frame.html.erb +5 -5
  12. data/app/views/infotable/tables/_pagination.html.erb +12 -12
  13. data/app/views/infotable/tables/_rail.html.erb +56 -0
  14. data/app/views/infotable/tables/_side_panel.html.erb +22 -10
  15. data/app/views/infotable/tables/_table.html.erb +43 -26
  16. data/app/views/infotable/tables/_table_rows.html.erb +3 -3
  17. data/app/views/infotable/tables/filters/_boolean.html.erb +2 -2
  18. data/app/views/infotable/tables/filters/_date.html.erb +2 -30
  19. data/app/views/infotable/tables/filters/_number.html.erb +2 -32
  20. data/app/views/infotable/tables/filters/_range.html.erb +66 -0
  21. data/app/views/infotable/tables/filters/_select.html.erb +4 -4
  22. data/app/views/infotable/tables/filters/_text.html.erb +3 -3
  23. data/app/views/infotable/tables/show.html.erb +22 -13
  24. data/config/locales/en.yml +23 -0
  25. data/config/locales/pl.yml +23 -0
  26. data/config/routes.rb +1 -0
  27. data/lib/generators/infotable/install/install_generator.rb +10 -64
  28. data/lib/infotable/base.rb +66 -0
  29. data/lib/infotable/configuration.rb +3 -1
  30. data/lib/infotable/engine.rb +0 -8
  31. data/lib/infotable/formatters/action_formatter.rb +7 -7
  32. data/lib/infotable/formatters/avatar_formatter.rb +2 -2
  33. data/lib/infotable/formatters/badge_formatter.rb +9 -9
  34. data/lib/infotable/formatters/boolean_formatter.rb +2 -2
  35. data/lib/infotable/formatters/link_formatter.rb +1 -1
  36. data/lib/infotable/formatters/percent_formatter.rb +1 -1
  37. data/lib/infotable/version.rb +1 -1
  38. data/lib/infotable.rb +0 -12
  39. metadata +5 -3
  40. data/lib/generators/infotable/install/templates/TAILWIND_CONFIG.md +0 -131
  41. data/lib/tasks/infotable.rake +0 -55
@@ -0,0 +1,24 @@
1
+ <%# Chips for the filters and search narrowing the table; each one removes itself. Locals: chips, table_name %>
2
+ <% if chips.any? %>
3
+ <div class="flex flex-wrap items-center gap-2 border-b border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900 px-6 py-2" data-active-filters>
4
+ <% chips.each do |chip| %>
5
+ <% remove_action = chip[:search] ? "click->infotable--table#clearSearch" : "click->infotable--drawer#clearSingleFilter" %>
6
+ <% chip_label = chip[:search] ? chip[:text] : "#{chip[:label]}: #{chip[:text]}" %>
7
+ <span class="inline-flex items-center gap-1 rounded-full bg-indigo-50 dark:bg-indigo-950 py-1 pl-3 pr-1 text-xs font-medium text-indigo-700 dark:text-indigo-300" data-active-filter="<%= chip[:search] ? 'search' : chip[:name] %>">
8
+ <% unless chip[:search] %><span class="text-indigo-500 dark:text-indigo-400"><%= chip[:label] %>:</span><% end %>
9
+ <span><%= chip[:text] %></span>
10
+ <button type="button"
11
+ class="ml-0.5 inline-flex h-4 w-4 items-center justify-center rounded-full text-indigo-500 dark:text-indigo-400 hover:bg-indigo-100 dark:hover:bg-indigo-900 hover:text-indigo-800 dark:hover:text-indigo-200 focus:outline-none focus:ring-2 focus:ring-indigo-500"
12
+ aria-label="<%= t('infotable.filters.active.remove', filter: chip_label) %>"
13
+ data-action="<%= remove_action %>"
14
+ <% unless chip[:search] %>data-filter-name="<%= chip[:name] %>" data-filter-type="<%= chip[:type] %>"<% end %>>
15
+ <svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2"><path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12"/></svg>
16
+ </button>
17
+ </span>
18
+ <% end %>
19
+ <% if chips.size > 1 %>
20
+ <button type="button" data-action="click->infotable--table#clearAllFilters" data-clear-all-filters
21
+ class="text-xs font-medium text-gray-600 dark:text-gray-400 underline hover:text-gray-900 dark:hover:text-gray-100"><%= t('infotable.filters.active.clear_all') %></button>
22
+ <% end %>
23
+ </div>
24
+ <% end %>
@@ -1,7 +1,7 @@
1
1
  <%# Column Visibility Panel %>
2
2
  <div class="px-4 py-4">
3
3
  <div class="mb-3">
4
- <p class="text-sm text-gray-600"><%= t('infotable.columns.instructions') %></p>
4
+ <p class="text-sm text-gray-600 dark:text-gray-400"><%= t('infotable.columns.instructions') %></p>
5
5
  </div>
6
6
 
7
7
  <form id="column-visibility-form-<%= table_name %>"
@@ -11,13 +11,13 @@
11
11
  class="space-y-2">
12
12
 
13
13
  <% table_class.columns.each do |column| %>
14
- <div class="column-item group p-3 bg-white rounded-lg border border-gray-100 hover:border-indigo-200 transition-all duration-150"
14
+ <div class="column-item group p-3 bg-white dark:bg-gray-900 rounded-lg border border-gray-100 dark:border-gray-800 hover:border-indigo-200 dark:hover:border-indigo-700 transition-all duration-150"
15
15
  data-column-name="<%= column[:name] %>"
16
16
  data-default-visible="<%= column[:visible] %>"
17
17
  data-default-pinned="<%= column[:pinned] %>">
18
18
  <div class="flex items-center gap-3">
19
19
  <%# Drag Handle %>
20
- <div class="drag-handle cursor-move flex-shrink-0 text-gray-400 hover:text-gray-600 transition-colors">
20
+ <div class="drag-handle cursor-move flex-shrink-0 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors">
21
21
  <svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
22
22
  <path d="M7 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 2zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 7 14zm6-8a2 2 0 1 0-.001-4.001A2 2 0 0 0 13 6zm0 2a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 8zm0 6a2 2 0 1 0 .001 4.001A2 2 0 0 0 13 14z"></path>
23
23
  </svg>
@@ -32,9 +32,9 @@
32
32
  data-default-visible="<%= column[:visible] %>"
33
33
  data-action="change->infotable--drawer#updateColumnVisibility"
34
34
  <%= 'checked' if column[:visible] %>
35
- class="w-4 h-4 text-indigo-600 border-gray-300 rounded focus:ring-indigo-500 focus:ring-1 transition-colors">
35
+ class="w-4 h-4 text-indigo-600 dark:text-indigo-400 border-gray-300 dark:border-gray-600 rounded focus:ring-indigo-500 focus:ring-1 transition-colors">
36
36
  <div class="flex-1">
37
- <span class="text-sm font-medium text-gray-700"><%= column[:label] %></span>
37
+ <span class="text-sm font-medium text-gray-700 dark:text-gray-300"><%= column[:label] %></span>
38
38
  <% if column[:type] %>
39
39
  <span class="ml-2 text-xs text-gray-400">(<%= column[:type] %>)</span>
40
40
  <% end %>
@@ -49,7 +49,7 @@
49
49
  data-column-name="<%= column[:name] %>"
50
50
  data-pin-direction="left"
51
51
  title="<%= t('infotable.columns.pin.left') %>"
52
- class="pin-btn pin-left w-7 h-7 rounded flex items-center justify-center <%= column[:pinned] == :left ? 'bg-indigo-100 text-indigo-600' : 'text-gray-400 hover:bg-gray-100 hover:text-gray-600' %> transition-colors">
52
+ class="pin-btn pin-left w-7 h-7 rounded flex items-center justify-center <%= column[:pinned] == :left ? 'bg-indigo-100 dark:bg-indigo-900/40 text-indigo-600 dark:text-indigo-400' : 'text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-600 dark:hover:text-gray-300' %> transition-colors">
53
53
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
54
54
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
55
55
  </svg>
@@ -60,7 +60,7 @@
60
60
  data-column-name="<%= column[:name] %>"
61
61
  data-pin-direction="right"
62
62
  title="<%= t('infotable.columns.pin.right') %>"
63
- class="pin-btn pin-right w-7 h-7 rounded flex items-center justify-center <%= column[:pinned] == :right ? 'bg-indigo-100 text-indigo-600' : 'text-gray-400 hover:bg-gray-100 hover:text-gray-600' %> transition-colors">
63
+ class="pin-btn pin-right w-7 h-7 rounded flex items-center justify-center <%= column[:pinned] == :right ? 'bg-indigo-100 dark:bg-indigo-900/40 text-indigo-600 dark:text-indigo-400' : 'text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-gray-600 dark:hover:text-gray-300' %> transition-colors">
64
64
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
65
65
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
66
66
  </svg>
@@ -73,18 +73,18 @@
73
73
  </form>
74
74
 
75
75
  <%# Footer Actions %>
76
- <div class="mt-4 pt-4 border-t border-gray-100 space-y-2">
76
+ <div class="mt-4 pt-4 border-t border-gray-100 dark:border-gray-800 space-y-2">
77
77
  <div class="flex gap-2">
78
78
  <button type="button"
79
79
  data-action="click->infotable--drawer#selectAllColumns"
80
80
  data-table-name="<%= table_name %>"
81
- class="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
81
+ class="flex-1 px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
82
82
  <%= t('infotable.columns.actions.select_all') %>
83
83
  </button>
84
84
  <button type="button"
85
85
  data-action="click->infotable--drawer#deselectAllColumns"
86
86
  data-table-name="<%= table_name %>"
87
- class="flex-1 px-3 py-2 border border-gray-200 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
87
+ class="flex-1 px-3 py-2 border border-gray-200 dark:border-gray-700 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
88
88
  <%= t('infotable.columns.actions.deselect_all') %>
89
89
  </button>
90
90
  </div>
@@ -93,7 +93,7 @@
93
93
  <button type="button"
94
94
  data-action="click->infotable--drawer#resetToDefaults"
95
95
  data-table-name="<%= table_name %>"
96
- class="w-full px-3 py-2 border border-red-200 rounded-lg text-sm font-medium text-red-700 bg-red-50 hover:bg-red-100 hover:border-red-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-red-500 transition-all">
96
+ class="w-full px-3 py-2 border border-red-200 rounded-lg text-sm font-medium text-red-700 dark:text-red-300 bg-red-50 hover:bg-red-100 hover:border-red-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-red-500 transition-all">
97
97
  <%= t('infotable.columns.actions.reset_to_defaults') %>
98
98
  </button>
99
99
  </div>
@@ -29,8 +29,8 @@
29
29
 
30
30
  <%# Render filter for each filterable column %>
31
31
  <% table_class.filterable_columns.each do |column| %>
32
- <div class="group p-4 bg-white rounded-lg border border-gray-100 hover:border-indigo-200 transition-all duration-150">
33
- <label class="block text-sm font-semibold text-gray-700 mb-3">
32
+ <div class="group p-4 bg-white dark:bg-gray-900 rounded-lg border border-gray-100 dark:border-gray-800 hover:border-indigo-200 dark:hover:border-indigo-700 transition-all duration-150">
33
+ <label class="block text-sm font-semibold text-gray-700 dark:text-gray-300 mb-3">
34
34
  <%= column[:label] %>
35
35
  </label>
36
36
 
@@ -45,12 +45,12 @@
45
45
  </div>
46
46
 
47
47
  <%# Drawer Footer with actions %>
48
- <div class="px-4 py-3 border-t border-gray-100 bg-white">
48
+ <div class="px-4 py-3 border-t border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900">
49
49
  <div class="flex gap-2">
50
50
  <button type="button"
51
51
  data-action="click->infotable--drawer#clearFilters"
52
52
  data-table-name="<%= table_name %>"
53
- class="<%= autofilter ? 'w-full' : 'flex-1' %> px-4 py-2 border border-gray-200 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
53
+ class="<%= autofilter ? 'w-full' : 'flex-1' %> px-4 py-2 border border-gray-200 dark:border-gray-700 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-300 focus:outline-none focus:ring-2 focus:ring-offset-1 focus:ring-indigo-500 transition-all">
54
54
  <%= t('infotable.filters.actions.clear_all') %>
55
55
  </button>
56
56
  <% unless autofilter %>
@@ -9,11 +9,11 @@
9
9
  )
10
10
  ) do %>
11
11
  <%# Loading placeholder - modern spinner design %>
12
- <div class="flex items-center justify-center py-12 border-t border-gray-100 bg-gradient-to-b from-white/[0.98] to-gray-50/[0.98] backdrop-blur-sm">
12
+ <div class="flex items-center justify-center py-12 border-t border-gray-100 dark:border-gray-800 bg-gradient-to-b from-white/[0.98] to-gray-50/[0.98] backdrop-blur-sm">
13
13
  <div class="text-center space-y-3">
14
14
  <div class="mx-auto animate-spin">
15
15
  <div class="relative">
16
- <svg class="h-10 w-10 text-indigo-500 drop-shadow-[0_4px_12px_rgba(99,102,241,0.2)]" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
16
+ <svg class="h-10 w-10 text-indigo-500 dark:text-indigo-400 drop-shadow-[0_4px_12px_rgba(99,102,241,0.2)]" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
17
17
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="3"></circle>
18
18
  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
19
19
  </svg>
@@ -22,14 +22,14 @@
22
22
  </div>
23
23
  </div>
24
24
  </div>
25
- <p class="text-sm font-medium text-gray-600 tracking-wide animate-pulse"><%= t('infotable.table.loading.more_items') %></p>
25
+ <p class="text-sm font-medium text-gray-600 dark:text-gray-400 tracking-wide animate-pulse"><%= t('infotable.table.loading.more_items') %></p>
26
26
  </div>
27
27
  </div>
28
28
  <% end %>
29
29
  <% else %>
30
30
  <%# No more pages - show end indicator %>
31
- <div class="border-t border-gray-100 bg-gradient-to-b from-gray-50/60 to-white/60 px-6 py-8 text-center">
32
- <div class="inline-flex items-center gap-2 text-sm text-gray-500">
31
+ <div class="border-t border-gray-100 dark:border-gray-800 bg-gradient-to-b from-gray-50/60 to-white/60 px-6 py-8 text-center">
32
+ <div class="inline-flex items-center gap-2 text-sm text-gray-500 dark:text-gray-400">
33
33
  <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
34
34
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
35
35
  </svg>
@@ -2,25 +2,25 @@
2
2
  <div class="flex flex-col sm:flex-row items-center justify-between gap-4">
3
3
  <%# Results info and per-page selector %>
4
4
  <div class="flex-1 flex items-center gap-4">
5
- <p class="text-sm text-gray-700">
5
+ <p class="text-sm text-gray-700 dark:text-gray-300">
6
6
  <%= t('infotable.pagination.showing') %>
7
- <span class="font-semibold text-gray-900"><%= pagy.from %></span>
7
+ <span class="font-semibold text-gray-900 dark:text-gray-100"><%= pagy.from %></span>
8
8
  <%= t('infotable.pagination.to') %>
9
- <span class="font-semibold text-gray-900"><%= pagy.to %></span>
9
+ <span class="font-semibold text-gray-900 dark:text-gray-100"><%= pagy.to %></span>
10
10
  <% if pagy.count %>
11
11
  <%= t('infotable.pagination.of') %>
12
- <span class="font-semibold text-gray-900"><%= pagy.count %></span>
12
+ <span class="font-semibold text-gray-900 dark:text-gray-100"><%= pagy.count %></span>
13
13
  <%= t('infotable.pagination.results') %>
14
14
  <% end %>
15
15
  </p>
16
16
 
17
17
  <%# Per-page selector %>
18
18
  <div class="flex items-center gap-2">
19
- <label for="per_page_<%= table_name %>" class="text-sm text-gray-700">
19
+ <label for="per_page_<%= table_name %>" class="text-sm text-gray-700 dark:text-gray-300">
20
20
  <%= t('infotable.pagination.rows_per_page') %>
21
21
  </label>
22
22
  <select id="per_page_<%= table_name %>"
23
- class="text-sm border border-gray-300 rounded-lg px-2 py-1 bg-white hover:border-gray-400 transition-colors cursor-pointer"
23
+ class="text-sm text-gray-700 dark:text-gray-200 border border-gray-300 dark:border-gray-600 rounded-lg px-2 py-1 bg-white dark:bg-gray-900 hover:border-gray-400 transition-colors cursor-pointer"
24
24
  data-action="change->infotable--table#changePerPage"
25
25
  data-table-name="<%= table_name %>"
26
26
  data-current-query="<%= table_url_params.except(:table_name).to_query %>">
@@ -38,7 +38,7 @@
38
38
  <%# Previous button %>
39
39
  <% if pagy.previous %>
40
40
  <%= link_to infotable_table_data_path(table_url_params(page: pagy.previous, per_page: pagy.limit)),
41
- class: "inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 hover:border-gray-400 transition-all",
41
+ class: "inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-400 transition-all",
42
42
  data: { turbo_frame: "#{table_name}_content" } do %>
43
43
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
44
44
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
@@ -46,7 +46,7 @@
46
46
  <span class="hidden sm:inline"><%= t('infotable.pagination.previous') %></span>
47
47
  <% end %>
48
48
  <% else %>
49
- <span class="inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-400 bg-gray-100 border border-gray-200 rounded-lg cursor-not-allowed">
49
+ <span class="inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-400 bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg cursor-not-allowed">
50
50
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
51
51
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
52
52
  </svg>
@@ -66,14 +66,14 @@
66
66
  <% pages.each do |page_num| %>
67
67
  <% if page_num == pagy.page %>
68
68
  <%# Current page - disabled/not clickable (gray) %>
69
- <span aria-current="page" class="inline-flex items-center justify-center w-10 h-10 text-sm font-semibold rounded-lg bg-gray-200 text-gray-600 border border-gray-300 cursor-not-allowed">
69
+ <span aria-current="page" class="inline-flex items-center justify-center w-10 h-10 text-sm font-semibold rounded-lg bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400 border border-gray-300 dark:border-gray-600 cursor-not-allowed">
70
70
  <%= page_num %>
71
71
  </span>
72
72
  <% else %>
73
73
  <%# Other pages - clickable %>
74
74
  <%= link_to page_num,
75
75
  infotable_table_data_path(table_url_params(page: page_num, per_page: pagy.limit)),
76
- class: "inline-flex items-center justify-center w-10 h-10 text-sm font-medium rounded-lg transition-all text-gray-700 bg-white border border-gray-300 hover:bg-gray-50 hover:border-gray-400",
76
+ class: "inline-flex items-center justify-center w-10 h-10 text-sm font-medium rounded-lg transition-all text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-400",
77
77
  data: { turbo_frame: "#{table_name}_content" } %>
78
78
  <% end %>
79
79
  <% end %>
@@ -82,7 +82,7 @@
82
82
  <%# Next button %>
83
83
  <% if pagy.next %>
84
84
  <%= link_to infotable_table_data_path(table_url_params(page: pagy.next, per_page: pagy.limit)),
85
- class: "inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-lg hover:bg-gray-50 hover:border-gray-400 transition-all",
85
+ class: "inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 border border-gray-300 dark:border-gray-600 rounded-lg hover:bg-gray-50 dark:hover:bg-gray-800 hover:border-gray-400 transition-all",
86
86
  data: { turbo_frame: "#{table_name}_content" } do %>
87
87
  <span class="hidden sm:inline"><%= t('infotable.pagination.next') %></span>
88
88
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
@@ -90,7 +90,7 @@
90
90
  </svg>
91
91
  <% end %>
92
92
  <% else %>
93
- <span class="inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-400 bg-gray-100 border border-gray-200 rounded-lg cursor-not-allowed">
93
+ <span class="inline-flex items-center gap-1 px-3 py-2 text-sm font-medium text-gray-400 bg-gray-100 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg cursor-not-allowed">
94
94
  <span class="hidden sm:inline"><%= t('infotable.pagination.next') %></span>
95
95
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
96
96
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
@@ -0,0 +1,56 @@
1
+ <%# Vertical rail with the table controls (`toolbar :rail`) %>
2
+ <% button = "relative flex items-center justify-center w-10 h-10 rounded-lg text-gray-500 dark:text-gray-400 hover:text-indigo-600 hover:bg-indigo-50 dark:hover:bg-indigo-950 focus:outline-none focus:ring-2 focus:ring-indigo-500 transition-colors" %>
3
+ <% icon = "w-5 h-5" %>
4
+ <% filter_count = initial_state[:filters].respond_to?(:keys) ? initial_state[:filters].keys.size : 0 %>
5
+ <aside class="flex flex-col items-center shrink-0 w-14 py-3 gap-1 border-l border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-900" aria-label="<%= t('infotable.drawer.label') %>">
6
+ <% if table_class.filterable_columns.any? && table_class.filters_button_visible? %>
7
+ <button type="button"
8
+ data-action="click->infotable--drawer#openFilters"
9
+ title="<%= t('infotable.table.buttons.filters') %>"
10
+ aria-label="<%= t('infotable.table.buttons.filters') %>"
11
+ class="<%= button %>">
12
+ <svg class="<%= icon %>" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
13
+ <path stroke-linecap="round" stroke-linejoin="round" d="M10.5 6h9.75M10.5 6a1.5 1.5 0 11-3 0m3 0a1.5 1.5 0 10-3 0M3.75 6H7.5m3 12h9.75m-9.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-3.75 0H7.5m9-6h3.75m-3.75 0a1.5 1.5 0 01-3 0m3 0a1.5 1.5 0 00-3 0m-9.75 0h9.75" />
14
+ </svg>
15
+ <span data-infotable--table-target="filterCount"
16
+ class="<%= 'hidden ' if filter_count.zero? %>absolute -top-1 -right-1 min-w-5 h-5 px-1 flex items-center justify-center text-xs font-medium text-white bg-indigo-600 rounded-full"><%= filter_count %></span>
17
+ </button>
18
+ <% end %>
19
+
20
+ <button type="button"
21
+ data-action="click->infotable--drawer#openColumns"
22
+ title="<%= t('infotable.table.buttons.columns') %>"
23
+ aria-label="<%= t('infotable.table.buttons.columns') %>"
24
+ class="<%= button %>">
25
+ <svg class="<%= icon %>" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
26
+ <path stroke-linecap="round" stroke-linejoin="round" d="M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" />
27
+ <path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
28
+ </svg>
29
+ </button>
30
+
31
+ <div class="mt-auto flex flex-col items-center gap-1 pt-3 w-10 border-t border-gray-100 dark:border-gray-800">
32
+ <a href="<%= export_url %>"
33
+ data-action="click->infotable--table#exportCsv"
34
+ data-infotable--table-target="exportButton"
35
+ data-exporting-text="<%= t('infotable.table.buttons.exporting') %>"
36
+ data-turbo="false"
37
+ download
38
+ title="<%= t('infotable.table.buttons.export_csv') %>"
39
+ class="<%= button %>">
40
+ <svg class="<%= icon %>" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
41
+ <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M16.5 12L12 16.5m0 0L7.5 12m4.5 4.5V3" />
42
+ </svg>
43
+ <span class="sr-only" data-infotable--table-target="exportButtonText"><%= t('infotable.table.buttons.export_csv') %></span>
44
+ </a>
45
+
46
+ <button type="button"
47
+ data-action="click->infotable--table#refresh"
48
+ title="<%= t('infotable.table.buttons.refresh') %>"
49
+ aria-label="<%= t('infotable.table.buttons.refresh') %>"
50
+ class="<%= button %>">
51
+ <svg class="<%= icon %>" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="1.5">
52
+ <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99" />
53
+ </svg>
54
+ </button>
55
+ </div>
56
+ </aside>
@@ -1,32 +1,44 @@
1
1
  <%# Side Panel with Tabs for Filters and Columns %>
2
- <div class="flex flex-col h-full bg-white">
2
+ <div class="flex flex-col h-full bg-white dark:bg-gray-900">
3
3
  <%# Panel Header %>
4
- <div class="flex items-center justify-between px-4 py-3 bg-white border-b border-gray-100">
4
+ <div class="flex items-center justify-between px-4 py-3 bg-white dark:bg-gray-900 border-b border-gray-100 dark:border-gray-800">
5
5
  <div class="flex items-center gap-2.5">
6
- <div class="p-2 bg-indigo-50 rounded-lg">
7
- <svg class="w-4 h-4 text-indigo-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
6
+ <div class="p-2 bg-indigo-50 dark:bg-indigo-950 rounded-lg">
7
+ <svg class="w-4 h-4 text-indigo-600 dark:text-indigo-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
8
8
  <path stroke-linecap="round" stroke-linejoin="round" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
9
9
  </svg>
10
10
  </div>
11
- <h3 class="text-base font-semibold text-gray-900" data-infotable--drawer-target="panelTitle" data-columns-title="<%= t('infotable.drawer.panel_title.customize_columns') %>" data-filters-title="<%= t('infotable.drawer.panel_title.filters') %>"><%= table_class.filterable_columns.any? ? t('infotable.drawer.panel_title.filters') : t('infotable.drawer.panel_title.customize_columns') %></h3>
11
+ <h3 class="text-base font-semibold text-gray-900 dark:text-gray-100" data-infotable--drawer-target="panelTitle" data-columns-title="<%= t('infotable.drawer.panel_title.customize_columns') %>" data-filters-title="<%= t('infotable.drawer.panel_title.filters') %>"><%= table_class.filterable_columns.any? ? t('infotable.drawer.panel_title.filters') : t('infotable.drawer.panel_title.customize_columns') %></h3>
12
12
  </div>
13
13
  <button type="button"
14
14
  data-action="click->infotable--drawer#close"
15
- class="p-1.5 text-gray-400 hover:text-gray-600 hover:bg-gray-50 rounded-md transition-colors">
15
+ class="p-1.5 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 rounded-md transition-colors">
16
16
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
17
17
  <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
18
18
  </svg>
19
19
  </button>
20
20
  </div>
21
21
 
22
+ <%# With `toolbar :rail` the header (and its search box) is hidden: search lives here %>
23
+ <% if table_class.rail_toolbar? && table_class.searchable_columns.any? %>
24
+ <div class="px-4 py-3 border-b border-gray-100 dark:border-gray-800">
25
+ <input type="search"
26
+ name="search"
27
+ placeholder="<%= t('infotable.search.placeholder') %>"
28
+ aria-label="<%= t('infotable.search.label') %>"
29
+ data-action="input->infotable--table#search"
30
+ class="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500">
31
+ </div>
32
+ <% end %>
33
+
22
34
  <%# Tabs Navigation %>
23
- <div class="flex border-b border-gray-100 bg-white px-4">
35
+ <div class="flex border-b border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-900 px-4">
24
36
  <% if table_class.filterable_columns.any? %>
25
37
  <button type="button"
26
38
  data-action="click->infotable--drawer#switchTab"
27
39
  data-tab="filters"
28
40
  data-infotable--drawer-target="tabButton"
29
- class="flex-1 px-3 py-2.5 text-sm font-medium text-indigo-600 border-b-2 border-indigo-600 transition-colors">
41
+ class="flex-1 px-3 py-2.5 text-sm font-medium text-indigo-600 dark:text-indigo-400 border-b-2 border-indigo-600 transition-colors">
30
42
  <%= t('infotable.drawer.tabs.filters') %>
31
43
  </button>
32
44
  <% end %>
@@ -35,11 +47,11 @@
35
47
  data-tab="columns"
36
48
  data-infotable--drawer-target="tabButton"
37
49
  data-table-name="<%= table_name %>"
38
- class="flex-1 px-3 py-2.5 text-sm font-medium <%= table_class.filterable_columns.any? ? 'text-gray-500 border-b-2 border-transparent hover:text-gray-700' : 'text-indigo-600 border-b-2 border-indigo-600' %> transition-colors flex items-center justify-center gap-2">
50
+ class="flex-1 px-3 py-2.5 text-sm font-medium <%= table_class.filterable_columns.any? ? 'text-gray-500 dark:text-gray-400 border-b-2 border-transparent hover:text-gray-700 dark:hover:text-gray-200' : 'text-indigo-600 dark:text-indigo-400 border-b-2 border-indigo-600' %> transition-colors flex items-center justify-center gap-2">
39
51
  <span><%= t('infotable.drawer.tabs.columns') %></span>
40
52
  <span data-infotable--drawer-target="columnBadge"
41
53
  data-badge-table-name="<%= table_name %>"
42
- class="px-2 py-0.5 text-xs font-medium bg-indigo-100 text-indigo-700 rounded-full">
54
+ class="px-2 py-0.5 text-xs font-medium bg-indigo-100 dark:bg-indigo-900/40 text-indigo-700 dark:text-indigo-300 rounded-full">
43
55
  <%= table_class.columns.count { |c| c[:visible] } %> / <%= table_class.columns.count %>
44
56
  </span>
45
57
  </button>
@@ -21,15 +21,30 @@
21
21
  <% title = local_assigns.fetch(:title, table_class.title || table_class.name.demodulize.titleize) %>
22
22
  <% subtitle = local_assigns.fetch(:subtitle, table_class.subtitle) %>
23
23
  <% initial_state = table_class.url_state? ? infotable_initial_state(table_name) : {} %>
24
- <div class="w-full relative overflow-hidden" data-controller="infotable--table infotable--drawer" data-infotable--table-name-value="<%= table_name %>" data-infotable--table-url-state-value="<%= table_class.url_state? %>">
25
- <div class="bg-white rounded-xl shadow-sm border border-gray-200 relative" style="overflow: hidden;">
26
- <%# Header section with controls %>
27
- <div class="px-6 py-4 border-b border-gray-200 bg-gray-50">
24
+ <% rail = table_class.rail_toolbar? %>
25
+ <%
26
+ export_params = {
27
+ table_name: table_name,
28
+ sort_column: initial_state[:sort_column],
29
+ sort_direction: initial_state[:sort_direction],
30
+ sort: initial_state[:sort],
31
+ visible_columns: table_class.visible_columns.map { |c| c[:name].to_s }.join(',')
32
+ }
33
+ export_params[:filters] = initial_state[:filters] if initial_state[:filters].present?
34
+ export_params[:search] = initial_state[:search] if initial_state[:search].present?
35
+ export_url = Infotable::Engine.routes.url_helpers.table_export_path(export_params.compact)
36
+ %>
37
+ <div class="w-full relative overflow-hidden dark:[color-scheme:dark]" data-controller="infotable--table infotable--drawer" data-infotable--table-name-value="<%= table_name %>" data-infotable--table-url-state-value="<%= table_class.url_state? %>"<% if table_class.checkbox_enabled? %> data-infotable--table-ids-url-value="<%= Infotable::Engine.routes.url_helpers.table_ids_path(table_name: table_name) %>"<% end %>>
38
+ <div class="bg-white dark:bg-gray-900 rounded-xl shadow-sm border border-gray-200 dark:border-gray-700 relative<%= " flex" if rail %>" style="overflow: hidden;">
39
+ <div class="<%= rail ? "flex-1 min-w-0" : "w-full" %>">
40
+ <%# Header section with controls (hidden with `toolbar :rail`) %>
41
+ <% unless rail %>
42
+ <div class="px-6 py-4 border-b border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800">
28
43
  <div class="flex justify-between items-center">
29
44
  <div>
30
- <h2 class="text-xl font-semibold text-gray-900"><%= title %></h2>
45
+ <h2 class="text-xl font-semibold text-gray-900 dark:text-gray-100"><%= title %></h2>
31
46
  <% if subtitle.present? %>
32
- <p class="mt-1 text-sm text-gray-500"><%= subtitle %></p>
47
+ <p class="mt-1 text-sm text-gray-500 dark:text-gray-400"><%= subtitle %></p>
33
48
  <% end %>
34
49
  </div>
35
50
  <div class="flex gap-3">
@@ -41,28 +56,16 @@
41
56
  placeholder="<%= t('infotable.search.placeholder') %>"
42
57
  aria-label="<%= t('infotable.search.label') %>"
43
58
  data-action="input->infotable--table#search"
44
- class="w-56 px-3 py-2 border border-gray-300 rounded-lg text-sm text-gray-700 bg-white focus:outline-none focus:ring-2 focus:ring-indigo-500">
59
+ class="w-56 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 focus:outline-none focus:ring-2 focus:ring-indigo-500">
45
60
  <% end %>
46
61
  <%# Export CSV button %>
47
- <%
48
- export_params = {
49
- table_name: table_name,
50
- sort_column: initial_state[:sort_column],
51
- sort_direction: initial_state[:sort_direction],
52
- sort: initial_state[:sort],
53
- visible_columns: table_class.visible_columns.map { |c| c[:name].to_s }.join(',')
54
- }
55
- export_params[:filters] = initial_state[:filters] if initial_state[:filters].present?
56
- export_params[:search] = initial_state[:search] if initial_state[:search].present?
57
- export_url = Infotable::Engine.routes.url_helpers.table_export_path(export_params.compact)
58
- %>
59
62
  <a href="<%= export_url %>"
60
63
  data-action="click->infotable--table#exportCsv"
61
64
  data-infotable--table-target="exportButton"
62
65
  data-exporting-text="<%= t('infotable.table.buttons.exporting') %>"
63
66
  data-turbo="false"
64
67
  download
65
- class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
68
+ class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
66
69
  <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
67
70
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
68
71
  </svg>
@@ -72,7 +75,7 @@
72
75
  <% if table_class.filters_button_visible? %>
73
76
  <button type="button"
74
77
  data-action="click->infotable--drawer#open"
75
- class="inline-flex items-center px-4 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
78
+ class="inline-flex items-center px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-medium text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-900 hover:bg-gray-50 dark:hover:bg-gray-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 transition-colors">
76
79
  <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
77
80
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 4a1 1 0 011-1h16a1 1 0 011 1v2.586a1 1 0 01-.293.707l-6.414 6.414a1 1 0 00-.293.707V17l-4 4v-6.586a1 1 0 00-.293-.707L3.293 7.293A1 1 0 013 6.586V4z" />
78
81
  </svg>
@@ -82,16 +85,25 @@
82
85
  </div>
83
86
  </div>
84
87
  </div>
88
+ <% end %>
85
89
 
86
90
  <%# Batch action bar: shown while rows are selected %>
87
91
  <% if table_class.batch_action_list.any? %>
88
- <div class="hidden items-center justify-between gap-3 px-6 py-3 border-b border-indigo-100 bg-indigo-50"
92
+ <div class="hidden items-center justify-between gap-3 px-6 py-3 border-b border-indigo-100 dark:border-indigo-900 bg-indigo-50 dark:bg-indigo-950"
89
93
  data-infotable--table-target="batchBar">
90
- <div class="flex items-center gap-3 text-sm text-indigo-900">
94
+ <div class="flex items-center gap-3 text-sm text-indigo-900 dark:text-indigo-100">
91
95
  <span data-infotable--table-target="batchCount"
92
96
  data-template="<%= t('infotable.batch.selected', count: '__COUNT__') %>"></span>
93
97
  <button type="button" data-action="click->infotable--table#clearSelection"
94
- class="text-indigo-600 hover:text-indigo-800 underline"><%= t('infotable.batch.clear') %></button>
98
+ class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-800 dark:hover:text-indigo-200 underline"><%= t('infotable.batch.clear') %></button>
99
+ <button type="button" hidden
100
+ data-infotable--table-target="selectAllMatching"
101
+ data-action="click->infotable--table#selectAllMatching"
102
+ data-template="<%= t('infotable.batch.select_all_matching', count: '__COUNT__') %>"
103
+ class="text-indigo-600 dark:text-indigo-400 hover:text-indigo-800 dark:hover:text-indigo-200 underline font-medium"></button>
104
+ <span hidden data-infotable--table-target="batchNote"
105
+ data-template="<%= t('infotable.batch.truncated', max: '__MAX__') %>"
106
+ class="text-amber-700"></span>
95
107
  </div>
96
108
  <div class="flex gap-2">
97
109
  <% table_class.batch_action_list.each do |action| %>
@@ -114,14 +126,19 @@
114
126
  <%# Loading state %>
115
127
  <div class="flex items-center justify-center py-16">
116
128
  <div class="text-center">
117
- <svg class="animate-spin h-8 w-8 text-indigo-600 mx-auto mb-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
129
+ <svg class="animate-spin h-8 w-8 text-indigo-600 dark:text-indigo-400 mx-auto mb-3" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
118
130
  <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
119
131
  <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
120
132
  </svg>
121
- <p class="text-sm text-gray-500"><%= t('infotable.table.loading.initial') %></p>
133
+ <p class="text-sm text-gray-500 dark:text-gray-400"><%= t('infotable.table.loading.initial') %></p>
122
134
  </div>
123
135
  </div>
124
136
  </turbo-frame>
137
+ </div>
138
+ <%# Vertical rail with the controls (`toolbar :rail`) %>
139
+ <% if rail %>
140
+ <%= render "infotable/tables/rail", table_name: table_name, table_class: table_class, export_url: export_url, initial_state: initial_state %>
141
+ <% end %>
125
142
  </div>
126
143
 
127
144
  <%# Side panel drawer - always available for column visibility, filters if available %>
@@ -14,7 +14,7 @@
14
14
  else "text-sm" # default
15
15
  end
16
16
  %>
17
- <tr class="infotable-row relative border-t border-gray-50 first:border-t-0 hover:shadow-sm hover:translate-x-px transition-all duration-200 ease-out <%= 'cursor-pointer' if row_link_enabled %>"
17
+ <tr class="infotable-row relative border-t border-gray-50 dark:border-gray-800 first:border-t-0 hover:shadow-sm hover:translate-x-px transition-all duration-200 ease-out <%= 'cursor-pointer' if row_link_enabled %>"
18
18
  <%= tag.attributes(data: { row_link: row_url, action: "click->infotable--table#handleRowClick" }) if row_link_enabled && row_url %>>
19
19
  <% if table_class.checkbox_enabled? %>
20
20
  <td class="<%= cell_padding %> w-10">
@@ -23,14 +23,14 @@
23
23
  aria-label="<%= t('infotable.batch.select_row') %>"
24
24
  data-infotable--table-target="rowCheckbox"
25
25
  data-action="change->infotable--table#toggleRow"
26
- class="h-4 w-4 rounded border-gray-300 text-indigo-600 focus:ring-indigo-500">
26
+ class="h-4 w-4 rounded border-gray-300 dark:border-gray-600 text-indigo-600 dark:text-indigo-400 focus:ring-indigo-500">
27
27
  </td>
28
28
  <% end %>
29
29
  <% table_class.columns.each do |column| %>
30
30
  <td data-column-name="<%= column[:name] %>"
31
31
  data-default-visible="<%= column[:visible] %>"
32
32
  style="width: <%= column[:width] %>; max-width: <%= column[:width] %>; overflow: hidden; text-overflow: ellipsis;"
33
- class="<%= cell_padding %> whitespace-nowrap <%= text_size %> text-gray-700">
33
+ class="<%= cell_padding %> whitespace-nowrap <%= text_size %> text-gray-700 dark:text-gray-300">
34
34
  <%= format_cell_value(record, column, table_class) %>
35
35
  </td>
36
36
  <% end %>
@@ -2,7 +2,7 @@
2
2
  <div class="relative">
3
3
  <select name="filters[<%= column[:name] %>][value]"
4
4
  id="<%= infotable_filter_id(table_name, column, 'value') %>"
5
- class="block w-full appearance-none rounded-lg border-0 bg-white pr-10 pl-3 py-2 text-base sm:text-sm text-neutral-900 shadow-sm focus:outline-none focus:ring-2 focus:ring-neutral-600 focus:ring-offset-0 transition-all [box-shadow:inset_0_0_0_1px_rgb(212_212_212)] focus:[box-shadow:inset_0_0_0_2px_rgb(82_82_82)] cursor-pointer disabled:cursor-not-allowed disabled:bg-neutral-100 disabled:opacity-75 bg-[url('data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20fill=%27none%27%20viewBox=%270%200%2020%2020%27%3e%3cpath%20stroke=%27%23737373%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%20stroke-width=%271.5%27%20d=%27M6%208l4%204%204-4%27/%3e%3c/svg%3e')] bg-[right_0.75rem_center] bg-no-repeat bg-[length:1.25em_1.25em]">
5
+ class="block w-full appearance-none rounded-lg border-0 bg-white dark:bg-gray-900 pr-10 pl-3 py-2 text-base sm:text-sm text-neutral-900 dark:text-neutral-100 shadow-sm focus:outline-none focus:ring-2 focus:ring-neutral-600 focus:ring-offset-0 transition-all [box-shadow:inset_0_0_0_1px_rgb(212_212_212)] dark:[box-shadow:inset_0_0_0_1px_rgb(82_82_82)] focus:[box-shadow:inset_0_0_0_2px_rgb(82_82_82)] dark:focus:[box-shadow:inset_0_0_0_2px_rgb(163_163_163)] cursor-pointer disabled:cursor-not-allowed disabled:bg-neutral-100 disabled:opacity-75 bg-[url('data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20fill=%27none%27%20viewBox=%270%200%2020%2020%27%3e%3cpath%20stroke=%27%23737373%27%20stroke-linecap=%27round%27%20stroke-linejoin=%27round%27%20stroke-width=%271.5%27%20d=%27M6%208l4%204%204-4%27/%3e%3c/svg%3e')] bg-[right_0.75rem_center] bg-no-repeat bg-[length:1.25em_1.25em]">
6
6
  <option value=""><%= t('infotable.filters.all') %></option>
7
7
  <option value="true"><%= t('infotable.filters.boolean.true') %></option>
8
8
  <option value="false"><%= t('infotable.filters.boolean.false') %></option>
@@ -10,7 +10,7 @@
10
10
  <option value="is_not_empty"><%= t('infotable.filters.boolean.not_empty') %></option>
11
11
  </select>
12
12
  <button type="button"
13
- class="absolute right-8 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors"
13
+ class="absolute right-8 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"
14
14
  data-action="click->infotable--drawer#clearSingleFilter"
15
15
  data-filter-name="<%= column[:name] %>"
16
16
  data-filter-type="boolean"
@@ -1,30 +1,2 @@
1
- <%# Date filter - from/to range with date pickers %>
2
- <div class="grid grid-cols-2 gap-2">
3
- <%# From date %>
4
- <div class="relative">
5
- <input type="date"
6
- name="filters[<%= column[:name] %>][from]"
7
- id="<%= infotable_filter_id(table_name, column, 'from') %>"
8
- placeholder="<%= t('infotable.filters.from') %>"
9
- class="block w-full rounded-lg border-0 bg-white pr-8 pl-3 py-2 text-base sm:text-sm text-neutral-900 placeholder:text-neutral-500 shadow-sm focus:outline-none focus:ring-2 focus:ring-neutral-600 focus:ring-offset-0 transition-all [box-shadow:inset_0_0_0_1px_rgb(212_212_212)] focus:[box-shadow:inset_0_0_0_2px_rgb(82_82_82)] disabled:cursor-not-allowed disabled:bg-neutral-100">
10
- <button type="button"
11
- class="absolute right-2 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 transition-colors"
12
- data-action="click->infotable--drawer#clearSingleFilter"
13
- data-filter-name="<%= column[:name] %>"
14
- data-filter-type="date"
15
- title="<%= t('infotable.filters.clear_filter') %>">
16
- <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24" stroke-width="2">
17
- <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
18
- </svg>
19
- </button>
20
- </div>
21
-
22
- <%# To date %>
23
- <div class="relative">
24
- <input type="date"
25
- name="filters[<%= column[:name] %>][to]"
26
- id="<%= infotable_filter_id(table_name, column, 'to') %>"
27
- placeholder="<%= t('infotable.filters.to') %>"
28
- class="block w-full rounded-lg border-0 bg-white pr-3 pl-3 py-2 text-base sm:text-sm text-neutral-900 placeholder:text-neutral-500 shadow-sm focus:outline-none focus:ring-2 focus:ring-neutral-600 focus:ring-offset-0 transition-all [box-shadow:inset_0_0_0_1px_rgb(212_212_212)] focus:[box-shadow:inset_0_0_0_2px_rgb(82_82_82)] disabled:cursor-not-allowed disabled:bg-neutral-100">
29
- </div>
30
- </div>
1
+ <%# Date filter: range or comparison, see _range %>
2
+ <%= render "infotable/tables/filters/range", column: column, table_name: table_name, kind: :date %>