Skip to content

Commit 669c2eb

Browse files
committed
Merge branch 'main' of github.com:adobe/react-spectrum into fix-download
# Conflicts: # packages/dev/s2-docs/src/SearchMenu.tsx
2 parents ee77fca + 31b8bb5 commit 669c2eb

File tree

4 files changed

+283
-102
lines changed

4 files changed

+283
-102
lines changed

packages/@react-spectrum/s2/src/Divider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ interface DividerSpectrumProps {
2929
*/
3030
size?: 'S' | 'M' | 'L',
3131
/**
32-
* How thick the Divider should be.
32+
* The orientation of the Divider.
3333
* @default 'horizontal'
3434
*/
3535
orientation?: 'horizontal' | 'vertical',

packages/dev/s2-docs/pages/s2/Icons.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Layout} from '../../src/Layout';
22
import {InstallCommand} from '../../src/InstallCommand';
33
import {Command} from '../../src/Command';
4-
import {IconCards} from '../../src/IconCards';
4+
import {IconCards} from '../../src/IconSearchView';
55
import {IconColors} from '../../src/IconColors';
66
import {IconSizes} from '../../src/IconSizes';
77
import {InlineAlert, Heading, Content} from '@react-spectrum/s2';

packages/dev/s2-docs/src/IconCards.tsx renamed to packages/dev/s2-docs/src/IconSearchView.tsx

Lines changed: 119 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,17 @@
22
'use client';
33

44
import {Autocomplete, GridLayout, ListBox, ListBoxItem, Size, useFilter, Virtualizer} from 'react-aria-components';
5-
import {Content, Heading, IllustratedMessage, pressScale, SearchField} from '@react-spectrum/s2';
5+
import Close from '@react-spectrum/s2/icons/Close';
6+
import {Content, Heading, IllustratedMessage, pressScale, SearchField, Skeleton, Text} from '@react-spectrum/s2';
67
import {focusRing, iconStyle, style} from '@react-spectrum/s2/style' with {type: 'macro'};
78
import {iconAliases} from './iconAliases.js';
89
// @ts-ignore
910
import icons from '/packages/@react-spectrum/s2/s2wf-icons/*.svg';
1011
// eslint-disable-next-line monorepo/no-internal-import
1112
import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults';
12-
import React, {useCallback, useRef} from 'react';
13+
import React, {useCallback, useMemo, useRef} from 'react';
1314

14-
const iconList = Object.keys(icons).map(name => ({id: name.replace(/^S2_Icon_(.*?)(Size\d+)?_2.*/, '$1'), icon: icons[name].default}));
15+
export const iconList = Object.keys(icons).map(name => ({id: name.replace(/^S2_Icon_(.*?)(Size\d+)?_2.*/, '$1'), icon: icons[name].default}));
1516

1617
const itemStyle = style({
1718
...focusRing(),
@@ -37,7 +38,8 @@ const itemStyle = style({
3738
gap: 4,
3839
alignItems: 'center',
3940
justifyContent: 'center',
40-
paddingX: 4
41+
paddingX: 4,
42+
cursor: 'default'
4143
});
4244

4345
let handleCopyImport = (id: string) => {
@@ -48,6 +50,119 @@ let handleCopyImport = (id: string) => {
4850
});
4951
};
5052

53+
interface IconSearchViewProps {
54+
filteredItems: typeof iconList
55+
}
56+
57+
export function IconSearchView({filteredItems}: IconSearchViewProps) {
58+
return (
59+
<Virtualizer layout={GridLayout} layoutOptions={{minItemSize: new Size(64, 64), maxItemSize: new Size(64, 64), minSpace: new Size(12, 12), preserveAspectRatio: true}}>
60+
<ListBox
61+
onAction={(item) => handleCopyImport(item.toString())}
62+
items={filteredItems}
63+
layout="grid"
64+
className={style({width: '100%', scrollPaddingY: 4})}
65+
renderEmptyState={() => (
66+
<IllustratedMessage styles={style({marginX: 'auto', marginY: 32})}>
67+
<NoSearchResults />
68+
<Heading>No results</Heading>
69+
<Content>Try a different search term.</Content>
70+
</IllustratedMessage>
71+
)}>
72+
{item => <IconItem item={item} />}
73+
</ListBox>
74+
</Virtualizer>
75+
);
76+
}
77+
78+
function IconItem({item}) {
79+
let Icon = item.icon;
80+
let ref = useRef(null);
81+
return (
82+
<ListBoxItem id={item.id} value={item} textValue={item.id} className={itemStyle} ref={ref} style={pressScale(ref)}>
83+
<Icon styles={iconStyle({size: 'XL'})} />
84+
<div
85+
className={style({
86+
maxWidth: '100%',
87+
textOverflow: 'ellipsis',
88+
overflow: 'hidden',
89+
whiteSpace: 'nowrap'
90+
})}>
91+
{item.id}
92+
</div>
93+
</ListBoxItem>
94+
);
95+
}
96+
97+
export function SkeletonIconItem({item}: {item: {id: string}}) {
98+
const PlaceholderIcon = Close;
99+
const ref = useRef(null);
100+
101+
const itemStyle = style({
102+
...focusRing(),
103+
size: 'full',
104+
backgroundColor: {
105+
default: 'gray-50',
106+
isHovered: 'gray-100',
107+
isFocused: 'gray-100',
108+
isSelected: 'neutral'
109+
},
110+
'--iconPrimary': {
111+
type: 'color',
112+
value: {
113+
default: 'neutral',
114+
isSelected: 'gray-25'
115+
}
116+
},
117+
font: 'ui-sm',
118+
borderRadius: 'default',
119+
transition: 'default',
120+
display: 'flex',
121+
flexDirection: 'column',
122+
gap: 4,
123+
alignItems: 'center',
124+
justifyContent: 'center',
125+
paddingX: 4
126+
});
127+
128+
return (
129+
<ListBoxItem
130+
id={item.id}
131+
value={item}
132+
textValue="skeleton"
133+
className={itemStyle}
134+
ref={ref}>
135+
<PlaceholderIcon styles={iconStyle({size: 'XL'})} />
136+
<div
137+
className={style({
138+
maxWidth: '100%',
139+
textOverflow: 'ellipsis',
140+
overflow: 'hidden',
141+
whiteSpace: 'nowrap'
142+
})}>
143+
<Text styles={style({font: 'ui-sm'})}>Name</Text>
144+
</div>
145+
</ListBoxItem>
146+
);
147+
}
148+
149+
export function IconSearchSkeleton() {
150+
const mockItems = useMemo(() => Array.from({length: 140}, (_, i) => ({id: `skeleton-${i}`})), []);
151+
152+
return (
153+
<Skeleton isLoading>
154+
<Virtualizer layout={GridLayout} layoutOptions={{minItemSize: new Size(64, 64), maxItemSize: new Size(64, 64), minSpace: new Size(12, 12), preserveAspectRatio: true}}>
155+
<ListBox
156+
items={mockItems}
157+
layout="grid"
158+
className={style({width: '100%', scrollPaddingY: 4})}>
159+
{(item) => <SkeletonIconItem item={item} />}
160+
</ListBox>
161+
</Virtualizer>
162+
</Skeleton>
163+
);
164+
}
165+
51166
export function IconCards() {
52167
let {contains} = useFilter({sensitivity: 'base'});
53168
let filter = useCallback((textValue, inputValue) => {
@@ -84,22 +199,3 @@ export function IconCards() {
84199
</Autocomplete>
85200
);
86201
}
87-
88-
function IconItem({item}) {
89-
let Icon = item.icon;
90-
let ref = useRef(null);
91-
return (
92-
<ListBoxItem id={item.id} value={item} textValue={item.id} className={itemStyle} ref={ref} style={pressScale(ref)}>
93-
<Icon styles={iconStyle({size: 'XL'})} />
94-
<div
95-
className={style({
96-
maxWidth: '100%',
97-
textOverflow: 'ellipsis',
98-
overflow: 'hidden',
99-
whiteSpace: 'nowrap'
100-
})}>
101-
{item.id}
102-
</div>
103-
</ListBoxItem>
104-
);
105-
}

0 commit comments

Comments
 (0)