Skip to content
Open
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
110 changes: 75 additions & 35 deletions packages/@react-spectrum/s2/src/TableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,15 @@ function CellFocusRing() {
return (
<div
role="presentation"
className={style({...cellFocus, position: 'absolute', inset: 0, pointerEvents: 'none'})({
className={style({
...cellFocus,
position: 'absolute',
top: 'var(--topFocusRing)',
bottom: 0,
insetStart: 0,
insetEnd: 0,
pointerEvents: 'none'
})({
isFocusVisible: true
})}
/>
Expand Down Expand Up @@ -1927,7 +1935,12 @@ const rowTextColor = {

const row = style<
RowRenderProps &
S2TableProps & {isInFooter?: boolean; isNextSelected?: boolean; isPrevSelected?: boolean}
S2TableProps & {
isInFooter?: boolean;
isNextSelected?: boolean;
isPrevSelected?: boolean;
isFirstItem?: boolean;
}
>({
height: 'full',
position: 'relative',
Expand Down Expand Up @@ -2030,20 +2043,18 @@ const row = style<
}
}
},
// When checkbox selection, render the gray divider between rows as a border
borderTopWidth: 0,
borderBottomWidth: {
selectionStyle: {
highlight: 0,
checkbox: 1
}
},
borderBottomWidth: 1,
borderStartWidth: 0,
borderEndWidth: 0,
borderStyle: 'solid',
borderColor: {
selectionStyle: {
highlight: 'transparent',
highlight: {
default: 'gray-300',
isSelected: 'transparent',
isNextSelected: 'transparent'
},
checkbox: {
default: 'gray-300',
forcedColors: 'ButtonBorder'
Expand Down Expand Up @@ -2074,41 +2085,62 @@ const row = style<
isSelected: '--borderColorBlue'
}
},
// When highlight selection, render gray dividers as box shadow
boxShadow: {
selectionStyle: {
highlight: {
default: '[inset 0 -1px 0px var(--borderColorGray)]',
isNextSelected: '[inset 0 0 0 var(--borderColorGray)]'
// TODO: Determine if we want to support gray dividers between selected grouped rows
// isSelected: {
// isNextSelected: '[inset 0 -1px 0px var(--borderColorGray)]'
// }
}
},
forcedColors: {
isFocusVisible: '[inset 0 0 0 2px Highlight]'
'--focusRingColor': {
type: 'outlineColor',
value: {
default: 'focus-ring',
forcedColors: 'Highlight'
}
},
fontWeight: {
default: 'normal',
isInFooter: 'bold'
},
isolation: 'isolate',
forcedColorAdjust: 'none'
forcedColorAdjust: 'none',
'--topFocusRing': {
type: 'top',
value: {
default: '[-1px]',
isFirstItem: 0
}
},
'--topHighlightBorder': {
type: 'top',
value: {
default: 0,
isSelected: '[-1px]',
// Don't overlap focus ring of row above.
isPrevSelected: 0,
isFirstItem: 0,
forcedColors: 0
}
},
'--bottomPosition': {
type: 'bottom',
value: {
selectionStyle: {
checkbox: {
default: '[-1px]',
// Avoid the next row's selected background covering this row's focus ring.
isNextSelected: 0
},
highlight: '[-1px]'
}
}
}
});

// Sticky cells (the drag cell, and the checkbox cell when present) get an inline z-index=2 applied by the virtualizer's layout
// To ensure that the highlight selection border is painted above the stick cells, set z-index to 3
// To ensure that the highlight selection border is painted above the sticky cells, set z-index to 3
const highlightSelectionBorder = css(
`&:before {
content: "";
width: 100%;
height: 100%;
top: var(--topHighlightBorder);
bottom: -1px;
inset-inline: 0;
position: absolute;
inset: 0;
z-index: 3;
box-sizing: border-box;
border-style: solid;
border-color: var(--borderColor);
border-top-width: var(--borderTopWidth);
Expand All @@ -2127,15 +2159,15 @@ const highlightSelectionBorder = css(
const focusIndicator = css(
`&:after {
content: "";
width: 100%;
height: 100%;
top: 0;
z-index: 2;
top: var(--topFocusRing);
bottom: var(--bottomPosition);
z-index: 3;
inset-inline-start: 0;
inset-inline-end: 0;
border-radius: 5px;
position: absolute;
outline-style: solid;
outline-color: var(--borderColorBlue);
outline-color: var(--focusRingColor);
outline-width: 2px;
outline-offset: -2px;
pointer-events: none;
Expand Down Expand Up @@ -2191,6 +2223,7 @@ export const Row = /*#__PURE__*/ (forwardRef as forwardRefType)(function Row<T>(
...tableVisualOptions,
selectionStyle,
isInFooter,
isFirstItem: isFirstItem(renderProps.id, renderProps.state),
isNextSelected: isNextSelected(renderProps.id, renderProps.state),
isPrevSelected: isPrevSelected(renderProps.id, renderProps.state)
}) +
Expand Down Expand Up @@ -2271,3 +2304,10 @@ export function isPrevSelected(id: Key | undefined, state: TableState<unknown>)
let keyBefore = state.collection.getKeyBefore(id);
return keyBefore != null && state.selectionManager.isSelected(keyBefore);
}

function isFirstItem(id: Key | undefined, state: TableState<unknown>) {
if (id == null || !state) {
return false;
}
return state.collection.getFirstKey() === id;
}