Skip to content

Commit c77fcd7

Browse files
authored
Website: Use modal for Site settings form on mobile – mobile Safari l… (#1885)
Replaces the site settings dropdown with a modal that remains open until the user:\ - Clicks outside of the dropdown - Clicks the dropdown toggle button - Presses the Escape key Why? Mobile Safari has a bug where selecting a `<select>` option moves the focus back to `<body>`. Unfortunately, this also closes the `@wordpress/components` dropdowns which react to the `onFocusOutside` callback. ## Alternatives tried * Using a Dropdown with a backdrop layer that closes it on tap. I couldn't get it to work without the same focus issue also affecting it, even after overwriting the `open` property. As it turns out, the `<Dropdown>` component is hardwired to call `onToggle()` both when the `x` is pressed AND when the focus is lost. ## Testing instructions * Open Playground on an iPhone or iPhone simulator * Confirm you can open the site settings form and change selection without closing the form * Confirm that submitting the form closes the modal * Confirm you're still getting the dropdown on desktop
1 parent d4327ea commit c77fcd7

File tree

1 file changed

+61
-26
lines changed
  • packages/playground/website/src/components/browser-chrome

1 file changed

+61
-26
lines changed

packages/playground/website/src/components/browser-chrome/index.tsx

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ import React from 'react';
22
import css from './style.module.css';
33
import AddressBar from '../address-bar';
44
import classNames from 'classnames';
5+
import { useMediaQuery } from '@wordpress/compose';
56
import {
67
useAppSelector,
78
getActiveClientInfo,
89
useActiveSite,
910
useAppDispatch,
1011
} from '../../lib/state/redux/store';
1112
import { SyncLocalFilesButton } from '../sync-local-files-button';
12-
import { Dropdown, Icon } from '@wordpress/components';
13+
import { Dropdown, Icon, Modal } from '@wordpress/components';
1314
import { cog } from '@wordpress/icons';
1415
import Button from '../button';
1516
import { ActiveSiteSettingsForm } from '../site-manager/site-settings-form';
@@ -40,6 +41,10 @@ export default function BrowserChrome({
4041
css.hasFullSizeWindow,
4142
className
4243
);
44+
const isMobileUi = useMediaQuery('(max-width: 875px)');
45+
const [isModalOpen, setIsModalOpen] = React.useState(false);
46+
const onToggle = () => setIsModalOpen(!isModalOpen);
47+
const closeModal = () => setIsModalOpen(false);
4348

4449
return (
4550
<div className={wrapperClass} data-cy="simulated-browser">
@@ -74,16 +79,13 @@ export default function BrowserChrome({
7479
</div>
7580

7681
<div className={css.toolbarButtons}>
77-
<Dropdown
78-
className="my-container-class-name"
79-
contentClassName="my-dropdown-content-classname"
80-
popoverProps={{ placement: 'bottom-start' }}
81-
renderToggle={({ isOpen, onToggle }) => (
82+
{isMobileUi ? (
83+
<>
8284
<Button
8385
variant="browser-chrome"
8486
aria-label="Edit Playground settings"
8587
onClick={onToggle}
86-
aria-expanded={isOpen}
88+
aria-expanded={isModalOpen}
8789
style={{
8890
padding: '0 10px',
8991
fill: '#FFF',
@@ -93,26 +95,59 @@ export default function BrowserChrome({
9395
>
9496
<Icon icon={cog} />
9597
</Button>
96-
)}
97-
renderContent={({ onClose }) => (
98-
<div
99-
style={{
100-
width: 400,
101-
maxWidth: '100vw',
102-
padding: 0,
103-
}}
104-
>
105-
<div className={css.headerSection}>
106-
<h2 style={{ margin: 0 }}>
107-
Playground settings
108-
</h2>
98+
{isModalOpen && (
99+
<Modal
100+
isFullScreen={true}
101+
title="Playground settings"
102+
onRequestClose={closeModal}
103+
>
104+
<ActiveSiteSettingsForm
105+
onSubmit={closeModal}
106+
/>
107+
</Modal>
108+
)}
109+
</>
110+
) : (
111+
<Dropdown
112+
className="my-container-class-name"
113+
contentClassName="my-dropdown-content-classname"
114+
popoverProps={{ placement: 'bottom-start' }}
115+
renderToggle={({ isOpen, onToggle }) => (
116+
<Button
117+
variant="browser-chrome"
118+
aria-label="Edit Playground settings"
119+
onClick={onToggle}
120+
aria-expanded={isOpen}
121+
style={{
122+
padding: '0 10px',
123+
fill: '#FFF',
124+
alignItems: 'center',
125+
display: 'flex',
126+
}}
127+
>
128+
<Icon icon={cog} />
129+
</Button>
130+
)}
131+
renderContent={({ onClose }) => (
132+
<div
133+
style={{
134+
width: 400,
135+
maxWidth: '100vw',
136+
padding: 0,
137+
}}
138+
>
139+
<div className={css.headerSection}>
140+
<h2 style={{ margin: 0 }}>
141+
Playground settings
142+
</h2>
143+
</div>
144+
<ActiveSiteSettingsForm
145+
onSubmit={onClose}
146+
/>
109147
</div>
110-
<ActiveSiteSettingsForm
111-
onSubmit={onClose}
112-
/>
113-
</div>
114-
)}
115-
/>
148+
)}
149+
/>
150+
)}
116151
{activeSite?.metadata?.storage === 'local-fs' ? (
117152
<SyncLocalFilesButton />
118153
) : null}

0 commit comments

Comments
 (0)