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
2 changes: 0 additions & 2 deletions packages/@react-spectrum/s2/exports/ListView.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export {ListView, ListViewContext, ListViewItem} from '../src/ListView';
export {DragPreview} from '../src/DragPreview';
export {Collection} from 'react-aria/Collection';
export type {ListViewProps, ListViewItemProps} from '../src/ListView';
export type {DragPreviewProps} from '../src/DragPreview';
export type {Selection, Key, SelectionMode} from '@react-types/shared';

export {Text} from '../src/Content';
2 changes: 0 additions & 2 deletions packages/@react-spectrum/s2/exports/TableView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export {
EditableCell,
TableFooter
} from '../src/TableView';
export {DragPreview} from '../src/DragPreview';
export {Collection} from 'react-aria/Collection';
export type {
TableViewProps,
Expand All @@ -20,7 +19,6 @@ export type {
ColumnProps,
TableFooterProps
} from '../src/TableView';
export type {DragPreviewProps} from '../src/DragPreview';
export type {
Selection,
Key,
Expand Down
2 changes: 0 additions & 2 deletions packages/@react-spectrum/s2/exports/TreeView.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
export {TreeView, TreeViewItem, TreeViewItemContent, TreeViewLoadMoreItem} from '../src/TreeView';
export {DragPreview} from '../src/DragPreview';
export {Collection} from 'react-aria/Collection';
export type {
TreeViewProps,
TreeViewItemProps,
TreeViewItemContentProps,
TreeViewLoadMoreItemProps
} from '../src/TreeView';
export type {DragPreviewProps} from '../src/DragPreview';
export type {Selection, Key, SelectionMode} from '@react-types/shared';

export {Text} from '../src/Content';
2 changes: 2 additions & 0 deletions packages/@react-spectrum/s2/exports/useDragAndDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export {
isFileDropItem,
isTextDropItem
} from 'react-aria/useDrop';
export {DragPreview} from '../src/DragPreview';
export type {DragAndDropHooks} from 'react-aria-components/useDragAndDrop';
export type {
DirectoryDropItem,
Expand Down Expand Up @@ -32,3 +33,4 @@ export type {
} from '@react-types/shared';
export type {DragAndDropOptions} from '../src/useDragAndDrop';
export type {DragAndDrop} from 'react-aria-components/useDragAndDrop';
export type {DragPreviewProps} from '../src/DragPreview';
19 changes: 17 additions & 2 deletions packages/@react-spectrum/s2/src/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,10 @@ const listView = style<GridListRenderProps & {isQuiet?: boolean; isDropTarget?:
default: 'default',
isQuiet: 'none'
},
borderColor: 'gray-300',
borderColor: {
default: 'gray-300',
forcedColors: 'ButtonBorder'
},
borderWidth: {
default: 1,
isQuiet: 0
Expand Down Expand Up @@ -435,6 +438,11 @@ const listitem = style<
isDisabled: 'disabled',
forcedColors: {
default: 'ButtonText',
isSelected: {
selectionStyle: {
highlight: 'HighlightText'
}
},
isDisabled: 'GrayText'
}
},
Expand Down Expand Up @@ -590,7 +598,14 @@ const listRowBackground = style<
}
}
},
forcedColors: 'transparent',
forcedColors: {
default: 'transparent',
selectionStyle: {
highlight: {
isSelected: 'Highlight'
}
}
},
':is([role="grid"][data-drop-target] *)': rootRowDropStyles,
isDropTarget: rowDropStyles
},
Expand Down
31 changes: 24 additions & 7 deletions packages/@react-spectrum/s2/src/TableView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ const table = style<
default: 'gray-300',
isDropTarget: 'blue-800',
forcedColors: {
default: 'ButtonBorder',
isDropTarget: 'Highlight'
}
},
Expand Down Expand Up @@ -1102,7 +1103,10 @@ function ResizerIndicator({isFocusVisible, isResizing}) {
const tableHeader = style({
height: 'full',
width: 'full',
backgroundColor: 'gray-75',
backgroundColor: {
default: 'gray-75',
forcedColors: 'transparent'
},
// Attempt to prevent 1px area where you can see scrolled cell content between the table outline and the table header
marginTop: '[-1px]',
'--resizerDisplay': {
Expand Down Expand Up @@ -1145,7 +1149,10 @@ const selectAllCheckboxColumn = style({
},
borderBottomWidth: 1,
borderStyle: 'solid',
backgroundColor: 'gray-75'
backgroundColor: {
default: 'gray-75',
forcedColors: 'transparent'
}
});

export interface TableHeaderProps<T> extends Omit<
Expand Down Expand Up @@ -1870,6 +1877,9 @@ const rowBackgroundColor = {
default: 'gray-25',
isQuiet: '--s2-container-bg'
},
forcedColors: {
default: 'Background'
},
isHovered: colorMix('gray-25', 'gray-900', 7), // table-row-hover-color
isPressed: colorMix('gray-25', 'gray-900', 10), // table-row-hover-color
isSelected: {
Expand All @@ -1893,17 +1903,21 @@ const rowBackgroundColor = {
}
},
isInFooter: 'gray-200',
forcedColors: {
default: 'Background'
},
':is([role="grid"][data-drop-target] *)': rootRowDropStyles,
isDropTarget: rowDropStyles
} as const;

const rowTextColor = {
default: baseColor('neutral-subdued'),
isSelected: baseColor('neutral'),
forcedColors: 'ButtonText',
forcedColors: {
default: 'ButtonText',
isSelected: {
selectionStyle: {
highlight: 'HighlightText'
}
}
},
isDisabled: {
default: 'disabled',
forcedColors: 'GrayText'
Expand Down Expand Up @@ -2030,7 +2044,10 @@ const row = style<
borderColor: {
selectionStyle: {
highlight: 'transparent',
checkbox: 'gray-300'
checkbox: {
default: 'gray-300',
forcedColors: 'ButtonBorder'
}
}
},
'--borderColorGray': {
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/react-aria/dnd.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ function DroppableTree() {

Collection components such as [ListBox](ListBox), [Table](Table), [Tree](Tree), and [GridList](GridList) support multiple **drop positions**.

* The `"root"` drop position allows dropping on the collection as a whole.
* The `"root"` drop position allows dropping on the collection as a whole.
* The `"on"` drop position allows dropping on individual collection items, such as a folder within a list.
* The `"before"` and `"after"` drop positions allow the user to insert or move items between other items. This is displayed by rendering a **drop indicator** between items.

Expand Down
4 changes: 2 additions & 2 deletions packages/dev/s2-docs/pages/s2/ListView.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -388,10 +388,10 @@ You can customize the drag preview by passing <TypeLink links={docs.links} type=

```tsx render type="s2"
"use client";
import {ListView, ListViewItem, DragPreview} from '@react-spectrum/s2/ListView';
import {ListView, ListViewItem} from '@react-spectrum/s2/ListView';
import {Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {DragPreview, useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {useListData} from '@react-spectrum/s2/useListData';
import File from '@react-spectrum/s2/icons/File';

Expand Down
4 changes: 2 additions & 2 deletions packages/dev/s2-docs/pages/s2/TableView.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -955,10 +955,10 @@ You can customize the drag preview by passing <TypeLink links={docs.links} type=

```tsx render type="s2"
"use client";
import {TableView, TableHeader, TableBody, Column, Row, Cell, Collection, DragPreview} from '@react-spectrum/s2/TableView';
import {TableView, TableHeader, TableBody, Column, Row, Cell, Collection} from '@react-spectrum/s2/TableView';
import {Text} from '@react-spectrum/s2';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {DragPreview, useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {useTreeData} from '@react-spectrum/s2/useTreeData';
import File from '@react-spectrum/s2/icons/File';
import Folder from '@react-spectrum/s2/icons/Folder';
Expand Down
4 changes: 2 additions & 2 deletions packages/dev/s2-docs/pages/s2/TreeView.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -395,9 +395,9 @@ You can customize the drag preview by passing <TypeLink links={docs.links} type=
```tsx render type="s2"
"use client";
import {Text} from '@react-spectrum/s2';
import {TreeView, TreeViewItem, TreeViewItemContent, DragPreview} from '@react-spectrum/s2/TreeView';
import {TreeView, TreeViewItem, TreeViewItemContent} from '@react-spectrum/s2/TreeView';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {DragPreview, useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {useTreeData} from '@react-spectrum/s2/useTreeData';
import {Collection} from '@react-spectrum/s2';
import Folder from '@react-spectrum/s2/icons/Folder';
Expand Down
6 changes: 2 additions & 4 deletions packages/dev/s2-docs/pages/s2/dnd.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ While dragging, a **drag preview** is displayed under the user's mouse or finger

```tsx render type="s2" files={['packages/dev/s2-docs/pages/s2/PokemonCOMPONENT.tsx']}
"use client";
import {useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {DragPreview} from '@react-spectrum/s2/COMPONENT';
import {DragPreview, useDragAndDrop} from '@react-spectrum/s2/useDragAndDrop';
import {Text} from '@react-spectrum/s2';
import File from '@react-spectrum/s2/icons/File';
import {PokemonCOMPONENT, Pokemon} from './PokemonCOMPONENT';
Expand Down Expand Up @@ -574,9 +573,8 @@ This example puts together many of the examples described above, allowing users

```tsx render type="s2"
"use client";
import {useDragAndDrop, isTextDropItem} from '@react-spectrum/s2/useDragAndDrop';
import {DragPreview, useDragAndDrop, isTextDropItem} from '@react-spectrum/s2/useDragAndDrop';
import {useListData} from '@react-spectrum/s2/useListData';
import {DragPreview} from '@react-spectrum/s2/COMPONENT';
import {Text} from '@react-spectrum/s2';
import File from '@react-spectrum/s2/icons/File';
import {PokemonCOMPONENT, Pokemon, defaultItems} from './PokemonCOMPONENT';
Expand Down
7 changes: 2 additions & 5 deletions packages/dev/s2-docs/skills/react-aria/test-utils-guidance.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ npm install @react-aria/test-utils --save-dev

### Core pattern

External consumers should import from `@react-aria/test-utils`. Tests inside the `packages/` monorepo should import everything from `@react-spectrum/test-utils-internal`, which re-exports `User` and all other test utilities:
```ts
import {act, render, User} from '@react-spectrum/test-utils-internal';
```
External consumers should import from `@react-aria/test-utils`.

Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions.

Expand Down Expand Up @@ -73,7 +70,7 @@ Skip the testers and write manual interactions for the following cases:
Components with draggable handles (Slider, ColorArea, ColorSlider, ColorWheel) need `getBoundingClientRect` mocked so move calculations work:

```ts
import {installMouseEvent} from '@react-spectrum/test-utils';
import {installMouseEvent} from '@react-aria/test-utils';
installMouseEvent();

beforeAll(() => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ npm install @react-spectrum/test-utils --save-dev

### Core pattern

External consumers import from `@react-spectrum/test-utils`. Tests inside the `packages/` monorepo should import everything from `@react-spectrum/test-utils-internal`, which re-exports `User` and all other test utilities:
```ts
import {act, render, User} from '@react-spectrum/test-utils-internal';
```
External consumers import from `@react-spectrum/test-utils`.

Initialize a `User` once per test file. Call `createTester` to get a tester for a specific ARIA pattern, then call tester methods to simulate interactions.

Expand Down
59 changes: 59 additions & 0 deletions packages/react-aria-components/test/Calendar.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ import {
startOfWeek,
today
} from '@internationalized/date';
import {Custom454Calendar} from '@internationalized/date/tests/customCalendarImpl';
import {ListBox, ListBoxItem} from '../src/ListBox';
import {Popover} from '../src/Popover';
import React, {useContext, useState} from 'react';
import {Select, SelectValue} from '../src/Select';
import userEvent from '@testing-library/user-event';

let TestCalendar = ({calendarProps, gridProps, cellProps}) => (
Expand Down Expand Up @@ -717,4 +721,59 @@ describe('Calendar', () => {
);
expect(heading).toHaveTextContent('April 2026');
});

it('should use getFormattableMonth for CalendarHeading with a custom calendar', () => {
let tree = render(
<TestCalendar
calendarProps={{
defaultFocusedValue: new CalendarDate(2022, 2, 3),
createCalendar: () => new Custom454Calendar()
}}
/>
);
let heading = tree.container.querySelector('.react-aria-CalendarHeading');
expect(heading).toHaveTextContent('February 2022');
});

it('should use getFormattableMonth for CalendarMonthPicker with a custom calendar', async () => {
// Jan 30, 2022 (Gregorian) is the first day of fiscal year 2022 in Custom454,
// so the focused date is month 1, day 1
let tree = render(
<Calendar
aria-label="Appointment date"
defaultFocusedValue={new CalendarDate(2022, 1, 30)}
createCalendar={() => new Custom454Calendar()}>
<header>
<Button slot="previous">◀</Button>
<CalendarMonthPicker>
{({items, value, onChange, 'aria-label': ariaLabel}) => (
<Select aria-label={ariaLabel} selectedKey={value} onSelectionChange={onChange}>
<Button>
<SelectValue />
</Button>
<Popover>
<ListBox items={items}>
{item => <ListBoxItem id={item.id}>{item.formatted}</ListBoxItem>}
</ListBox>
</Popover>
</Select>
)}
</CalendarMonthPicker>
<Button slot="next">▶</Button>
</header>
<CalendarGrid>{date => <CalendarCell date={date} />}</CalendarGrid>
</Calendar>
);

let monthPicker = tree.getByLabelText('month');
expect(monthPicker).toHaveTextContent('Feb');
await user.click(monthPicker);
// The Custom454Calendar's fiscal year starts in February, so month 1 should
// display as "Feb" (Gregorian February), not "Jan".
expect(
within(tree.getByRole('listbox'))
.getAllByRole('option')
.map(o => o.textContent)
).toEqual(['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec', 'Jan']);
});
});
7 changes: 6 additions & 1 deletion packages/react-aria/src/calendar/useCalendarHeading.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ export function useCalendarHeading(
);
}

return formatter.format(startDate.toDate(state.timeZone));
// Custom calendars like the 4-5-4 fiscal calendar use getFormattableMonth to map
// their internal month back to the Gregorian month that should be displayed.
let displayDate = startDate.calendar.getFormattableMonth
? startDate.calendar.getFormattableMonth(startDate)
: startDate;
return formatter.format(displayDate.toDate(state.timeZone));
}, [formatter, isDays, startDate, state.timeZone, state.visibleRange.end]);
}
7 changes: 6 additions & 1 deletion packages/react-aria/src/calendar/useCalendarMonthPicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,15 @@ export function useCalendarMonthPicker(
let numMonths = state.focusedDate.calendar.getMonthsInYear(state.focusedDate);
for (let i = 1; i <= numMonths; i++) {
let date = state.focusedDate.set({month: i});
// Calendars like the 4-5-4 fiscal calendar use getFormattableMonth to map
// their internal month back to the Gregorian month that should be displayed.
let displayDate = date.calendar.getFormattableMonth
? date.calendar.getFormattableMonth(date)
: date;
months.push({
id: i,
date,
formatted: formatter.format(date.toDate(state.timeZone))
formatted: formatter.format(displayDate.toDate(state.timeZone))
});
}

Expand Down
Loading