|
1 | | -<div style="background: white; border-radius: 1rem; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -2px rgba(0,0,0,0.05); overflow: hidden;"> |
2 | | - <div style="background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); padding: 1.5rem; border-bottom: 1px solid #bae6fd;"> |
3 | | - <div style="display: flex; align-items: center; gap: 0.75rem;"> |
4 | | - <div style="background: linear-gradient(135deg, #0ea5e9 0%, #0284c7 100%); color: white; padding: 0.5rem; border-radius: 0.5rem;"> |
5 | | - <svg style="width: 1.25rem; height: 1.25rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 1 | +<div class="card-elevated overflow-hidden"> |
| 2 | + <div class="bg-gradient-to-br from-sky-50 to-cyan-50 p-6 border-b border-sky-200"> |
| 3 | + <div class="flex-center-sm"> |
| 4 | + <div class="bg-gradient-to-br from-sky-500 to-sky-600 text-white p-2 rounded-lg"> |
| 5 | + <svg class="icon-size-md" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
6 | 6 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" /> |
7 | 7 | </svg> |
8 | 8 | </div> |
9 | | - <h3 style="font-size: 1.125rem; font-weight: 600; color: #0c4a6e; margin: 0;">Search & Filter Topics</h3> |
| 9 | + <h3 class="text-lg font-semibold text-sky-900 m-0">Search & Filter Topics</h3> |
10 | 10 | </div> |
11 | 11 | </div> |
12 | | - <div style="padding: 1.5rem;"> |
| 12 | + <div class="card-body-sm"> |
13 | 13 | <%= form_for :search, url: topics_path, method: :get, data: { controller: "topics", topics_target: "searchForm", turbo_frame: "topic-list", turbo_action: "advance" } do |f| %> |
14 | | - <div id="topics-search-grid" style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 1.25rem; align-items: start;"> |
| 14 | + <div id="topics-search-grid" class="form-grid-auto items-start"> |
15 | 15 | <!-- Query --> |
16 | 16 | <div class="form-grid-full"> |
17 | 17 | <%= f.label :query, class: "input-label" %> |
|
23 | 23 | </div> |
24 | 24 |
|
25 | 25 | <!-- Language & Tags --> |
26 | | - <div style="min-width:0; grid-column: 1 / -1;"> |
27 | | - <div style="display:grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap:1rem; align-items:start;"> |
28 | | - <div style="position:relative;"> |
| 26 | + <div class="min-w-0 col-span-full"> |
| 27 | + <div class="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4 items-start"> |
| 28 | + <div class="relative"> |
29 | 29 | <%= f.label :language_id, "Language", class: "input-label" %> |
30 | | - <div style="position:relative;"> |
| 30 | + <div class="relative"> |
31 | 31 | <%= f.select :language_id, |
32 | 32 | options_from_collection_for_select(languages, :id, :name, params.dig(:search, :language_id)), |
33 | 33 | { prompt: "Select language" }, |
|
37 | 37 | </div> |
38 | 38 | </div> |
39 | 39 |
|
40 | | - <div data-controller="select-tags" style="position:relative;"> |
| 40 | + <div data-controller="select-tags" class="relative"> |
41 | 41 | <%= f.label :tag_list, "Tags", class: "input-label" %> |
42 | 42 | <%= f.select :tag_list, |
43 | 43 | options_for_select(Tag.order(:name).pluck(:name), Array(params.dig(:search, :tag_list))), |
|
51 | 51 | </div> |
52 | 52 |
|
53 | 53 | <!-- Year --> |
54 | | - <div style="min-width:0; position:relative;"> |
| 54 | + <div class="min-w-0 relative"> |
55 | 55 | <%= f.label :year, class: "input-label" %> |
56 | | - <div style="position:relative;"> |
| 56 | + <div class="relative"> |
57 | 57 | <%= f.select :year, |
58 | 58 | options_for_select((Date.today.year-10..Date.today.year).to_a, params.dig(:search, :year)), |
59 | 59 | { prompt: "Select year" }, |
|
64 | 64 | </div> |
65 | 65 |
|
66 | 66 | <!-- Month --> |
67 | | - <div style="min-width:0; position:relative;"> |
| 67 | + <div class="min-w-0 relative"> |
68 | 68 | <%= f.label :month, class: "input-label" %> |
69 | | - <div style="position:relative;"> |
| 69 | + <div class="relative"> |
70 | 70 | <%= f.select :month, |
71 | 71 | options_for_select((1..12).to_a, params.dig(:search, :month)), |
72 | 72 | { prompt: "Select month" }, |
|
78 | 78 | </div> |
79 | 79 |
|
80 | 80 | <!-- State --> |
81 | | - <div style="min-width:0; position:relative;"> |
| 81 | + <div class="min-w-0 relative"> |
82 | 82 | <%= f.label :state, class: "input-label" %> |
83 | | - <div style="position:relative;"> |
| 83 | + <div class="relative"> |
84 | 84 | <%= f.select :state, |
85 | 85 | options_for_select(Topic::STATES.index_with(&:itself), params.dig(:search, :state)), |
86 | 86 | { prompt: "Select state" }, |
|
92 | 92 | </div> |
93 | 93 |
|
94 | 94 | <!-- Order --> |
95 | | - <div style="min-width:0; position:relative;"> |
| 95 | + <div class="min-w-0 relative"> |
96 | 96 | <%= f.label :order, class: "input-label" %> |
97 | | - <div style="position:relative;"> |
| 97 | + <div class="relative"> |
98 | 98 | <%= f.select :order, |
99 | 99 | options_for_select(%w[desc asc].map { |o| [o, o] }, params.dig(:search, :order)), |
100 | 100 | {}, |
|
106 | 106 | </div> |
107 | 107 |
|
108 | 108 | <!-- Clear Button --> |
109 | | - <div style="margin-top: 1.25rem; display: flex; justify-content: flex-end;"> |
| 109 | + <div class="mt-5 flex justify-end"> |
110 | 110 | <%= link_to topics_path, |
111 | | - class: "clear-filters-btn", |
112 | | - style: "background:#6b7280; color:white; padding:0.625rem 1.25rem; border-radius:0.5rem; text-decoration:none; font-weight:600; font-size:0.875rem; display:inline-flex; align-items:center; gap:0.5rem; transition:all 0.2s; box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05);" do %> |
113 | | - <svg style="width: 1rem; height: 1rem;" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
| 111 | + class: "bg-gray-500 text-white py-2.5 px-5 rounded-lg no-underline font-semibold text-sm inline-flex items-center gap-2 transition-all shadow-sm hover:bg-gray-600 hover:-translate-y-0.5 hover:shadow-md" do %> |
| 112 | + <svg class="icon-size" fill="none" stroke="currentColor" viewBox="0 0 24 24"> |
114 | 113 | <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" /> |
115 | 114 | </svg> |
116 | 115 | <span>Clear Filters</span> |
|
119 | 118 | <% end %> |
120 | 119 | </div> |
121 | 120 | </div> |
122 | | - |
123 | | -<style> |
124 | | - /* Modern form input and select focus states */ |
125 | | - input[type="text"]:focus, select:focus { |
126 | | - outline: none !important; |
127 | | - border-color: #3b82f6 !important; |
128 | | - box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.1) !important; |
129 | | - background: white !important; |
130 | | - } |
131 | | - |
132 | | - /* Select hover state */ |
133 | | - select:hover:not(:focus) { |
134 | | - border-color: #9ca3af !important; |
135 | | - background: #fafafa !important; |
136 | | - } |
137 | | - |
138 | | - /* Clear Filters button hover - specific to search form only */ |
139 | | - .clear-filters-btn:hover { |
140 | | - background: #4b5563 !important; |
141 | | - transform: translateY(-1px); |
142 | | - box-shadow: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -1px rgba(0,0,0,0.06) !important; |
143 | | - } |
144 | | - |
145 | | - /* Responsive grid collapse */ |
146 | | - @media (max-width: 768px) { |
147 | | - div[style*="grid-template-columns: repeat(auto-fit, minmax(250px, 1fr))"] { |
148 | | - grid-template-columns: 1fr !important; |
149 | | - } |
150 | | - } |
151 | | - |
152 | | - /* Prevent grid items from forcing overflow */ |
153 | | - #topics-search-grid > div { min-width: 0 !important; } |
154 | | - /* Ensure the grid itself can shrink */ |
155 | | - #topics-search-grid { min-width: 0; } |
156 | | -</style> |
0 commit comments