Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

S2 CardView and ghost loading #6978

Merged
merged 24 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0468889
Add S2 Illustrations
devongovett Aug 8, 2024
3710152
Fix storybook
devongovett Aug 8, 2024
aa61cba
fix name
devongovett Aug 8, 2024
28f6a86
S2 cards
devongovett Aug 7, 2024
660e768
Add slot contexts to all S2 components
devongovett Aug 9, 2024
20efb05
Merge branch 's2-contexts' of github.com:adobe/react-spectrum into s2…
devongovett Aug 9, 2024
f510229
separate button and menu size in ActionMenu
devongovett Aug 9, 2024
bb848fc
Support illustrations in cards and add auto sizing for action menu an…
devongovett Aug 9, 2024
337a562
Add skeleton loading states
devongovett Aug 13, 2024
e5c307a
Merge branch 'main' of github.com:adobe/react-spectrum into s2-card
devongovett Aug 26, 2024
9ce8efa
Fix merge
devongovett Aug 26, 2024
8ec3f04
Add SkeletonCollection, improve waterfall keyboard navigation, clean up
devongovett Aug 30, 2024
c1487ac
Fixes and cleanup
devongovett Aug 30, 2024
62d17f3
Review comments
devongovett Sep 9, 2024
6a4ee24
Merge branch 'main' into s2-card
devongovett Sep 9, 2024
30f45ef
fix background
devongovett Sep 9, 2024
d28ec8a
Merge branch 's2-card' of github.com:adobe/react-spectrum into s2-card
devongovett Sep 9, 2024
179f36c
Fix RTL keyboard navigation
devongovett Sep 9, 2024
f79182a
Update layout when content size changes might cause scrollbars to app…
devongovett Sep 10, 2024
7f57237
Fix React < 18 tests
devongovett Sep 10, 2024
d412c67
Always update whenever content size changes
devongovett Sep 10, 2024
13d7b64
Add prop docs
devongovett Sep 10, 2024
c3efc31
More cleanup and docs
devongovett Sep 11, 2024
1bff41b
Design updates
devongovett Sep 11, 2024
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
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ module.exports = {
'AsyncIterable': 'readonly',
'FileSystemFileEntry': 'readonly',
'FileSystemDirectoryEntry': 'readonly',
'FileSystemEntry': 'readonly'
'FileSystemEntry': 'readonly',
'globalThis': 'readonly'
},
settings: {
jsdoc: {
Expand Down
20 changes: 8 additions & 12 deletions packages/@react-aria/selection/src/ListKeyboardDelegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,12 +148,10 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
getKeyRightOf(key: Key) {
// This is a temporary solution for CardView until we refactor useSelectableCollection.
// https://github.com/orgs/adobe/projects/19/views/32?pane=issue&itemId=77825042
// @ts-ignore
if (this.layoutDelegate.getKeyRightOf) {
// @ts-ignore
key = this.layoutDelegate.getKeyRightOf(key);
// @ts-ignore
return this.findNextNonDisabled(key, key => this.layoutDelegate.getKeyRightOf(key));
let layoutDelegateMethod = this.direction === 'ltr' ? 'getKeyRightOf' : 'getKeyLeftOf';
if (this.layoutDelegate[layoutDelegateMethod]) {
key = this.layoutDelegate[layoutDelegateMethod](key);
return this.findNextNonDisabled(key, key => this.layoutDelegate[layoutDelegateMethod](key));
}

if (this.layout === 'grid') {
Expand All @@ -170,12 +168,10 @@ export class ListKeyboardDelegate<T> implements KeyboardDelegate {
}

getKeyLeftOf(key: Key) {
// @ts-ignore
if (this.layoutDelegate.getKeyLeftOf) {
// @ts-ignore
key = this.layoutDelegate.getKeyLeftOf(key);
// @ts-ignore
return this.findNextNonDisabled(key, key => this.layoutDelegate.getKeyLeftOf(key));
let layoutDelegateMethod = this.direction === 'ltr' ? 'getKeyLeftOf' : 'getKeyRightOf';
if (this.layoutDelegate[layoutDelegateMethod]) {
key = this.layoutDelegate[layoutDelegateMethod](key);
return this.findNextNonDisabled(key, key => this.layoutDelegate[layoutDelegateMethod](key));
}

if (this.layout === 'grid') {
Expand Down
50 changes: 33 additions & 17 deletions packages/@react-aria/virtualizer/src/ScrollView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -143,12 +143,17 @@ export function useScrollView(props: ScrollViewProps, ref: RefObject<HTMLElement
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

let isUpdatingSize = useRef(false);
let updateSize = useEffectEvent((flush: typeof flushSync) => {
let dom = ref.current;
if (!dom) {
if (!dom && !isUpdatingSize.current) {
return;
}

// Prevent reentrancy when resize observer fires, triggers re-layout that results in
// content size update, causing below layout effect to fire. This avoids infinite loops.
isUpdatingSize.current = true;

let isTestEnv = process.env.NODE_ENV === 'test' && !process.env.VIRT_ON;
let isClientWidthMocked = Object.getOwnPropertyNames(window.HTMLElement.prototype).includes('clientWidth');
let isClientHeightMocked = Object.getOwnPropertyNames(window.HTMLElement.prototype).includes('clientHeight');
Expand Down Expand Up @@ -177,27 +182,38 @@ export function useScrollView(props: ScrollViewProps, ref: RefObject<HTMLElement
});
}
}

isUpdatingSize.current = false;
});

let didUpdateSize = useRef(false);
// Update visible rect when the content size changes, in case scrollbars need to appear or disappear.
let lastContentSize = useRef<Size | null>(null);
useLayoutEffect(() => {
// React doesn't allow flushSync inside effects, so queue a microtask.
// We also need to wait until all refs are set (e.g. when passing a ref down from a parent).
queueMicrotask(() => {
if (!didUpdateSize.current) {
didUpdateSize.current = true;
updateSize(flushSync);
if (!isUpdatingSize.current) {
// Detect when scrollbar state might have changed.
let prevShowX = lastContentSize.current?.width > state.width;
let prevShowY = lastContentSize.current?.height > state.height;
let curShowX = contentSize.width > state.width;
let curShowY = contentSize.height > state.height;

if (lastContentSize.current && prevShowX === curShowX && prevShowY === curShowY) {
return;
}

// React doesn't allow flushSync inside effects, so queue a microtask.
// We also need to wait until all refs are set (e.g. when passing a ref down from a parent).
// If we are in an `act` environment, update immediately without a microtask so you don't need
// to mock timers in tests. In this case, the update is synchronous already.
if (globalThis.IS_REACT_ACT_ENVIRONMENT) {
updateSize(fn => fn());
} else {
queueMicrotask(() => updateSize(flushSync));
}
});
}, [updateSize]);
useEffect(() => {
if (!didUpdateSize.current) {
// If useEffect ran before the above microtask, we are in a synchronous render (e.g. act).
// Update the size here so that you don't need to mock timers in tests.
didUpdateSize.current = true;
updateSize(fn => fn());
}
}, [updateSize]);

lastContentSize.current = contentSize;
});

let onResize = useCallback(() => {
updateSize(flushSync);
}, [updateSize]);
Expand Down