mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
left_sidebar: Standardize topic list filter input.
This follow-up commit replaces the current left sidebar topic list filter input implementation with the redesigned input_wrapper component. This commit also serves as the base for supporting inputs using the search_pill_widget, and thus adjusts the previously defined logic at certain places to ensure that the input pills are handled and displayed accurately. Fixes part of #34476.
This commit is contained in:
@@ -838,7 +838,7 @@ export function initialize(): void {
|
||||
|
||||
// LEFT SIDEBAR
|
||||
|
||||
$("body").on("click", "#clear_search_topic_button", topic_list.clear_topic_search);
|
||||
$("body").on("click", ".filter-topics .input-button", topic_list.clear_topic_search);
|
||||
|
||||
$(".streams_filter_icon").on("click", (e) => {
|
||||
e.stopPropagation();
|
||||
|
@@ -1,6 +1,8 @@
|
||||
import $ from "jquery";
|
||||
|
||||
$("body").on("input", ".input-element", function (this: HTMLInputElement, _e: JQuery.Event) {
|
||||
// We use the `input` tag in the selector to avoid conflicts with the pill containing
|
||||
// counterpart, which uses a `contenteditable` div instead of an input element.
|
||||
$("body").on("input", "input.input-element", function (this: HTMLInputElement, _e: JQuery.Event) {
|
||||
if (this.value.length === 0) {
|
||||
$(this).removeClass("input-element-nonempty");
|
||||
} else {
|
||||
@@ -8,6 +10,25 @@ $("body").on("input", ".input-element", function (this: HTMLInputElement, _e: JQ
|
||||
}
|
||||
});
|
||||
|
||||
$("body").on(
|
||||
"input change",
|
||||
".has-input-pills .pill-container",
|
||||
function (this: HTMLInputElement, _e: JQuery.Event) {
|
||||
// We define another event handler for inputs with pill, similar to the one above.
|
||||
// However, due to the way inputs with pill use a contenteditable div instead of an
|
||||
// input element, we need to check the textContent of the pill container instead of
|
||||
// the value of an input element.
|
||||
// Here we need to listen to the `change` event in conjunction with the `input` event
|
||||
// to handle the addition or removal of input pills.
|
||||
const value = this.textContent?.trim() ?? "";
|
||||
if (value.length === 0) {
|
||||
$(this).removeClass("input-element-nonempty");
|
||||
} else {
|
||||
$(this).addClass("input-element-nonempty");
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
$("body").on(
|
||||
"click",
|
||||
".filter-input .input-button",
|
||||
|
@@ -374,26 +374,17 @@ export class LeftSidebarTopicListWidget extends TopicListWidget {
|
||||
|
||||
export function clear_topic_search(e: JQuery.Event): void {
|
||||
e.stopPropagation();
|
||||
|
||||
search_pill_widget?.clear(true);
|
||||
|
||||
const $input = $("#topic_filter_query");
|
||||
if ($input.length > 0) {
|
||||
$input.text("");
|
||||
$input.trigger("blur");
|
||||
|
||||
search_pill_widget?.clear(true);
|
||||
update_clear_button();
|
||||
|
||||
// Since this changes the contents of the search input, we
|
||||
// need to rerender the topic list.
|
||||
const stream_ids = [...active_widgets.keys()];
|
||||
|
||||
const stream_id = stream_ids[0];
|
||||
assert(stream_id !== undefined);
|
||||
const widget = active_widgets.get(stream_id);
|
||||
assert(widget !== undefined);
|
||||
const parent_widget = widget.get_parent();
|
||||
|
||||
rebuild_left_sidebar(parent_widget, stream_id);
|
||||
}
|
||||
// Since the `clear` function of the search_pill_widget
|
||||
// takes care of clearing both the text content and the
|
||||
// pills, we just need to trigger an input event on the
|
||||
// contenteditable element to reset the topic list via
|
||||
// the `input` event handler without having to manually
|
||||
// manage the reset of the topic list.
|
||||
$input.trigger("input");
|
||||
}
|
||||
|
||||
export function active_stream_id(): number | undefined {
|
||||
@@ -517,7 +508,7 @@ const filter_options = new Map<string, string>([
|
||||
|
||||
export function update_clear_button(): void {
|
||||
const $filter_query = $("#topic_filter_query");
|
||||
const $clear_button = $("#clear_search_topic_button");
|
||||
const $clear_button = $(".filter-topics .input-button");
|
||||
if (get_left_sidebar_topic_search_term() === "" && get_typeahead_search_term() === "") {
|
||||
$clear_button.css("visibility", "hidden");
|
||||
// When we use backspace to clear the content of the search box,
|
||||
|
@@ -60,6 +60,38 @@
|
||||
var(--input-button-ending-offset)
|
||||
);
|
||||
}
|
||||
|
||||
/* Special styles for input with pills */
|
||||
&.has-input-pills .pill-container {
|
||||
.input {
|
||||
flex-grow: 1;
|
||||
/* Override default values in web/styles/input_pill.css */
|
||||
padding: 0;
|
||||
line-height: inherit;
|
||||
|
||||
&:empty::before {
|
||||
color: var(--color-text-placeholder);
|
||||
content: attr(data-placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
.pill {
|
||||
height: 1.25em; /* 20px at 16px/1em */
|
||||
}
|
||||
|
||||
&:has(.input:hover) {
|
||||
border-color: var(--color-border-input-hover);
|
||||
}
|
||||
|
||||
&:has(.input:focus) {
|
||||
box-shadow: 0 0 5px var(--color-box-shadow-input-focus);
|
||||
}
|
||||
|
||||
&:has(.input:focus),
|
||||
&.input-element-nonempty:has(.input) {
|
||||
@extend .input-active-styles;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
@@ -77,11 +109,15 @@
|
||||
padding: 0.25em; /* 4px at 16px/1em */
|
||||
}
|
||||
|
||||
.filter-input .input-element {
|
||||
/* We use the `input` tag in the selector to avoid conflicts
|
||||
with the pill containing counterpart, which uses a `contenteditable`
|
||||
div instead of an input element, and thus doesn't support the
|
||||
placeholder pseudo-classes. */
|
||||
.filter-input input.input-element {
|
||||
&:placeholder-shown {
|
||||
/* In case of filter inputs, when the input field
|
||||
is empty, we hide the input button and adjust
|
||||
the right padding to compensate for the same. */
|
||||
is empty, we hide the input button and adjust
|
||||
the right padding to compensate for the same. */
|
||||
padding-right: 0.5em;
|
||||
|
||||
~ .input-button {
|
||||
|
@@ -1363,31 +1363,8 @@ li.top_left_scheduled_messages {
|
||||
}
|
||||
}
|
||||
|
||||
.topic-list-filter {
|
||||
grid-area: filter-box;
|
||||
padding-right: var(--line-height-sidebar-row-prominent);
|
||||
box-shadow: none;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
gap: 0.125em; /* 2px at 16px em */
|
||||
background-color: var(--color-background-active-narrow-filter);
|
||||
font-weight: 400;
|
||||
|
||||
.input:empty::before {
|
||||
color: var(--color-text-placeholder);
|
||||
content: attr(data-placeholder);
|
||||
}
|
||||
|
||||
.input {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
#clear_search_topic_button {
|
||||
visibility: hidden;
|
||||
height: 2em; /* 32px at 16px/1em */
|
||||
.filter-topics {
|
||||
font-weight: initial;
|
||||
}
|
||||
|
||||
.searching-for-more-topics img {
|
||||
|
@@ -1,13 +1,7 @@
|
||||
<div class="left-sidebar-filter-input-container">
|
||||
<div class="topic_search_section filter-topics left-sidebar-filter-row">
|
||||
<div class="topic-list-filter home-page-input filter_text_input pill-container" id="left-sidebar-filter-topic-input">
|
||||
<div class="input" contenteditable="true" id="topic_filter_query"
|
||||
data-placeholder="{{t 'Filter topics' }}">
|
||||
{{~! Squash whitespace so that placeholder is displayed when empty. ~}}
|
||||
</div>
|
||||
{{#> input_wrapper input_type="filter-input" custom_classes="topic_search_section filter-topics has-input-pills" icon="search" input_button_icon="close"}}
|
||||
<div class="input-element home-page-input pill-container" id="left-sidebar-filter-topic-input">
|
||||
<div class="input" contenteditable="true" id="topic_filter_query" data-placeholder="{{t 'Filter topics' }}"></div>
|
||||
</div>
|
||||
<button type="button" class="clear_search_button" id="clear_search_topic_button">
|
||||
<i class="zulip-icon zulip-icon-close" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
{{/input_wrapper}}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user