WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit e128c72

Browse files
committed
flip を個別 demo に移動
1 parent 312cff5 commit e128c72

25 files changed

+7044
-42
lines changed

103/src/App.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
useDismiss,
66
useInteractions,
77
offset,
8-
flip,
98
autoUpdate,
109
FloatingPortal,
1110
} from '@floating-ui/react';
@@ -40,7 +39,6 @@ function App() {
4039
whileElementsMounted: autoUpdate,
4140
middleware: [
4241
offset( 5 ),
43-
flip( { padding: 10 } ),
4442
],
4543
} );
4644

@@ -62,7 +60,7 @@ function App() {
6260
}, [ selectedIndex, options ] );
6361

6462
return (
65-
<>
63+
<div style={{paddingBlock: '50vh'}}>
6664
Basic React App<br />
6765
選択値: { selectedIndex }<br />
6866
<button
@@ -122,7 +120,7 @@ function App() {
122120
</FloatingPortal>
123121
) }
124122
<div>後続のコンテンツ</div>
125-
</>
123+
</div>
126124
);
127125
}
128126

104/src/App.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {
55
useDismiss,
66
useInteractions,
77
offset,
8-
flip,
98
size,
109
autoUpdate,
1110
FloatingPortal,
@@ -42,7 +41,6 @@ function App() {
4241
whileElementsMounted: autoUpdate,
4342
middleware: [
4443
offset( 5 ),
45-
flip( { padding: 10 } ),
4644
size( {
4745
apply( { rects, elements, availableHeight } ) {
4846
Object.assign( elements.floating.style, {

105/src/App.tsx

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { useState, useMemo, useRef } from 'react';
1+
import { useState, useMemo } from 'react';
22
import {
33
useFloating,
44
useClick,
55
useDismiss,
6-
useListNavigation,
76
useInteractions,
87
offset,
98
flip,
@@ -34,7 +33,6 @@ function App() {
3433
];
3534

3635
const [ isOpen, setIsOpen ] = useState< boolean >( false );
37-
const [ activeIndex, setActiveIndex ] = useState< number | null >( null );
3836
const [ selectedIndex, setSelectedIndex ] = useState< number | null >( null );
3937

4038
const { refs, floatingStyles, context } = useFloating< HTMLElement >( {
@@ -57,20 +55,11 @@ function App() {
5755
],
5856
} );
5957

60-
const listRef = useRef< ( HTMLElement | null )[] >( [] );
61-
6258
const click = useClick( context, { event: "mousedown" } );
6359
const dismiss = useDismiss( context );
64-
const listNav = useListNavigation( context, {
65-
listRef,
66-
activeIndex,
67-
selectedIndex,
68-
onNavigate: setActiveIndex,
69-
loop: true,
70-
} );
7160

7261
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [
73-
click, dismiss, listNav
62+
click, dismiss,
7463
] );
7564

7665
const handleSelect = ( index: number ) => {
@@ -114,18 +103,13 @@ function App() {
114103
{ options.map( ( { value, label, thumb }, i ) => (
115104
<button
116105
key={ value }
117-
ref={ ( node ) => {
118-
listRef.current[ i ] = node;
119-
} }
120106
type="button"
121-
tabIndex={ i === activeIndex ? 0 : - 1 }
122107
style={ {
123108
display: "flex",
124109
gap: 8,
125110
width: "100%",
126111
border: 0,
127112
textAlign: "left",
128-
background: i === activeIndex ? "cyan" : "",
129113
} }
130114
{ ...getItemProps( {
131115
onClick() {

105/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react'
44
// https://vitejs.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7-
base: '/2025-floating-ui-react/105/',
7+
base: '/2025-floating-ui-react/104/',
88
})

106/src/App.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
useFloating,
44
useClick,
55
useDismiss,
6-
useRole,
76
useListNavigation,
87
useInteractions,
98
offset,
@@ -69,10 +68,9 @@ function App() {
6968
onNavigate: setActiveIndex,
7069
loop: true,
7170
} );
72-
const role = useRole( context, { role: "listbox" } );
7371

7472
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [
75-
click, dismiss, listNav, role
73+
click, dismiss, listNav
7674
] );
7775

7876
const handleSelect = ( index: number ) => {

106/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react'
44
// https://vitejs.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7-
base: '/2025-floating-ui-react/106/',
7+
base: '/2025-floating-ui-react/105/',
88
})

107/src/App.tsx

Lines changed: 126 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,18 @@
1-
import { useState, useMemo } from 'react';
2-
import { Select } from './Select';
1+
import { useState, useMemo, useRef } from 'react';
2+
import {
3+
useFloating,
4+
useClick,
5+
useDismiss,
6+
useRole,
7+
useListNavigation,
8+
useInteractions,
9+
offset,
10+
flip,
11+
size,
12+
autoUpdate,
13+
FloatingPortal,
14+
FloatingFocusManager,
15+
} from '@floating-ui/react';
316

417
function App() {
518
const options = [
@@ -21,24 +34,125 @@ function App() {
2134
{ value: 'ZA', label: '南アフリカ', thumb: 'https://cdn.jsdelivr.net/npm/[email protected]/flags/4x3/za.svg' },
2235
];
2336

37+
const [ isOpen, setIsOpen ] = useState< boolean >( false );
38+
const [ activeIndex, setActiveIndex ] = useState< number | null >( null );
2439
const [ selectedIndex, setSelectedIndex ] = useState< number | null >( null );
2540

26-
const selectedValue = useMemo( () => {
41+
const { refs, floatingStyles, context } = useFloating< HTMLElement >( {
42+
placement: "bottom-start",
43+
open: isOpen,
44+
onOpenChange: setIsOpen,
45+
whileElementsMounted: autoUpdate,
46+
middleware: [
47+
offset( 5 ),
48+
flip( { padding: 10 } ),
49+
size( {
50+
apply( { rects, elements, availableHeight } ) {
51+
Object.assign( elements.floating.style, {
52+
maxHeight: `${ availableHeight }px`,
53+
minWidth: `${ rects.reference.width }px`,
54+
} );
55+
},
56+
padding: 10,
57+
} ),
58+
],
59+
} );
60+
61+
const listRef = useRef< ( HTMLElement | null )[] >( [] );
62+
63+
const click = useClick( context, { event: "mousedown" } );
64+
const dismiss = useDismiss( context );
65+
const listNav = useListNavigation( context, {
66+
listRef,
67+
activeIndex,
68+
selectedIndex,
69+
onNavigate: setActiveIndex,
70+
loop: true,
71+
} );
72+
const role = useRole( context, { role: "listbox" } );
73+
74+
const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions( [
75+
click, dismiss, listNav, role
76+
] );
77+
78+
const handleSelect = ( index: number ) => {
79+
setSelectedIndex( index );
80+
setIsOpen( false );
81+
};
82+
83+
const selectedLabel = useMemo( () => {
2784
if ( selectedIndex === null ) return null;
28-
return options[ selectedIndex ]?.value ?? null;
85+
return options[ selectedIndex ]?.label ?? null;
2986
}, [ selectedIndex, options ] );
3087

3188
return (
3289
<>
3390
Basic React App<br />
34-
選択値(index): { selectedIndex }<br />
35-
選択値(value): { selectedValue ?? 'なし' }<br />
36-
<Select
37-
label="国を選択"
38-
selectedIndex={ selectedIndex }
39-
options={ options }
40-
onChange={ setSelectedIndex }
41-
/>
91+
選択値: { selectedIndex }<br />
92+
<button
93+
type="button"
94+
ref={ refs.setReference }
95+
aria-label="国を選択"
96+
onClick={ () => refs.domReference.current?.focus() }
97+
{ ...getReferenceProps() }
98+
>
99+
{ selectedLabel ?? "選択してください" }
100+
</button>
101+
102+
{ isOpen && (
103+
<FloatingPortal>
104+
<FloatingFocusManager context={ context } modal={ false }>
105+
<div
106+
ref={ refs.setFloating }
107+
style={ {
108+
...floatingStyles,
109+
overflowY: "auto",
110+
background: "#eee",
111+
minWidth: 100,
112+
borderRadius: 8,
113+
} }
114+
{ ...getFloatingProps() }
115+
>
116+
{ options.map( ( { value, label, thumb }, i ) => (
117+
<button
118+
key={ value }
119+
ref={ ( node ) => {
120+
listRef.current[ i ] = node;
121+
} }
122+
type="button"
123+
tabIndex={ i === activeIndex ? 0 : - 1 }
124+
style={ {
125+
display: "flex",
126+
gap: 8,
127+
width: "100%",
128+
border: 0,
129+
textAlign: "left",
130+
background: i === activeIndex ? "cyan" : "",
131+
} }
132+
{ ...getItemProps( {
133+
onClick() {
134+
handleSelect( i );
135+
},
136+
onKeyDown( event ) {
137+
if (
138+
event.key === "Enter" ||
139+
event.key === " "
140+
) {
141+
event.preventDefault();
142+
handleSelect( i );
143+
}
144+
},
145+
} ) }
146+
>
147+
<img src={ thumb } alt="" width="16" />
148+
{ label }
149+
{ i === selectedIndex && "✅" }
150+
</button>
151+
) ) }
152+
</div>
153+
</FloatingFocusManager>
154+
</FloatingPortal>
155+
) }
42156
<div>後続のコンテンツ</div>
43157
</>
44158
);

107/vite.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react'
44
// https://vitejs.dev/config/
55
export default defineConfig({
66
plugins: [react()],
7-
base: '/2025-floating-ui-react/107/',
7+
base: '/2025-floating-ui-react/106/',
88
})

108/.gitignore

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
*.local
14+
15+
# Editor directories and files
16+
.vscode/*
17+
!.vscode/extensions.json
18+
.idea
19+
.DS_Store
20+
*.suo
21+
*.ntvs*
22+
*.njsproj
23+
*.sln
24+
*.sw?

108/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!doctype html>
2+
<html lang="ja">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Vite + React + TS</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/main.tsx"></script>
12+
</body>
13+
</html>

0 commit comments

Comments
 (0)