Previews

No matching results.

x
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<div class="p-8">
<turbo-frame id="preview-clickable-table">
<div data-controller="midwest-table" class="midwest-table-wrapper">
<div class="midwest-table-loading-overlay" aria-hidden="true">
<div class="midwest-loading-icon" role="img" aria-label="Loading" decorative="true">
<div class="midwest-loading-icon-inner">
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
<svg viewbox="0 0 120 30" xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="Midwest-LoadingIcon__Svg" focusable="false" aria-hidden="true">
<circle cx="15" cy="15" r="15">
<animate attributename="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcmode="linear" repeatcount="indefinite"></animate>
<animate attributename="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcmode="linear" repeatcount="indefinite"></animate>
</circle>
<circle cx="60" cy="15" r="9" fill-opacity="0.3">
<animate attributename="r" from="9" to="9" begin="0s" dur="0.8s" values="9;15;9" calcmode="linear" repeatcount="indefinite"></animate>
<animate attributename="fill-opacity" from="0.5" to="0.5" begin="0s" dur="0.8s" values=".5;1;.5" calcmode="linear" repeatcount="indefinite"></animate>
</circle>
<circle cx="105" cy="15" r="15">
<animate attributename="r" from="15" to="15" begin="0s" dur="0.8s" values="15;9;15" calcmode="linear" repeatcount="indefinite"></animate>
<animate attributename="fill-opacity" from="1" to="1" begin="0s" dur="0.8s" values="1;.5;1" calcmode="linear" repeatcount="indefinite"></animate>
</circle>
</svg>
</div>
</div>
</div>
<div class="midwest-table-scroll">
<table class="midwest-table">
<caption class="sr-only">Users</caption>
<thead class="midwest-table-head">
<tr>
<th scope="col" class="midwest-table-th align-start sortable sorted" aria-sort="ascending">
<a class="midwest-table-sort-link" href="?sort=name&dir=desc">
Name
<span class="midwest-table-sort-icon" aria-hidden="true"></span>
</a>
</th>
<th scope="col" class="midwest-table-th align-start sortable" aria-sort="none">
<a class="midwest-table-sort-link" href="?sort=email&dir=asc">
Email
<span class="midwest-table-sort-icon" aria-hidden="true"></span>
</a>
</th>
<th scope="col" class="midwest-table-th align-start sortable" aria-sort="none">
<a class="midwest-table-sort-link" href="?sort=role&dir=asc">
Role
<span class="midwest-table-sort-icon" aria-hidden="true"></span>
</a>
</th>
<th scope="col" class="midwest-table-th align-start">
Status
</th>
<th scope="col" class="midwest-table-th align-start">
Joined
</th>
</tr>
</thead>
<tbody class="midwest-table-body">
<tr class="midwest-table-row" data-href="#user-1" data-action="click->midwest-table#navigateRow">
<td class="midwest-table-td align-start">
Alice Johnson
</td>
<td class="midwest-table-td align-start">
alice@example.com
</td>
<td class="midwest-table-td align-start">
Engineer
</td>
<td class="midwest-table-td align-start">
<span variant="success" class="midwest-badge size-default theme-primary">
<span class="value">Active</span>
</span>
</td>
<td class="midwest-table-td align-start">
Jan 2022
</td>
</tr>
<tr class="midwest-table-row" data-href="#user-2" data-action="click->midwest-table#navigateRow">
<td class="midwest-table-td align-start">
Bob Smith
</td>
<td class="midwest-table-td align-start">
bob@example.com
</td>
<td class="midwest-table-td align-start">
Designer
</td>
<td class="midwest-table-td align-start">
<span variant="success" class="midwest-badge size-default theme-primary">
<span class="value">Active</span>
</span>
</td>
<td class="midwest-table-td align-start">
Mar 2021
</td>
</tr>
<tr class="midwest-table-row" data-href="#user-3" data-action="click->midwest-table#navigateRow">
<td class="midwest-table-td align-start">
Carol White
</td>
<td class="midwest-table-td align-start">
carol@example.com
</td>
<td class="midwest-table-td align-start">
Manager
</td>
<td class="midwest-table-td align-start">
<span variant="neutral" class="midwest-badge size-default theme-primary">
<span class="value">Inactive</span>
</span>
</td>
<td class="midwest-table-td align-start">
Nov 2020
</td>
</tr>
<tr class="midwest-table-row" data-href="#user-4" data-action="click->midwest-table#navigateRow">
<td class="midwest-table-td align-start">
David Lee
</td>
<td class="midwest-table-td align-start">
david@example.com
</td>
<td class="midwest-table-td align-start">
Engineer
</td>
<td class="midwest-table-td align-start">
<span variant="success" class="midwest-badge size-default theme-primary">
<span class="value">Active</span>
</span>
</td>
<td class="midwest-table-td align-start">
Jul 2023
</td>
</tr>
<tr class="midwest-table-row" data-href="#user-5" data-action="click->midwest-table#navigateRow">
<td class="midwest-table-td align-start">
Eve Martinez
</td>
<td class="midwest-table-td align-start">
eve@example.com
</td>
<td class="midwest-table-td align-start">
Designer
</td>
<td class="midwest-table-td align-start">
<span variant="neutral" class="midwest-badge size-default theme-primary">
<span class="value">Inactive</span>
</span>
</td>
<td class="midwest-table-td align-start">
Feb 2024
</td>
</tr>
</tbody>
</table>
</div>
</div>
</turbo-frame></div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<%
row_class = Struct.new(:id, :name, :email, :role, :active, :created_at, keyword_init: true)
# Inline presenter subclass for the preview (normally lives in app/tables/)
preview_table_class = Class.new(Midwest::TablePresenter) do
default_sort :name
default_direction :asc
allowed_sorts %i[name email role]
# Full-row click: each row navigates to the URL returned by the callable.
# In a real app you would use view helpers:
# row_href ->(row, view) { view.user_path(row) }
row_href ->(row) { "#user-#{row.id}" }
column 'Name', key: :name, sortable: true
column 'Email', key: :email, sortable: true
column 'Role', key: :role, sortable: true
column 'Status' do |row, view|
variant = row.active ? :success : :neutral
view.midwest_badge(row.active ? 'Active' : 'Inactive', variant: variant)
end
column 'Joined', key: :created_at
def derived_frame_id
'preview-clickable-table'
end
end
rows = [
row_class.new(id: 1, name: 'Alice Johnson', email: 'alice@example.com', role: 'Engineer', active: true, created_at: 'Jan 2022'),
row_class.new(id: 2, name: 'Bob Smith', email: 'bob@example.com', role: 'Designer', active: true, created_at: 'Mar 2021'),
row_class.new(id: 3, name: 'Carol White', email: 'carol@example.com', role: 'Manager', active: false, created_at: 'Nov 2020'),
row_class.new(id: 4, name: 'David Lee', email: 'david@example.com', role: 'Engineer', active: true, created_at: 'Jul 2023'),
row_class.new(id: 5, name: 'Eve Martinez', email: 'eve@example.com', role: 'Designer', active: false, created_at: 'Feb 2024'),
]
table = preview_table_class.new(
params: ActionController::Parameters.new('sort' => 'name', 'dir' => 'asc'),
scope: rows,
request: nil
)
%>
<div class="p-8">
<%= turbo_frame_tag table.frame_id do %>
<%= midwest_table_from table, caption: 'Users' %>
<% end %>
</div>

No assets to display.
Add a .js or .css file alongside the component to see it here.

Accessibility

Figma embed for Table/clickable_rows_with_presenter

Annotate a preview to embed its Figma design here:

@figma "https://figma.com/..."