From eb4a2b9d4e80d495bf0a11c87bb31d18e94e9cc0 Mon Sep 17 00:00:00 2001 From: YashRE42 <33805964+YashRE42@users.noreply.github.com> Date: Mon, 3 Feb 2020 21:31:11 +0530 Subject: [PATCH] navbar: Improve structure & styling for top navbar. This updates the logged-in top navbar to display the stream/message name, number of users, and description. It also replaces the search bar with a search icon that expands into a full-width search bar. Co-authored-by: Max Nussenbaum Fixes: #164. Fixes: #5198. --- frontend_tests/casper_tests/03-narrow.js | 4 +- frontend_tests/node_tests/search.js | 21 +- frontend_tests/node_tests/search_legacy.js | 6 +- static/js/hotkey.js | 11 +- static/js/search.js | 6 +- static/js/subs.js | 12 + static/js/tab_bar.js | 262 ++++++++--------- static/styles/night_mode.scss | 23 +- static/styles/zulip.scss | 313 +++++++++++++-------- static/templates/tab_bar.hbs | 30 +- templates/zerver/app/navbar.html | 9 +- 11 files changed, 379 insertions(+), 318 deletions(-) diff --git a/frontend_tests/casper_tests/03-narrow.js b/frontend_tests/casper_tests/03-narrow.js index 7ada48a2be..23af1e85ad 100644 --- a/frontend_tests/casper_tests/03-narrow.js +++ b/frontend_tests/casper_tests/03-narrow.js @@ -251,9 +251,9 @@ expect_stream_subject(); casper.then(check_narrow_title('frontend test - Zulip Dev - Zulip')); casper.then(function () { - // This time, un-narrow by hitting the search 'x' + // Un-narrow by clicking "Zulip" casper.test.info('Un-narrowing'); - casper.click('#search_exit'); + casper.click('.brand'); }); expect_home(); diff --git a/frontend_tests/node_tests/search.js b/frontend_tests/node_tests/search.js index f78d7f56e5..b1f2bb0ed4 100644 --- a/frontend_tests/node_tests/search.js +++ b/frontend_tests/node_tests/search.js @@ -5,6 +5,7 @@ zrequire('search'); zrequire('search_pill'); zrequire('Filter', 'js/filter'); zrequire('search_pill_widget'); +zrequire('tab_bar'); const noop = () => {}; const return_true = () => true; @@ -38,13 +39,6 @@ run_test('update_button_visibility', () => { const search_query = $('#search_query'); const search_button = $('.search_button'); - search_query.is = return_false; - search_query.val(''); - narrow_state.active = return_false; - search_button.prop('disabled', false); - search.update_button_visibility(); - assert(search_button.prop('disabled')); - search_query.is = return_true; search_query.val(''); narrow_state.active = return_false; @@ -237,7 +231,6 @@ run_test('initizalize', () => { search_query_box.is = return_true; func(ev); assert(is_blurred); - assert(search_button.prop('disabled')); operators = [{ negated: false, @@ -268,7 +261,7 @@ run_test('initizalize', () => { search_query_box.val("test string"); narrow_state.search_string = () => 'ver'; callback(); - assert.equal(search_query_box.val(), 'ver'); + assert.equal(search_query_box.val(), 'test string'); } }; @@ -284,17 +277,7 @@ run_test('initizalize', () => { } }; - let is_deactivated; - narrow.deactivate = () => { - is_deactivated = true; - }; - search.initialize(); - - const search_exit_callback = $('#search_exit').get_on_handler('click'); - - search_exit_callback(); - assert(is_deactivated); }); run_test('initiate_search', () => { diff --git a/frontend_tests/node_tests/search_legacy.js b/frontend_tests/node_tests/search_legacy.js index a057904c60..3da968b8b8 100644 --- a/frontend_tests/node_tests/search_legacy.js +++ b/frontend_tests/node_tests/search_legacy.js @@ -2,6 +2,7 @@ set_global('page_params', { search_pills_enabled: false, }); zrequire('search'); +zrequire('tab_bar'); const noop = () => {}; const return_true = () => true; @@ -26,8 +27,6 @@ run_test('update_button_visibility', () => { search_query.val(''); narrow_state.active = return_false; search_button.prop('disabled', false); - search.update_button_visibility(); - assert(search_button.prop('disabled')); search_query.is = return_true; search_query.val(''); @@ -213,7 +212,6 @@ run_test('initialize', () => { search_query_box.is = return_true; func(ev); assert(is_blurred); - assert(search_button.prop('disabled')); _setup('ver'); search.is_using_input_method = true; @@ -239,7 +237,7 @@ run_test('initialize', () => { search_query_box.val("test string"); narrow_state.search_string = () => 'ver'; callback(); - assert.equal(search_query_box.val(), 'ver'); + assert.equal(search_query_box.val(), 'test string'); } }; diff --git a/static/js/hotkey.js b/static/js/hotkey.js index a3f135f108..03216e944b 100644 --- a/static/js/hotkey.js +++ b/static/js/hotkey.js @@ -231,9 +231,14 @@ exports.process_escape_key = function (e) { return true; } - if (page_params.search_pills_enabled && $('#searchbox').has(':focus')) { - $('#searchbox .pill').blur(); - $('#searchbox #search_query').blur(); + if ($('#searchbox').has(':focus')) { + $("input:focus,textarea:focus").blur(); + if (page_params.search_pills_enabled) { + $('#searchbox .pill').blur(); + $('#searchbox #search_query').blur(); + } else { + tab_bar.exit_search(); + } return true; } diff --git a/static/js/search.js b/static/js/search.js index 738423561c..5ced4bb678 100644 --- a/static/js/search.js +++ b/static/js/search.js @@ -45,8 +45,6 @@ function update_buttons_with_focus(focused) { || search_query_box.val() || narrow_state.active()) { $('.search_button').prop('disabled', false); - } else { - $('.search_button').prop('disabled', true); } } @@ -156,7 +154,6 @@ exports.initialize = function () { // Some of these functions don't actually need to be exported, // but the code was moved here from elsewhere, and it would be // more work to re-order everything and make them private. - $('#search_exit').on('click', narrow.deactivate); search_query_box.on('focus', exports.focus_search); search_query_box.on('blur', function () { @@ -176,8 +173,6 @@ exports.initialize = function () { // really it would be OK if they did). setTimeout(function () { - const search_string = narrow_state.search_string(); - search_query_box.val(search_string); exports.update_button_visibility(); }, 100); }); @@ -204,6 +199,7 @@ exports.initiate_search = function () { if (page_params.search_pills_enabled) { $('#search_query').focus(); } else { + tab_bar.open_search_bar_and_close_narrow_description(); $('#search_query').select(); } }; diff --git a/static/js/subs.js b/static/js/subs.js index 070840ae35..507fd6d4f7 100644 --- a/static/js/subs.js +++ b/static/js/subs.js @@ -140,6 +140,12 @@ exports.update_stream_name = function (sub, new_name) { if (compose_state.stream_name() === old_name) { compose_state.stream_name(new_name); } + + // Update navbar stream name if needed + const filter = narrow_state.filter(); + if (filter && filter.operands("stream")[0] === old_name) { + tab_bar.update_stream_name(new_name); + } }; exports.update_stream_description = function (sub, description, rendered_description) { @@ -152,6 +158,12 @@ exports.update_stream_description = function (sub, description, rendered_descrip // Update stream settings stream_edit.update_stream_description(sub); + + // Update navbar stream description if needed + const filter = narrow_state.filter(); + if (filter && filter.operands("stream")[0] === sub.name) { + tab_bar.update_stream_description(sub.rendered_description); + } }; exports.update_stream_privacy = function (sub, values) { diff --git a/static/js/tab_bar.js b/static/js/tab_bar.js index 91d7b4970c..5ebca5aef2 100644 --- a/static/js/tab_bar.js +++ b/static/js/tab_bar.js @@ -1,172 +1,138 @@ const render_tab_bar = require('../templates/tab_bar.hbs'); -function make_tab(title, hash, data, extra_class, home) { - return {active: "inactive", - cls: extra_class || "", - title: title, - hash: hash, - data: data, - home: home || false }; +function get_sub_count(current_stream) { + const sub_count = current_stream.subscriber_count; + return sub_count; } -function make_tab_data() { - const tabs = []; - const filter = narrow_state.filter(); - - function filtered_to_non_home_view_stream() { - if (!filter.has_operator('stream')) { - return false; - } - const stream_name = filter.operands('stream')[0]; - const stream_id = stream_data.get_stream_id(stream_name); - if (!stream_id) { - return true; - } - - return stream_data.is_muted(stream_id); +function get_formatted_sub_count(current_stream) { + let sub_count = get_sub_count(current_stream); + if (sub_count >= 1000) { + // parseInt() is used to floor the value of division to an integer + sub_count = parseInt(sub_count / 1000, 10) + "k"; } + return sub_count; +} - function in_all() { - return filter !== undefined && - (filtered_to_non_home_view_stream() || - filter.has_operand("in", "all")); +function make_tab_data(filter) { + const tab_data = {}; + if (filter === undefined) { + return { + title: 'All messages', + icon: 'home', + }; } - - if (in_all()) { - tabs.push(make_tab("All Messages", "#narrow/in/all", undefined, "root")); - } else if (page_params.narrow !== undefined) { - tabs.push(make_tab("Stream " + page_params.narrow_stream, - hash_util.operators_to_hash([page_params.narrow[0]]), - page_params.narrow_stream, 'stream')); - if (page_params.narrow_topic !== undefined) { - tabs.push(make_tab("Topic " + page_params.narrow_topic, - hash_util.operators_to_hash(page_params.narrow), - null)); + tab_data.title = filter.get_title(); + tab_data.icon = filter.get_icon(); + if (tab_data.icon === 'hashtag' || tab_data.icon === 'lock') { + const stream = filter.operands("stream")[0]; + const current_stream = stream_data.get_sub_by_name(stream); + if (current_stream) { + tab_data.rendered_narrow_description = current_stream.rendered_description; + tab_data.sub_count = get_sub_count(current_stream); + tab_data.formatted_sub_count = get_formatted_sub_count(current_stream); + tab_data.stream_settings_link = "#streams/" + current_stream.stream_id + "/" + current_stream.name; + } else { + tab_data.title = 'Unknown Stream'; + tab_data.sub_count = '0'; + tab_data.formatted_sub_count = '0'; + tab_data.rendered_narrow_description = "This stream does not exist or is private."; } } - - if (narrow_state.active() && narrow_state.operators().length > 0) { - let stream; - const ops = narrow_state.operators(); - // Second breadcrumb item - let hashed = hash_util.operators_to_hash(ops.slice(0, 1)); - if (filter.has_operator("stream")) { - stream = filter.operands("stream")[0]; - tabs.push(make_tab(stream, hashed, stream, 'stream')); - } else if (filter.has_operator("pm-with") || - filter.has_operand("is", "private")) { - - tabs.push(make_tab("Private Messages", '#narrow/is/private', - undefined, 'private_message ')); - - if (filter.has_operator("pm-with")) { - const emails = filter.operands("pm-with")[0].split(','); - const names = emails.map(email => { - if (!people.get_by_email(email)) { - return email; - } - return people.get_by_email(email).full_name; - }); - - tabs.push(make_tab(names.join(', '), hashed)); - } - - } else if (filter.has_operator("group-pm-with")) { - - tabs.push(make_tab("Group Private", '#narrow/group-pm-with', - undefined, 'private_message ')); - - - } else if (filter.has_operand("is", "starred")) { - tabs.push(make_tab("Starred", hashed)); - } else if (filter.has_operand("streams", "public")) { - tabs.push(make_tab("Public Streams", hashed)); - } else if (filter.has_operator("near")) { - tabs.push(make_tab("Near " + filter.operands("near")[0], hashed)); - } else if (filter.has_operator("id")) { - tabs.push(make_tab("ID " + filter.operands("id")[0], hashed)); - } else if (filter.has_operand("is", "mentioned")) { - tabs.push(make_tab("Mentions", hashed)); - } else if (filter.has_operator("sender")) { - let sender = filter.operands("sender")[0]; - if (people.get_by_email(sender)) { - sender = people.get_by_email(sender).full_name; - } - tabs.push(make_tab("Sent by " + sender, hashed)); - } else if (filter.has_operator("search")) { - // Search is not a clickable link, since we don't have - // a search narrow - tabs.push(make_tab("Search results", false)); - } - - // Third breadcrumb item for stream-topic naarrows - if (filter.has_operator("stream") && - filter.has_operator("topic")) { - const topic = filter.operands("topic")[0]; - hashed = hash_util.operators_to_hash(ops.slice(0, 2)); - - tabs.push(make_tab(topic, hashed, null)); - } - } - - if (tabs.length === 0) { - tabs.push(make_tab('All messages', "#", "home", "root", true)); - } - - // Last tab is not a link - tabs[tabs.length - 1].hash = null; - - return tabs; + return tab_data; } exports.colorize_tab_bar = function () { - const stream_tab = $('#tab_list .stream'); - if (stream_tab.length > 0) { - let stream_name = stream_tab.data('name'); - if (stream_name === undefined) { - return; - } - stream_name = stream_name.toString(); - - const color_for_stream = stream_data.get_color(stream_name); - const stream_dark = stream_color.get_color_class(color_for_stream); - const stream_light = colorspace.getHexColor( - colorspace.getLighterColor( - colorspace.getDecimalColor(color_for_stream), 0.2)); - - if (stream_tab.hasClass("stream")) { - stream_tab.css('background-color', color_for_stream); - if (stream_tab.hasClass("inactive")) { - stream_tab.hover ( - function () { - $(this).css('background-color', stream_light); - }, function () { - $(this).css('background-color', color_for_stream); - } - ); - } - stream_tab.removeClass(stream_color.color_classes); - stream_tab.addClass(stream_dark); - } - } + const filter = narrow_state.filter(); + if (filter === undefined || !filter.has_operator('stream')) {return;} + const color_for_stream = stream_data.get_color(filter.operands("stream")[0]); + const stream_light = colorspace.getHexColor(colorspace.getDecimalColor(color_for_stream)); + $("#tab_list .fa-hashtag").css('color', stream_light); + $("#tab_list .fa-lock").css('color', stream_light); }; -function build_tab_bar() { - const tabs = make_tab_data(); - +function display_tab_bar(tab_bar_data) { const tab_bar = $("#tab_bar"); tab_bar.empty(); - - tabs[tabs.length - 1].active = "active"; - const rendered = render_tab_bar({tabs: tabs}); - + const rendered = render_tab_bar(tab_bar_data); tab_bar.append(rendered); - exports.colorize_tab_bar(); + if (tab_bar_data.stream_settings_link) { + exports.colorize_tab_bar(); + } tab_bar.removeClass('notdisplayed'); } +function build_tab_bar(filter) { + // This makes sure we don't waste time appending tab_bar on a template where it's never used + if (filter && !filter.is_common_narrow()) { + exports.open_search_bar_and_close_narrow_description(); + } else { + const tab_bar_data = make_tab_data(filter); + display_tab_bar(tab_bar_data); + $(".search_closed").on("click", function (e) { + exports.open_search_bar_and_close_narrow_description(); + $('#search_query').select(); + e.preventDefault(); + e.stopPropagation(); + }); + exports.close_search_bar_and_open_narrow_description(); + } +} + +exports.exit_search = function () { + const filter = narrow_state.filter(); + if (!filter || filter.is_common_narrow()) { + // for common narrows, we change the UI (and don't redirect) + exports.close_search_bar_and_open_narrow_description(); + } else { + // for "searching narrows", we redirect + window.location.replace(filter.generate_redirect_url()); + } +}; + +exports.update_stream_name = function (new_name) { + const stream_name = $(".stream a"); + if (stream_name !== undefined) { + stream_name.text(new_name); + } +}; + +exports.update_stream_description = function () { + // TODO: Implement this properly. Really, this and update_stream + // name should just do a full rerender of the tab_tab component; + // they're rare events and that rendering is cheap. + + // TODO: Do similar rerenders for stream privacy or subscriber + // count changes. + return; +}; + exports.initialize = function () { - build_tab_bar(); + const filter = narrow_state.filter(); + build_tab_bar(filter); + + // register navbar click handlers + $('#search_exit').on("click", function (e) { + tab_bar.exit_search(); + e.preventDefault(); + e.stopPropagation(); + }); + + $(".search_open").on("click", function (e) { + $('#search_query').typeahead('lookup').focus(); + e.preventDefault(); + e.stopPropagation(); + }); +}; + +exports.open_search_bar_and_close_narrow_description = function () { + $(".navbar-search").addClass("expanded"); + $("#tab_list").addClass("hidden"); +}; + +exports.close_search_bar_and_open_narrow_description = function () { + $(".navbar-search").removeClass("expanded"); + $("#tab_list").removeClass("hidden"); }; window.tab_bar = exports; diff --git a/static/styles/night_mode.scss b/static/styles/night_mode.scss index 691b863235..72fd0cf65b 100644 --- a/static/styles/night_mode.scss +++ b/static/styles/night_mode.scss @@ -83,9 +83,8 @@ body.night-mode { /* do not turn the .message_header .stream_label text dark on hover because they're on a dark background, and don't change the dark labels dark either. */ - .message_header:not(.dark_background) a.stream_label:not(.dark_background):hover, - #tab_list li.stream:not(.dark_background) { - color: hsl(212, 28%, 18%) !important; + .message_header:not(.dark_background) a.stream_label:not(.dark_background):hover { + color: hsl(212, 28%, 18%); } /* these are converting grey things to "new grey" */ @@ -204,8 +203,7 @@ on a dark background, and don't change the dark labels dark either. */ } .message-header-contents, - .message_header_private_message .message-header-contents, - #tab_bar #tab_list li.active { + .message_header_private_message .message-header-contents { background-color: hsla(0, 0%, 0%, 0.2); } @@ -226,6 +224,19 @@ on a dark background, and don't change the dark labels dark either. */ .top-navbar-border { border-color: hsla(0, 0%, 0%, 0.6); } + #tab_bar #tab_list li.sub_count::before { + background: hsla(0, 0%, 100%, 0.5); + } + #tab_bar #tab_list li.sub_count::after { + background: hsla(0, 0%, 100%, 0.5); + } + + #searchbox_legacy { + #tab_bar #tab_list li.sub_count, + #tab_bar #tab_list li.narrow_description { + color: hsla(0, 0%, 90%, 1); + } + } .overlay, #subscription_overlay #stream-creation #stream_creation_form #stream_creating_indicator:not(:empty), @@ -354,8 +365,6 @@ on a dark background, and don't change the dark labels dark either. */ } thead, - #searchbox, - #searchbox_legacy, .drafts-container .drafts-header, .nav > li > a:hover, .subscriptions-container .subscriptions-header, diff --git a/static/styles/zulip.scss b/static/styles/zulip.scss index 2b423be004..ed227d2769 100644 --- a/static/styles/zulip.scss +++ b/static/styles/zulip.scss @@ -1372,6 +1372,7 @@ div.focused_table { } #tab_bar { + width: 100%; z-index: 2; padding-top: 0px; overflow: hidden; @@ -1379,97 +1380,161 @@ div.focused_table { float: left; letter-spacing: normal; height: 40px; - #tab_list { - list-style: none; + display: flex; + align-content: flex-start; + flex-wrap: nowrap; margin: 0px 0px 0px 0px; height: 40px; line-height: 40px; font-size: 16px; border: none; white-space: nowrap; - - li { + width: calc(100% - 1px); + cursor: default; + .hidden { + display: none; + } + span { white-space: nowrap; list-style-type: none; display: inline-block; + vertical-align: top; position: relative; - font-weight: 300; - background-color: hsl(0, 0%, 98%); - margin: 0px; - padding: 0px; - text-overflow: ellipsis; - padding: 0 5px; - } + font-weight: 600; + font-size: 16px; + line-height: 16px; + margin: 0 -4px 0 0; + padding: 12px 6px; - li.private_message a { - color: hsl(0, 0%, 100%); - } - - a { - text-decoration: none; - color: inherit; - border-color: inherit; - width: 100%; - display: inline-block; - padding: 0px 5px; - max-width: 150px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - li.active { - background-color: hsl(0, 0%, 88%); - max-width: 150px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - } - - li.private_message { - border-top-color: hsla(0, 0%, 0%, 0.0); - border-right-color: hsla(0, 0%, 0%, 0.0); - border-bottom-color: hsla(0, 0%, 0%, 0.0); - background-color: hsl(0, 0%, 27%); - border-left-color: hsl(0, 0%, 27%); - color: hsl(0, 0%, 100%); - border-width: 0px; - } - - .root { - border-color: hsl(0, 0%, 88%); - background-color: hsl(0, 0%, 88%); - margin: 0px; - a { - color: hsl(0, 0%, 52%); - padding-right: 2px; - &:hover { - color: hsl(0, 0%, 0%); + @media (max-width: 500px) { + padding: 7px 3.5px; // based on having ~41.66% decrease + } + &:not(.search_closed):not(.sub_count):not(.narrow_description) { + flex-shrink: 1; + overflow: hidden; + } + &:not(.stream) { + text-overflow: ellipsis; + } + i { + margin-right: 3px; + } + .fa { + margin: 0px 3px 0px 5px; + .fa-envelope { + font-size: 14px; + margin: 0px 5px 0px 5px; + } + .fa-hashtag { + font-size: 1.2rem; + // font-weight: 800; + margin: 0px 2px 0px 5px; } } } - li.inactive { - border-width: 0px; - margin-right: -4px; - font-size: 14px; - &::before { - left: 100%; - top: 50%; - content: " "; - height: 0px; - width: 0px; - position: absolute; - pointer-events: none; - z-index: 1; - transform: scale(.9999); + .stream { + text-overflow: clip; + overflow: hidden; + a { + color: inherit; + text-decoration: none; + padding-right: 2px; } } - li.active.root { - padding: 0px 10px; + .sub_count, + .narrow_description { + background: none; + font-size: 14px; + color: hsl(0, 0%, 40%); + font-weight: 400; + line-height: 20px; } + + .sub_count { + margin-left: 10px; + margin-right: 10px; + .fa.fa-user-o { + margin-left: 0px; + } + &::before { + content: ""; + position: absolute; + left: -5px; + top: 25%; + width: 1px; + height: 50%; + background: hsl(0, 0%, 88%); + @media (max-width: 500px) { + top: 10%; + } + } + &::after { + content: ""; + position: absolute; + right: -5px; + top: 25%; + width: 1px; + height: 50%; + background: hsl(0, 0%, 88%); + @media (max-width: 500px) { + top: 10%; + } + } + } + + .narrow_description { + // the actual value of flex shrink does not matter, it is the + // ratio of this value to other flex items that determines the + // behavior while shrinking, here the other item has the .stream + // class and a flex of 1, so the value here *is* the ratio, and + // is chosen such that the narrow description shrinks to close + // before the stream name must begin to shrink + flex-shrink: 100; + overflow: hidden; + white-space: nowrap; + margin: 0; + .emoji { + margin: 0; + padding: 0; + } + padding: 12px 0px; + padding-left: 2px; + + @media (max-width: 500px) { + padding: 7px 0; + padding-left: 2px; + } + } + + .search_closed { + flex: 0; // makes sure search icon is always visible + margin-left: auto; // aligns search icon to right end of box + margin-right: 40px; // 27 = 15 (gets icon inside border) + 25 (margin against border) + + cursor: pointer; + font-size: 20px; + + padding: 12px 0px 0px 0px; + @media (max-width: 500px) { + padding: 5px 0px 0px 0px; + } + } + } +} + +.search_icon { + color: hsl(0, 0%, 80%); + text-decoration: none; + width: 0; + height: 0; + padding-top: 12px; + padding-left: 50px; + &:hover { + color: hsl(0, 0%, 0%); + text-decoration: none; } } @@ -1580,12 +1645,20 @@ div.focused_table { width: 100%; height: 40px; - .navbar-search { - margin-top: 0px; - width: auto; - float: none; + .navbar-search:not(.expanded) { + display: none; + } + + .navbar-search.expanded { overflow: hidden; - height: 40px; + margin-top: 0px; + right: 2; + width: calc(100% - 2px); + position: absolute; + .search_button { + display: inline; + margin-right: 16px; + } } .input-append { @@ -1600,6 +1673,10 @@ div.focused_table { top: 10px; z-index: 5; } + + .fa-search:not(.deactivated) { + cursor: pointer; + } } #search_query { @@ -1608,7 +1685,7 @@ div.focused_table { height: 40px; padding: 0px; padding-left: 35px; - padding-right: 20px; + padding-right: 40px; border: none; border-radius: 0px; font-family: 'Source Sans Pro'; @@ -1646,19 +1723,6 @@ div.focused_table { visibility: hidden; } - .search_icon { - color: hsl(0, 0%, 80%); - text-decoration: none; - display: block; - width: 1px; - height: 1px; - } - - .search_icon:hover { - color: hsl(0, 0%, 0%); - text-decoration: none; - } - #search_arrows { /* Bootstrap wants font-size: 0 to eliminate space between the buttons. We need to inherit the font size, so we @@ -1701,7 +1765,7 @@ div.focused_table { left: 0px; text-align: center; vertical-align: middle; - border-right: 2px solid hsl(204, 20%, 74%); + // border-right: 2px solid hsl(204, 20%, 74%); } #streamlist-toggle-button { @@ -2515,17 +2579,10 @@ div.topic_edit_spinner .loading_indicator_spinner { width: 30px; } - #top_navbar.rightside-userlist .navbar-search { - margin-right: 100px; - } - #top_navbar.rightside-userlist #navbar-buttons { margin-right: 41px; } - .navbar-search { - margin-right: 60px; - } .nav .dropdown-menu { min-width: 180px; @@ -2539,6 +2596,25 @@ div.topic_edit_spinner .loading_indicator_spinner { .column-middle { margin-right: 7px; } + + .top-navbar-container, + #searchbox_legacy .navbar-search.expanded { + width: calc(100% - 91px); + } + + .search_closed .fa-search { + right: 115px; + } + + #top_navbar:not(.rightside-userlist) { + .search_closed .fa-search { + right: 72px; + } + .top-navbar-border, + #searchbox_legacy .navbar-search.expanded { + width: calc(100% - 50px); + } + } } @media (max-width: 775px) { @@ -2604,17 +2680,34 @@ div.topic_edit_spinner .loading_indicator_spinner { display: block; } - #searchbox, - #searchbox_legacy { - margin-left: 42px; + .top-navbar-border { + margin-left: 40px; } - #top_navbar.rightside-userlist .navbar-search { - margin-right: 127px; + .top-navbar-border { + width: calc(100% - 116px); + } + // todo: Figure out why this has to be different + // from above at this width and resolve it + // #searchbox_legacy .navbar-search.expanded, + #searchbox_legacy .navbar-search.expanded { + width: calc(100% - 131px); } - .navbar-search { - margin-right: 81px; + .search_closed .fa-search { + right: 115px; + } + + #top_navbar:not(.rightside-userlist) { + // .search_closed .fa-search { + // right: 115px; + // } + .top-navbar-border { + width: calc(100% - 75px); + } + #searchbox_legacy .navbar-search.expanded { + width: calc(100% - 90px); + } } } @@ -2636,6 +2729,10 @@ div.topic_edit_spinner .loading_indicator_spinner { margin-top: 10px; } + .search_closed .fa-search { + top: 5px; + } + #streamlist-toggle, #navbar-buttons, .navbar-search, @@ -2665,10 +2762,6 @@ div.topic_edit_spinner .loading_indicator_spinner { top: -5px; } - #top_navbar.rightside-userlist .navbar-search { - margin-right: 115px; - } - #searchbox, #searchbox_legacy { .input-append .fa-search { @@ -2677,7 +2770,7 @@ div.topic_edit_spinner .loading_indicator_spinner { .search_button, .search_button[disabled]:hover { - top: 2px; + top: 0px; } } diff --git a/static/templates/tab_bar.hbs b/static/templates/tab_bar.hbs index 2839189cf0..9722f73ee9 100644 --- a/static/templates/tab_bar.hbs +++ b/static/templates/tab_bar.hbs @@ -1,19 +1,19 @@ - + + {{#if sub_count}} + {{formatted_sub_count}} + {{/if}} + {{#if rendered_narrow_description}} + {{rendered_markdown rendered_narrow_description}} + {{/if}} + + diff --git a/templates/zerver/app/navbar.html b/templates/zerver/app/navbar.html index c7224a32c6..4e09c2b244 100644 --- a/templates/zerver/app/navbar.html +++ b/templates/zerver/app/navbar.html @@ -12,12 +12,12 @@ 0 -
+
{% if search_pills_enabled %}