🎃

Salesforceのセクション的なものを作ってみた div if:true編

2023/09/30に公開

はじめに

LWCでsalesforceのセクションの様なものを作る必要があったので、
キャッチアップとして作ってみたいと思います。
ちなみにセクションの様なものというのは、
こんなものです。
1.ヘッダーにボタンがついている。

2.折りたたみ機能がついている。

ベースは
SLDSのExpandable SectionButtonsを使用しています。

この記事でわかること

  1. LWCのHTML側でif:tureを使って、salseforceのセクションのレイアウトで折りたたみ機能を作成する。

完成イメージ

左端に折りたたみ機能のついたボタンを配置。
右端に別機能のボタンを配置。
今回の挙動確認は折りたたみ機能のみ。

手順

セクションのレイアウトをSLDSから拝借

SLDSのExpandable Sectionから
セクションのBaseを拝借。

<div class="slds-section slds-is-open">
  <h3 class="slds-section__title">
    <button aria-controls="expando-unique-id" aria-expanded="true" class="slds-button slds-section__title-action">
      <svg class="slds-section__title-action-icon slds-button__icon slds-button__icon_left" aria-hidden="true">
        <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#switch"></use>
      </svg>
      <span class="slds-truncate" title="Section Title">Section Title</span>
    </button>
  </h3>
  <div class="slds-section__content" id="expando-unique-id">
    <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      Nullam quis risus eget urna mollis ornare vel eu leo. Nulla vitae elit libero, a pharetra augue.</p>
  </div>
</div>

これを元に編集していく。

ヘッダーの部分は、こんな感じ。

  <h3 class="slds-section__title">
    <button aria-controls="expando-unique-id" aria-expanded="true" class="slds-button slds-section__title-action">
      <svg class="slds-section__title-action-icon slds-button__icon slds-button__icon_left" aria-hidden="true">
        <use xlink:href="/assets/icons/utility-sprite/svg/symbols.svg#switch"></use>
      </svg>
      <span class="slds-truncate" title="Section Title">Section Title</span>
    </button>
  </h3>

このままだとヘッダー全体にボタン機能がつき
右端にボタンが配置できなくなってるので、修正。

      <div class="slds-section__title slds-theme_shade">
        <div>
          <button
            class= "toggle-button"
            onclick={toggleSection}
          >
            ポケモン図鑑
          </button>
        </div>
        <div>
          <button
            class="slds-button slds-button_neutral header-search-button"
            onclick={toggleSearch}
          >
            検索
          </button>
        </div>
      </div>

CSSは以下の通り
ボタンの位置を修正しちゃうと色々不都合がでてきたので、ちょっと修正。

/* セクション全体の配置位置 */

.slds-section {
    /* マージンをリセット */
    margin-top: 0;
    margin-bottom: 0;
    /* パディングをリセット */
    padding: 0;
}

.toggle-button {
    border: none;
}


/* セクションのヘッダーの位置と背景色 */

.slds-section__title.slds-theme_shade {
    padding: 0px 8px;
    display: flex;
    justify-content: space-between;
}

/* ヘッダーのボタンサイズ */

.slds-button.slds-button_neutral.header-search-button {
    font-size: 13px;
    height: 26px;
}

今度はボディ部分だが、ここは

<div class="slds-section__content" id="expando-unique-id">
    <p>Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
      Nullam quis risus eget urna mollis ornare vel eu leo. Nulla vitae elit libero, a pharetra augue.</p>
  </div>

しか書かれていないので
ざっくり修正。

<div class="slds-section__content" id="expando-unique-id" if:true={isExpanded}>
        <div class="form-row">
          <label class="pokemon-key">図鑑No.</label>
          <input class="pokemon-value" type="number"></input>
        </div>
        <div class="form-row">
          <label class="pokemon-key">名前</label>
          <label class="pokemon-value">ピカチュウ</label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">タイプ1</label>
          <label class="pokemon-value">でんき</label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">タイプ1</label>
          <label class="pokemon-value"></label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">詳細</label>
          <label class="pokemon-value">これはこう。あれもこう。</label>
        </div>
      </div>

JavaScriptでisExpandedがtrueとなれば表示。falseなら非表示とした。
CSSとJavaScriptは以下の通り。

/* セクションのボディの各出力項目のkey-valueの親 */

.form-row {
    display: flex;
    align-items: center;
}

/* labelのkey */

.pokemon-key {
    width: 130px;
    margin: 5px;
}

/* labelのvalue */

.header-search-button {
    position: relative;
    right: 8px;
}

import { LightningElement, track } from "lwc";

export default class MyComponent extends LightningElement {
  @track isExpanded = false;

  toggleSection() {
    this.isExpanded = !this.isExpanded;
  }
}

全体のコード

pokemonData.html

<template>
  <!-- 大枠 -->
  <div class="slds-box">
    <!-- セクション -->
    <div class="slds-section slds-is-open">
      <div class="slds-section__title slds-theme_shade">
        <div>
          <button
            class= "toggle-button"
            onclick={toggleSection}
          >
            ポケモン図鑑
          </button>
        </div>
        <div>
          <button
            class="slds-button slds-button_neutral header-search-button"
            onclick={toggleSearch}
          >
            検索
          </button>
        </div>
      </div>
      <!-- 表示/非表示させるもの -->
      <div class="slds-section__content" id="expando-unique-id" if:true={isExpanded}>
        <div class="form-row">
          <label class="pokemon-key">図鑑No.</label>
          <input class="pokemon-value" type="number"></input>
        </div>
        <div class="form-row">
          <label class="pokemon-key">名前</label>
          <label class="pokemon-value">ピカチュウ</label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">タイプ1</label>
          <label class="pokemon-value">でんき</label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">タイプ1</label>
          <label class="pokemon-value"></label>
        </div>
        <div class="form-row">
          <label class="pokemon-key">詳細</label>
          <label class="pokemon-value">これはこう。あれもこう。</label>
        </div>
      </div>
    </div>
  </div>
</template>

pokemonData.css

/* 大枠 */

.slds-box {
    background-color: #ffff;
    padding: 0;
    overflow: hidden;
    border: solid 1px rgb(113, 113, 113);
}

/* セクション全体の配置位置 */

.slds-section {
    /* マージンをリセット */
    margin-top: 0;
    margin-bottom: 0;
    /* パディングをリセット */
    padding: 0;
}

.toggle-button {
    border: none;
}

/* セクションのヘッダーの位置と背景色 */

.slds-section__title.slds-theme_shade {
    padding: 0px 8px;
    display: flex;
    justify-content: space-between;
}

/* セクションのボディの各出力項目のkey-valueの親 */

.form-row {
    display: flex;
    align-items: center;
}

/* labelのkey */

.pokemon-key {
    width: 130px;
    margin: 5px;
}

/* labelのvalue */

.header-search-button {
    position: relative;
    right: 8px;
}

/* ヘッダーのボタンサイズ */

.slds-button.slds-button_neutral.header-search-button {
    font-size: 13px;
    height: 26px;
}

pokemonData.js

import { LightningElement, track } from "lwc";

export default class MyComponent extends LightningElement {
  @track isExpanded = false;

  toggleSection() {
    this.isExpanded = !this.isExpanded;
  }
}

挙動確認


動きました。

終わりに

今回はHTML側のif:trueで表示非表示を切り替えましたが、
aria-expanded="true"aria-expanded="false"でも切り替えられるそうです。
SLDSではむしろそちらを想定していた作りだった様なので、そちらも触れていけたらなと思います。

あ、折りたたみボタン入れ忘れた。。。

Discussion