-
{message}
-
-
- {discardActionMarkup}
- {saveActionMarkup}
-
-
+ const discardActionMarkup = discardAction && (
+
+ );
+
+ const saveActionContent =
+ saveAction && saveAction.content
+ ? saveAction.content
+ : i18n.translate('Polaris.ContextualSaveBar.save');
+
+ const saveActionMarkup = saveAction && (
+
+ );
+
+ const width = getWidth(logo, 104);
+
+ const imageMarkup = logo && (
+
+ );
+
+ const logoMarkup = alignContentFlush ? null : (
+
+ {imageMarkup}
+
+ );
+
+ return (
+
+
+ {logoMarkup}
+
+
{message}
+
+
+ {discardActionMarkup}
+ {saveActionMarkup}
+
- {discardConfirmationModalMarkup}
-
- );
- }
-
- private handleDiscardAction = () => {
- const {discardAction} = this.props;
- if (discardAction && discardAction.onAction) {
- discardAction.onAction();
- }
- this.setState({discardConfirmationModalVisible: false});
- };
-
- private toggleDiscardConfirmationModal = () => {
- this.setState((prevState) => ({
- discardConfirmationModalVisible: !prevState.discardConfirmationModalVisible,
- }));
- };
+
+ {discardConfirmationModalMarkup}
+
+ );
}
-
-// Use named export once withAppProvider is refactored away
-// eslint-disable-next-line import/no-default-export
-export default withAppProvider
()(ContextualSaveBar);
diff --git a/src/components/Frame/components/ContextualSaveBar/index.ts b/src/components/Frame/components/ContextualSaveBar/index.ts
index 4e105cade86..1443ea6b788 100644
--- a/src/components/Frame/components/ContextualSaveBar/index.ts
+++ b/src/components/Frame/components/ContextualSaveBar/index.ts
@@ -1,3 +1 @@
-import ContextualSaveBar from './ContextualSaveBar';
-
-export {ContextualSaveBar};
+export {ContextualSaveBar} from './ContextualSaveBar';
diff --git a/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx b/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx
index 81daf1584f9..6beebf9e359 100644
--- a/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx
+++ b/src/components/Frame/components/ContextualSaveBar/tests/ContextualSaveBar.test.tsx
@@ -1,7 +1,7 @@
import React from 'react';
-import {mountWithAppProvider, trigger} from 'test-utilities/legacy';
+import {act, mountWithAppProvider, trigger} from 'test-utilities/legacy';
import {Button, Image} from 'components';
-import ContextualSaveBar from '../ContextualSaveBar';
+import {ContextualSaveBar} from '../ContextualSaveBar';
import {DiscardConfirmationModal} from '../components';
describe('', () => {
@@ -117,7 +117,9 @@ describe('', () => {
const discardConfirmationModal = contextualSaveBar.find(
DiscardConfirmationModal,
);
- trigger(discardConfirmationModal, 'onCancel');
+ act(() => {
+ trigger(discardConfirmationModal, 'onCancel');
+ });
expect(discardConfirmationModal.prop('open')).toBe(false);
});
@@ -138,7 +140,9 @@ describe('', () => {
DiscardConfirmationModal,
);
- trigger(discardConfirmationModal, 'onDiscard');
+ act(() => {
+ trigger(discardConfirmationModal, 'onDiscard');
+ });
expect(discardAction.onAction).toHaveBeenCalled();
});
diff --git a/src/components/Frame/tests/Frame.test.tsx b/src/components/Frame/tests/Frame.test.tsx
index 31b25e62790..7d725ec115d 100644
--- a/src/components/Frame/tests/Frame.test.tsx
+++ b/src/components/Frame/tests/Frame.test.tsx
@@ -155,6 +155,30 @@ describe('', () => {
expect(mainAnchor.getDOMNode()).toBe(document.activeElement);
});
+ it('sets focus to target element when the skip to content link is clicked', () => {
+ const targetId = 'SkipToContentTarget';
+ const targetRef = React.createRef();
+
+ const skipToContentTarget = (
+ // eslint-disable-next-line jsx-a11y/anchor-is-valid
+
+ );
+
+ const frame = mountWithAppProvider(
+ {skipToContentTarget},
+ );
+
+ const triggerAnchor = frame.find('a').at(0);
+ const targetAnchor = frame.find(`#${targetId}`);
+ trigger(triggerAnchor, 'onFocus');
+ trigger(triggerAnchor, 'onClick');
+
+ expect(triggerAnchor.getDOMNode().getAttribute('href')).toBe(
+ `#${targetId}`,
+ );
+ expect(targetAnchor.getDOMNode()).toBe(document.activeElement);
+ });
+
it('renders with a has nav data attribute when nav is passed', () => {
const navigation = ;
const frame = mountWithAppProvider();
diff --git a/src/components/Link/README.md b/src/components/Link/README.md
index b31a1a05081..878a40b8bc3 100644
--- a/src/components/Link/README.md
+++ b/src/components/Link/README.md
@@ -94,7 +94,9 @@ Use for text links that are the same color as the surrounding text.
```
-Monochrome styles will be applied to links rendered within a `Banner`
+### Monochrome link in a banner
+
+Monochrome styles will be applied to links rendered within a `Banner`.
```jsx
@@ -154,13 +156,27 @@ To provide consistency and clarity:
fulfilling orders
```
-#### Don’t
+
+
+
+
+#### Do
```jsx
+/* Somewhere in the code: */
+fulfilling orders
+
+/* Elsewhere in the code: */
fulfilling orders
```
+#### Don’t
+
```jsx
+/* Somewhere in the code: */
+fulfilling orders
+
+/* Elsewhere in the code: */
order fulfillment section
```
diff --git a/src/components/Modal/Modal.tsx b/src/components/Modal/Modal.tsx
index 539420c1627..e7b4f50a402 100644
--- a/src/components/Modal/Modal.tsx
+++ b/src/components/Modal/Modal.tsx
@@ -283,10 +283,12 @@ class Modal extends React.Component {
/>
);
+ const labelledBy = title ? this.headerId : undefined;
+
dialog = (