【Polaris和訳】Components/Lists and tables④
この記事について
この記事は、Polaris/Components/Lists and tablesの記事を和訳したものです。
記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
Filters with query field hidden
React
function ResourceListFiltersExample() {
const [accountStatus, setAccountStatus] = useState(null)
const [moneySpent, setMoneySpent] = useState(null)
const [taggedWith, setTaggedWith] = useState(null)
const [queryValue, setQueryValue] = useState(null)
const handleAccountStatusChange = useCallback((value) => setAccountStatus(value), [])
const handleMoneySpentChange = useCallback((value) => setMoneySpent(value), [])
const handleTaggedWithChange = useCallback((value) => setTaggedWith(value), [])
const handleFiltersQueryChange = useCallback((value) => setQueryValue(value), [])
const handleAccountStatusRemove = useCallback(() => setAccountStatus(null), [])
const handleMoneySpentRemove = useCallback(() => setMoneySpent(null), [])
const handleTaggedWithRemove = useCallback(() => setTaggedWith(null), [])
const handleQueryValueRemove = useCallback(() => setQueryValue(null), [])
const handleFiltersClearAll = useCallback(() => {
handleAccountStatusRemove()
handleMoneySpentRemove()
handleTaggedWithRemove()
handleQueryValueRemove()
}, [
handleAccountStatusRemove,
handleMoneySpentRemove,
handleQueryValueRemove,
handleTaggedWithRemove,
])
const filters = [
{
key: "accountStatus",
label: "Account status",
filter: (
<ChoiceList
title="Account status"
titleHidden
choices={[
{ label: "Enabled", value: "enabled" },
{ label: "Not invited", value: "not invited" },
{ label: "Invited", value: "invited" },
{ label: "Declined", value: "declined" },
]}
selected={accountStatus || []}
onChange={handleAccountStatusChange}
allowMultiple
/>
),
shortcut: true,
},
{
key: "taggedWith",
label: "Tagged with",
filter: (
<TextField
label="Tagged with"
value={taggedWith}
onChange={handleTaggedWithChange}
autoComplete="off"
labelHidden
/>
),
shortcut: true,
},
{
key: "moneySpent",
label: "Money spent",
filter: (
<RangeSlider
label="Money spent is between"
labelHidden
value={moneySpent || [0, 500]}
prefix="$"
output
min={0}
max={2000}
step={1}
onChange={handleMoneySpentChange}
/>
),
},
]
const appliedFilters = []
if (!isEmpty(accountStatus)) {
const key = "accountStatus"
appliedFilters.push({
key,
label: disambiguateLabel(key, accountStatus),
onRemove: handleAccountStatusRemove,
})
}
if (!isEmpty(moneySpent)) {
const key = "moneySpent"
appliedFilters.push({
key,
label: disambiguateLabel(key, moneySpent),
onRemove: handleMoneySpentRemove,
})
}
if (!isEmpty(taggedWith)) {
const key = "taggedWith"
appliedFilters.push({
key,
label: disambiguateLabel(key, taggedWith),
onRemove: handleTaggedWithRemove,
})
}
return (
<div style={{ height: "568px" }}>
<Card>
<ResourceList
resourceName={{ singular: "customer", plural: "customers" }}
filterControl={
<Filters
queryValue={queryValue}
filters={filters}
appliedFilters={appliedFilters}
onQueryChange={handleFiltersQueryChange}
onQueryClear={handleQueryValueRemove}
onClearAll={handleFiltersClearAll}
hideQueryField
/>
}
items={[
{
id: 341,
url: "customers/341",
name: "Mae Jemison",
location: "Decatur, USA",
},
{
id: 256,
url: "customers/256",
name: "Ellen Ochoa",
location: "Los Angeles, USA",
},
]}
renderItem={(item) => {
const { id, url, name, location } = item
const media = <Avatar customer size="medium" name={name} />
return (
<ResourceList.Item
id={id}
url={url}
media={media}
accessibilityLabel={`View details for ${name}`}
>
<h3>
<TextStyle variation="strong">{name}</TextStyle>
</h3>
<div>{location}</div>
</ResourceList.Item>
)
}}
/>
</Card>
</div>
)
function disambiguateLabel(key, value) {
switch (key) {
case "moneySpent":
return `Money spent is between $${value[0]} and $${value[1]}`
case "taggedWith":
return `Tagged with ${value}`
case "accountStatus":
return value.map((val) => `Customer ${val}`).join(", ")
default:
return value
}
}
function isEmpty(value) {
if (Array.isArray(value)) {
return value.length === 0
} else {
return value === "" || value == null
}
}
}
HTML
<div>
<div style="height: 568px;">
<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="accountStatus">
<button class="Polaris-Button" type="button">
<span class="Polaris-Button__Content"
><span class="Polaris-Button__Text">Account status</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 data-key="taggedWith">
<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__RightContainer Polaris-Filters-ConnectedFilterControl--queryFieldHidden"
>
<div class="Polaris-Filters-ConnectedFilterControl__Item">
<div>
<button
id="Activator-accountStatus"
class="Polaris-Button"
type="button"
tabindex="0"
aria-controls="Polarispopover5"
aria-owns="Polarispopover5"
aria-expanded="false"
>
<span class="Polaris-Button__Content"
><span class="Polaris-Button__Text">Account status</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 class="Polaris-Filters-ConnectedFilterControl__MoreFiltersButtonContainer">
<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>
<span class="Polaris-VisuallyHidden">
<div class="Polaris-Filters__TagsContainer" aria-live="polite"></div>
</span>
</div>
</div>
<ul class="Polaris-ResourceList" aria-live="polite">
<li class="Polaris-ResourceItem__ListItem">
<div class="Polaris-ResourceItem__ItemWrapper">
<div class="Polaris-ResourceItem" data-href="customers/341">
<a
aria-describedby="341"
aria-label="View details for Mae Jemison"
class="Polaris-ResourceItem__Link"
tabindex="0"
id="PolarisResourceListItemOverlay27"
href="customers/341"
data-polaris-unstyled="true"
></a>
<div class="Polaris-ResourceItem__Container" id="341">
<div class="Polaris-ResourceItem__Owned">
<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>
</div>
</div>
</li>
<li class="Polaris-ResourceItem__ListItem">
<div class="Polaris-ResourceItem__ItemWrapper">
<div class="Polaris-ResourceItem" data-href="customers/256">
<a
aria-describedby="256"
aria-label="View details for Ellen Ochoa"
class="Polaris-ResourceItem__Link"
tabindex="0"
id="PolarisResourceListItemOverlay28"
href="customers/256"
data-polaris-unstyled="true"
></a>
<div class="Polaris-ResourceItem__Container" id="256">
<div class="Polaris-ResourceItem__Owned">
<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>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div id="PolarisPortalsContainer">
<div data-portal-id="sheet-Polarisportal18"></div>
<div data-portal-id="popover-Polarisportal19"></div>
</div>
</div>
,
Props
appliedFilters
AppliedFilterInterface[]
タグとしてレンダリングされる、適用されたフィルター。削除コールバックは、それぞれのキー
children
React.ReactNode
コントロールとインラインで表示するコンテンツ
disabled
boolean
すべてのフィルターを無効にします
filtersRequired
FilterInterface[]
シートに追加される利用可能なフィルタです。ショートカットフィルタは、シートの外に公開されます。
focused
boolean
クエリーフィールドがフォーカスされているかどうか
helpText
string | React.ReactNode
フィルターの下に表示する追加のヒントテキスト
hideQueryField
boolean
クエリフィールドを隠す
hideTags
boolean
適用されたフィルタのタグを隠す
queryPlaceholder
string
クエリフィールドのプレースホルダーテキスト
queryValue
string
クエリフィールドに現在入力されているテキスト
onClearAllRequired
() => void
全てをリセットするボタンが押された時のコールバック
onQueryBlur
() => void
クエリーフィールドがぼかされたときのコールバック
onQueryChangeRequired
(queryValue: string) => void
クエリフィールドが変更されたときのコールバック
onQueryClearRequired
() => void
クリアボタンが押された時のコールバック
onQueryFocus
() => void
クエリフィールドがフォーカスされた時のコールバック
アクセシビリティ
フィルターコンポーネントは、他の複数のコンポーネントのアクセシビリティ機能に依存しています。
カスタム機能によるアクセシビリティの確保
カスタム HTML をコンポーネントに渡して追加のアクションを行うことができるため、構築したフィルタリングシステムが全体としてアクセス可能であることを確認してください。
すべてのマーチャントは
- すべてのコントロールのラベルを識別し、理解できること
- 状態の変化が通知されること
- すべての操作をキーボードで行うことができる
ベストプラクティス
フィルターコンポーネントは
- 最も一般的に使用されているフィルタリングカテゴリーを促進することで、マーチャントの労力を軽減する。
- 促進されるフィルタの数は 2、3 個以下にする
- 小さな画面サイズを考慮して、各フィルターのインターフェイスをデザインし、フィルターの総数を増やす。
- フィルタリングに関連するコンテンツにのみ Children を使用する。
コンテンツガイドライン
テキストフィールド
テキストフィールドには、マーチャントが何を入力すべきかがわかるように、明確なラベルを付けてください。
フィルターバッジ
名前の目的がそれだけで明らかな場合は、フィルターの名前を使用します。例えば、フルフィルドと書かれたフィルターバッジを見ると、フルフィルドのステータスカテゴリーに該当することが直感的にわかります。
フィルター名だけでは曖昧な場合は、ステータスに関連する説明語を追加します。たとえば、「Low」は文脈的に意味をなしません。リスク」という言葉を加えれば、マーチャントはそれがリスクカテゴリーのものだとわかります。
同じカテゴリーのタグをまとめます。
すべてのタグピルを選択した場合:途中で切り捨てる
Index table
インデックステーブルは、注文や商品など、同じ種類のオブジェクトの集まりを表示します。インデックステーブルの主な役割は、マーチャントがオブジェクトを一目で把握し、アクションを実行したり、全ページ表示にナビゲートしたりすることです。
インデックステーブルは以下のことも可能です。
- カスタマイズされたインデックスの行と列をサポート
- 複数のオブジェクトに対して一度にアクションを実行できるバルクアクションの搭載
- 長いリストのソートやフィルタリングのサポート
- 長いリストを読みやすくするためのページネーションとの組み合わせ
Simple index table
シンプルなアイテムで構成されたインデックステーブルで、バルクアクション、ソート、フィルタリングはありません。
React
function SimpleIndexTableExample() {
const customers = [
{
id: "3411",
url: "customers/341",
name: "Mae Jemison",
location: "Decatur, USA",
orders: 20,
amountSpent: "$2,400",
},
{
id: "2561",
url: "customers/256",
name: "Ellen Ochoa",
location: "Los Angeles, USA",
orders: 30,
amountSpent: "$140",
},
]
const resourceName = {
singular: "customer",
plural: "customers",
}
const { selectedResources, allResourcesSelected, handleSelectionChange } =
useIndexResourceState(customers)
const rowMarkup = customers.map(({ id, name, location, orders, amountSpent }, index) => (
<IndexTable.Row id={id} key={id} selected={selectedResources.includes(id)} position={index}>
<IndexTable.Cell>
<TextStyle variation="strong">{name}</TextStyle>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
))
return (
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={allResourcesSelected ? "All" : selectedResources.length}
onSelectionChange={handleSelectionChange}
headings={[
{ title: "Name" },
{ title: "Location" },
{ title: "Order count" },
{ title: "Amount spent" },
]}
>
{rowMarkup}
</IndexTable>
</Card>
)
}
HTML
<div>
<div class="Polaris-Card">
<div class="Polaris-IndexTable">
<div class="Polaris-IndexTable__StickyTable" role="presentation">
<div>
<div></div>
<div>
<div class="Polaris-IndexTable__StickyTableHeader">
<div class="Polaris-IndexTable__StickyTableColumnHeader">
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 146px;"
>
<div
class="Polaris-Stack Polaris-Stack--spacingNone Polaris-Stack--alignmentCenter Polaris-Stack--noWrap"
>
<div class="Polaris-Stack__Item">
<div
class="Polaris-IndexTable__FirstStickyHeaderElement"
style="min-width: calc(22px);"
>
<div class="Polaris-IndexTable__ColumnHeaderCheckboxWrapper">
<label
class="Polaris-Choice Polaris-Choice--labelHidden"
for="PolarisCheckbox3"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="PolarisCheckbox3"
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 customers</span></label
>
</div>
</div>
</div>
<div class="Polaris-Stack__Item">
<div class="Polaris-IndexTable--stickyTableHeadingSecondScrolling">Name</div>
</div>
</div>
</div>
</div>
<div class="Polaris-IndexTable__StickyTableHeadings">
<div
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__StickyTableHeading--second"
data-index-table-sticky-heading="true"
style="min-width: 94px;"
>
Name
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 154px;"
>
Location
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 116px;"
>
Order count
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 131px;"
>
Amount spent
</div>
</div>
</div>
</div>
</div>
</div>
<div class="Polaris-IndexTable-ScrollContainer">
<table class="Polaris-IndexTable__Table">
<thead>
<tr>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--first"
data-index-table-heading="true"
>
<div class="Polaris-IndexTable__ColumnHeaderCheckboxWrapper">
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="PolarisCheckbox2"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="PolarisCheckbox2"
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 customers</span></label
>
</div>
</th>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--second"
data-index-table-heading="true"
style="left: 52px;"
>
Name
</th>
<th class="Polaris-IndexTable__TableHeading" data-index-table-heading="true">
Location
</th>
<th class="Polaris-IndexTable__TableHeading" data-index-table-heading="true">
Order count
</th>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--last"
data-index-table-heading="true"
>
Amount spent
</th>
</tr>
</thead>
<tbody>
<tr class="Polaris-IndexTable__TableRow">
<td class="Polaris-IndexTable__TableCell Polaris-IndexTable__TableCell--first">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--expanded"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="3411"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="3411"
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 customer</span></label
>
</div>
</div>
</td>
<td class="Polaris-IndexTable__TableCell">
<span class="Polaris-TextStyle--variationStrong">Mae Jemison</span>
</td>
<td class="Polaris-IndexTable__TableCell">Decatur, USA</td>
<td class="Polaris-IndexTable__TableCell">20</td>
<td class="Polaris-IndexTable__TableCell">$2,400</td>
</tr>
<tr class="Polaris-IndexTable__TableRow">
<td class="Polaris-IndexTable__TableCell Polaris-IndexTable__TableCell--first">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--expanded"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="2561"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="2561"
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 customer</span></label
>
</div>
</div>
</td>
<td class="Polaris-IndexTable__TableCell">
<span class="Polaris-TextStyle--variationStrong">Ellen Ochoa</span>
</td>
<td class="Polaris-IndexTable__TableCell">Los Angeles, USA</td>
<td class="Polaris-IndexTable__TableCell">30</td>
<td class="Polaris-IndexTable__TableCell">$140</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="Polaris-IndexTable__ScrollBarContainer">
<div class="Polaris-IndexTable__ScrollBar" style="--p-scroll-bar-content-width:543px;">
<div class="Polaris-IndexTable__ScrollBarContent"></div>
</div>
</div>
</div>
<div id="PolarisPortalsContainer"></div>
</div>
Simple small screen index table
小画面のインデックステーブルで、シンプルな項目を持ち、一括操作やソート、フィルタリングはできません。
React
function SimpleSmallScreenIndexTableExample() {
const customers = [
{
id: "3412",
url: "customers/341",
name: "Mae Jemison",
location: "Decatur, USA",
orders: 20,
amountSpent: "$2,400",
},
{
id: "2562",
url: "customers/256",
name: "Ellen Ochoa",
location: "Los Angeles, USA",
orders: 30,
amountSpent: "$140",
},
]
const resourceName = {
singular: "customer",
plural: "customers",
}
const { selectedResources, allResourcesSelected, handleSelectionChange } =
useIndexResourceState(customers)
const rowMarkup = customers.map(({ id, name, location, orders, amountSpent }, index) => (
<IndexTable.Row id={id} key={id} selected={selectedResources.includes(id)} position={index}>
<div style={{ padding: "1.2rem 1.6rem" }}>
<p>
<TextStyle variation="strong">{name}</TextStyle>
</p>
<p>{location}</p>
<p>{orders}</p>
<p>{amountSpent}</p>
</div>
</IndexTable.Row>
))
return (
<div style={{ width: "430px" }}>
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={allResourcesSelected ? "All" : selectedResources.length}
onSelectionChange={handleSelectionChange}
condensed
headings={[
{ title: "Name" },
{ title: "Location" },
{ title: "Order count" },
{ title: "Amount spent" },
]}
>
{rowMarkup}
</IndexTable>
</Card>
</div>
)
}
HTML
<div>
<div style="width: 430px;">
<div class="Polaris-Card">
<div class="Polaris-IndexTable">
<div
class="Polaris-IndexTable__StickyTable Polaris-IndexTable__StickyTable--condensed"
role="presentation"
>
<div>
<div></div>
<div>
<div class="Polaris-IndexTable__HeaderWrapper">
<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>
</div>
<ul data-selectmode="false" class="Polaris-IndexTable__CondensedList">
<li class="Polaris-IndexTable__TableRow Polaris-IndexTable--condensedRow">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--condensed"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="3412"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="3412"
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 customer</span></label
>
</div>
</div>
<div style="padding: 1.2rem 1.6rem;">
<p><span class="Polaris-TextStyle--variationStrong">Mae Jemison</span></p>
<p>Decatur, USA</p>
<p>20</p>
<p>$2,400</p>
</div>
</li>
<li class="Polaris-IndexTable__TableRow Polaris-IndexTable--condensedRow">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--condensed"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="2562"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="2562"
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 customer</span></label
>
</div>
</div>
<div style="padding: 1.2rem 1.6rem;">
<p><span class="Polaris-TextStyle--variationStrong">Ellen Ochoa</span></p>
<p>Los Angeles, USA</p>
<p>30</p>
<p>$140</p>
</div>
</li>
</ul>
</div>
<div
class="Polaris-IndexTable__ScrollBarContainer Polaris-IndexTable--scrollBarContainerCondensed"
>
<div class="Polaris-IndexTable__ScrollBar" style="--p-scroll-bar-content-width:0px;">
<div class=""></div>
</div>
</div>
</div>
</div>
<div id="PolarisPortalsContainer"></div>
</div>
Index Table with empty state
リソースがまだ存在しないときのインデックステーブルの目的を説明するために使用します。これにより、読み込み状態のリストから、ゼロ、1、または多数のリソースが存在するリストへとスムーズに移行することができます。
React
function IndexTableWithCustomEmptyStateExample() {
const customers = []
const resourceName = {
singular: "customer",
plural: "customers",
}
const { selectedResources, allResourcesSelected, handleSelectionChange } =
useIndexResourceState(customers)
const emptyStateMarkup = (
<EmptySearchResult
title={"No customers yet"}
description={"Try changing the filters or search term"}
withIllustration
/>
)
const rowMarkup = customers.map(({ id, name, location, orders, amountSpent }, index) => (
<IndexTable.Row id={id} key={id} selected={selectedResources.includes(id)} position={index}>
<IndexTable.Cell>
<TextStyle variation="strong">{name}</TextStyle>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
))
return (
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={allResourcesSelected ? "All" : selectedResources.length}
onSelectionChange={handleSelectionChange}
emptyState={emptyStateMarkup}
headings={[
{ title: "Name" },
{ title: "Location" },
{ title: "Order count" },
{ title: "Amount spent" },
]}
>
{rowMarkup}
</IndexTable>
</Card>
)
}
HTML
<div>
<div class="Polaris-Card">
<div class="Polaris-IndexTable">
<div class="Polaris-IndexTable__EmptySearchResultWrapper">
<div class="Polaris-Stack Polaris-Stack--vertical Polaris-Stack--alignmentCenter">
<div class="Polaris-Stack__Item">
<img
src="data:image/svg+xml,%3csvg width='60' height='60' fill='none' xmlns='http://www.w3.org/2000/svg'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M41.87 24a17.87 17.87 0 11-35.74 0 17.87 17.87 0 0135.74 0zm-3.15 18.96a24 24 0 114.24-4.24L59.04 54.8a3 3 0 11-4.24 4.24L38.72 42.96z' fill='%238C9196'/%3e%3c/svg%3e"
alt="Empty search results"
draggable="false"
/>
</div>
<div class="Polaris-Stack__Item">
<p class="Polaris-DisplayText Polaris-DisplayText--sizeSmall">No customers yet</p>
</div>
<div class="Polaris-Stack__Item">
<span class="Polaris-TextStyle--variationSubdued">
<p>Try changing the filters or search term</p>
</span>
</div>
</div>
</div>
</div>
</div>
<div id="PolarisPortalsContainer"></div>
</div>
Index Table with buld actions
マーチャントがアイテムを選択し、その選択に対してアクションを実行することができます。
React
function IndexTableWithBulkActionsExample() {
const customers = [
{
id: "3413",
url: "customers/341",
name: "Mae Jemison",
location: "Decatur, USA",
orders: 20,
amountSpent: "$2,400",
},
{
id: "2563",
url: "customers/256",
name: "Ellen Ochoa",
location: "Los Angeles, USA",
orders: 30,
amountSpent: "$140",
},
]
const resourceName = {
singular: "customer",
plural: "customers",
}
const { selectedResources, allResourcesSelected, handleSelectionChange } =
useIndexResourceState(customers)
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 rowMarkup = customers.map(({ id, name, location, orders, amountSpent }, index) => (
<IndexTable.Row id={id} key={id} selected={selectedResources.includes(id)} position={index}>
<IndexTable.Cell>
<TextStyle variation="strong">{name}</TextStyle>
</IndexTable.Cell>
<IndexTable.Cell>{location}</IndexTable.Cell>
<IndexTable.Cell>{orders}</IndexTable.Cell>
<IndexTable.Cell>{amountSpent}</IndexTable.Cell>
</IndexTable.Row>
))
return (
<Card>
<IndexTable
resourceName={resourceName}
itemCount={customers.length}
selectedItemsCount={allResourcesSelected ? "All" : selectedResources.length}
onSelectionChange={handleSelectionChange}
bulkActions={bulkActions}
promotedBulkActions={promotedBulkActions}
headings={[
{ title: "Name" },
{ title: "Location" },
{ title: "Order count" },
{ title: "Amount spent" },
]}
>
{rowMarkup}
</IndexTable>
</Card>
)
}
HTML
<div>
<div class="Polaris-Card">
<div class="Polaris-IndexTable">
<div class="Polaris-IndexTable__StickyTable" role="presentation">
<div>
<div></div>
<div>
<div class="Polaris-IndexTable__StickyTableHeader">
<div class="Polaris-IndexTable__StickyTableColumnHeader">
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 146px;"
>
<div
class="Polaris-Stack Polaris-Stack--spacingNone Polaris-Stack--alignmentCenter Polaris-Stack--noWrap"
>
<div class="Polaris-Stack__Item">
<div
class="Polaris-IndexTable__FirstStickyHeaderElement"
style="min-width: calc(22px);"
>
<div class="Polaris-IndexTable__ColumnHeaderCheckboxWrapper">
<label
class="Polaris-Choice Polaris-Choice--labelHidden"
for="PolarisCheckbox6"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="PolarisCheckbox6"
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 customers</span></label
>
</div>
</div>
</div>
<div class="Polaris-Stack__Item">
<div class="Polaris-IndexTable--stickyTableHeadingSecondScrolling">Name</div>
</div>
</div>
</div>
</div>
<div class="Polaris-IndexTable__StickyTableHeadings">
<div
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__StickyTableHeading--second"
data-index-table-sticky-heading="true"
style="min-width: 94px;"
>
Name
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 154px;"
>
Location
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 116px;"
>
Order count
</div>
<div
class="Polaris-IndexTable__TableHeading"
data-index-table-sticky-heading="true"
style="min-width: 131px;"
>
Amount spent
</div>
</div>
</div>
</div>
</div>
</div>
<div class="Polaris-IndexTable-ScrollContainer">
<table class="Polaris-IndexTable__Table">
<thead>
<tr>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--first"
data-index-table-heading="true"
>
<div class="Polaris-IndexTable__ColumnHeaderCheckboxWrapper">
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="PolarisCheckbox5"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="PolarisCheckbox5"
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 customers</span></label
>
</div>
</th>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--second"
data-index-table-heading="true"
style="left: 52px;"
>
Name
</th>
<th class="Polaris-IndexTable__TableHeading" data-index-table-heading="true">
Location
</th>
<th class="Polaris-IndexTable__TableHeading" data-index-table-heading="true">
Order count
</th>
<th
class="Polaris-IndexTable__TableHeading Polaris-IndexTable__TableHeading--last"
data-index-table-heading="true"
>
Amount spent
</th>
</tr>
</thead>
<tbody>
<tr class="Polaris-IndexTable__TableRow">
<td class="Polaris-IndexTable__TableCell Polaris-IndexTable__TableCell--first">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--expanded"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="3413"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="3413"
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 customer</span></label
>
</div>
</div>
</td>
<td class="Polaris-IndexTable__TableCell">
<span class="Polaris-TextStyle--variationStrong">Mae Jemison</span>
</td>
<td class="Polaris-IndexTable__TableCell">Decatur, USA</td>
<td class="Polaris-IndexTable__TableCell">20</td>
<td class="Polaris-IndexTable__TableCell">$2,400</td>
</tr>
<tr class="Polaris-IndexTable__TableRow">
<td class="Polaris-IndexTable__TableCell Polaris-IndexTable__TableCell--first">
<div class="Polaris-IndexTable-Checkbox__TableCellContentContainer">
<div
class="Polaris-IndexTable-Checkbox__Wrapper Polaris-IndexTable-Checkbox--expanded"
>
<label class="Polaris-Choice Polaris-Choice--labelHidden" for="2563"
><span class="Polaris-Choice__Control"
><span class="Polaris-Checkbox"
><input
id="2563"
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 customer</span></label
>
</div>
</div>
</td>
<td class="Polaris-IndexTable__TableCell">
<span class="Polaris-TextStyle--variationStrong">Ellen Ochoa</span>
</td>
<td class="Polaris-IndexTable__TableCell">Los Angeles, USA</td>
<td class="Polaris-IndexTable__TableCell">30</td>
<td class="Polaris-IndexTable__TableCell">$140</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="Polaris-IndexTable__ScrollBarContainer">
<div class="Polaris-IndexTable__ScrollBar" style="--p-scroll-bar-content-width:543px;">
<div class="Polaris-IndexTable__ScrollBarContent"></div>
</div>
</div>
</div>
<div id="PolarisPortalsContainer"></div>
</div>
Shopify アプリのご紹介
Shopify アプリである、「商品ページ発売予告アプリ | リテリア Coming Soon」は、商品ページを買えない状態のまま、発売日時の予告をすることができるアプリです。Shopify で Coming Soon 機能を実現することができます。
Shopify アプリである、「らくらく日本語フォント設定|リテリア Font Picker」は、ノーコードで日本語フォントを使用できるアプリです。日本語フォントを導入することでブランドを演出することができます。
Discussion