Skip to content

UX: display search input and open modal on click #32508

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions app/assets/javascripts/admin/addon/components/admin-search.gjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { hash } from "@ember/helper";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
import { LinkTo } from "@ember/routing";
import { service } from "@ember/service";
import { htmlSafe } from "@ember/template";
import { TrackedObject } from "@ember-compat/tracked-built-ins";
Expand Down Expand Up @@ -194,6 +196,15 @@ export default class AdminSearch extends Component {
</div>
<DButton class="btn-flat" @icon="filter" @action={{this.toggleFilters}} />
</div>
{{#if @fullPageLink}}
<LinkTo
@route="adminSearch"
@query={{hash filter=this.filter}}
class="admin-search__full-page-link"
>
{{i18n "admin.search.full_page_link"}}
</LinkTo>
{{/if}}

{{#if this.showFilters}}
<AdminSearchFilters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export default class AdminSearchModal extends Component {
@inline={{@inline}}
@hideHeader={{true}}
>
<AdminSearch />
<AdminSearch @fullPageLink={{true}} />
</DModal>
</template>
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Service, { service } from "@ember/service";
import KeyValueStore from "discourse/lib/key-value-store";
import { ADMIN_PANEL, MAIN_PANEL } from "discourse/lib/sidebar/panels";
import AdminSearchModal from "admin/components/modal/admin-search";

export default class AdminSidebarStateManager extends Service {
@service sidebarState;
Expand Down Expand Up @@ -57,6 +58,10 @@ export default class AdminSidebarStateManager extends Service {
this.sidebarState.isForcingSidebar = false;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need it because importing when I import admin/components/modal/admin-search in admin-sidebar.js it was failing for non admin users.

get modals() {
return { adminSearch: AdminSearchModal };
}

#forceAdminSidebar() {
this.sidebarState.setPanel(ADMIN_PANEL);
this.sidebarState.setSeparatedMode();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Component from "@glimmer/component";
import { service } from "@ember/service";
import BackToForum from "./back-to-forum";
import BackToForum from "discourse/components/sidebar/back-to-forum";
import Search from "discourse/components/sidebar/search";
import ToggleAllSections from "./toggle-all-sections";

export default class PanelHeader extends Component {
Expand All @@ -17,6 +18,9 @@ export default class PanelHeader extends Component {
<BackToForum />
<ToggleAllSections @sections={{@sections}} />
</div>
<div class="sidebar-panel-header__row">
<Search />
</div>
</div>
{{/if}}
</template>
Expand Down
50 changes: 50 additions & 0 deletions app/assets/javascripts/discourse/app/components/sidebar/search.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import Component from "@glimmer/component";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { service } from "@ember/service";
import DButton from "discourse/components/d-button";
import { translateModKey } from "discourse/lib/utilities";
import { i18n } from "discourse-i18n";

export default class Search extends Component {
@service sidebarState;

get shouldDisplay() {
return this.sidebarState.currentPanel.searchable;
}

get sidebarShortcutCombo() {
return `${translateModKey("Meta")}+/`;
}

@action
onClick(event) {
event?.preventDefault();
return this.sidebarState.currentPanel.onSearchClick;
}

<template>
{{#if this.shouldDisplay}}
<div class="sidebar-search">
<div class="sidebar-search__input-container">
<DButton
@action={{this.onClick}}
@icon="magnifying-glass"
class="btn-transparent sidebar-search__icon"
/>
{{! template-lint-disable no-pointer-down-event-binding }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need mousedown because mouseup is too late. I want to prevent input to get focus, so when modal is closed, the user cannot type anything into this fake input.

<input
{{on "mousedown" this.onClick}}
placeholder={{i18n "sidebar.search"}}
type="text"
enterkeyhint="done"
class="sidebar-search__input"
/>
<span
class="sidebar-search__shortcut-hint"
>{{this.sidebarShortcutCombo}}</span>
</div>
</div>
{{/if}}
</template>
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,6 @@ export const ADMIN_NAV_MAP = [
icon: "house",
moderator: true,
},
{
name: "admin_search",
route: "adminSearch",
label: "admin.config.search_everything.title",
description: "admin.config.search_everything.header_description",
icon: "magnifying-glass",
moderator: true,
},
{
name: "admin_users",
route: "adminUsers",
Expand Down
10 changes: 10 additions & 0 deletions app/assets/javascripts/discourse/app/lib/sidebar/admin-sidebar.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,4 +407,14 @@ export default class AdminSidebarPanel extends BaseCustomSidebarPanel {
);
});
}

get searchable() {
return true;
}

get onSearchClick() {
getOwnerWithFallback(this)
.lookup("service:modal")
.show(this.adminSidebarStateManager.modals.adminSearch);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,20 @@ export default class BaseCustomSidebarPanel {
return false;
}

/**
* @returns {boolean} Controls whether the search is shown
*/
get searchable() {
return false;
}

/**
* @returns {Function} Action when search input is clicked.
*/
onSearchClick() {
return null;
}

get scrollActiveLinkIntoView() {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ acceptance("Admin - Site Settings", function (needs) {

// navigate back to the "Settings" page, the title filter
// has been removed from navigation
await click(".sidebar-section-link-wrapper:nth-child(5) a");
await click(".sidebar-section-link-wrapper:nth-child(4) a");
assert.dom(".row.setting").exists({ count: 4 });
});

Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/admin/search.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
background: none !important;
width: 100% !important;
}

&__full-page-link {
align-self: self-end;
padding-right: 2.3em;
}
}

// Fitler
Expand Down Expand Up @@ -150,4 +155,5 @@

.admin-search-modal {
--modal-max-width: 700px;
--modal-min-height: 200px;
}
4 changes: 4 additions & 0 deletions app/assets/stylesheets/common/base/menu-panel.scss
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@
.badge-notification {
vertical-align: text-bottom;
}

.sidebar-search {
width: 100%;
}
}

.search-menu .menu-panel {
Expand Down
50 changes: 50 additions & 0 deletions app/assets/stylesheets/common/base/sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,56 @@
}
}

.sidebar-search {
width: 100%;

&__input-container {
display: flex;
align-items: center;
border: 1px solid var(--primary-400);
background: var(--d-input-bg-color);
box-sizing: border-box;
margin-top: 0.5em;
margin-bottom: 0.5em;
}

&__icon.btn.btn-transparent {
border: 0;
background: var(--d-input-bg-color);
padding-left: var(--d-sidebar-row-horizontal-padding);
padding-right: var(--d-sidebar-row-horizontal-padding);

&:hover {
background: var(--d-input-bg-color) !important;
}

.d-icon:hover {
color: var(--primary-high);
}
}

&__input[type="text"] {
margin-bottom: 0;
border: 0;
padding: 0;
width: 100%;
height: var(--d-sidebar-row-height);
cursor: pointer;

&:focus {
outline: none;
}
}

&__shortcut-hint {
background-color: rgba(var(--tertiary-rgb), 0.1);
padding: 0.25em 0.5em;
margin-right: 0.5em;
font-size: var(--font-down-3);
color: var(--primary-medium);
}
}

.sidebar-panel-header__row {
display: flex;
justify-content: space-between;
Expand Down
2 changes: 2 additions & 0 deletions config/locales/client.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5081,6 +5081,7 @@ en:
back_to_forum: "Back to Forum"
collapse_all_sections: "Collapse all sections"
expand_all_sections: "Expand all sections"
search: "Search everything"
footer:
interface_color_selector:
light: "Light"
Expand Down Expand Up @@ -5599,6 +5600,7 @@ en:
modal_title: "Search anything in admin"
title: "Search"
instructions: "Type to search for pages, settings, reports, themes, components, and more..."
full_page_link: "Switch to full page search"
no_results: "We couldn’t find anything matching ‘%{filter}’."
result_types:
page:
Expand Down
32 changes: 24 additions & 8 deletions spec/system/admin_search_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,10 @@
describe "Admin Search", type: :system do
fab!(:current_user) { Fabricate(:admin) }
let(:search_modal) { PageObjects::Modals::AdminSearch.new }
let(:sidebar) { PageObjects::Components::NavigationMenu::Sidebar.new }

before { sign_in(current_user) }

def open_search_modal
send_keys([SystemHelpers::PLATFORM_KEY_MODIFIER, "/"])
expect(search_modal).to be_open
end

it "can search for settings, pages, themes, components, and reports" do
theme = Fabricate(:theme, name: "Discourse Invincible Theme")
component = Fabricate(:theme, name: "Discourse Redacted", component: true)
Expand All @@ -20,7 +16,7 @@ def open_search_modal
.returns([stub(key: "theme_metadata.description", value: "Some description")])

visit "/admin"
open_search_modal
sidebar.click_search_input

search_modal.search("min_topic_title")
expect(search_modal.find_result("setting", 0)).to have_content("Min topic title length")
Expand Down Expand Up @@ -55,7 +51,7 @@ def open_search_modal

it "can search full page" do
visit "/admin"
open_search_modal
sidebar.click_search_input
search_modal.search("min_topic_title")
search_modal.input_enter
expect(page).to have_current_path("/admin/search?filter=min_topic_title")
Expand All @@ -65,14 +61,34 @@ def open_search_modal
)
end

it "can go to full page search with link" do
visit "/admin"
sidebar.click_search_input
search_modal.search("min_topic_title")
search_modal.click_switch_to_full_page

expect(page).to have_current_path("/admin/search?filter=min_topic_title")
expect(search_modal.find_result("setting", 0)).to have_content("Min topic title length")
expect(search_modal.find_result("setting", 0)).to have_content(
I18n.t("site_settings.min_topic_title_length"),
)
end

it "informs user about no results" do
visit "/admin"
open_search_modal
sidebar.click_search_input

search_modal.search("very long search phrase")

expect(search_modal).to have_content(
"We couldn’t find anything matching ‘very long search phrase’.",
)
end

it "opens search modal with keyboard shortcut" do
visit "/admin"

send_keys([SystemHelpers::PLATFORM_KEY_MODIFIER, "/"])
expect(search_modal).to be_open
end
end
5 changes: 1 addition & 4 deletions spec/system/admin_sidebar_navigation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
expect(links.map(&:text)).to eq(
[
I18n.t("admin_js.admin.dashboard.title"),
I18n.t("admin_js.admin.config.search_everything.title"),
I18n.t("admin_js.admin.config.users.title"),
I18n.t("admin_js.admin.config.groups.title"),
I18n.t("admin_js.admin.config.site_settings.title"),
Expand Down Expand Up @@ -98,11 +97,10 @@
)

sidebar.toggle_all_sections
expect(page).to have_selector(".sidebar-section-link-content-text", count: 6)
expect(page).to have_selector(".sidebar-section-link-content-text", count: 5)
expect(all(".sidebar-section-link-content-text").map(&:text)).to eq(
[
I18n.t("admin_js.admin.dashboard.title"),
I18n.t("admin_js.admin.config.search_everything.title"),
I18n.t("admin_js.admin.config.users.title"),
I18n.t("admin_js.admin.config.groups.title"),
I18n.t("admin_js.admin.config.site_settings.title"),
Expand Down Expand Up @@ -152,7 +150,6 @@
expect(links.map(&:text)).to eq(
[
I18n.t("admin_js.admin.dashboard.title"),
I18n.t("admin_js.admin.config.search_everything.title"),
I18n.t("admin_js.admin.config.users.title"),
I18n.t("admin_js.admin.config.groups.title"),
I18n.t("admin_js.admin.config.whats_new.title"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ def click_back_to_forum
page.find(".sidebar-sections__back-to-forum").click
self
end

def click_search_input
page.find(".sidebar-search__input").click
end
end
end
end
Expand Down
Loading
Loading