Skip to content

Commit 9e907a4

Browse files
authored
Reworked sidebar and added grouping, a chip appears on filter or tag selection that is easily seen and can be removed and no topics matching a filter, gives a clear error message and the ability to clear filters easily (#78)
Signed-off-by: Kai Wagner <kai.wagner@percona.com>
1 parent 1eebcff commit 9e907a4

6 files changed

Lines changed: 181 additions & 30 deletions

File tree

app/assets/stylesheets/components/sidebar.css

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,61 @@
152152
text-align: right;
153153
}
154154

155+
.filter-subsection {
156+
margin-bottom: var(--spacing-4);
157+
158+
&:last-child {
159+
margin-bottom: 0;
160+
}
161+
}
162+
163+
.filter-subsection-label {
164+
display: block;
165+
font-size: var(--font-size-xs);
166+
font-weight: var(--font-weight-semibold);
167+
text-transform: uppercase;
168+
letter-spacing: 0.06em;
169+
color: var(--color-text-muted);
170+
margin-bottom: var(--spacing-2);
171+
padding-left: var(--spacing-1);
172+
}
173+
155174
.sidebar .quick-filters {
156-
list-style: square inside;
175+
list-style: none;
157176
padding-left: 0;
177+
margin: 0;
158178

159-
& a {
179+
& li {
180+
border-radius: var(--border-radius-sm);
181+
overflow: hidden;
182+
}
183+
184+
& li + li {
185+
margin-top: 1px;
186+
}
187+
188+
& a, & a.quick-filter-link {
189+
display: block;
190+
padding: var(--spacing-2) var(--spacing-3);
160191
color: var(--color-text-link);
161192
text-decoration: none;
162193
font-weight: var(--font-weight-medium);
194+
font-size: var(--font-size-sm);
195+
border-radius: var(--border-radius-sm);
196+
transition: background var(--transition-fast), color var(--transition-fast);
163197
}
164198

165199
& a:hover {
166-
text-decoration: underline;
200+
background: var(--color-bg-hover);
201+
text-decoration: none;
202+
}
203+
204+
& a.is-active {
205+
background: var(--color-primary-50);
206+
color: var(--color-primary-700);
207+
font-weight: var(--font-weight-semibold);
208+
border-left: 3px solid var(--color-primary-500);
209+
padding-left: calc(var(--spacing-3) - 3px);
167210
}
168211
}
169212

app/assets/stylesheets/components/topics.css

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,64 @@
1+
.topics-filter-chip {
2+
display: inline-flex;
3+
align-items: center;
4+
gap: var(--spacing-2);
5+
padding: var(--spacing-1) var(--spacing-3);
6+
margin: var(--spacing-3) var(--spacing-4) 0;
7+
background: var(--color-primary-50);
8+
border: var(--border-width) solid var(--color-primary-200);
9+
border-radius: 999px;
10+
color: var(--color-primary-700);
11+
font-size: var(--font-size-sm);
12+
font-weight: var(--font-weight-medium);
13+
text-decoration: none;
14+
transition: background var(--transition-fast), border-color var(--transition-fast);
15+
16+
&:hover {
17+
background: var(--color-primary-100);
18+
border-color: var(--color-primary-500);
19+
}
20+
}
21+
22+
.topics-filter-chip-close {
23+
font-size: var(--font-size-xs);
24+
opacity: 0.6;
25+
}
26+
27+
.topic-empty-row td {
28+
border-bottom: none;
29+
padding: var(--spacing-10) var(--spacing-4);
30+
}
31+
32+
.topics-empty-state {
33+
display: flex;
34+
flex-direction: column;
35+
align-items: center;
36+
gap: var(--spacing-3);
37+
color: var(--color-text-muted);
38+
39+
& i {
40+
font-size: 2rem;
41+
opacity: 0.4;
42+
}
43+
44+
& p {
45+
margin: 0;
46+
font-size: var(--font-size-base);
47+
}
48+
}
49+
50+
.topics-empty-clear {
51+
color: var(--color-text-link);
52+
font-weight: var(--font-weight-medium);
53+
text-decoration: none;
54+
55+
&:hover {
56+
text-decoration: underline;
57+
}
58+
}
59+
60+
/* ─────────────────────────────────────────────────────────────────── */
61+
162
.section-header {
263
display: flex;
364
justify-content: space-between;

app/helpers/topics_helper.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,22 @@ def topic_title_link(topic)
234234
topic_path(topic)
235235
end
236236
end
237+
238+
def topic_filter_labels
239+
{
240+
"no_contrib_replies" => "No contributor/committer replies",
241+
"patch_no_replies" => "Patch, no replies",
242+
"reading_incomplete" => "Reading in progress",
243+
"new_for_me" => "New for me",
244+
"started_by_me" => "Started by me",
245+
"messaged_by_me" => "I posted here",
246+
"starred_by_me" => "Starred by me",
247+
"starred_by_team" => "Starred by team",
248+
"team_unread" => "Not yet read by team",
249+
"team_reading_others" => "Teammates reading",
250+
"team_reading_any" => "Team reading",
251+
"team_started" => "Started by team",
252+
"team_messaged" => "Team messages"
253+
}
254+
end
237255
end

app/views/topics/_sidebar.html.slim

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,39 @@
2626
.sidebar-section
2727
h3.sidebar-heading Quick filters
2828
.sidebar-content
29-
ul.quick-filters
30-
li = link_to "No contributor/committer replies", topics_path(filter: "no_contrib_replies")
31-
li = link_to "Patch, no replies", topics_path(filter: "patch_no_replies")
32-
- if user_signed_in?
33-
li = link_to "Reading in progress", topics_path(filter: "reading_incomplete")
34-
li = link_to "New for me", topics_path(filter: "new_for_me")
35-
li = link_to "Started by me", topics_path(filter: "started_by_me")
36-
li = link_to "I posted here", topics_path(filter: "messaged_by_me")
37-
li = link_to "Starred by me", topics_path(filter: "starred_by_me")
38-
- current_user.teams.each do |team|
39-
li = link_to "#{team.name}: starred by team", topics_path(filter: "starred_by_team", team_id: team.id)
40-
li = link_to "#{team.name}: not yet read by team", topics_path(filter: "team_unread", team_id: team.id)
41-
li = link_to "#{team.name}: my teammates are reading", topics_path(filter: "team_reading_others", team_id: team.id)
42-
li = link_to "#{team.name}: my team is reading", topics_path(filter: "team_reading_any", team_id: team.id)
43-
li = link_to "#{team.name}: started by team", topics_path(filter: "team_started", team_id: team.id)
44-
li = link_to "#{team.name}: messages by team", topics_path(filter: "team_messaged", team_id: team.id)
45-
- if user_signed_in? && @available_note_tags.present?
46-
.sidebar-section
47-
h3.sidebar-heading My tags
48-
ul.quick-filters.tags-list
49-
- @available_note_tags.each do |tag, count|
50-
li = link_to "##{tag} (#{count})", topics_path(note_tag: tag)
29+
- active_filter = params[:filter]
30+
- active_team_id = params[:team_id]&.to_i
31+
32+
.filter-subsection
33+
span.filter-subsection-label Status
34+
ul.quick-filters
35+
li = link_to "No contributor/committer replies", topics_path(filter: "no_contrib_replies"), class: ("quick-filter-link is-active" if active_filter == "no_contrib_replies")
36+
li = link_to "Patch, no replies", topics_path(filter: "patch_no_replies"), class: ("quick-filter-link is-active" if active_filter == "patch_no_replies")
37+
38+
- if user_signed_in?
39+
.filter-subsection
40+
span.filter-subsection-label My activity
41+
ul.quick-filters
42+
li = link_to "Reading in progress", topics_path(filter: "reading_incomplete"), class: ("quick-filter-link is-active" if active_filter == "reading_incomplete")
43+
li = link_to "New for me", topics_path(filter: "new_for_me"), class: ("quick-filter-link is-active" if active_filter == "new_for_me")
44+
li = link_to "Started by me", topics_path(filter: "started_by_me"), class: ("quick-filter-link is-active" if active_filter == "started_by_me")
45+
li = link_to "I posted here", topics_path(filter: "messaged_by_me"), class: ("quick-filter-link is-active" if active_filter == "messaged_by_me")
46+
li = link_to "Starred by me", topics_path(filter: "starred_by_me"), class: ("quick-filter-link is-active" if active_filter == "starred_by_me")
47+
48+
- current_user.teams.each do |team|
49+
.filter-subsection
50+
span.filter-subsection-label = team.name
51+
ul.quick-filters
52+
li = link_to "Starred by team", topics_path(filter: "starred_by_team", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "starred_by_team" && active_team_id == team.id)
53+
li = link_to "Not yet read by team", topics_path(filter: "team_unread", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "team_unread" && active_team_id == team.id)
54+
li = link_to "Teammates reading", topics_path(filter: "team_reading_others", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "team_reading_others" && active_team_id == team.id)
55+
li = link_to "Team reading", topics_path(filter: "team_reading_any", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "team_reading_any" && active_team_id == team.id)
56+
li = link_to "Started by team", topics_path(filter: "team_started", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "team_started" && active_team_id == team.id)
57+
li = link_to "Team messages", topics_path(filter: "team_messaged", team_id: team.id), class: ("quick-filter-link is-active" if active_filter == "team_messaged" && active_team_id == team.id)
58+
59+
- if user_signed_in? && @available_note_tags.present?
60+
.sidebar-section
61+
h3.sidebar-heading My tags
62+
ul.quick-filters.tags-list
63+
- @available_note_tags.each do |tag, count|
64+
li = link_to "##{tag} (#{count})", topics_path(note_tag: tag), class: ("quick-filter-link is-active" if params[:note_tag] == tag)

app/views/topics/_topics.html.slim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
- topic_participants_map ||= @topic_participants_map || {}
22

3+
- if topics.empty?
4+
tr.topic-empty-row
5+
td colspan=3
6+
.topics-empty-state
7+
i.fa-regular.fa-folder-open aria-hidden="true"
8+
p No topics match this filter.
9+
- if params[:filter].present? || params[:note_tag].present?
10+
= link_to "Clear filters", topics_path, class: "topics-empty-clear"
11+
312
- topics.each do |topic|
413
- tp_data = topic_participants_map[topic.id] || {}
514
- top_participants = tp_data[:top] || []

app/views/topics/index.html.slim

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
- cache_block = lambda do
2+
- if params[:filter].present?
3+
= link_to topics_path(note_tag: params[:note_tag]), class: "topics-filter-chip" do
4+
i.fa-solid.fa-filter aria-hidden="true"
5+
span = topic_filter_labels[params[:filter]] || params[:filter].humanize
6+
i.fa-solid.fa-xmark.topics-filter-chip-close aria-hidden="true"
7+
- elsif params[:note_tag].present?
8+
= link_to topics_path, class: "topics-filter-chip" do
9+
i.fa-solid.fa-tag aria-hidden="true"
10+
span = "##{params[:note_tag]}"
11+
i.fa-solid.fa-xmark.topics-filter-chip-close aria-hidden="true"
12+
213
#new-topics-banner data-controller="new-topics-banner" data-new-topics-banner-url-value=new_topics_count_topics_path(viewing_since: @viewing_since.iso8601, filter: params[:filter], team_id: params[:team_id]) data-new-topics-banner-interval-ms-value="180000"
314
= render partial: "new_topics_banner", locals: { count: @new_topics_count, viewing_since: @viewing_since }
415

5-
- if @active_note_tag.present?
6-
.tag-filter-banner
7-
span Filtering by ##{@active_note_tag}
8-
= link_to "Clear", topics_path, class: "clear-tag-filter"
9-
1016
.topics-table
1117
table
1218
thead

0 commit comments

Comments
 (0)