⭐️

【Polaris和訳】Components/Lists and tables⑪

2021/11/06に公開約41,900字

この記事について

この記事は、Polaris/Components/Lists and tablesの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Resource list with all of its elements

リソースリストで利用可能なほとんどの小道具を含む幅広い例として使用します。

Image from Gyazo

React
function ResourceListExample() {
  const [selectedItems, setSelectedItems] = useState([])
  const [sortValue, setSortValue] = useState("DATE_MODIFIED_DESC")
  const [taggedWith, setTaggedWith] = useState("VIP")
  const [queryValue, setQueryValue] = useState(null)

  const handleTaggedWithChange = useCallback((value) => setTaggedWith(value), [])
  const handleQueryValueChange = useCallback((value) => setQueryValue(value), [])
  const handleTaggedWithRemove = useCallback(() => setTaggedWith(null), [])
  const handleQueryValueRemove = useCallback(() => setQueryValue(null), [])
  const handleClearAll = useCallback(() => {
    handleTaggedWithRemove()
    handleQueryValueRemove()
  }, [handleQueryValueRemove, handleTaggedWithRemove])

  const resourceName = {
    singular: "customer",
    plural: "customers",
  }

  const items = [
    {
      id: 112,
      url: "customers/341",
      name: "Mae Jemison",
      location: "Decatur, USA",
      latestOrderUrl: "orders/1456",
    },
    {
      id: 212,
      url: "customers/256",
      name: "Ellen Ochoa",
      location: "Los Angeles, USA",
      latestOrderUrl: "orders/1457",
    },
  ]

  const promotedBulkActions = [
    {
      content: "Edit customers",
      onAction: () => console.log("Todo: implement bulk edit"),
    },
  ]

  const bulkActions = [
    {
      content: "Add tags",
      onAction: () => console.log("Todo: implement bulk add tags"),
    },
    {
      content: "Remove tags",
      onAction: () => console.log("Todo: implement bulk remove tags"),
    },
    {
      content: "Delete customers",
      onAction: () => console.log("Todo: implement bulk delete"),
    },
  ]

  const filters = [
    {
      key: "taggedWith3",
      label: "Tagged with",
      filter: (
        <TextField
          label="Tagged with"
          value={taggedWith}
          onChange={handleTaggedWithChange}
          autoComplete="off"
          labelHidden
        />
      ),
      shortcut: true,
    },
  ]

  const appliedFilters = !isEmpty(taggedWith)
    ? [
        {
          key: "taggedWith3",
          label: disambiguateLabel("taggedWith3", taggedWith),
          onRemove: handleTaggedWithRemove,
        },
      ]
    : []

  const filterControl = (
    <Filters
      queryValue={queryValue}
      filters={filters}
      appliedFilters={appliedFilters}
      onQueryChange={handleQueryValueChange}
      onQueryClear={handleQueryValueRemove}
      onClearAll={handleClearAll}
    >
      <div style={{ paddingLeft: "8px" }}>
        <Button onClick={() => console.log("New filter saved")}>Save</Button>
      </div>
    </Filters>
  )

  return (
    <Card>
      <ResourceList
        resourceName={resourceName}
        items={items}
        renderItem={renderItem}
        selectedItems={selectedItems}
        onSelectionChange={setSelectedItems}
        promotedBulkActions={promotedBulkActions}
        bulkActions={bulkActions}
        sortValue={sortValue}
        sortOptions={[
          { label: "Newest update", value: "DATE_MODIFIED_DESC" },
          { label: "Oldest update", value: "DATE_MODIFIED_ASC" },
        ]}
        onSortChange={(selected) => {
          setSortValue(selected)
          console.log(`Sort option changed to ${selected}.`)
        }}
        filterControl={filterControl}
      />
    </Card>
  )

  function renderItem(item) {
    const { id, url, name, location, latestOrderUrl } = item
    const media = <Avatar customer size="medium" name={name} />
    const shortcutActions = latestOrderUrl
      ? [{ content: "View latest order", url: latestOrderUrl }]
      : null
    return (
      <ResourceItem
        id={id}
        url={url}
        media={media}
        accessibilityLabel={`View details for ${name}`}
        shortcutActions={shortcutActions}
        persistActions
      >
        <h3>
          <TextStyle variation="strong">{name}</TextStyle>
        </h3>
        <div>{location}</div>
      </ResourceItem>
    )
  }

  function disambiguateLabel(key, value) {
    switch (key) {
      case "taggedWith3":
        return `Tagged with ${value}`
      default:
        return value
    }
  }

  function isEmpty(value) {
    if (Array.isArray(value)) {
      return value.length === 0
    } else {
      return value === "" || value == null
    }
  }
}
HTML
<div>
  <div class="Polaris-Card">
    <div class="Polaris-ResourceList__ResourceListWrapper">
      <div class="Polaris-ResourceList__FiltersWrapper">
        <div class="Polaris-Filters">
          <div
            class="Polaris-Filters-ConnectedFilterControl__ProxyButtonContainer"
            aria-hidden="true"
          >
            <div data-key="taggedWith3">
              <button class="Polaris-Button" type="button">
                <span class="Polaris-Button__Content"
                  ><span class="Polaris-Button__Text">Tagged with</span
                  ><span class="Polaris-Button__Icon">
                    <div class="">
                      <span class="Polaris-Icon"
                        ><span class="Polaris-VisuallyHidden"></span
                        ><svg
                          viewBox="0 0 20 20"
                          class="Polaris-Icon__Svg"
                          focusable="false"
                          aria-hidden="true"
                        >
                          <path d="m5 8 5 5 5-5H5z"></path></svg
                      ></span>
                    </div> </span
                ></span>
              </button>
            </div>
          </div>
          <div class="Polaris-Filters-ConnectedFilterControl__Wrapper">
            <div
              class="Polaris-Filters-ConnectedFilterControl Polaris-Filters-ConnectedFilterControl--right"
            >
              <div class="Polaris-Filters-ConnectedFilterControl__CenterContainer">
                <div class="Polaris-Filters-ConnectedFilterControl__Item">
                  <div class="Polaris-Labelled--hidden">
                    <div class="Polaris-Labelled__LabelWrapper">
                      <div class="Polaris-Label">
                        <label
                          id="PolarisTextField8Label"
                          for="PolarisTextField8"
                          class="Polaris-Label__Text"
                          >Filter customers</label
                        >
                      </div>
                    </div>
                    <div class="Polaris-Connected">
                      <div class="Polaris-Connected__Item Polaris-Connected__Item--primary">
                        <div class="Polaris-TextField">
                          <div class="Polaris-TextField__Prefix" id="PolarisTextField8Prefix">
                            <span class="Polaris-Filters__SearchIcon"
                              ><span class="Polaris-Icon"
                                ><span class="Polaris-VisuallyHidden"></span
                                ><svg
                                  viewBox="0 0 20 20"
                                  class="Polaris-Icon__Svg"
                                  focusable="false"
                                  aria-hidden="true"
                                >
                                  <path
                                    d="M8 12a4 4 0 1 1 0-8 4 4 0 0 1 0 8zm9.707 4.293-4.82-4.82A5.968 5.968 0 0 0 14 8 6 6 0 0 0 2 8a6 6 0 0 0 6 6 5.968 5.968 0 0 0 3.473-1.113l4.82 4.82a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414z"
                                  ></path></svg></span
                            ></span>
                          </div>
                          <input
                            id="PolarisTextField8"
                            placeholder="Filter customers"
                            autocomplete="off"
                            class="Polaris-TextField__Input Polaris-TextField__Input--hasClearButton"
                            aria-labelledby="PolarisTextField8Label PolarisTextField8Prefix"
                            aria-invalid="false"
                            value=""
                          />
                          <div class="Polaris-TextField__Backdrop"></div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
              <div
                class="Polaris-Filters-ConnectedFilterControl__MoreFiltersButtonContainer Polaris-Filters-ConnectedFilterControl--onlyButtonVisible"
              >
                <div class="Polaris-Filters-ConnectedFilterControl__Item">
                  <div>
                    <button class="Polaris-Button" type="button">
                      <span class="Polaris-Button__Content"
                        ><span class="Polaris-Button__Text">More filters</span></span
                      >
                    </button>
                  </div>
                </div>
              </div>
            </div>
            <div class="Polaris-Filters-ConnectedFilterControl__AuxiliaryContainer">
              <div style="padding-left: 8px;">
                <button class="Polaris-Button" type="button">
                  <span class="Polaris-Button__Content"
                    ><span class="Polaris-Button__Text">Save</span></span
                  >
                </button>
              </div>
            </div>
          </div>
          <div class="Polaris-Filters__TagsContainer" aria-live="polite">
            <span class="Polaris-Tag Polaris-Tag--removable"
              ><span title="Tagged with VIP" class="Polaris-Tag__TagText">Tagged with VIP</span
              ><button
                type="button"
                aria-label="Remove Tagged with VIP"
                class="Polaris-Tag__Button"
              >
                <span class="Polaris-Icon"
                  ><span class="Polaris-VisuallyHidden"></span
                  ><svg
                    viewBox="0 0 20 20"
                    class="Polaris-Icon__Svg"
                    focusable="false"
                    aria-hidden="true"
                  >
                    <path
                      d="m11.414 10 4.293-4.293a.999.999 0 1 0-1.414-1.414L10 8.586 5.707 4.293a.999.999 0 1 0-1.414 1.414L8.586 10l-4.293 4.293a.999.999 0 1 0 1.414 1.414L10 11.414l4.293 4.293a.997.997 0 0 0 1.414 0 .999.999 0 0 0 0-1.414L11.414 10z"
                    ></path></svg
                ></span></button
            ></span>
          </div>
        </div>
      </div>
      <div class="Polaris-ResourceList__HeaderOuterWrapper">
        <div>
          <div></div>
          <div>
            <div
              class="Polaris-ResourceList__HeaderWrapper Polaris-ResourceList__HeaderWrapper--hasSort Polaris-ResourceList__HeaderWrapper--hasSelect"
            >
              <div class="Polaris-ResourceList__HeaderContentWrapper">
                <div class="Polaris-ResourceList__HeaderTitleWrapper">Showing 2 customers</div>
                <div class="Polaris-ResourceList__CheckableButtonWrapper">
                  <div
                    class="Polaris-CheckableButton Polaris-CheckableButton__CheckableButton--plain"
                  >
                    <div class="Polaris-CheckableButton__Checkbox">
                      <label
                        class="Polaris-Choice Polaris-Choice--labelHidden"
                        for="PolarisCheckbox10"
                        ><span class="Polaris-Choice__Control"
                          ><span class="Polaris-Checkbox"
                            ><input
                              id="PolarisCheckbox10"
                              type="checkbox"
                              class="Polaris-Checkbox__Input"
                              aria-invalid="false"
                              role="checkbox"
                              aria-checked="false"
                              value="" /><span class="Polaris-Checkbox__Backdrop"></span
                            ><span class="Polaris-Checkbox__Icon"
                              ><span class="Polaris-Icon"
                                ><span class="Polaris-VisuallyHidden"></span
                                ><svg
                                  viewBox="0 0 20 20"
                                  class="Polaris-Icon__Svg"
                                  focusable="false"
                                  aria-hidden="true"
                                >
                                  <path
                                    d="m8.315 13.859-3.182-3.417a.506.506 0 0 1 0-.684l.643-.683a.437.437 0 0 1 .642 0l2.22 2.393 4.942-5.327a.436.436 0 0 1 .643 0l.643.684a.504.504 0 0 1 0 .683l-5.91 6.35a.437.437 0 0 1-.642 0"
                                  ></path></svg></span></span></span></span
                        ><span class="Polaris-Choice__Label">Select all 2 customers</span></label
                      >
                    </div>
                    <span class="Polaris-CheckableButton__Label">Showing 2 customers</span>
                  </div>
                </div>
                <div class="Polaris-ResourceList__SortWrapper">
                  <div class="Polaris-Labelled--hidden">
                    <div class="Polaris-Labelled__LabelWrapper">
                      <div class="Polaris-Label">
                        <label
                          id="PolarisSelect2Label"
                          for="PolarisSelect2"
                          class="Polaris-Label__Text"
                          >Sort by</label
                        >
                      </div>
                    </div>
                    <div class="Polaris-Select">
                      <select
                        id="PolarisSelect2"
                        class="Polaris-Select__Input"
                        aria-invalid="false"
                      >
                        <option value="DATE_MODIFIED_DESC">Newest update</option>
                        <option value="DATE_MODIFIED_ASC">Oldest update</option>
                      </select>
                      <div class="Polaris-Select__Content" aria-hidden="true" aria-disabled="false">
                        <span class="Polaris-Select__InlineLabel">Sort by</span
                        ><span class="Polaris-Select__SelectedOption">Newest update</span
                        ><span class="Polaris-Select__Icon"
                          ><span class="Polaris-Icon"
                            ><span class="Polaris-VisuallyHidden"></span
                            ><svg
                              viewBox="0 0 20 20"
                              class="Polaris-Icon__Svg"
                              focusable="false"
                              aria-hidden="true"
                            >
                              <path d="m10 16-4-4h8l-4 4zm0-12 4 4H6l4-4z"></path></svg></span
                        ></span>
                      </div>
                      <div class="Polaris-Select__Backdrop"></div>
                    </div>
                  </div>
                </div>
                <div class="Polaris-ResourceList__SelectButtonWrapper">
                  <button class="Polaris-Button" type="button">
                    <span class="Polaris-Button__Content"
                      ><span class="Polaris-Button__Icon"
                        ><span class="Polaris-Icon"
                          ><span class="Polaris-VisuallyHidden"></span
                          ><svg
                            viewBox="0 0 20 20"
                            class="Polaris-Icon__Svg"
                            focusable="false"
                            aria-hidden="true"
                          >
                            <path
                              fill-rule="evenodd"
                              d="M4.5 3A1.5 1.5 0 0 0 3 4.5v11A1.5 1.5 0 0 0 4.5 17h11a1.5 1.5 0 0 0 1.5-1.5v-11A1.5 1.5 0 0 0 15.5 3h-11zm9.207 5.707a1 1 0 0 0-1.414-1.414L9 10.586 7.707 9.293a1 1 0 0 0-1.414 1.414l2 2a1 1 0 0 0 1.414 0l4-4z"
                            ></path></svg></span></span
                      ><span class="Polaris-Button__Text">Select</span></span
                    >
                  </button>
                </div>
              </div>
              <div class="Polaris-ResourceList__BulkActionsWrapper">
                <div>
                  <div
                    class="Polaris-BulkActions__Group Polaris-BulkActions__Group--largeScreen Polaris-BulkActions__Group--exited"
                  >
                    <div class="Polaris-BulkActions__ButtonGroupWrapper">
                      <div
                        class="Polaris-ButtonGroup Polaris-ButtonGroup--segmented"
                        data-buttongroup-segmented="true"
                      >
                        <div class="Polaris-ButtonGroup__Item">
                          <div class="Polaris-CheckableButton">
                            <div class="Polaris-CheckableButton__Checkbox">
                              <label
                                class="Polaris-Choice Polaris-Choice--labelHidden"
                                for="PolarisCheckbox11"
                                ><span class="Polaris-Choice__Control"
                                  ><span class="Polaris-Checkbox"
                                    ><input
                                      id="PolarisCheckbox11"
                                      type="checkbox"
                                      class="Polaris-Checkbox__Input"
                                      aria-invalid="false"
                                      role="checkbox"
                                      aria-checked="false"
                                      value="" /><span class="Polaris-Checkbox__Backdrop"></span
                                    ><span class="Polaris-Checkbox__Icon"
                                      ><span class="Polaris-Icon"
                                        ><span class="Polaris-VisuallyHidden"></span
                                        ><svg
                                          viewBox="0 0 20 20"
                                          class="Polaris-Icon__Svg"
                                          focusable="false"
                                          aria-hidden="true"
                                        >
                                          <path
                                            d="m8.315 13.859-3.182-3.417a.506.506 0 0 1 0-.684l.643-.683a.437.437 0 0 1 .642 0l2.22 2.393 4.942-5.327a.436.436 0 0 1 .643 0l.643.684a.504.504 0 0 1 0 .683l-5.91 6.35a.437.437 0 0 1-.642 0"
                                          ></path></svg></span></span></span></span
                                ><span class="Polaris-Choice__Label"
                                  >Select all 2 customers</span
                                ></label
                              >
                            </div>
                            <span class="Polaris-CheckableButton__Label">0 selected</span>
                          </div>
                        </div>
                        <div class="Polaris-ButtonGroup__Item">
                          <div class="Polaris-BulkActions__BulkActionButton">
                            <button class="Polaris-Button" type="button">
                              <span class="Polaris-Button__Content"
                                ><span class="Polaris-Button__Text">Edit customers</span></span
                              >
                            </button>
                          </div>
                        </div>
                        <div class="Polaris-ButtonGroup__Item">
                          <div>
                            <div>
                              <div class="Polaris-BulkActions__BulkActionButton">
                                <button
                                  class="Polaris-Button"
                                  type="button"
                                  tabindex="0"
                                  aria-controls="Polarispopover13"
                                  aria-owns="Polarispopover13"
                                  aria-expanded="false"
                                >
                                  <span class="Polaris-Button__Content"
                                    ><span class="Polaris-Button__Text">More actions</span
                                    ><span class="Polaris-Button__Icon">
                                      <div class="">
                                        <span class="Polaris-Icon"
                                          ><span class="Polaris-VisuallyHidden"></span
                                          ><svg
                                            viewBox="0 0 20 20"
                                            class="Polaris-Icon__Svg"
                                            focusable="false"
                                            aria-hidden="true"
                                          >
                                            <path d="m5 8 5 5 5-5H5z"></path></svg
                                        ></span>
                                      </div> </span
                                  ></span>
                                </button>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
      <ul class="Polaris-ResourceList" aria-live="polite">
        <li class="Polaris-ResourceItem__ListItem">
          <div class="Polaris-ResourceItem__ItemWrapper">
            <div
              class="Polaris-ResourceItem Polaris-ResourceItem--selectable Polaris-ResourceItem--persistActions"
              data-href="customers/341"
            >
              <a
                aria-describedby="112"
                aria-label="View details for Mae Jemison"
                class="Polaris-ResourceItem__Link"
                tabindex="0"
                id="PolarisResourceListItemOverlay55"
                href="customers/341"
                data-polaris-unstyled="true"
              ></a>
              <div class="Polaris-ResourceItem__Container" id="112">
                <div class="Polaris-ResourceItem__Owned">
                  <div class="Polaris-ResourceItem__Handle">
                    <div class="Polaris-ResourceItem__CheckboxWrapper">
                      <div>
                        <label
                          class="Polaris-Choice Polaris-Choice--labelHidden"
                          for="PolarisResourceListItemCheckbox55"
                          ><span class="Polaris-Choice__Control"
                            ><span class="Polaris-Checkbox"
                              ><input
                                id="PolarisResourceListItemCheckbox55"
                                type="checkbox"
                                class="Polaris-Checkbox__Input"
                                aria-invalid="false"
                                role="checkbox"
                                aria-checked="false"
                                value="" /><span class="Polaris-Checkbox__Backdrop"></span
                              ><span class="Polaris-Checkbox__Icon"
                                ><span class="Polaris-Icon"
                                  ><span class="Polaris-VisuallyHidden"></span
                                  ><svg
                                    viewBox="0 0 20 20"
                                    class="Polaris-Icon__Svg"
                                    focusable="false"
                                    aria-hidden="true"
                                  >
                                    <path
                                      d="m8.315 13.859-3.182-3.417a.506.506 0 0 1 0-.684l.643-.683a.437.437 0 0 1 .642 0l2.22 2.393 4.942-5.327a.436.436 0 0 1 .643 0l.643.684a.504.504 0 0 1 0 .683l-5.91 6.35a.437.437 0 0 1-.642 0"
                                    ></path></svg></span></span></span></span
                          ><span class="Polaris-Choice__Label"
                            >View details for Mae Jemison</span
                          ></label
                        >
                      </div>
                    </div>
                  </div>
                  <div class="Polaris-ResourceItem__Media">
                    <span
                      aria-label="Mae Jemison"
                      role="img"
                      class="Polaris-Avatar Polaris-Avatar--sizeMedium"
                      ><span class="Polaris-Avatar__Initials"
                        ><svg class="Polaris-Avatar__Svg" viewBox="0 0 40 40">
                          <path
                            fill="currentColor"
                            d="M8.28 27.5A14.95 14.95 0 0120 21.8c4.76 0 8.97 2.24 11.72 5.7a14.02 14.02 0 01-8.25 5.91 14.82 14.82 0 01-6.94 0 14.02 14.02 0 01-8.25-5.9zM13.99 12.78a6.02 6.02 0 1112.03 0 6.02 6.02 0 01-12.03 0z"
                          ></path></svg></span
                    ></span>
                  </div>
                </div>
                <div class="Polaris-ResourceItem__Content">
                  <h3><span class="Polaris-TextStyle--variationStrong">Mae Jemison</span></h3>
                  <div>Decatur, USA</div>
                </div>
                <div class="Polaris-ResourceItem__Actions">
                  <div class="Polaris-ButtonGroup">
                    <div class="Polaris-ButtonGroup__Item Polaris-ButtonGroup__Item--plain">
                      <a
                        class="Polaris-Button Polaris-Button--plain"
                        href="orders/1456"
                        data-polaris-unstyled="true"
                        ><span class="Polaris-Button__Content"
                          ><span class="Polaris-Button__Text">View latest order</span></span
                        ></a
                      >
                    </div>
                  </div>
                </div>
                <div class="Polaris-ResourceItem__Disclosure">
                  <div>
                    <button
                      class="Polaris-Button Polaris-Button--plain Polaris-Button--iconOnly"
                      aria-label="Actions dropdown"
                      type="button"
                      tabindex="0"
                      aria-controls="Polarispopover11"
                      aria-owns="Polarispopover11"
                      aria-expanded="false"
                    >
                      <span class="Polaris-Button__Content"
                        ><span class="Polaris-Button__Icon"
                          ><span class="Polaris-Icon"
                            ><span class="Polaris-VisuallyHidden"></span
                            ><svg
                              viewBox="0 0 20 20"
                              class="Polaris-Icon__Svg"
                              focusable="false"
                              aria-hidden="true"
                            >
                              <path
                                d="M6 10a2 2 0 1 1-4.001-.001A2 2 0 0 1 6 10zm6 0a2 2 0 1 1-4.001-.001A2 2 0 0 1 12 10zm6 0a2 2 0 1 1-4.001-.001A2 2 0 0 1 18 10z"
                              ></path></svg></span></span
                      ></span>
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </li>
        <li class="Polaris-ResourceItem__ListItem">
          <div class="Polaris-ResourceItem__ItemWrapper">
            <div
              class="Polaris-ResourceItem Polaris-ResourceItem--selectable Polaris-ResourceItem--persistActions"
              data-href="customers/256"
            >
              <a
                aria-describedby="212"
                aria-label="View details for Ellen Ochoa"
                class="Polaris-ResourceItem__Link"
                tabindex="0"
                id="PolarisResourceListItemOverlay56"
                href="customers/256"
                data-polaris-unstyled="true"
              ></a>
              <div class="Polaris-ResourceItem__Container" id="212">
                <div class="Polaris-ResourceItem__Owned">
                  <div class="Polaris-ResourceItem__Handle">
                    <div class="Polaris-ResourceItem__CheckboxWrapper">
                      <div>
                        <label
                          class="Polaris-Choice Polaris-Choice--labelHidden"
                          for="PolarisResourceListItemCheckbox56"
                          ><span class="Polaris-Choice__Control"
                            ><span class="Polaris-Checkbox"
                              ><input
                                id="PolarisResourceListItemCheckbox56"
                                type="checkbox"
                                class="Polaris-Checkbox__Input"
                                aria-invalid="false"
                                role="checkbox"
                                aria-checked="false"
                                value="" /><span class="Polaris-Checkbox__Backdrop"></span
                              ><span class="Polaris-Checkbox__Icon"
                                ><span class="Polaris-Icon"
                                  ><span class="Polaris-VisuallyHidden"></span
                                  ><svg
                                    viewBox="0 0 20 20"
                                    class="Polaris-Icon__Svg"
                                    focusable="false"
                                    aria-hidden="true"
                                  >
                                    <path
                                      d="m8.315 13.859-3.182-3.417a.506.506 0 0 1 0-.684l.643-.683a.437.437 0 0 1 .642 0l2.22 2.393 4.942-5.327a.436.436 0 0 1 .643 0l.643.684a.504.504 0 0 1 0 .683l-5.91 6.35a.437.437 0 0 1-.642 0"
                                    ></path></svg></span></span></span></span
                          ><span class="Polaris-Choice__Label"
                            >View details for Ellen Ochoa</span
                          ></label
                        >
                      </div>
                    </div>
                  </div>
                  <div class="Polaris-ResourceItem__Media">
                    <span
                      aria-label="Ellen Ochoa"
                      role="img"
                      class="Polaris-Avatar Polaris-Avatar--sizeMedium"
                      ><span class="Polaris-Avatar__Initials"
                        ><svg class="Polaris-Avatar__Svg" viewBox="0 0 40 40">
                          <path
                            fill="currentColor"
                            d="M8.28 27.5A14.95 14.95 0 0120 21.8c4.76 0 8.97 2.24 11.72 5.7a14.02 14.02 0 01-8.25 5.91 14.82 14.82 0 01-6.94 0 14.02 14.02 0 01-8.25-5.9zM13.99 12.78a6.02 6.02 0 1112.03 0 6.02 6.02 0 01-12.03 0z"
                          ></path></svg></span
                    ></span>
                  </div>
                </div>
                <div class="Polaris-ResourceItem__Content">
                  <h3><span class="Polaris-TextStyle--variationStrong">Ellen Ochoa</span></h3>
                  <div>Los Angeles, USA</div>
                </div>
                <div class="Polaris-ResourceItem__Actions">
                  <div class="Polaris-ButtonGroup">
                    <div class="Polaris-ButtonGroup__Item Polaris-ButtonGroup__Item--plain">
                      <a
                        class="Polaris-Button Polaris-Button--plain"
                        href="orders/1457"
                        data-polaris-unstyled="true"
                        ><span class="Polaris-Button__Content"
                          ><span class="Polaris-Button__Text">View latest order</span></span
                        ></a
                      >
                    </div>
                  </div>
                </div>
                <div class="Polaris-ResourceItem__Disclosure">
                  <div>
                    <button
                      class="Polaris-Button Polaris-Button--plain Polaris-Button--iconOnly"
                      aria-label="Actions dropdown"
                      type="button"
                      tabindex="0"
                      aria-controls="Polarispopover12"
                      aria-owns="Polarispopover12"
                      aria-expanded="false"
                    >
                      <span class="Polaris-Button__Content"
                        ><span class="Polaris-Button__Icon"
                          ><span class="Polaris-Icon"
                            ><span class="Polaris-VisuallyHidden"></span
                            ><svg
                              viewBox="0 0 20 20"
                              class="Polaris-Icon__Svg"
                              focusable="false"
                              aria-hidden="true"
                            >
                              <path
                                d="M6 10a2 2 0 1 1-4.001-.001A2 2 0 0 1 6 10zm6 0a2 2 0 1 1-4.001-.001A2 2 0 0 1 12 10zm6 0a2 2 0 1 1-4.001-.001A2 2 0 0 1 18 10z"
                              ></path></svg></span></span
                      ></span>
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </li>
      </ul>
    </div>
  </div>
  <div id="PolarisPortalsContainer">
    <div data-portal-id="sheet-Polarisportal13"></div>
    <div data-portal-id="popover-Polarisportal14"></div>
    <div data-portal-id="popover-Polarisportal15"></div>
    <div data-portal-id="popover-Polarisportal16"></div>
  </div>
</div>
,,,

Props

alternateTool
React.ReactNode
ソートコントロールの代わりに表示する ReactNode


bulkActions
(ActionListSection | DisableableAction & BadgeAction)[]
現在選択されているアイテムで利用可能なアクション


emptySearchState
React.ReactNode
リストの検索やフィルタリングで結果が返ってこなかったときに表示するマークアップである。filterControlが設定されていて、アイテムが空で、emptyState`が設定されていない場合にレンダリングされる。


emptyState
React.ReactNode
リソースがまだ存在しないときに表示するマークアップ。セットされていて、アイテムが空のときにレンダリングされる。


filterControl
React.ReactNode


hasMoreItems
boolean
items prop に現在設定されているよりも多くのアイテムがあるかどうかを示します。BulkActions コンポーネントに paginatedSelectAllAction プロップと paginatedSelectAllText プロップを設定するかどうかを決定します。


isFiltered
boolean
リストにフィルターが適用されているかどうかを示します。


itemsRequired
ItemType[]
アイテムのデータ。各アイテムは renderItem に渡されます。


loading
boolean
バックグラウンドアクションが実行されている間、アイテムリストをスピナーでオーバーレイします。


promotedBulkActions
(MenuGroupDescriptor | DisableableAction & BadgeAction)[]
最大 2 つのバルクアクションが、より目立つように表示されます。


resourceName
{plural: string, singular: string}
カスタマーやプロダクトなどのリソースの名前


selectable
boolean
リストの一番上に Select All ボタンを表示し、各リストアイテムの前にチェックボックスを表示します。bulkActions が提供されていない場合に使用します。


selectedItems
string[] | "All"
現在選択されているアイテムの ID のコレクション


showHeader
boolean
ヘッダーを表示するかどうかのブール値


sortOptions
(string | StrictOption)[]
選択できるソートオプションのコレクション


sortValue
string
ソートコントロールの現在の値


totalItemsCount
number
リソースの合計数


idForItem
(item: ItemType, index: number) => string
各アイテムのユニークな ID をカスタマイズする関数


onSelectionChange
(selectedItems: string[] | "All") => void
選択範囲が変更されたときのコールバック


onSortChange
(selected: string, id: string) => void
ソートオプションが変更されたときのコールバック


renderItemRequired
(item: ItemType, id: string, index: number) => React.ReactNode
各リストアイテムをレンダリングする関数で、ResourceItem コンポーネントを返す必要があります。


resolveItemId
(item: ItemType) => string
アイテムの id を解決する関数です。

ビルド

プロジェクトでリソースリストを使用するには、以下のコンポーネントとサブコンポーネントを組み合わせる必要があります。

  • リソースリスト
  • ResourceItem またはカスタマイズされたリストアイテム
  • フィルター(オプション)
  • ページネーションコンポーネント(オプション)

リソースリストコンポーネントは、リストのソート、フィルタリング、ページネーションのための UI 要素を提供しますが、これらの操作のためのロジックは提供しません。ソートオプションが変更されたり、フィルタが追加されたり、2 ページ目が要求されたりした場合には、そのイベント(ネットワーク要求を含む)を処理し、新しいプロップでコンポーネントを更新する必要があります。

目的

Shopify は、顧客、製品、注文などのマーチャントビジネスを表すオブジェクトを中心に構成されています。例えば、個々の注文には、リンクできる専用のページが与えられています。Shopify ではこのようなオブジェクトをリソースと呼び、オブジェクトの専用ページを詳細ページと呼んでいます。

問題点

注文を例にとります。マーチャントはたくさんの注文を抱えています。注文をスキャンして、どの状態にあるのかを確認し、どれが最初にアクションを起こす必要があるのかを見つける方法が必要です。言い換えれば、個々の注文を見つけて、その詳細情報を呼び出し、アクションを起こす方法が必要なのです。

ソリューション

リソースリストの機能は以下の通りです。

  • 個々のリソースをコンパクトにまとめたコンテンツフォーマット
  • 1 つまたは複数の個別リソースに対してアクションを起こすためのシステム
  • 個々のリソースの詳細ページに移動するための手段

詳細ページには、個々のリソースのすべてのコンテンツとアクションが表示されるため、リソースリストは、これらの詳細ページの要約と考えることができます。このように、リソースリストは Shopify のナビゲーション階層の中間レベルに位置しています。

Image from Gyazo

リソースリストはデータテーブルではありません
広い画面では、リソースリストはしばしばテーブルのように見えます。しかし、リソースリストとデータテーブルは目的が異なります。

データテーブルは、データビジュアライゼーションの一種です。比較や分析のために高度に構造化されたデータを表示するのに適しています。

データの視覚化や分析を目的としたユースケースでは、データテーブルコンポーネントを使用します。オブジェクトを見つけてアクションを起こすことが目的の場合は、リソースリストを使用します。

ベストプラクティス

リソースリストは Shopify の様々な場所で使用できます。最近のマーケティング活動をまとめたカードの中に、短いリソースリストを入れることができます。また、Shopify のメイン製品リストのように、ページ全体をリソースリストに割り当てることもできます。

リソースリストは

  • クリックするとアクションを起こすアイテムがあること。そのアクションは、リソースの詳細ページに移動するなど、アイテムの詳細を提供するものであること。

  • マーチャントのニーズに合わせて、リストアイテムのコンテンツやレイアウトをカスタマイズすることができます。

  • リストが長い場合、特にマーチャントのタスクによってソート順が異なる場合は、ソートをサポートしてください。

  • リストが長くなる可能性がある場合は、フィルタリングをサポートします。

  • 現在のリストに 50 以上のアイテムが含まれている場合は、ページ分割を行います。

  • loading prop が true でアイテムが処理されている場合、最初のページロード時にスケルトンページコンポーネントをページの残りの部分に使用します。
    リソースリストは、オプションで以下のことができます。

  • 一度に多くのリストアイテムに適用されることの多いタスクのために、バルクアクションを提供する。例えば、マーチャントが多数の商品に同じタグを追加したい場合などです。

コンテンツのガイドライン

リソースリストは

リソースの種類を識別するために、通常は以下のような見出しを付けます。

Image from Gyazo

リソースのすべてのメンバーが表示されていない場合は、それを示す。最近購入した製品をまとめてリンクするカードの場合。

Image from Gyazo

関連コンポーネント

Section header

セクションヘッダーコンポーネントは、リスト内のアイテムをグループ化するために使用します。マーチャントは、どのアイテムが関連しているかをすぐに確認することができます。

Android

デフォルト

同じ日に受け取った注文など、関連するコンテンツをまとめて表示する場合に使用します。

Image from Gyazo

iOs

デフォルト

同じ日に受け取った注文など、関連するコンテンツをグループ化するために使用します。

Image from Gyazo

固定

リストのセクションが画面の高さよりも長くなる可能性がある場合に使用します。例えば、マーチャントは 1 日に多くの注文を受ける可能性があるため、注文リストのセクションヘッダーを固定する必要があります。

Image from Gyazo

ベストプラクティス

  • グループのリストは、アルファベット順や日付順など、わかりやすい方法で作成してください。
  • 長いセクションタイトルでリストを乱雑にしないようにしてください(スキャンしにくくなります)。
  • 通常、各グループに 1 つのアイテムしかないリストの場合は、セクションヘッダーの使用を避けてください。セクションヘッダーが多ければ多いほど、マーチャントがリストをスキャンするのが難しくなります。

コンテンツのガイドライン

  • タイトルは短くする

Image from Gyazo

日付と数字について詳しくはこちら

  • 明確なソート順を使用する

Image from Gyazo

関連コンポーネント

Shopify アプリのご紹介

Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。

https://apps.shopify.com/shopify-application-314?locale=ja&from=daniel

Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。

https://apps.shopify.com/font-picker-1?locale=ja&from=daniel

Discussion

ログインするとコメントできます