diff --git a/.changeset/strange-bananas-obey.md b/.changeset/strange-bananas-obey.md
new file mode 100644
index 00000000000..3735026db35
--- /dev/null
+++ b/.changeset/strange-bananas-obey.md
@@ -0,0 +1,11 @@
+---
+'@shopify/polaris': minor
+---
+
+Added support for an `EditColumns` button rendered in the `IndexFilters` deprecating the `Tabs`'s `edit-columns` action.
+
+- `IndexFilters`
+ - Added support for rendering an Edit Columns button using the `showEditColumnsButton` flag.
+ - Added the edition `mode` to the `onEditStart(mode)` callback.
+- `Tabs`
+ - Removed the `edit-columns` action type.
diff --git a/polaris-react/locales/cs.json b/polaris-react/locales/cs.json
index fbe80e16b66..9c5da0e0c77 100644
--- a/polaris-react/locales/cs.json
+++ b/polaris-react/locales/cs.json
@@ -214,7 +214,6 @@
"rename": "Přejmenovat zobrazení",
"duplicate": "Duplikování zobrazení",
"edit": "Upravit zobrazení",
- "editColumns": "Upravit sloupce",
"delete": "Odstranit zobrazení",
"copy": "{name} – kopie",
"deleteModal": {
@@ -391,7 +390,11 @@
"cancel": "Zrušit"
}
},
- "searchFilterTooltipWithShortcut": "Hledejte a filtrujte (F)"
+ "searchFilterTooltipWithShortcut": "Hledejte a filtrujte (F)",
+ "EditColumnsButton": {
+ "tooltip": "Upravit sloupce",
+ "accessibilityLabel": "Přizpůsobit pořadí a viditelnost sloupců tabulky"
+ }
},
"ActionList": {
"SearchField": {
diff --git a/polaris-react/locales/da.json b/polaris-react/locales/da.json
index 4f3d39fdfcd..017e6fa3c57 100644
--- a/polaris-react/locales/da.json
+++ b/polaris-react/locales/da.json
@@ -214,7 +214,6 @@
"rename": "Omdøb visning",
"duplicate": "Dupliker visning",
"edit": "Rediger visning",
- "editColumns": "Rediger kolonner",
"delete": "Slet visning",
"copy": "Kopi af {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Gem",
"cancel": "Annuller"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Rediger kolonner",
+ "accessibilityLabel": "Tilpas rækkefølgen og synligheden af tabelkolonner"
}
},
"ActionList": {
diff --git a/polaris-react/locales/de.json b/polaris-react/locales/de.json
index 1066bf858ac..cbd575ea79e 100644
--- a/polaris-react/locales/de.json
+++ b/polaris-react/locales/de.json
@@ -214,7 +214,6 @@
"rename": "Ansicht umbenennen",
"duplicate": "Ansicht duplizieren",
"edit": "Ansicht bearbeiten",
- "editColumns": "Spalten bearbeiten",
"delete": "Ansicht löschen",
"copy": "Kopie von {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Speichern",
"cancel": "Abbrechen"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Spalten bearbeiten",
+ "accessibilityLabel": "Reihenfolge und Sichtbarkeit der Tabellenspalten anpassen"
}
},
"ActionList": {
diff --git a/polaris-react/locales/en.json b/polaris-react/locales/en.json
index 133a633151c..05b6fc13eae 100644
--- a/polaris-react/locales/en.json
+++ b/polaris-react/locales/en.json
@@ -192,6 +192,10 @@
"za": "Z-A"
}
},
+ "EditColumnsButton": {
+ "tooltip": "Edit columns",
+ "accessibilityLabel": "Customize table column order and visibility"
+ },
"UpdateButtons": {
"cancel": "Cancel",
"update": "Update",
@@ -291,7 +295,6 @@
"rename": "Rename view",
"duplicate": "Duplicate view",
"edit": "Edit view",
- "editColumns": "Edit columns",
"delete": "Delete view",
"copy": "Copy of {name}",
"deleteModal": {
diff --git a/polaris-react/locales/es.json b/polaris-react/locales/es.json
index f2294fa6368..9a5b11ae52b 100644
--- a/polaris-react/locales/es.json
+++ b/polaris-react/locales/es.json
@@ -214,7 +214,6 @@
"rename": "Cambiar nombre de vista",
"duplicate": "Duplicar vista",
"edit": "Editar vista",
- "editColumns": "Editar columnas",
"delete": "Eliminar vista",
"copy": "Copia de {name}",
"deleteModal": {
@@ -390,6 +389,10 @@
"save": "Guardar",
"cancel": "Cancelar"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Editar columnas",
+ "accessibilityLabel": "Personalizar el orden y la visibilidad de las columnas de la tabla"
}
},
"ActionList": {
diff --git a/polaris-react/locales/fi.json b/polaris-react/locales/fi.json
index bcdd010fdbb..c26e3c61751 100644
--- a/polaris-react/locales/fi.json
+++ b/polaris-react/locales/fi.json
@@ -214,7 +214,6 @@
"rename": "Nimeä näkymä uudelleen",
"duplicate": "Kopioi näkymä",
"edit": "Muokkaa näkymää",
- "editColumns": "Muokkaa sarakkeita",
"delete": "Poista näkymä",
"copy": "Kopio tiedostosta {name}",
"deleteModal": {
@@ -389,7 +388,11 @@
"cancel": "Peruuta"
}
},
- "searchFilterTooltipWithShortcut": "Hae ja suodata (F)"
+ "searchFilterTooltipWithShortcut": "Hae ja suodata (F)",
+ "EditColumnsButton": {
+ "tooltip": "Muokkaa sarakkeita",
+ "accessibilityLabel": "Muokkaa taulukon sarakkeiden järjestystä ja näkyvyyttä"
+ }
},
"ActionList": {
"SearchField": {
diff --git a/polaris-react/locales/fr.json b/polaris-react/locales/fr.json
index 3fb24bdb206..7c8e7ee6c81 100644
--- a/polaris-react/locales/fr.json
+++ b/polaris-react/locales/fr.json
@@ -214,7 +214,6 @@
"rename": "Renommer la vue",
"duplicate": "Dupliquer la vue",
"edit": "Modifier la vue",
- "editColumns": "Modifier les colonnes",
"delete": "Supprimer la vue",
"copy": "Copie de {name}",
"deleteModal": {
@@ -390,6 +389,10 @@
"save": "Enregistrer",
"cancel": "Annuler"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Modifier les colonnes",
+ "accessibilityLabel": "Personnaliser l’ordre et la visibilité des colonnes du tableau"
}
},
"ActionList": {
diff --git a/polaris-react/locales/it.json b/polaris-react/locales/it.json
index 5d2271b9fa6..b7fb6853b69 100644
--- a/polaris-react/locales/it.json
+++ b/polaris-react/locales/it.json
@@ -214,7 +214,6 @@
"rename": "Rinomina vista",
"duplicate": "Duplica vista",
"edit": "Modifica vista",
- "editColumns": "Modifica colonne",
"delete": "Elimina vista",
"copy": "Copia di {name}",
"deleteModal": {
@@ -390,6 +389,10 @@
"save": "Salva",
"cancel": "Annulla"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Modifica colonne",
+ "accessibilityLabel": "Personalizza l'ordine e la visibilità delle colonne della tabella"
}
},
"ActionList": {
diff --git a/polaris-react/locales/ja.json b/polaris-react/locales/ja.json
index 49b90ad07a4..7299f1d11f8 100644
--- a/polaris-react/locales/ja.json
+++ b/polaris-react/locales/ja.json
@@ -214,7 +214,6 @@
"rename": "ビューの名前を変更",
"duplicate": "ビューを複製",
"edit": "ビューを編集",
- "editColumns": "列を編集",
"delete": "ビューを削除",
"copy": "{name}のコピー",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "保存",
"cancel": "キャンセル"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "列を編集",
+ "accessibilityLabel": "表の列の順序および表示をカスタマイズする"
}
},
"ActionList": {
diff --git a/polaris-react/locales/ko.json b/polaris-react/locales/ko.json
index 23912856465..f6f1d817849 100644
--- a/polaris-react/locales/ko.json
+++ b/polaris-react/locales/ko.json
@@ -214,7 +214,6 @@
"rename": "보기 이름 바꾸기",
"duplicate": "보기 복제",
"edit": "보기 편집",
- "editColumns": "열 편집",
"delete": "보기 삭제",
"copy": "{name}의 사본",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "저장",
"cancel": "취소"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "열 편집",
+ "accessibilityLabel": "표의 주문 열 및 표시 방법 사용자 지정"
}
},
"ActionList": {
diff --git a/polaris-react/locales/nb.json b/polaris-react/locales/nb.json
index 8596d73d578..03908de8c90 100644
--- a/polaris-react/locales/nb.json
+++ b/polaris-react/locales/nb.json
@@ -214,7 +214,6 @@
"rename": "Gi visning nytt navn",
"duplicate": "Dupliser visning",
"edit": "Rediger visning",
- "editColumns": "Rediger kolonner",
"delete": "Slett visning",
"copy": "Kopi av {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Lagre",
"cancel": "Avbryt"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Endre kolonner",
+ "accessibilityLabel": "Tilpass kolonnerekkefølge og -synlighet i tabellen"
}
},
"ActionList": {
diff --git a/polaris-react/locales/nl.json b/polaris-react/locales/nl.json
index 2232bf5af5b..ba933543236 100644
--- a/polaris-react/locales/nl.json
+++ b/polaris-react/locales/nl.json
@@ -214,7 +214,6 @@
"rename": "Naam van weergave wijzigen",
"duplicate": "Weergave dupliceren",
"edit": "Weergave bewerken",
- "editColumns": "Kolommen bewerken",
"delete": "Weergave verwijderen",
"copy": "Kopie van {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Opslaan",
"cancel": "Annuleren"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Kolommen bewerken",
+ "accessibilityLabel": "Kolomvolgorde en zichtbaarheid van tabel aanpassen"
}
},
"ActionList": {
diff --git a/polaris-react/locales/pl.json b/polaris-react/locales/pl.json
index f5b44fb783e..dc6d6098d74 100644
--- a/polaris-react/locales/pl.json
+++ b/polaris-react/locales/pl.json
@@ -214,7 +214,6 @@
"rename": "Zmień nazwę widoku",
"duplicate": "Duplikuj widok",
"edit": "Edytuj widok",
- "editColumns": "Edytuj kolumny",
"delete": "Usuń widok",
"copy": "Kopia {name}",
"deleteModal": {
@@ -391,6 +390,10 @@
"save": "Zapisz",
"cancel": "Anuluj"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Edytuj kolumny",
+ "accessibilityLabel": "Dostosuj kolejność i widoczność kolumn tabeli"
}
},
"ActionList": {
diff --git a/polaris-react/locales/pt-BR.json b/polaris-react/locales/pt-BR.json
index 2479dcb22d6..0261cdbad43 100644
--- a/polaris-react/locales/pt-BR.json
+++ b/polaris-react/locales/pt-BR.json
@@ -214,7 +214,6 @@
"rename": "Renomear visualização",
"duplicate": "Duplicar visualização",
"edit": "Editar visualização",
- "editColumns": "Editar colunas",
"delete": "Excluir visualização",
"copy": "Cópia de {name}",
"deleteModal": {
@@ -390,6 +389,10 @@
"save": "Salvar",
"cancel": "Cancelar"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Editar colunas",
+ "accessibilityLabel": "Personalizar a ordem e a visibilidade das colunas da tabela"
}
},
"ActionList": {
diff --git a/polaris-react/locales/pt-PT.json b/polaris-react/locales/pt-PT.json
index 6054a65c21b..fe32c16b993 100644
--- a/polaris-react/locales/pt-PT.json
+++ b/polaris-react/locales/pt-PT.json
@@ -214,7 +214,6 @@
"rename": "Renomear visualização",
"duplicate": "Duplicar visualização",
"edit": "Editar visualização",
- "editColumns": "Editar colunas",
"delete": "Eliminar visualização",
"copy": "Cópia de {name}",
"deleteModal": {
@@ -390,6 +389,10 @@
"save": "Guardar",
"cancel": "Cancelar"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Editar colunas",
+ "accessibilityLabel": "Personalizar visibilidade e ordem da coluna da tabela"
}
},
"ActionList": {
diff --git a/polaris-react/locales/sv.json b/polaris-react/locales/sv.json
index 31b04d806f4..f347cb985bb 100644
--- a/polaris-react/locales/sv.json
+++ b/polaris-react/locales/sv.json
@@ -214,7 +214,6 @@
"rename": "Döp om vy",
"duplicate": "Duplicera vy",
"edit": "Redigera vy",
- "editColumns": "Redigera kolumner",
"delete": "Radera vy",
"copy": "Kopia av {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Spara",
"cancel": "Avbryt"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Redigera kolumner",
+ "accessibilityLabel": "Anpassa tabellkolumnernas ordning och synlighet"
}
},
"ActionList": {
diff --git a/polaris-react/locales/th.json b/polaris-react/locales/th.json
index e86ec0e8f1f..dace0a6950f 100644
--- a/polaris-react/locales/th.json
+++ b/polaris-react/locales/th.json
@@ -214,7 +214,6 @@
"rename": "เปลี่ยนชื่อมุมมอง",
"duplicate": "ทำซ้ำมุมมอง",
"edit": "แก้ไขมุมมอง",
- "editColumns": "แก้ไขคอลัมน์",
"delete": "ลบมุมมอง",
"copy": "สำเนาของ {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "บันทึก",
"cancel": "ยกเลิก"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "แก้ไขคอลัมน์",
+ "accessibilityLabel": "ปรับแต่งลำดับและการแสดงผลคอลัมน์ในตาราง"
}
},
"ActionList": {
diff --git a/polaris-react/locales/tr.json b/polaris-react/locales/tr.json
index 4290695aeef..02bc265b773 100644
--- a/polaris-react/locales/tr.json
+++ b/polaris-react/locales/tr.json
@@ -214,7 +214,6 @@
"rename": "Görünümü yeniden adlandır",
"duplicate": "Görünümü çoğalt",
"edit": "Görünümü düzenle",
- "editColumns": "Sütunları düzenle",
"delete": "Görünümü sil",
"copy": "{name} kopyası",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Kaydet",
"cancel": "İptal"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Sütunları düzenleyin",
+ "accessibilityLabel": "Tablonun sütun sırasını ve görünürlüğünü özelleştirin"
}
},
"ActionList": {
diff --git a/polaris-react/locales/vi.json b/polaris-react/locales/vi.json
index 701c8911ac2..283ad465365 100644
--- a/polaris-react/locales/vi.json
+++ b/polaris-react/locales/vi.json
@@ -214,7 +214,6 @@
"rename": "Đổi tên chế độ xem",
"duplicate": "Sao chép chế độ xem",
"edit": "Chỉnh sửa chế độ xem",
- "editColumns": "Sửa cột",
"delete": "Xóa chế độ xem",
"copy": "Bản sao của {name}",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "Lưu",
"cancel": "Hủy"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "Sửa cột",
+ "accessibilityLabel": "Tùy chỉnh thứ tự và khả năng hiển thị của cột trong bảng"
}
},
"ActionList": {
diff --git a/polaris-react/locales/zh-CN.json b/polaris-react/locales/zh-CN.json
index 4c9a640826c..39be4afc9dd 100644
--- a/polaris-react/locales/zh-CN.json
+++ b/polaris-react/locales/zh-CN.json
@@ -214,7 +214,6 @@
"rename": "重命名视图",
"duplicate": "复制视图",
"edit": "编辑视图",
- "editColumns": "编辑列",
"delete": "删除视图",
"copy": "{name} 的副本",
"deleteModal": {
@@ -389,6 +388,10 @@
"save": "保存",
"cancel": "取消"
}
+ },
+ "EditColumnsButton": {
+ "tooltip": "编辑列",
+ "accessibilityLabel": "自定义表列顺序和可见性"
}
},
"ActionList": {
diff --git a/polaris-react/locales/zh-TW.json b/polaris-react/locales/zh-TW.json
index 02b4ad72d08..a119423dd6b 100644
--- a/polaris-react/locales/zh-TW.json
+++ b/polaris-react/locales/zh-TW.json
@@ -214,7 +214,6 @@
"rename": "重新命名檢視畫面",
"duplicate": "複製檢視畫面",
"edit": "編輯檢視畫面",
- "editColumns": "編輯欄",
"delete": "刪除檢視畫面",
"copy": "{name}的副本",
"deleteModal": {
@@ -389,7 +388,11 @@
"cancel": "取消"
}
},
- "searchFilterTooltipWithShortcut": "搜尋和篩選 (F)"
+ "searchFilterTooltipWithShortcut": "搜尋和篩選 (F)",
+ "EditColumnsButton": {
+ "tooltip": "編輯欄",
+ "accessibilityLabel": "自訂表格欄順序和能見度"
+ }
},
"ActionList": {
"SearchField": {
diff --git a/polaris-react/src/components/IndexFilters/IndexFilters.stories.tsx b/polaris-react/src/components/IndexFilters/IndexFilters.stories.tsx
index f30b136577e..ba3d0b4b9cb 100644
--- a/polaris-react/src/components/IndexFilters/IndexFilters.stories.tsx
+++ b/polaris-react/src/components/IndexFilters/IndexFilters.stories.tsx
@@ -403,6 +403,10 @@ export function WithFilteringByDefault() {
return ;
}
+export function WithEditColumsButton() {
+ return ;
+}
+
export function WithoutKeyboardShortcuts() {
return ;
}
@@ -951,6 +955,7 @@ export function Disabled() {
mode={mode}
setMode={setMode}
disabled
+ showEditColumnsButton
/>
diff --git a/polaris-react/src/components/IndexFilters/IndexFilters.tsx b/polaris-react/src/components/IndexFilters/IndexFilters.tsx
index 9aaae0fcbbb..73c0d6e45c0 100644
--- a/polaris-react/src/components/IndexFilters/IndexFilters.tsx
+++ b/polaris-react/src/components/IndexFilters/IndexFilters.tsx
@@ -21,6 +21,7 @@ import {
SortButton,
SearchFilterButton,
UpdateButtons,
+ EditColumnsButton,
} from './components';
import type {
IndexFiltersPrimaryAction,
@@ -48,6 +49,11 @@ const transitionStyles = {
type ExecutedCallback = (name: string) => Promise;
+type ActionableIndexFiltersMode = Exclude<
+ IndexFiltersMode,
+ IndexFiltersMode.Default
+>;
+
export interface IndexFiltersProps
extends Omit<
FiltersProps,
@@ -71,7 +77,7 @@ export interface IndexFiltersProps
/** The cancel action to display */
cancelAction: IndexFiltersCancelAction;
/** Optional callback invoked when a merchant begins to edit a view */
- onEditStart?: () => void;
+ onEditStart?: (mode: ActionableIndexFiltersMode) => void;
/** The current mode of the IndexFilters component. Used to determine which view to show */
mode: IndexFiltersMode;
/** Callback to set the mode of the IndexFilters component */
@@ -96,6 +102,8 @@ export interface IndexFiltersProps
closeOnChildOverlayClick?: boolean;
/** Optional override to the default keyboard shortcuts available */
disableKeyboardShortcuts?: boolean;
+ /** Whether to display the edit columns button with the other default mode filter actions */
+ showEditColumnsButton?: boolean;
}
export function IndexFilters({
@@ -134,6 +142,7 @@ export function IndexFilters({
hideQueryField,
closeOnChildOverlayClick,
disableKeyboardShortcuts,
+ showEditColumnsButton,
}: IndexFiltersProps) {
const i18n = useI18n();
const {mdDown} = useBreakpoints();
@@ -230,10 +239,13 @@ export function IndexFilters({
};
}, [cancelAction, onExecutedCancelAction]);
- const beginEdit = useCallback(() => {
- setMode(IndexFiltersMode.Filtering);
- onEditStart?.();
- }, [onEditStart, setMode]);
+ const beginEdit = useCallback(
+ (mode: ActionableIndexFiltersMode) => {
+ setMode(mode);
+ onEditStart?.(mode);
+ },
+ [onEditStart, setMode],
+ );
const updateButtonsMarkup = useMemo(
() => (
@@ -270,10 +282,21 @@ export function IndexFilters({
disabled,
]);
+ function handleClickEditColumnsButon() {
+ beginEdit(IndexFiltersMode.EditingColumns);
+ }
+
+ const editColumnsMarkup = showEditColumnsButton ? (
+
+ ) : null;
+
const isActionLoading = primaryAction?.loading || cancelAction?.loading;
function handleClickFilterButton() {
- beginEdit();
+ beginEdit(IndexFiltersMode.Filtering);
}
const searchFilterTooltipLabelId = disableKeyboardShortcuts
@@ -310,7 +333,7 @@ export function IndexFilters({
if (mode !== IndexFiltersMode.Default) {
return;
}
- beginEdit();
+ beginEdit(IndexFiltersMode.Filtering);
}
return (
@@ -393,6 +416,7 @@ export function IndexFilters({
}}
/>
)}
+ {editColumnsMarkup}
{sortMarkup}
>
) : null}
diff --git a/polaris-react/src/components/IndexFilters/components/EditColumnsButton/EditColumnsButton.tsx b/polaris-react/src/components/IndexFilters/components/EditColumnsButton/EditColumnsButton.tsx
new file mode 100644
index 00000000000..f531c77a33b
--- /dev/null
+++ b/polaris-react/src/components/IndexFilters/components/EditColumnsButton/EditColumnsButton.tsx
@@ -0,0 +1,40 @@
+import React from 'react';
+import {Columns3Minor} from '@shopify/polaris-icons';
+
+import {useI18n} from '../../../../utilities/i18n';
+import {Button} from '../../../Button';
+import {Tooltip} from '../../../Tooltip';
+import {Text} from '../../../Text';
+
+export interface EditColumnsButtonProps {
+ onClick: () => void;
+ disabled?: boolean;
+}
+
+export function EditColumnsButton({onClick, disabled}: EditColumnsButtonProps) {
+ const i18n = useI18n();
+
+ const tooltipContent = (
+
+ {i18n.translate('Polaris.IndexFilters.EditColumnsButton.tooltip')}
+
+ );
+
+ return (
+
+
+
+ );
+}
diff --git a/polaris-react/src/components/IndexFilters/components/EditColumnsButton/index.ts b/polaris-react/src/components/IndexFilters/components/EditColumnsButton/index.ts
new file mode 100644
index 00000000000..6557d2de83b
--- /dev/null
+++ b/polaris-react/src/components/IndexFilters/components/EditColumnsButton/index.ts
@@ -0,0 +1 @@
+export {EditColumnsButton} from './EditColumnsButton';
diff --git a/polaris-react/src/components/IndexFilters/components/index.ts b/polaris-react/src/components/IndexFilters/components/index.ts
index 6989dec4cce..956db0bf98b 100644
--- a/polaris-react/src/components/IndexFilters/components/index.ts
+++ b/polaris-react/src/components/IndexFilters/components/index.ts
@@ -2,3 +2,4 @@ export {Container} from './Container';
export {SearchFilterButton} from './SearchFilterButton';
export {SortButton} from './SortButton';
export {UpdateButtons} from './UpdateButtons';
+export {EditColumnsButton} from './EditColumnsButton';
diff --git a/polaris-react/src/components/IndexFilters/tests/IndexFilters.test.tsx b/polaris-react/src/components/IndexFilters/tests/IndexFilters.test.tsx
index 1eb9e2b6373..edd5cde4baf 100644
--- a/polaris-react/src/components/IndexFilters/tests/IndexFilters.test.tsx
+++ b/polaris-react/src/components/IndexFilters/tests/IndexFilters.test.tsx
@@ -8,7 +8,12 @@ import {Filters} from '../../Filters';
import {IndexFilters} from '..';
import {IndexFiltersMode} from '../../../utilities/index-filters';
import type {IndexFiltersProps} from '../IndexFilters';
-import {SearchFilterButton, SortButton, UpdateButtons} from '../components';
+import {
+ SearchFilterButton,
+ SortButton,
+ UpdateButtons,
+ EditColumnsButton,
+} from '../components';
describe('IndexFilters', () => {
const defaultProps: IndexFiltersProps = {
@@ -86,6 +91,7 @@ describe('IndexFilters', () => {
setMode: jest.fn(),
canCreateNewView: true,
onCreateNewView: jest.fn(),
+ showEditColumnsButton: false,
};
beforeEach(() => {
@@ -109,6 +115,23 @@ describe('IndexFilters', () => {
expect(setMode).toHaveBeenCalledWith(IndexFiltersMode.Filtering);
});
+ it('calls onEditStart with IndexFiltersMode.Filtering when clicked', () => {
+ const setMode = jest.fn();
+ const onEditStart = jest.fn();
+ const wrapper = mountWithApp(
+ ,
+ );
+ wrapper.act(() => {
+ wrapper.find(SearchFilterButton)!.trigger('onClick');
+ });
+
+ expect(onEditStart).toHaveBeenCalledWith(IndexFiltersMode.Filtering);
+ });
+
it('renders non-disabled tabs if the current mode is Default', () => {
const wrapper = mountWithApp();
@@ -214,6 +237,17 @@ describe('IndexFilters', () => {
expect(wrapper).not.toContainReactComponent(SortButton);
expect(wrapper).not.toContainReactComponent(SearchFilterButton);
});
+
+ it('does not render the EditColumnsButton', () => {
+ const wrapper = mountWithApp(
+ ,
+ );
+
+ expect(wrapper).not.toContainReactComponent(EditColumnsButton);
+ });
});
describe('pressing f', () => {
@@ -234,7 +268,7 @@ describe('IndexFilters', () => {
}),
);
- expect(onEditStart).toHaveBeenCalled();
+ expect(onEditStart).toHaveBeenCalledWith(IndexFiltersMode.Filtering);
});
});
@@ -314,7 +348,7 @@ describe('IndexFilters', () => {
}),
);
- expect(onEditStart).not.toHaveBeenCalled();
+ expect(onEditStart).not.toHaveBeenCalledWith(IndexFiltersMode.Filtering);
});
it('does not call the cancelAction.onAction method when pressing escape in Filtering mode', () => {
@@ -395,5 +429,76 @@ describe('IndexFilters', () => {
disabled: true,
});
});
+
+ it('renders EditColumnsButton with the disabled prop', () => {
+ const wrapper = mountWithApp(
+ ,
+ );
+
+ expect(wrapper).toContainReactComponent(EditColumnsButton, {
+ disabled: true,
+ });
+ });
+ });
+
+ describe('EditColumnsButton', () => {
+ it('renders when showEditColumnsButton is true', () => {
+ const wrapper = mountWithApp(
+ ,
+ );
+
+ expect(wrapper).toContainReactComponent(EditColumnsButton);
+ });
+
+ it('does not renders when showEditColumnsButton is false', () => {
+ const wrapper = mountWithApp(
+ ,
+ );
+
+ expect(wrapper).not.toContainReactComponent(EditColumnsButton);
+ });
+
+ it.each([IndexFiltersMode.EditingColumns, IndexFiltersMode.Filtering])(
+ 'does not renders when IndexFiltersMode is %s',
+ (mode: IndexFiltersMode) => {
+ const wrapper = mountWithApp(
+ ,
+ );
+
+ expect(wrapper).not.toContainReactComponent(EditColumnsButton);
+ },
+ );
+
+ it('sets mode to EditingColumns when clicked', () => {
+ const setMode = jest.fn();
+ const wrapper = mountWithApp(
+ ,
+ );
+ wrapper.act(() => {
+ wrapper.find(EditColumnsButton)!.trigger('onClick');
+ });
+
+ expect(setMode).toHaveBeenCalledWith(IndexFiltersMode.EditingColumns);
+ });
+
+ it('calls onEditStart with IndexFiltersMode.EditingColumns when clicked', () => {
+ const onEditStart = jest.fn();
+ const wrapper = mountWithApp(
+ ,
+ );
+ wrapper.act(() => {
+ wrapper.find(EditColumnsButton)!.trigger('onClick');
+ });
+
+ expect(onEditStart).toHaveBeenCalledWith(IndexFiltersMode.EditingColumns);
+ });
});
});
diff --git a/polaris-react/src/components/Tabs/Tabs.stories.tsx b/polaris-react/src/components/Tabs/Tabs.stories.tsx
index a73c6cbb85a..8cab13664bf 100644
--- a/polaris-react/src/components/Tabs/Tabs.stories.tsx
+++ b/polaris-react/src/components/Tabs/Tabs.stories.tsx
@@ -108,12 +108,7 @@ export function Fitted() {
);
}
-type AlphaTabAction =
- | 'rename'
- | 'edit'
- | 'edit-columns'
- | 'duplicate'
- | 'delete';
+type AlphaTabAction = 'rename' | 'edit' | 'duplicate' | 'delete';
export function WithActions() {
const sleep = (ms: number) =>
diff --git a/polaris-react/src/components/Tabs/components/Tab/Tab.tsx b/polaris-react/src/components/Tabs/components/Tab/Tab.tsx
index b6ef30c4074..e97b7d2edb6 100644
--- a/polaris-react/src/components/Tabs/components/Tab/Tab.tsx
+++ b/polaris-react/src/components/Tabs/components/Tab/Tab.tsx
@@ -14,7 +14,6 @@ import type {
import {
InfoMinor,
DuplicateMinor,
- Columns3Minor,
EditMinor,
DeleteMinor,
ChevronDownMinor,
@@ -221,10 +220,6 @@ export const Tab = forwardRef(
icon: EditMinor,
content: i18n.translate('Polaris.Tabs.Tab.edit'),
},
- 'edit-columns': {
- icon: Columns3Minor,
- content: i18n.translate('Polaris.Tabs.Tab.editColumns'),
- },
delete: {
icon: DeleteMinor,
content: i18n.translate('Polaris.Tabs.Tab.delete'),
diff --git a/polaris-react/src/components/Tabs/components/Tab/tests/Tab.test.tsx b/polaris-react/src/components/Tabs/components/Tab/tests/Tab.test.tsx
index 999ac2128e5..e20b1841e5d 100644
--- a/polaris-react/src/components/Tabs/components/Tab/tests/Tab.test.tsx
+++ b/polaris-react/src/components/Tabs/components/Tab/tests/Tab.test.tsx
@@ -25,11 +25,6 @@ describe('Tab', () => {
onAction: jest.fn(),
onPrimaryAction: jest.fn(),
},
- {
- type: 'edit-columns',
- onAction: jest.fn(),
- onPrimaryAction: jest.fn(),
- },
{
type: 'duplicate',
onAction: jest.fn(),
@@ -160,11 +155,6 @@ describe('Tab', () => {
icon: expect.any(Function),
onAction: expect.any(Function),
},
- {
- content: 'Edit columns',
- icon: expect.any(Function),
- onAction: expect.any(Function),
- },
{
content: 'Duplicate view',
icon: expect.any(Function),
@@ -207,12 +197,6 @@ describe('Tab', () => {
onAction: expect.any(Function),
disabled: true,
},
- {
- content: 'Edit columns',
- icon: expect.any(Function),
- onAction: expect.any(Function),
- disabled: true,
- },
{
content: 'Duplicate view',
icon: expect.any(Function),
@@ -233,7 +217,6 @@ describe('Tab', () => {
it.each([
['rename', 'Rename view'],
['edit', 'Edit view'],
- ['edit-columns', 'Edit columns'],
['duplicate', 'Duplicate view'],
['delete', 'Delete view'],
])(
diff --git a/polaris-react/src/components/Tabs/types.ts b/polaris-react/src/components/Tabs/types.ts
index 08e64ef5e60..865ffcb9d8d 100644
--- a/polaris-react/src/components/Tabs/types.ts
+++ b/polaris-react/src/components/Tabs/types.ts
@@ -2,12 +2,7 @@ import type {ReactNode} from 'react';
import type {ActionListItemDescriptor} from '../../types';
-export type TabAction =
- | 'rename'
- | 'edit'
- | 'edit-columns'
- | 'duplicate'
- | 'delete';
+export type TabAction = 'rename' | 'edit' | 'duplicate' | 'delete';
interface TabActionDescriptor
extends Omit {
diff --git a/polaris.shopify.com/content/components/tables/index-table.md b/polaris.shopify.com/content/components/tables/index-table.md
index 64498ba1e4f..4b1e5842e5d 100644
--- a/polaris.shopify.com/content/components/tables/index-table.md
+++ b/polaris.shopify.com/content/components/tables/index-table.md
@@ -29,10 +29,13 @@ keywords:
examples:
- fileName: index-table-default.tsx
title: Default
- description: A index table with simple items and no bulk actions, sorting, or filtering.
+ description: An index table with simple items and no bulk actions, sorting, or filtering.
- fileName: index-table-with-views-search-filter-sorting.tsx
title: With saved views, search, filtering, and sorting
description: An index table with saved views, search, filtering, sorting, and bulk actions
+ - fileName: index-filters-with-edit-colums-button.tsx
+ title: With edit columns button
+ description: An index table with edit columns, saved views, search, filtering, sorting, and bulk actions
- fileName: index-table-with-disabled-rows.tsx
title: With disabled rows
description: An index table with saved views, search, filtering, sorting, and bulk actions
diff --git a/polaris.shopify.com/pages/examples/index-filters-with-edit-colums-button.tsx b/polaris.shopify.com/pages/examples/index-filters-with-edit-colums-button.tsx
new file mode 100644
index 00000000000..782cb5c6d91
--- /dev/null
+++ b/polaris.shopify.com/pages/examples/index-filters-with-edit-colums-button.tsx
@@ -0,0 +1,400 @@
+import {
+ TextField,
+ IndexTable,
+ LegacyCard,
+ IndexFilters,
+ useSetIndexFiltersMode,
+ useIndexResourceState,
+ Text,
+ ChoiceList,
+ RangeSlider,
+ Badge,
+} from '@shopify/polaris';
+import type {IndexFiltersProps, TabProps} from '@shopify/polaris';
+import {useState, useCallback} from 'react';
+import {withPolarisExample} from '../../src/components/PolarisExampleWrapper';
+
+function IndexFiltersDefaultExample() {
+ const sleep = (ms: number) =>
+ new Promise((resolve) => setTimeout(resolve, ms));
+ const [itemStrings, setItemStrings] = useState([
+ 'All',
+ 'Unpaid',
+ 'Open',
+ 'Closed',
+ 'Local delivery',
+ 'Local pickup',
+ ]);
+ const deleteView = (index: number) => {
+ const newItemStrings = [...itemStrings];
+ newItemStrings.splice(index, 1);
+ setItemStrings(newItemStrings);
+ setSelected(0);
+ };
+
+ const duplicateView = async (name: string) => {
+ setItemStrings([...itemStrings, name]);
+ setSelected(itemStrings.length);
+ await sleep(1);
+ return true;
+ };
+
+ const tabs: TabProps[] = itemStrings.map((item, index) => ({
+ content: item,
+ index,
+ onAction: () => {},
+ id: `${item}-${index}`,
+ isLocked: index === 0,
+ actions:
+ index === 0
+ ? []
+ : [
+ {
+ type: 'rename',
+ onAction: () => {},
+ onPrimaryAction: async (value: string): Promise => {
+ const newItemsStrings = tabs.map((item, idx) => {
+ if (idx === index) {
+ return value;
+ }
+ return item.content;
+ });
+ await sleep(1);
+ setItemStrings(newItemsStrings);
+ return true;
+ },
+ },
+ {
+ type: 'duplicate',
+ onPrimaryAction: async (value: string): Promise => {
+ await sleep(1);
+ duplicateView(value);
+ return true;
+ },
+ },
+ {
+ type: 'edit',
+ },
+ {
+ type: 'delete',
+ onPrimaryAction: async () => {
+ await sleep(1);
+ deleteView(index);
+ return true;
+ },
+ },
+ ],
+ }));
+ const [selected, setSelected] = useState(0);
+ const onCreateNewView = async (value: string) => {
+ await sleep(500);
+ setItemStrings([...itemStrings, value]);
+ setSelected(itemStrings.length);
+ return true;
+ };
+ const sortOptions: IndexFiltersProps['sortOptions'] = [
+ {label: 'Order', value: 'order asc', directionLabel: 'Ascending'},
+ {label: 'Order', value: 'order desc', directionLabel: 'Descending'},
+ {label: 'Customer', value: 'customer asc', directionLabel: 'A-Z'},
+ {label: 'Customer', value: 'customer desc', directionLabel: 'Z-A'},
+ {label: 'Date', value: 'date asc', directionLabel: 'A-Z'},
+ {label: 'Date', value: 'date desc', directionLabel: 'Z-A'},
+ {label: 'Total', value: 'total asc', directionLabel: 'Ascending'},
+ {label: 'Total', value: 'total desc', directionLabel: 'Descending'},
+ ];
+ const [sortSelected, setSortSelected] = useState(['order asc']);
+ const {mode, setMode} = useSetIndexFiltersMode();
+ const onHandleCancel = () => {};
+
+ const onHandleSave = async () => {
+ await sleep(1);
+ return true;
+ };
+
+ const primaryAction: IndexFiltersProps['primaryAction'] =
+ selected === 0
+ ? {
+ type: 'save-as',
+ onAction: onCreateNewView,
+ disabled: false,
+ loading: false,
+ }
+ : {
+ type: 'save',
+ onAction: onHandleSave,
+ disabled: false,
+ loading: false,
+ };
+ const [accountStatus, setAccountStatus] = useState(
+ undefined,
+ );
+ const [moneySpent, setMoneySpent] = useState<[number, number] | undefined>(
+ undefined,
+ );
+ const [taggedWith, setTaggedWith] = useState('');
+ const [queryValue, setQueryValue] = useState('');
+
+ const handleAccountStatusChange = useCallback(
+ (value: string[]) => setAccountStatus(value),
+ [],
+ );
+ const handleMoneySpentChange = useCallback(
+ (value: [number, number]) => setMoneySpent(value),
+ [],
+ );
+ const handleTaggedWithChange = useCallback(
+ (value: string) => setTaggedWith(value),
+ [],
+ );
+ const handleFiltersQueryChange = useCallback(
+ (value: string) => setQueryValue(value),
+ [],
+ );
+ const handleAccountStatusRemove = useCallback(
+ () => setAccountStatus(undefined),
+ [],
+ );
+ const handleMoneySpentRemove = useCallback(
+ () => setMoneySpent(undefined),
+ [],
+ );
+ const handleTaggedWithRemove = useCallback(() => setTaggedWith(''), []);
+ const handleQueryValueRemove = useCallback(() => setQueryValue(''), []);
+ const handleFiltersClearAll = useCallback(() => {
+ handleAccountStatusRemove();
+ handleMoneySpentRemove();
+ handleTaggedWithRemove();
+ handleQueryValueRemove();
+ }, [
+ handleAccountStatusRemove,
+ handleMoneySpentRemove,
+ handleQueryValueRemove,
+ handleTaggedWithRemove,
+ ]);
+
+ const filters = [
+ {
+ key: 'accountStatus',
+ label: 'Account status',
+ filter: (
+
+ ),
+ shortcut: true,
+ },
+ {
+ key: 'taggedWith',
+ label: 'Tagged with',
+ filter: (
+
+ ),
+ shortcut: true,
+ },
+ {
+ key: 'moneySpent',
+ label: 'Money spent',
+ filter: (
+
+ ),
+ },
+ ];
+
+ const appliedFilters: IndexFiltersProps['appliedFilters'] = [];
+ if (accountStatus && !isEmpty(accountStatus)) {
+ const key = 'accountStatus';
+ appliedFilters.push({
+ key,
+ label: disambiguateLabel(key, accountStatus),
+ onRemove: handleAccountStatusRemove,
+ });
+ }
+ if (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,
+ });
+ }
+
+ const orders = [
+ {
+ id: '1020',
+ order: (
+
+ #1020
+
+ ),
+ date: 'Jul 20 at 4:34pm',
+ customer: 'Jaydon Stanton',
+ total: '$969.44',
+ paymentStatus: Paid,
+ fulfillmentStatus: Unfulfilled,
+ },
+ {
+ id: '1019',
+ order: (
+
+ #1019
+
+ ),
+ date: 'Jul 20 at 3:46pm',
+ customer: 'Ruben Westerfelt',
+ total: '$701.19',
+ paymentStatus: Partially paid,
+ fulfillmentStatus: Unfulfilled,
+ },
+ {
+ id: '1018',
+ order: (
+
+ #1018
+
+ ),
+ date: 'Jul 20 at 3.44pm',
+ customer: 'Leo Carder',
+ total: '$798.24',
+ paymentStatus: Paid,
+ fulfillmentStatus: Unfulfilled,
+ },
+ ];
+ const resourceName = {
+ singular: 'order',
+ plural: 'orders',
+ };
+
+ const {selectedResources, allResourcesSelected, handleSelectionChange} =
+ useIndexResourceState(orders);
+
+ const rowMarkup = orders.map(
+ (
+ {id, order, date, customer, total, paymentStatus, fulfillmentStatus},
+ index,
+ ) => (
+
+
+
+ {order}
+
+
+ {date}
+ {customer}
+ {total}
+ {paymentStatus}
+ {fulfillmentStatus}
+
+ ),
+ );
+
+ return (
+
+ {}}
+ onSort={setSortSelected}
+ primaryAction={primaryAction}
+ cancelAction={{
+ onAction: onHandleCancel,
+ disabled: false,
+ loading: false,
+ }}
+ tabs={tabs}
+ selected={selected}
+ onSelect={setSelected}
+ canCreateNewView
+ onCreateNewView={onCreateNewView}
+ filters={filters}
+ appliedFilters={appliedFilters}
+ onClearAll={handleFiltersClearAll}
+ mode={mode}
+ setMode={setMode}
+ showEditColumnsButton
+ />
+
+ {rowMarkup}
+
+
+ );
+
+ function disambiguateLabel(key: string, value: string | any[]): string {
+ switch (key) {
+ case 'moneySpent':
+ return `Money spent is between $${value[0]} and $${value[1]}`;
+ case 'taggedWith':
+ return `Tagged with ${value}`;
+ case 'accountStatus':
+ return (value as string[]).map((val) => `Customer ${val}`).join(', ');
+ default:
+ return value as string;
+ }
+ }
+
+ function isEmpty(value: string | any[]) {
+ if (Array.isArray(value)) {
+ return value.length === 0;
+ } else {
+ return value === '' || value == null;
+ }
+ }
+}
+
+export default withPolarisExample(IndexFiltersDefaultExample);