Criando um ícone de pesquisa com um tema

Olá!

Eu estava tentando inserir um ícone ao lado do cabeçalho de pesquisa para tentar aprender como inserir itens no Discourse, para começar.

No entanto, isso não funcionou.

<script>
node = document.getElementsByClassName('search-page-heading');
node.insertAdjacentElements('beforebegin', '<svg class="PixlzThemeSearchIcon" aria-hidden="true"><use xlink:href="#search"></use></svg>');
</script>

Pode ser um erro bobo (como alguns de vocês sabem, eu fico mais estúpido à noite), mas a ajuda é apreciada.
Obrigado!

Olá,

Se entendi corretamente, você gostaria de adicionar o ícone de busca aqui na página de busca :arrow_down_small:

Acho que, para isso, você precisará sobrescrever o template do Discourse.
Veja como fazer: Sobrescrevendo templates do Discourse, mas sugiro ler toda a documentação.


Neste caso, ficaria mais ou menos assim. Primeiro, você precisa encontrar o template da página de busca. Aqui estão os templates: https://github.com/discourse/discourse/tree/main/app/assets/javascripts/discourse/app/templates

O template que estamos procurando é o full-page-search.hbs, e podemos ver claramente qual parte devemos editar para fazer essa alteração.

Esta é a parte do cabeçalho do template que vamos editar… mas isso vem um pouco mais tarde…

    <h1 class="search-page-heading">
      {{#if this.hasResults}}
        <div class="result-count" id="search-result-count" aria-live="polite">
          {{html-safe this.resultCountLabel}}
        </div>
      {{else}}
        {{i18n "search.full_page_title"}}
      {{/if}}
    </h1>

Agora que sabemos, pela documentação acima, devemos começar assim:

O template vai para a seção header.

<script type="text/x-handlebars" data-template-name="full-page-search">

</script>

Depois, temos que copiar todo o template para dentro:

Fica assim
<script type="text/x-handlebars" data-template-name="full-page-search">
  <DSection @pageClass="search" @class="search-container">
    <ScrollTracker @name="full-page-search" @tag={{this.searchTerm}} @class="hidden" />
    <div class="search-header" role="search">
      <h1 class="search-page-heading">
        {{#if this.hasResults}}
          <div class="result-count" id="search-result-count" aria-live="polite">
            {{html-safe this.resultCountLabel}}
          </div>
        {{else}}
          {{i18n "search.full_page_title"}}
        {{/if}}
      </h1>
      <div class="search-bar">
        <SearchTextField @value={{this.searchTerm}} @class="full-page-search search no-blur search-query" @aria-label={{i18n "search.search_term_label"}} @enter={{action "search" (hash collapseFilters=true)}} @hasAutofocus={{this.hasAutofocus}} @aria-controls="search-result-count" />
        <ComboBox @id="search-type" @value={{this.search_type}} @content={{this.searchTypes}} @onChange={{action (mut this.search_type)}} @options={{hash
            castInteger=true
          }} />
        <DButton @action={{action "search" (hash collapseFilters=true)}} @icon="search" @label="search.search_button" @class="btn-primary search-cta" @ariaLabel="search.search_button" @disabled={{this.searchButtonDisabled}} />
      </div>
      {{#if this.usingDefaultSearchType}}
        {{!-- context is only provided when searching from mobile view --}}
        {{#if this.context}}
          <div class="search-context">
            <label>
              <Input @type="checkbox" name="searchContext" @checked={{this.searchContextEnabled}} /> {{this.searchContextDescription}}
            </label>
          </div>
        {{/if}}

        <div class="search-filters">
          <SearchAdvancedOptions @searchTerm={{readonly this.searchTerm}} @onChangeSearchTerm={{action (mut this.searchTerm)}} @search={{action "search" (hash collapseFilters=true)}} @searchButtonDisabled={{this.searchButtonDisabled}} @expandFilters={{this.expandFilters}} />
        </div>
      {{/if}}

      <div class="search-notice">
        {{#if this.invalidSearch}}
          <div class="fps-invalid">
            {{i18n "search.too_short"}}
          </div>
        {{/if}}
      </div>

    </div>

    <div class="search-advanced">
      {{#if this.hasResults}}
        {{#if this.usingDefaultSearchType}}
          <div class={{this.searchInfoClassNames}} role="region" ariaLabel={{i18n "search.sort_or_bulk_actions"}}>
            {{#if this.canBulkSelect}}
              <DButton @icon="list" @class="btn-default bulk-select" @title="topics.bulk.toggle" @action={{action "toggleBulkSelect"}} />
              {{#if this.selected}}
                <DButton @class="btn-default bulk-select-btn" @selected={{this.selected}} @action={{action "showBulkActions"}} @icon="wrench" />
              {{/if}}
            {{/if}}

            {{#if this.bulkSelectEnabled}}
              {{#if this.hasUnselectedResults}}
                <DButton @icon="check-square" @class="btn-default" @action={{action "selectAll"}} @label="search.select_all" />
              {{/if}}

              {{#if this.hasSelection}}
                <DButton @icon="far-square" @class="btn-default" @action={{action "clearAll"}} @label="search.clear_all" />
              {{/if}}
            {{/if}}

            <div class="sort-by inline-form">
              <label>
                {{i18n "search.sort_by"}}
              </label>
              <ComboBox @value={{this.sortOrder}} @content={{this.sortOrders}} @onChange={{action (mut this.sortOrder)}} @id="search-sort-by" @options={{hash
                  castInteger=true
                }} />
            </div>
          </div>
        {{/if}}
      {{/if}}

      <PluginOutlet @name="full-page-search-below-search-info" @tagName="span" @connectorTagName="div" @args={{hash search=this.searchTerm}} />

      {{#if this.searching}}
        {{loading-spinner size="medium"}}
      {{else}}
        <div class="search-results" role="region">
          <LoadMore @selector=".fps-result" @action={{action "loadMore"}}>
            {{#if this.usingDefaultSearchType}}
              <SearchResultEntries @posts={{this.model.posts}} @bulkSelectEnabled={{this.bulkSelectEnabled}} @selected={{this.selected}} @highlightQuery={{this.highlightQuery}} @searchLogId={{this.model.grouped_search_result.search_log_id}} />

              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#unless this.hasResults}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>

                    {{#if this.model.grouped_search_result.error}}
                      <div class="warning">
                        {{this.model.grouped_search_result.error}}
                      </div>
                    {{/if}}

                    {{#if this.showSuggestion}}
                      <div class="no-results-suggestion">
                        {{i18n "search.cant_find"}}
                        {{#if this.canCreateTopic}}
                          <a href {{action "createTopic" this.searchTerm}}>{{i18n "search.start_new_topic"}}</a>
                          {{#unless this.siteSettings.login_required}}
                            {{i18n "search.or_search_google"}}
                          {{/unless}}
                        {{else}}
                          {{i18n "search.search_google"}}
                        {{/if}}
                      </div>

                      <GoogleSearch @searchTerm={{this.searchTerm}} />
                    {{/if}}
                  {{/if}}
                {{/unless}}

                {{#if this.hasResults}}
                  <h3 class="search-footer">
                    {{#if this.model.grouped_search_result.more_full_page_results}}
                      {{#if this.isLastPage}}
                        {{i18n "search.more_results"}}
                      {{/if}}
                    {{else}}
                      {{i18n "search.no_more_results"}}
                    {{/if}}
                  </h3>
                {{/if}}
              </ConditionalLoadingSpinner>
            {{else}}
              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#if this.hasResults}}
                  {{#if this.model.categories.length}}
                    <h4 class="category-heading">
                      {{i18n "search.categories"}}
                    </h4>
                    <div class="category-items">
                      {{#each this.model.categories as |category|}}
                        {{category-link category extraClasses="fps-category-item"}}
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.tags.length}}
                    <h4 class="tag-heading">
                      {{i18n "search.tags"}}
                    </h4>

                    <div class="tag-items">
                      {{#each this.model.tags as |tag|}}
                        <div class="fps-tag-item">
                          <a href={{tag.url}}>
                            {{tag.id}}
                          </a>
                        </div>
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.users}}
                    <div class="user-items">
                      {{#each this.model.users as |user|}}
                        <UserLink @user={{user}} @class="fps-user-item">
                          {{avatar user imageSize="large"}}

                          <div class="user-titles">
                            {{#if user.name}}
                              <span class="name">
                                {{user.name}}
                              </span>
                            {{/if}}

                            <span class="username">
                              {{user.username}}
                            </span>
                          </div>
                        </UserLink>
                      {{/each}}
                    </div>
                  {{/if}}
                {{else}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>
                  {{/if}}
                {{/if}}
              </ConditionalLoadingSpinner>
            {{/if}}
          </LoadMore>
        </div>
      {{/if}}
    </div>
  </DSection>
</script>

Agora podemos editar a parte do cabeçalho que mencionei antes. Neste caso, é uma alteração bem simples, mas você pode fazer alterações mais complexas. Certifique-se de que seu template personalizado esteja sempre atualizado. Se houver alguma alteração no template principal, você também deve atualizar seu template personalizado para que tudo funcione corretamente. :slightly_smiling_face:

Neste caso, basta adicionar um ícone {{d-icon "search"}} antes do título da página completa e antes da contagem de resultados.

O template completo fica assim :arrow_down_small:

<script type="text/x-handlebars" data-template-name="full-page-search">
  <DSection @pageClass="search" @class="search-container">
    <ScrollTracker @name="full-page-search" @tag={{this.searchTerm}} @class="hidden" />
    <div class="search-header" role="search">
      <h1 class="search-page-heading">
        {{#if this.hasResults}}
          <div class="result-count" id="search-result-count" aria-live="polite">
            {{d-icon "search"}}
            {{html-safe this.resultCountLabel}}
          </div>
        {{else}}
          {{d-icon "search"}}
          {{i18n "search.full_page_title"}}
        {{/if}}
      </h1>
      <div class="search-bar">
        <SearchTextField @value={{this.searchTerm}} @class="full-page-search search no-blur search-query" @aria-label={{i18n "search.search_term_label"}} @enter={{action "search" (hash collapseFilters=true)}} @hasAutofocus={{this.hasAutofocus}} @aria-controls="search-result-count" />
        <ComboBox @id="search-type" @value={{this.search_type}} @content={{this.searchTypes}} @onChange={{action (mut this.search_type)}} @options={{hash
            castInteger=true
          }} />
        <DButton @action={{action "search" (hash collapseFilters=true)}} @icon="search" @label="search.search_button" @class="btn-primary search-cta" @ariaLabel="search.search_button" @disabled={{this.searchButtonDisabled}} />
      </div>
      {{#if this.usingDefaultSearchType}}
        {{!-- context is only provided when searching from mobile view --}}
        {{#if this.context}}
          <div class="search-context">
            <label>
              <Input @type="checkbox" name="searchContext" @checked={{this.searchContextEnabled}} /> {{this.searchContextDescription}}
            </label>
          </div>
        {{/if}}

        <div class="search-filters">
          <SearchAdvancedOptions @searchTerm={{readonly this.searchTerm}} @onChangeSearchTerm={{action (mut this.searchTerm)}} @search={{action "search" (hash collapseFilters=true)}} @searchButtonDisabled={{this.searchButtonDisabled}} @expandFilters={{this.expandFilters}} />
        </div>
      {{/if}}

      <div class="search-notice">
        {{#if this.invalidSearch}}
          <div class="fps-invalid">
            {{i18n "search.too_short"}}
          </div>
        {{/if}}
      </div>

    </div>

    <div class="search-advanced">
      {{#if this.hasResults}}
        {{#if this.usingDefaultSearchType}}
          <div class={{this.searchInfoClassNames}} role="region" ariaLabel={{i18n "search.sort_or_bulk_actions"}}>
            {{#if this.canBulkSelect}}
              <DButton @icon="list" @class="btn-default bulk-select" @title="topics.bulk.toggle" @action={{action "toggleBulkSelect"}} />
              {{#if this.selected}}
                <DButton @class="btn-default bulk-select-btn" @selected={{this.selected}} @action={{action "showBulkActions"}} @icon="wrench" />
              {{/if}}
            {{/if}}

            {{#if this.bulkSelectEnabled}}
              {{#if this.hasUnselectedResults}}
                <DButton @icon="check-square" @class="btn-default" @action={{action "selectAll"}} @label="search.select_all" />
              {{/if}}

              {{#if this.hasSelection}}
                <DButton @icon="far-square" @class="btn-default" @action={{action "clearAll"}} @label="search.clear_all" />
              {{/if}}
            {{/if}}

            <div class="sort-by inline-form">
              <label>
                {{i18n "search.sort_by"}}
              </label>
              <ComboBox @value={{this.sortOrder}} @content={{this.sortOrders}} @onChange={{action (mut this.sortOrder)}} @id="search-sort-by" @options={{hash
                  castInteger=true
                }} />
            </div>
          </div>
        {{/if}}
      {{/if}}

      <PluginOutlet @name="full-page-search-below-search-info" @tagName="span" @connectorTagName="div" @args={{hash search=this.searchTerm}} />

      {{#if this.searching}}
        {{loading-spinner size="medium"}}
      {{else}}
        <div class="search-results" role="region">
          <LoadMore @selector=".fps-result" @action={{action "loadMore"}}>
            {{#if this.usingDefaultSearchType}}
              <SearchResultEntries @posts={{this.model.posts}} @bulkSelectEnabled={{this.bulkSelectEnabled}} @selected={{this.selected}} @highlightQuery={{this.highlightQuery}} @searchLogId={{this.model.grouped_search_result.search_log_id}} />

              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#unless this.hasResults}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>

                    {{#if this.model.grouped_search_result.error}}
                      <div class="warning">
                        {{this.model.grouped_search_result.error}}
                      </div>
                    {{/if}}

                    {{#if this.showSuggestion}}
                      <div class="no-results-suggestion">
                        {{i18n "search.cant_find"}}
                        {{#if this.canCreateTopic}}
                          <a href {{action "createTopic" this.searchTerm}}>{{i18n "search.start_new_topic"}}</a>
                          {{#unless this.siteSettings.login_required}}
                            {{i18n "search.or_search_google"}}
                          {{/unless}}
                        {{else}}
                          {{i18n "search.search_google"}}
                        {{/if}}
                      </div>

                      <GoogleSearch @searchTerm={{this.searchTerm}} />
                    {{/if}}
                  {{/if}}
                {{/unless}}

                {{#if this.hasResults}}
                  <h3 class="search-footer">
                    {{#if this.model.grouped_search_result.more_full_page_results}}
                      {{#if this.isLastPage}}
                        {{i18n "search.more_results"}}
                      {{/if}}
                    {{else}}
                      {{i18n "search.no_more_results"}}
                    {{/if}}
                  </h3>
                {{/if}}
              </ConditionalLoadingSpinner>
            {{else}}
              <ConditionalLoadingSpinner @condition={{this.loading}}>
                {{#if this.hasResults}}
                  {{#if this.model.categories.length}}
                    <h4 class="category-heading">
                      {{i18n "search.categories"}}
                    </h4>
                    <div class="category-items">
                      {{#each this.model.categories as |category|}}
                        {{category-link category extraClasses="fps-category-item"}}
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.tags.length}}
                    <h4 class="tag-heading">
                      {{i18n "search.tags"}}
                    </h4>

                    <div class="tag-items">
                      {{#each this.model.tags as |tag|}}
                        <div class="fps-tag-item">
                          <a href={{tag.url}}>
                            {{tag.id}}
                          </a>
                        </div>
                      {{/each}}
                    </div>
                  {{/if}}

                  {{#if this.model.users}}
                    <div class="user-items">
                      {{#each this.model.users as |user|}}
                        <UserLink @user={{user}} @class="fps-user-item">
                          {{avatar user imageSize="large"}}

                          <div class="user-titles">
                            {{#if user.name}}
                              <span class="name">
                                {{user.name}}
                              </span>
                            {{/if}}

                            <span class="username">
                              {{user.username}}
                            </span>
                          </div>
                        </UserLink>
                      {{/each}}
                    </div>
                  {{/if}}
                {{else}}
                  {{#if this.searchActive}}
                    <h3>{{i18n "search.no_results"}}</h3>
                  {{/if}}
                {{/if}}
              </ConditionalLoadingSpinner>
            {{/if}}
          </LoadMore>
        </div>
      {{/if}}
    </div>
  </DSection>
</script>

Espero que isso ajude :slightly_smiling_face:

Tudo bem, isso quase funcionou!

Modifiquei o banner de pesquisa e ele faz isso


Nunca soube que seria tão complexo, mas obrigado! Pensei que seria um script JS simples de 3 linhas

Sim, acho que é por causa do seu CSS personalizado. Provavelmente você terá que personalizar esta área. :slightly_smiling_face:

Desculpe pela demora na resposta, mas este é o CSS para isso.

svg.PixlzThemeSearchIcon {
      position: relative;
      display: table-row;
      height: 50px !important;
      width: 50px;
      top: 227px;
      left: 220px;
      fill: #e0e0e0;
}

Há algo de errado com ele?

Olá,

Você não precisa adicionar CSS personalizado ao SVG se quiser que ele apareça antes do título, pois o colocamos nas tags <h2>, então ele usará os estilos <h2>. Mas você tem que modificar a seção do título de pesquisa. Se eu estiver correto, esta captura de tela que você compartilhou acima é do seu tema DarkPixlz’s Modern Theme?

Verifiquei esse tema e acho que o problema é que você usa preenchimentos (paddings) e tamanho de fonte enormes para alinhar o título ao centro e não há espaço suficiente para o ícone de pesquisa.

.search-container .search-page-heading {
  padding: 2em 3.8em;
  font-size: 5em;
}

Minha sugestão:

Eu uso margens em vez de preenchimentos, mas não são necessárias nas laterais - porque .search-header já tem 10% de preenchimento nas laterais - para ter espaço suficiente para o ícone e usar um tamanho de fonte menor, especialmente no celular. Para corrigir o alinhamento vertical, você pode adicionar 1em de margem superior, pois seu .main-outlet tem um preenchimento de 3em na parte superior.

Provavelmente é melhor ver se eu mudo o fundo.

.search-container .search-page-heading {
  margin: 1em 0 2em 0;
  font-size: 5em; // use um tamanho de fonte menor em telas menores
  text-align: center;
}

Obrigado, funcionou :slight_smile: