Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions packages/@react-spectrum/list/src/ListViewItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import {CSSTransition} from 'react-transition-group';
import type {DraggableItemResult} from '@react-aria/dnd';
import {FocusRing, useFocusRing} from '@react-aria/focus';
import {Grid} from '@react-spectrum/layout';
import {isFocusVisible as isGlobalFocusVisible, useHover, usePress} from '@react-aria/interactions';
import ListGripper from '@spectrum-icons/ui/ListGripper';
import listStyles from './styles.css';
import {ListViewContext} from './ListView';
import {mergeProps} from '@react-aria/utils';
import React, {useContext, useRef} from 'react';
import {useButton} from '@react-aria/button';
import {useGridCell, useGridSelectionCheckbox} from '@react-aria/grid';
import {useHover, usePress} from '@react-aria/interactions';
import {useLocale} from '@react-aria/i18n';
import {useVisuallyHidden} from '@react-aria/visually-hidden';

Expand Down Expand Up @@ -131,6 +131,12 @@ export function ListViewItem(props) {
isFlushWithContainerBottom = true;
}
}
// previous item isn't selected
// and the previous item isn't focused or, if it is focused, then if focus globally isn't visible or just focus isn't in the listview
let roundTops = (!state.selectionManager.isSelected(item.prevKey)
&& (state.selectionManager.focusedKey !== item.prevKey || !(isGlobalFocusVisible() && state.selectionManager.isFocused)));
let roundBottoms = (!state.selectionManager.isSelected(item.nextKey)
&& (state.selectionManager.focusedKey !== item.nextKey || !(isGlobalFocusVisible() && state.selectionManager.isFocused)));

return (
<div
Expand All @@ -140,7 +146,11 @@ export function ListViewItem(props) {
listStyles,
'react-spectrum-ListView-row',
{
'focus-ring': isFocusVisible
'focus-ring': isFocusVisible,
'round-tops':
roundTops || (isHovered && !state.selectionManager.isSelected(item.key) && state.selectionManager.focusedKey !== item.key),
'round-bottoms':
roundBottoms || (isHovered && !state.selectionManager.isSelected(item.key) && state.selectionManager.focusedKey !== item.key)
}
)
}
Expand All @@ -157,6 +167,7 @@ export function ListViewItem(props) {
'focus-ring': isFocusVisible,
'is-hovered': isHovered,
'is-selected': isSelected,
'is-prev-selected': state.selectionManager.isSelected(item.prevKey),
'is-next-selected': state.selectionManager.isSelected(item.nextKey),
'react-spectrum-ListViewItem--highlightSelection': state.selectionManager.selectionBehavior === 'replace' && (isSelected || state.selectionManager.isSelected(item.nextKey)),
'react-spectrum-ListViewItem--draggable': isDraggable,
Expand Down
72 changes: 46 additions & 26 deletions packages/@react-spectrum/list/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,6 @@
pointer-events: none;
}

/* Box shadow for bottom border for non-selected rows that is immmediately above a selected row. */
&.is-next-selected {
&:after {
box-shadow: inset 0 -1px 0 0 var(--spectrum-global-color-blue-500);
}
}
Comment on lines -59 to -64
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor note, potentially ignorable:
By simplifying this, a wiggle case has returned:

  1. Go to https://reactspectrum.blob.core.windows.net/reactspectrum/59530d349cab3e68b3c57100957b6659c7effe87/storybook/index.html?path=/story/listview--selection-multiple-checkbox and select the second row.
  2. Repeatedly select and deselect the first row. Note that the border between the two rows wiggles

I'm fine with ignoring it in favor of simpler css, I probably overengineered this css to avoid this wiggle in the first place haha

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I'll have a look at this separately. good find though


&.is-selected {
background-color: var(--spectrum-table-row-background-color-selected);
&.is-hovered,
Expand All @@ -76,18 +69,10 @@

/* Box shadow for left, right, and bottom border for selected rows. */
&:after {
box-shadow: inset 1px 0 0 0 var(--spectrum-global-color-blue-500), inset -1px 0 0 0 var(--spectrum-global-color-blue-500), inset 0 -1px 0 0 var(--spectrum-global-color-blue-500);
}

/* Box shadow for left, right, bottom, and top border for first row when selected (needs 1px top blue border). */
&.react-spectrum-ListViewItem--firstRow {
&:after {
box-shadow: inset 1px 0 0 0 var(--spectrum-global-color-blue-500), inset -1px 0 0 0 var(--spectrum-global-color-blue-500), inset 0 -1px 0 0 var(--spectrum-global-color-blue-500), inset 0 1px 0 0 var(--spectrum-global-color-blue-500);
}
box-shadow: inset 1px 0 0 0 var(--spectrum-global-color-blue-500), inset -1px 0 0 0 var(--spectrum-global-color-blue-500), inset 0 -1px 0 0 var(--spectrum-global-color-blue-500), inset 0 1px 0 0 var(--spectrum-global-color-blue-500);
}

/* Box shadow for left, right, and bottom border for last row when selected (needs 1px bottom blue border). */
&.react-spectrum-ListViewItem--lastRow {
&.is-prev-selected {
&:after {
box-shadow: inset 1px 0 0 0 var(--spectrum-global-color-blue-500), inset -1px 0 0 0 var(--spectrum-global-color-blue-500), inset 0 -1px 0 0 var(--spectrum-global-color-blue-500);
}
Expand All @@ -97,7 +82,7 @@

&:not(.react-spectrum-ListView--quiet) {
.react-spectrum-ListViewItem {
/* Box shadow for bottom border for non-selected rows that aren't immediatly above a selected row (grey border bottom). */
/* Box shadow for bottom border for non-selected rows that aren't immediately above a selected row (grey border bottom). */
/* Also omit bottom border for last row if the total content height of the ListView is equal or greater than the height of the container. This avoids overlapping bottom borders. */
&:not(.is-selected):not(.is-next-selected):not(.react-spectrum-ListViewItem--isFlushBottom) {
&:after {
Expand Down Expand Up @@ -177,10 +162,46 @@
}
}

.react-spectrum-ListView--quiet {
.react-spectrum-ListView.react-spectrum-ListView--quiet {
background-color: var(--spectrum-alias-background-color-transparent);
border-width: 0;
border-radius: 0;

.react-spectrum-ListView-row {
&.round-tops {
&:focus-ring {
&:before {
border-start-start-radius: var(--spectrum-listview-item-border-radius);
}
}
& > .react-spectrum-ListViewItem {
border-start-start-radius: var(--spectrum-listview-item-border-radius);
border-start-end-radius: var(--spectrum-listview-item-border-radius);

&:after {
border-start-start-radius: var(--spectrum-listview-item-border-radius);
border-start-end-radius: var(--spectrum-listview-item-border-radius);
}
}
}

&.round-bottoms {
&:focus-ring {
&:before {
border-end-start-radius: var(--spectrum-listview-item-border-radius);
}
}
& > .react-spectrum-ListViewItem {
border-end-start-radius: var(--spectrum-listview-item-border-radius);
border-end-end-radius: var(--spectrum-listview-item-border-radius);

&:after {
border-end-start-radius: var(--spectrum-listview-item-border-radius);
border-end-end-radius: var(--spectrum-listview-item-border-radius);
}
}
}
}
}

.react-spectrum-ListViewItem {
Expand Down Expand Up @@ -234,8 +255,7 @@
grid-template-rows: 1fr auto;
grid-template-areas:
"draghandle checkbox icon image content actions actionmenu chevron"
"draghandle checkbox icon image description actions actionmenu chevron"
;
"draghandle checkbox icon image description actions actionmenu chevron";
align-items: center;
}

Expand Down Expand Up @@ -275,6 +295,7 @@
.react-spectrum-ListViewItem-checkbox {
min-height: 0;
height: 100%;

> span {
margin: 0;
}
Expand Down Expand Up @@ -345,8 +366,7 @@
.react-spectrum-ListViewItem-grid {
grid-template-areas:
"icon image content . badge"
"icon image description . badge"
;
"icon image description . badge";
grid-template-columns: auto auto auto 1fr;
}

Expand All @@ -358,8 +378,9 @@
border-radius: var(--spectrum-alias-border-radius-regular);
}

&.react-spectrum-ListViewItem-dragPreview--multiple {
&.react-spectrum-ListViewItem-dragPreview--multiple {
position: relative;

&:after {
content: '';
display: block;
Expand All @@ -381,9 +402,8 @@
}
}
}
.react-spectrum-ListView {
.react-spectrum-ListView:not(.react-spectrum-ListView--quiet) {
/* give first and last items border-radius to match listview container */

.react-spectrum-ListViewItem--firstRow.react-spectrum-ListViewItem {
border-start-start-radius: var(--spectrum-listview-item-start-end-border-radius);
border-start-end-radius: var(--spectrum-listview-item-start-end-border-radius);
Expand Down
32 changes: 28 additions & 4 deletions packages/@react-spectrum/list/stories/ListView.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,15 @@ let decorator = (storyFn, context) => {
storyFn() :
(
<>
<label htmlFor="focus-before">Focus before</label>
<input id="focus-before" />
<span style={{paddingInline: '10px'}}>
<label htmlFor="focus-before">Focus before</label>
<input id="focus-before" />
</span>
{storyFn()}
<label htmlFor="focus-after">Focus after</label>
<input id="focus-after" />
<span style={{paddingInline: '10px'}}>
<label htmlFor="focus-after">Focus after</label>
<input id="focus-after" />
</span>
</>
);
};
Expand Down Expand Up @@ -272,6 +276,26 @@ storiesOf('ListView', module)
{item => <Item>{item.name}</Item>}
</ListView>
))
.add('isQuiet, selectionStyle: highlight', () => (
<ListView width="250px" isQuiet selectionMode="single" selectionStyle="highlight">
<Item textValue="Home">Home</Item>
<Item textValue="Apps">Apps</Item>
<Item textValue="Document Cloud">Document Cloud</Item>
<Item textValue="Creative Cloud">Creative Cloud</Item>
<Item textValue="Send & Track">Send & Track</Item>
<Item textValue="Reviews">Reviews</Item>
</ListView>
))
.add('isQuiet, selectionStyle: highlight, multiple', () => (
<ListView width="250px" isQuiet selectionMode="multiple" selectionStyle="highlight">
<Item textValue="Home">Home</Item>
<Item textValue="Apps">Apps</Item>
<Item textValue="Document Cloud">Document Cloud</Item>
<Item textValue="Creative Cloud">Creative Cloud</Item>
<Item textValue="Send & Track">Send & Track</Item>
<Item textValue="Reviews">Reviews</Item>
</ListView>
))
.add('selectionStyle: highlight, onAction', () => (
<ListView width="250px" height={400} onSelectionChange={action('onSelectionChange')} selectionStyle="highlight" selectionMode="multiple" items={items} onAction={action('onAction')}>
{item => <Item>{item.name}</Item>}
Expand Down