diff --git a/UNRELEASED.md b/UNRELEASED.md
index be6f7362a56..a54ef68b532 100644
--- a/UNRELEASED.md
+++ b/UNRELEASED.md
@@ -18,6 +18,7 @@ Use [the changelog guidelines](https://git.io/polaris-changelog-guidelines) to f
- Fixed vertical alignment of Tabs disclosure activator ([#2087](https://github.com/Shopify/polaris-react/pull/2087))
- Fixed `Modal` setting an invalid `id` on `aria-labelledby` when no `title` is set ([#2115](https://github.com/Shopify/polaris-react/pull/2115))
- Fixed error warnings in `Card` and `RollupActions` tests ([#2125](https://github.com/Shopify/polaris-react/pull/2125))
+- Added default accessibility label from `ResourceItem` ([#2097](https://github.com/Shopify/polaris-react/pull/2097))
### Documentation
diff --git a/a11y_shitlist.json b/a11y_shitlist.json
deleted file mode 100644
index b53b472b144..00000000000
--- a/a11y_shitlist.json
+++ /dev/null
@@ -1,98 +0,0 @@
-{
- "all-components-app-provider--with-i18n": [
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay1"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay2"
- }
- ],
- "all-components-app-provider--default": [
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay1"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay2"
- }
- ],
- "all-components-popover--popover-with-lazy-loaded-list": [
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name",
- "context": "",
- "message": "This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.",
- "type": "error",
- "typeCode": 1,
- "selector": "#Popover1 > div > div > ul > li:nth-child(1) > div > button"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name",
- "context": "",
- "message": "This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.",
- "type": "error",
- "typeCode": 1,
- "selector": "#Popover1 > div > div > ul > li:nth-child(2) > div > button"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name",
- "context": "",
- "message": "This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.",
- "type": "error",
- "typeCode": 1,
- "selector": "#Popover1 > div > div > ul > li:nth-child(3) > div > button"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name",
- "context": "",
- "message": "This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.",
- "type": "error",
- "typeCode": 1,
- "selector": "#Popover1 > div > div > ul > li:nth-child(4) > div > button"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.Button.Name",
- "context": "",
- "message": "This button element does not have a name available to an accessibility API. Valid names are: title undefined, element content, aria-label undefined, aria-labelledby undefined.",
- "type": "error",
- "typeCode": 1,
- "selector": "#Popover1 > div > div > ul > li:nth-child(5) > div > button"
- }
- ],
- "all-components-resource-list--resource-list-with-filtering": [
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay1"
- },
- {
- "code": "WCAG2AA.Principle4.Guideline4_1.4_1_2.H91.A.NoContent",
- "context": "",
- "message": "Anchor element found with a valid href attribute, but no link content has been supplied.",
- "type": "error",
- "typeCode": 1,
- "selector": "#ResourceListItemOverlay2"
- }
- ]
-}
diff --git a/locales/de.json b/locales/de.json
index 114639e2308..a2d34fc5a57 100644
--- a/locales/de.json
+++ b/locales/de.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} Produkte",
"Item": {
"actionsDropdownLabel": "Aktionen für {accessibilityLabel}",
- "actionsDropdown": "Dropdown-Liste mit Aktionen"
+ "actionsDropdown": "Dropdown-Liste mit Aktionen",
+ "viewItem": "Details anzeigen für {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Aktionen",
diff --git a/locales/en.json b/locales/en.json
index 74774b6beb6..37cc2dd866d 100644
--- a/locales/en.json
+++ b/locales/en.json
@@ -170,7 +170,8 @@
"Item": {
"actionsDropdownLabel": "Actions for {accessibilityLabel}",
- "actionsDropdown": "Actions dropdown"
+ "actionsDropdown": "Actions dropdown",
+ "viewItem": "View details for {itemName}"
},
"BulkActions": {
diff --git a/locales/es.json b/locales/es.json
index 87fa46c9172..4d11a6b6e86 100644
--- a/locales/es.json
+++ b/locales/es.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} artículos",
"Item": {
"actionsDropdownLabel": "Acciones para {accessibilityLabel}",
- "actionsDropdown": "Menú desplegable de acciones"
+ "actionsDropdown": "Menú desplegable de acciones",
+ "viewItem": "Ver detalles de {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Acciones",
diff --git a/locales/fr.json b/locales/fr.json
index eb448e5692c..1219315a900 100644
--- a/locales/fr.json
+++ b/locales/fr.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} articles",
"Item": {
"actionsDropdownLabel": "Actions pour {accessibilityLabel}",
- "actionsDropdown": "Actions de la liste déroulante"
+ "actionsDropdown": "Actions de la liste déroulante",
+ "viewItem": "Afficher les détails de {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Actions",
diff --git a/locales/hi.json b/locales/hi.json
index 3dbfc7348d2..e2fef7fedf8 100644
--- a/locales/hi.json
+++ b/locales/hi.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} आइटम",
"Item": {
"actionsDropdownLabel": "{accessibilityLabel} के लिए कार्रवाई",
- "actionsDropdown": "कार्रवाई ड्रॉपडाउन"
+ "actionsDropdown": "कार्रवाई ड्रॉपडाउन",
+ "viewItem": "{itemName} के लिए विवरण देखें"
},
"BulkActions": {
"actionsActivatorLabel": "कार्रवाई",
diff --git a/locales/it.json b/locales/it.json
index bdb0293db8b..555526079d7 100644
--- a/locales/it.json
+++ b/locales/it.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} articoli",
"Item": {
"actionsDropdownLabel": "Azioni per {accessibilityLabel}",
- "actionsDropdown": "Menu a tendina delle azioni"
+ "actionsDropdown": "Menu a tendina delle azioni",
+ "viewItem": "Visualizza dettagli di {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Azioni",
diff --git a/locales/ja.json b/locales/ja.json
index 7940dc1e9c8..65ae166b9ad 100644
--- a/locales/ja.json
+++ b/locales/ja.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength}個のアイテム",
"Item": {
"actionsDropdownLabel": "{accessibilityLabel}のアクション",
- "actionsDropdown": "アクションドロップダウン"
+ "actionsDropdown": "アクションドロップダウン",
+ "viewItem": "{itemName}の詳細を表示する"
},
"BulkActions": {
"actionsActivatorLabel": "アクション",
diff --git a/locales/ms.json b/locales/ms.json
index 7ec66f6bccc..620de1e8a48 100644
--- a/locales/ms.json
+++ b/locales/ms.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} item",
"Item": {
"actionsDropdownLabel": "Tindakan untuk {accessibilityLabel}",
- "actionsDropdown": "Juntai bawah tindakan"
+ "actionsDropdown": "Juntai bawah tindakan",
+ "viewItem": "Lihat butiran untuk {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Tindakan",
diff --git a/locales/nl.json b/locales/nl.json
index 235c4f27018..18cd621834f 100644
--- a/locales/nl.json
+++ b/locales/nl.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} artikelen",
"Item": {
"actionsDropdownLabel": "Acties voor {accessibilityLabel}",
- "actionsDropdown": "Vervolgkeuze acties"
+ "actionsDropdown": "Vervolgkeuze acties",
+ "viewItem": "Details weergeven voor {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Acties",
diff --git a/locales/pt-BR.json b/locales/pt-BR.json
index 6d17cd6e7b1..0caaeb954e6 100644
--- a/locales/pt-BR.json
+++ b/locales/pt-BR.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} itens",
"Item": {
"actionsDropdownLabel": "Ações para {accessibilityLabel}",
- "actionsDropdown": "Menu suspenso Ações"
+ "actionsDropdown": "Menu suspenso Ações",
+ "viewItem": "Visualizar detalhes de {itemName}"
},
"BulkActions": {
"actionsActivatorLabel": "Ações",
diff --git a/locales/zh-CN.json b/locales/zh-CN.json
index 7a373fd68c9..059cf3cf998 100644
--- a/locales/zh-CN.json
+++ b/locales/zh-CN.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} 件产品",
"Item": {
"actionsDropdownLabel": "{accessibilityLabel}的操作",
- "actionsDropdown": "操作下拉菜单"
+ "actionsDropdown": "操作下拉菜单",
+ "viewItem": "查看 {itemName} 详细信息"
},
"BulkActions": {
"actionsActivatorLabel": "编辑",
diff --git a/locales/zh-TW.json b/locales/zh-TW.json
index f4c5de1f3fc..53bc1bf81ef 100644
--- a/locales/zh-TW.json
+++ b/locales/zh-TW.json
@@ -150,7 +150,8 @@
"ariaLivePlural": "{itemsLength} 件商品",
"Item": {
"actionsDropdownLabel": "{accessibilityLabel} 的動作",
- "actionsDropdown": "動作下拉式選單"
+ "actionsDropdown": "動作下拉式選單",
+ "viewItem": "檢視 {itemName} 的詳細資訊"
},
"BulkActions": {
"actionsActivatorLabel": "動作",
diff --git a/scripts/pa11y-utilities.js b/scripts/pa11y-utilities.js
deleted file mode 100644
index 0664c24c2ae..00000000000
--- a/scripts/pa11y-utilities.js
+++ /dev/null
@@ -1,45 +0,0 @@
-const hash = require('object-hash');
-
-function shitlistCheck(results, immutableShitlist) {
- const mutableShitlist = {};
- const remainingIssues = [];
- Object.keys(immutableShitlist).forEach((key) => {
- mutableShitlist[key] = Array.from(immutableShitlist[key]);
- });
-
- const filteredResults = results.map((result) => {
- if (mutableShitlist[result.exampleID]) {
- result.issues = result.issues.filter((issue) => {
- const issueHash = hash(issue);
- const matchIndex = mutableShitlist[result.exampleID].findIndex(
- (shitlistedResult) => {
- return hash(shitlistedResult) === issueHash;
- },
- );
- if (matchIndex >= 0) {
- mutableShitlist[result.exampleID].splice(matchIndex, 1);
- }
- return matchIndex === -1;
- });
- }
- return result;
- });
-
- Object.keys(mutableShitlist).forEach((key) => {
- if (mutableShitlist[key].length) {
- remainingIssues.push({
- exampleID: key,
- issues: mutableShitlist[key],
- });
- }
- });
-
- return {
- results: filteredResults.filter((result) => result.issues.length),
- remainingIssues: Object.keys(remainingIssues).length
- ? remainingIssues
- : null,
- };
-}
-
-module.exports.shitlistCheck = shitlistCheck;
diff --git a/scripts/pa11y.js b/scripts/pa11y.js
index 7458c9ae9c2..9b0f6f623d2 100644
--- a/scripts/pa11y.js
+++ b/scripts/pa11y.js
@@ -1,9 +1,6 @@
/* eslint-disable no-console */
const puppeteer = require('puppeteer');
const pa11y = require('pa11y');
-const shitlistCheck = require('./pa11y-utilities.js').shitlistCheck;
-
-const shitlist = require('./../a11y_shitlist.json');
const NUMBER_OF_BROWSERS = 5;
@@ -106,28 +103,7 @@ async function runPa11y() {
process.exit(1);
}
- const {results, remainingIssues} = shitlistCheck(rawResults, shitlist);
-
- if (remainingIssues) {
- console.log(
- `
-========================================================================
-The following items were fixed, and therefore should be removed from the shitlist.
-Please edit the file a11y_shitlist.json to remove them and run these tests again.',
-========================================================================
-`,
- );
- remainingIssues.forEach((issue) => {
- console.log(
- '------------------------------------------------------------------------',
- );
- console.log(issue.exampleID);
- console.log(
- '------------------------------------------------------------------------',
- );
- console.log(JSON.stringify(issue.issues, null, 2));
- });
- }
+ const results = rawResults.filter((result) => result.issues.length);
console.log(
`
@@ -153,7 +129,7 @@ The following issues were discovered and need to be fixed before this code can b
console.log('No issues!');
}
- if (results.length || remainingIssues) {
+ if (results.length) {
process.exit(1);
}
process.exit(0);
diff --git a/src/components/AppProvider/README.md b/src/components/AppProvider/README.md
index 6af878df6a3..0d657cb6761 100644
--- a/src/components/AppProvider/README.md
+++ b/src/components/AppProvider/README.md
@@ -46,6 +46,9 @@ AppProvider works by default without any additional options passed to it.
defaultItemSingular: 'item',
defaultItemPlural: 'items',
showing: 'Showing {itemsCount} {resource}',
+ Item: {
+ viewItem: 'View details for {itemName}',
+ },
},
Common: {
checkbox: 'checkbox',
@@ -106,6 +109,9 @@ With an `i18n`, `AppProvider` will provide these translations to polaris compone
showing: '{itemsCount} {resource} affichés',
defaultItemPlural: 'articles',
defaultItemSingular: 'article',
+ Item: {
+ viewItem: "Afficher les détails de l'{itemName}",
+ },
},
},
}}
diff --git a/src/components/ResourceItem/ResourceItem.tsx b/src/components/ResourceItem/ResourceItem.tsx
index e632d38cf3c..e2422e14f71 100644
--- a/src/components/ResourceItem/ResourceItem.tsx
+++ b/src/components/ResourceItem/ResourceItem.tsx
@@ -137,7 +137,7 @@ class BaseResourceItem extends React.Component {
persistActions = false,
accessibilityLabel,
name,
- context: {selectable, selectMode, loading},
+ context: {selectable, selectMode, loading, resourceName},
i18n,
} = this.props;
@@ -268,10 +268,16 @@ class BaseResourceItem extends React.Component {
const tabIndex = loading ? -1 : 0;
+ const ariaLabel =
+ accessibilityLabel ||
+ i18n.translate('Polaris.ResourceList.Item.viewItem', {
+ itemName: name || (resourceName && resourceName.singular) || '',
+ });
+
const accessibleMarkup = url ? (
{
) : (
', () => {
expect(item.find(Checkbox).prop('label')).toBe(expectedLabel);
});
+ it('is used on for the aria-label attribute if an `accessibilityLabel` is not provided', () => {
+ const item = mountWithAppProvider(
+
+
+ ,
+ );
+
+ const expectedLabel = `View details for ${name}`;
+
+ expect(item.find(UnstyledLink).prop('aria-label')).toBe(expectedLabel);
+ });
+
it('is used on the disclosure action menu when there are persistent actions', () => {
const item = mountWithAppProvider(
@@ -133,6 +145,20 @@ describe('', () => {
});
});
+ describe('ResourceName.singular', () => {
+ it('is used on for the aria-label attribute if a `name` and `accessibilityLabel` is not provided', () => {
+ const item = mountWithAppProvider(
+
+
+ ,
+ );
+
+ const expectedLabel = `View details for ${mockDefaultContext.resourceName.singular}`;
+
+ expect(item.find(UnstyledLink).prop('aria-label')).toBe(expectedLabel);
+ });
+ });
+
describe('url', () => {
it('does not render an by default', () => {
const element = mountWithAppProvider(
diff --git a/tests/pa11y-utilities.test.js b/tests/pa11y-utilities.test.js
deleted file mode 100644
index 171cd25d967..00000000000
--- a/tests/pa11y-utilities.test.js
+++ /dev/null
@@ -1,76 +0,0 @@
-const shitlistCheck = require('./../scripts/pa11y-utilities.js').shitlistCheck;
-
-describe('shitlistCheck', () => {
- const shitlist = {
- 伊藤美来: [
- {
- code: 'ショッキングブルー',
- },
- ],
- 豊田萌絵: [
- {
- code: 'Pyxis',
- },
- ],
- };
-
- it('filters errors on the shitlist', () => {
- const issueList = [
- {
- exampleID: '伊藤美来',
- issues: [{code: 'ショッキングブルー'}, {code: '風の戦士'}],
- },
- ];
-
- const {results} = shitlistCheck(issueList, shitlist);
-
- expect(
- results[0].issues.findIndex(({code}) => code === 'ショッキングブルー'),
- ).toBe(-1);
- expect(results[0].issues.findIndex(({code}) => code === '風の戦士')).toBe(
- 0,
- );
- expect(results[0].issues).toHaveLength(1);
- });
-
- it('leaves errors not on the shitlist', () => {
- const issueList = [
- {
- exampleID: '伊藤美来',
- issues: [{code: '美来の色探し'}, {code: '風の戦士'}],
- },
- ];
-
- const {results} = shitlistCheck(issueList, shitlist);
-
- expect(results[0].issues).toHaveLength(2);
- });
-
- it('removes entries with no issues from the list', () => {
- const issueList = [
- {
- exampleID: '虹香',
- issues: [],
- },
- ];
-
- const {results} = shitlistCheck(issueList, shitlist);
-
- expect(results).toHaveLength(0);
- });
-
- it('returns a list with errors that werent found', () => {
- const issueList = [
- {
- exampleID: '伊藤美来',
- issues: [{code: 'ショッキングブルー'}],
- },
- ];
-
- const {remainingIssues} = shitlistCheck(issueList, shitlist);
-
- expect(remainingIssues).toHaveLength(1);
- expect(remainingIssues[0].issues).toHaveLength(1);
- expect(remainingIssues[0].issues[0].code).toBe('Pyxis');
- });
-});