Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: adobe/react-spectrum
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: main
Choose a base ref
...
head repository: michayou/react-spectrum
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 5 commits
  • 10 files changed
  • 2 contributors

Commits on Aug 20, 2020

  1. Copy the full SHA
    1275348 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    4df059a View commit details
  3. linted

    michayou committed Aug 20, 2020
    Copy the full SHA
    1fe955b View commit details

Commits on Aug 21, 2020

  1. This decides if it will act like a mobile device based on the screen …

    …width not the window max-width.
    michayou committed Aug 21, 2020
    Copy the full SHA
    8c9139a View commit details
  2. Merge pull request #1 from michayou/picker

    Picker
    michayou authored Aug 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    272ed20 View commit details
4 changes: 2 additions & 2 deletions packages/@react-spectrum/combobox/src/ComboBox.tsx
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
*/

import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium';
import {classNames, unwrapDOMRef, useMediaQuery, useStyleProps} from '@react-spectrum/utils';
import {classNames, unwrapDOMRef, useStyleProps, isMobileDevice} from '@react-spectrum/utils';
import {DismissButton, useOverlayPosition} from '@react-aria/overlays';
import {DOMRefValue, FocusableRefValue} from '@react-types/shared';
import {FieldButton} from '@react-spectrum/button';
@@ -82,7 +82,7 @@ function ComboBox<T extends object>(props: SpectrumComboBoxProps<T>, ref: RefObj
isOpen: state.isOpen
});

let isMobile = useMediaQuery('(max-width: 700px)');
let isMobile = isMobileDevice();

let comboBoxAutoFocus;
// Focus first/last item on menu open if focusStategy is set (done by up/down arrows)
4 changes: 2 additions & 2 deletions packages/@react-spectrum/dialog/src/DialogTrigger.tsx
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ import {OverlayTriggerState, useOverlayTriggerState} from '@react-stately/overla
import {PressResponder} from '@react-aria/interactions';
import React, {Fragment, ReactElement, useRef} from 'react';
import {SpectrumDialogClose, SpectrumDialogProps, SpectrumDialogTriggerProps} from '@react-types/dialog';
import {unwrapDOMRef, useMediaQuery} from '@react-spectrum/utils';
import { unwrapDOMRef, isMobileDevice} from '@react-spectrum/utils';
import {useOverlayPosition, useOverlayTrigger} from '@react-aria/overlays';

function DialogTrigger(props: SpectrumDialogTriggerProps) {
@@ -39,7 +39,7 @@ function DialogTrigger(props: SpectrumDialogTriggerProps) {

// On small devices, show a modal or tray instead of a popover.
// TODO: DNA variable?
let isMobile = useMediaQuery('(max-width: 700px)');
let isMobile = isMobileDevice();
if (isMobile) {
// handle cases where desktop popovers need a close button for the mobile modal view
if (type !== 'modal' && mobileType === 'modal') {
4 changes: 2 additions & 2 deletions packages/@react-spectrum/menu/src/MenuTrigger.tsx
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* governing permissions and limitations under the License.
*/

import {classNames, unwrapDOMRef, useDOMRef, useMediaQuery} from '@react-spectrum/utils';
import { classNames, unwrapDOMRef, useDOMRef, isMobileDevice} from '@react-spectrum/utils';
import {DismissButton, useOverlayPosition} from '@react-aria/overlays';
import {DOMRef, DOMRefValue} from '@react-types/shared';
import {FocusScope} from '@react-aria/focus';
@@ -52,7 +52,7 @@ function MenuTrigger(props: SpectrumMenuTriggerProps, ref: DOMRef<HTMLElement>)
isOpen: state.isOpen
});

let isMobile = useMediaQuery('(max-width: 700px)');
let isMobile = isMobileDevice();
let menuContext = {
...menuProps,
ref: menuRef,
9 changes: 9 additions & 0 deletions packages/@react-spectrum/picker/docs/Picker.mdx
Original file line number Diff line number Diff line change
@@ -397,3 +397,12 @@ function Example() {
);
}
```
### Display Items In
Picker normally chooses whether to display items as a tray or popover. This allows you to override that decision.
```tsx example
<Picker label="Choose frequency" displayItemsIn='tray'>
<Item key="rarely">Rarely</Item>
<Item key="sometimes">Sometimes</Item>
<Item key="always">Always</Item>
</Picker>
```
12 changes: 7 additions & 5 deletions packages/@react-spectrum/picker/src/Picker.tsx
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@

import AlertMedium from '@spectrum-icons/ui/AlertMedium';
import ChevronDownMedium from '@spectrum-icons/ui/ChevronDownMedium';
import {classNames, dimensionValue, SlotProvider, unwrapDOMRef, useDOMRef, useMediaQuery, useStyleProps} from '@react-spectrum/utils';
import { classNames, dimensionValue, SlotProvider, unwrapDOMRef, useDOMRef, isMobileDevice, useStyleProps} from '@react-spectrum/utils';
import {DismissButton, useOverlayPosition} from '@react-aria/overlays';
import {DOMRef, DOMRefValue, FocusableRefValue, LabelPosition} from '@react-types/shared';
import {FieldButton} from '@react-spectrum/button';
@@ -55,7 +55,8 @@ function Picker<T extends object>(props: SpectrumPickerProps<T>, ref: DOMRef<HTM
isRequired,
necessityIndicator,
menuWidth,
name
name,
displayItemsIn
} = props;

let {styleProps} = useStyleProps(props);
@@ -101,7 +102,7 @@ function Picker<T extends object>(props: SpectrumPickerProps<T>, ref: DOMRef<HTM
let isLoadingMore = props.isLoading && state.collection.size > 0;

// On small screen devices, the listbox is rendered in a tray, otherwise a popover.
let isMobile = useMediaQuery('(max-width: 700px)');
let isMobile = isMobileDevice();
let listbox = (
<FocusScope restoreFocus>
<DismissButton onDismiss={() => state.close()} />
@@ -134,9 +135,10 @@ function Picker<T extends object>(props: SpectrumPickerProps<T>, ref: DOMRef<HTM
}, [scale, isMobile, triggerRef, state.selectedKey]);

let overlay;
if (isMobile) {
let useTray = displayItemsIn ? displayItemsIn === 'tray' : isMobile;
if (useTray) {
overlay = (
<Tray isOpen={state.isOpen} onClose={state.close} shouldCloseOnBlur>
<Tray isOpen={state.isOpen} onClose={state.close} shouldCloseOnBlur >
{listbox}
</Tray>
);
25 changes: 23 additions & 2 deletions packages/@react-spectrum/picker/stories/Picker.stories.tsx
Original file line number Diff line number Diff line change
@@ -49,7 +49,6 @@ let withSection = [
]}
];


storiesOf('Picker', module)
.add(
'default',
@@ -476,7 +475,29 @@ storiesOf('Picker', module)
'async loading',
() => (
<AsyncLoadingExample />
)
)
)
.add(
'force tray or popover',
() => (
<div>
<Picker label="Force Tray" onSelectionChange={(action('selectionChange'))} displayItemsIn="tray">
<Item key="One">One</Item>
<Item key="Two">Two</Item>
<Item key="Three">Three</Item>
</Picker>
<Picker label="Force Popup" onSelectionChange={(action('selectionChange'))} displayItemsIn="popover">
<Item key="One">One</Item>
<Item key="Two">Two</Item>
<Item key="Three">Three</Item>
</Picker>
<Picker label="Picker Decides" onSelectionChange={(action('selectionChange'))}>
<Item key="One">One</Item>
<Item key="Two">Two</Item>
<Item key="Three">Three</Item>
</Picker>
</div>
)
);

function AsyncLoadingExample() {
44 changes: 44 additions & 0 deletions packages/@react-spectrum/picker/test/Picker.test.js
Original file line number Diff line number Diff line change
@@ -1722,4 +1722,48 @@ describe('Picker', function () {
expect(document.activeElement).not.toBe(picker);
});
});
describe('force tray or popover', function () {
it('open as tray', function () {
let {getByRole, queryByTestId} = render(
<Provider theme={theme}>
<Picker label="Test" displayItemsIn="tray">
<Item>One</Item>
<Item>Two</Item>
<Item>Three</Item>
</Picker>
</Provider>
);

let picker = getByRole('button');
// make sure to run through mousedown AND mouseup, like would really happen, otherwise a mouseup listener
// sits around until the component is unmounted
act(() => { triggerPress(picker); });
act(() => jest.runAllTimers());

expect(queryByTestId('tray')).toBeVisible();
expect(queryByTestId('popover')).not.toBeInTheDocument();
});

it('open as popover', function () {
let {getByRole, queryByTestId} = render(
<Provider theme={theme}>
<Picker label="Test" displayItemsIn="popover">
<Item>One</Item>
<Item>Two</Item>
<Item>Three</Item>
</Picker>
</Provider>
);

let picker = getByRole('button');
// make sure to run through mousedown AND mouseup, like would really happen, otherwise a mouseup listener
// sits around until the component is unmounted
act(() => { triggerPress(picker); });
act(() => jest.runAllTimers());


expect(queryByTestId('tray')).not.toBeInTheDocument();
expect(queryByTestId('popover')).toBeVisible();
});
});
});
1 change: 1 addition & 0 deletions packages/@react-spectrum/utils/src/index.ts
Original file line number Diff line number Diff line change
@@ -20,4 +20,5 @@ export * from './styleProps';
export * from './Slots';
export * from './useHasChild';
export * from './useResizeObserver';
export * from './isMobileDevice';

17 changes: 17 additions & 0 deletions packages/@react-spectrum/utils/src/isMobileDevice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2020 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

const MOBILE_SCREEN_WIDTH = 700;

export function isMobileDevice(): boolean {
return window?.screen.width <= MOBILE_SCREEN_WIDTH;
}
7 changes: 6 additions & 1 deletion packages/@react-types/select/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -59,5 +59,10 @@ export interface SpectrumPickerProps<T> extends AriaSelectProps<T>, SpectrumLabe
/**
* The name of the Picker input, used when submitting an HTML form.
*/
name?: string
name?: string,
/**
* If set to 'tray', the items will open in a tray. If 'popover', as a popover.
* If not defined, Picker will make its best guess based on window max-width.
*/
displayItemsIn?: 'tray' | 'popover'
}