테마에 맞는 검색 아이콘 만들기

안녕하세요!

처음으로 디스코스에 항목을 삽입하는 방법을 배우고자 검색 헤더 옆에 아이콘을 삽입해 보려고 했습니다.

하지만 작동하지 않았습니다.

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

아마도 멍청한 실수일 수 있습니다(여러분 중 일부가 아시다시피 저는 밤이 되면 더 멍청해집니다) 하지만 도움이 필요합니다.
감사합니다!

안녕하세요,

제 이해가 맞다면 검색 페이지에 검색 아이콘을 추가하고 싶으신 것이죠 :arrow_down_small:

이 작업을 위해 Discourse 템플릿을 오버라이드해야 할 것 같습니다.
방법은 다음과 같습니다: Discourse 템플릿 오버라이드 하지만 전체 문서를 읽어보시는 것을 권장합니다.


이 경우 다음과 같이 보입니다. 먼저 검색 페이지 템플릿을 찾아야 합니다. 템플릿 목록은 여기 있습니다: https://github.com/discourse/discourse/tree/main/app/assets/javascripts/discourse/app/templates

우리가 찾는 템플릿은 full-page-search.hbs이며, 이 변경 사항을 위해 어떤 부분을 편집해야 하는지 명확히 볼 수 있습니다.

편집할 템플릿의 헤더 부분은 다음과 같습니다… 하지만 아직 조금 더 기다려야 합니다…

    <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>

이제 위에서 언급한 문서에 따르면, 다음과 같이 시작해야 합니다:

템플릿은 header 섹션에 위치합니다.

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

</script>

그 다음 내부에 전체 템플릿을 복사해야 합니다:

다음과 같은 모습입니다
<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>

이제 이전에 언급했던 헤더 부분을 편집할 수 있습니다. 이 경우 변경 사항은 정말로 간단하지만 더 복잡한 변경 사항도 가능합니다. 커스텀 템플릿이 항상 최신 상태인지 확인하십시오. 코어 템플릿에 변경 사항이 있으면 모든 것이 정상적으로 작동하도록 커스텀 템플릿도 업데이트해야 합니다. :slightly_smiling_face:

이 경우 우리는 전체 페이지 제목과 결과 수 앞에 아이콘 {{d-icon "search"}}만 추가하면 됩니다.

전체 템플릿은 다음과 같습니다 :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>

도움이 되길 바랍니다 :slightly_smiling_face:

좋아요, 거의 성공했네요!

검색 배너를 수정했는데 이렇게 동작합니다.


이렇게 복잡할 줄은 몰랐지만, 감사합니다! 단순한 3줄짜리 JS 스크립트로 끝날 줄 알았거든요.

네, 아마도 사용자 정의 CSS 때문인 것 같아요. 이 영역을 직접 수정해야 할 가능성이 높습니다. :slightly_smiling_face:

늦게 답변드려 죄송합니다. 해당 CSS입니다.

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

이 안에 잘못된 부분이 있을까요?

안녕하세요,

제목 앞에 표시되도록 하려면 SVG에 사용자 지정 CSS를 추가할 필요가 없습니다. 이미 h2 태그 안에 넣어두었기 때문에 h2 스타일이 적용됩니다. 다만 검색 제목 섹션을 수정해야 합니다. 제가 맞다면, 위에서 공유하신 스크린샷은 테마 DarkPixlz’s Modern Theme의 것인가요?

해당 테마를 확인해 본 결과, 제목을 중앙 정렬하기 위해 패딩과 폰트 크기를 크게 설정하고 있어 검색 아이콘에 충분한 공간이 확보되지 않는 것으로 보입니다.

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

제안 사항:

패딩 대신 마진을 사용하되, 양쪽에는 적용할 필요가 없습니다. .search-header에 이미 양쪽 10%의 패딩이 있기 때문입니다. 아이콘에 충분한 공간을 확보하기 위해, 특히 모바일에서는 더 작은 폰트 크기를 사용하세요. 세로 정렬을 수정하려면, .main-outlet에 상단 3em의 패딩이 있으므로 상단에 1em의 마진을 추가할 수 있습니다.

배경을 변경하면 더 나아 보일 것입니다.

.search-container .search-page-heading {
  margin: 1em 0 2em 0;
  font-size: 5em; // 작은 화면에서는 더 작은 폰트 크기를 사용하세요
  text-align: center;
}

감사합니다, 잘 작동했어요 :slight_smile: