Skip to content

Commit da39150

Browse files
committed
Enhance mobile support: responsive layouts, touch-friendly dividers, and improved accessibility adjustments across examples.
1 parent 1ef5987 commit da39150

6 files changed

Lines changed: 331 additions & 143 deletions

File tree

examples/BasicExample.tsx

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { SplitPane, Pane } from '../src';
33

44
export function BasicExample() {
55
const [direction, setDirection] = useState<'horizontal' | 'vertical'>(
66
'horizontal'
77
);
88

9+
// Default to vertical on mobile for better usability
10+
useEffect(() => {
11+
const isMobile = window.innerWidth <= 768;
12+
if (isMobile) {
13+
setDirection('vertical');
14+
}
15+
}, []);
16+
917
return (
1018
<div className="example-container">
1119
<div className="example-info">
1220
<h2>Basic Split Pane</h2>
1321
<p>
14-
A simple two-pane layout. Click to toggle direction.{' '}
22+
A simple two-pane layout.{' '}
1523
<button
1624
onClick={() =>
1725
setDirection((d) =>
@@ -26,6 +34,7 @@ export function BasicExample() {
2634
borderRadius: '4px',
2735
color: 'white',
2836
cursor: 'pointer',
37+
minHeight: '32px',
2938
}}
3039
>
3140
{direction}
@@ -34,11 +43,11 @@ export function BasicExample() {
3443
</div>
3544
<div className="example-content">
3645
<SplitPane direction={direction}>
37-
<Pane minSize={100} defaultSize="30%">
46+
<Pane minSize={80} defaultSize={direction === 'vertical' ? '40%' : '30%'}>
3847
<div className="pane-content sidebar">
3948
<h2>Sidebar</h2>
4049
<p>
41-
This pane has a minimum size of 100px and starts at 30% width.
50+
Min size: 80px. Drag the divider to resize.
4251
</p>
4352
<div className="file-tree">
4453
<div className="file-tree-item folder">src</div>
@@ -59,29 +68,24 @@ export function BasicExample() {
5968
</div>
6069
</div>
6170
</Pane>
62-
<Pane minSize={200}>
71+
<Pane minSize={100}>
6372
<div className="pane-content editor">
6473
<h2>Main Content</h2>
6574
<p>
66-
Drag the divider to resize. Use arrow keys when focused for
67-
keyboard control.
75+
Use arrow keys when focused for keyboard control.
6876
</p>
6977
<div className="code-block">
7078
<code>
7179
{`import { SplitPane, Pane } from 'react-split-pane';
7280
73-
function App() {
74-
return (
75-
<SplitPane direction="horizontal">
76-
<Pane minSize={100}>
77-
Sidebar
78-
</Pane>
79-
<Pane>
80-
Main Content
81-
</Pane>
82-
</SplitPane>
83-
);
84-
}`}
81+
<SplitPane direction="${direction}">
82+
<Pane minSize={80}>
83+
Sidebar
84+
</Pane>
85+
<Pane>
86+
Main Content
87+
</Pane>
88+
</SplitPane>`}
8589
</code>
8690
</div>
8791
</div>

examples/NestedExample.tsx

Lines changed: 19 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
import React from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { SplitPane, Pane } from '../src';
33

44
export function NestedExample() {
5+
const [isMobile, setIsMobile] = useState(false);
6+
7+
useEffect(() => {
8+
setIsMobile(window.innerWidth <= 768);
9+
}, []);
10+
511
return (
612
<div className="example-container">
713
<div className="example-info">
814
<h2>Nested Split Panes</h2>
915
<p>
10-
Create complex layouts by nesting split panes. This shows a typical
11-
IDE layout.
16+
Create complex layouts by nesting split panes. IDE-style layout.
1217
</p>
1318
</div>
1419
<div className="example-content">
15-
<SplitPane direction="horizontal">
16-
<Pane minSize={150} defaultSize={200}>
20+
<SplitPane direction={isMobile ? 'vertical' : 'horizontal'}>
21+
<Pane minSize={80} defaultSize={isMobile ? '30%' : 200}>
1722
<div className="pane-content sidebar">
1823
<h2>Explorer</h2>
1924
<div className="file-tree">
@@ -42,55 +47,24 @@ export function NestedExample() {
4247
>
4348
Pane.tsx
4449
</div>
45-
<div
46-
className="file-tree-item folder"
47-
style={{ marginLeft: '1rem' }}
48-
>
49-
examples
50-
</div>
51-
<div
52-
className="file-tree-item file"
53-
style={{ marginLeft: '2rem' }}
54-
>
55-
BasicExample.tsx
56-
</div>
57-
<div
58-
className="file-tree-item file"
59-
style={{ marginLeft: '2rem' }}
60-
>
61-
NestedExample.tsx
62-
</div>
63-
<div
64-
className="file-tree-item file"
65-
style={{ marginLeft: '1rem' }}
66-
>
67-
package.json
68-
</div>
69-
<div
70-
className="file-tree-item file"
71-
style={{ marginLeft: '1rem' }}
72-
>
73-
README.md
74-
</div>
7550
</div>
7651
</div>
7752
</Pane>
78-
<Pane>
53+
<Pane minSize={100}>
7954
<SplitPane direction="vertical">
80-
<Pane minSize={100}>
55+
<Pane minSize={60}>
8156
<div className="pane-content editor">
82-
<h2>Editor - SplitPane.tsx</h2>
57+
<h2>Editor</h2>
8358
<div className="code-block">
8459
<code>
85-
{`export function SplitPane(props: SplitPaneProps) {
60+
{`export function SplitPane(props) {
8661
const {
8762
direction = 'horizontal',
88-
resizable = true,
8963
children,
9064
} = props;
9165
9266
return (
93-
<div className={containerClassName}>
67+
<div className={className}>
9468
{renderChildren()}
9569
</div>
9670
);
@@ -99,37 +73,16 @@ export function NestedExample() {
9973
</div>
10074
</div>
10175
</Pane>
102-
<Pane minSize={80} defaultSize={150}>
76+
<Pane minSize={50} defaultSize={isMobile ? 80 : 150}>
10377
<div className="pane-content console">
10478
<h2>Terminal</h2>
105-
<div style={{ marginTop: '0.5rem', fontSize: '0.8rem' }}>
79+
<div style={{ marginTop: '0.5rem', fontSize: '0.75rem' }}>
10680
<div style={{ color: '#50fa7b' }}>$ npm test</div>
10781
<div style={{ color: '#888', marginTop: '0.25rem' }}>
108-
✓ src/utils/calculations.test.ts (14 tests)
109-
</div>
110-
<div style={{ color: '#888' }}>
111-
✓ src/components/SplitPane.test.tsx (6 tests)
82+
✓ 14 tests passed
11283
</div>
11384
<div style={{ color: '#50fa7b', marginTop: '0.25rem' }}>
114-
Tests: 20 passed
115-
</div>
116-
<div
117-
style={{
118-
color: '#888',
119-
marginTop: '0.5rem',
120-
animation: 'blink 1s infinite',
121-
}}
122-
>
123-
$
124-
<span
125-
style={{
126-
display: 'inline-block',
127-
width: '8px',
128-
height: '14px',
129-
background: '#50fa7b',
130-
marginLeft: '4px',
131-
}}
132-
/>
85+
All tests passed
13386
</div>
13487
</div>
13588
</div>

examples/TouchExample.tsx

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,42 @@
1-
import React, { useState } from 'react';
1+
import React, { useState, useEffect } from 'react';
22
import { SplitPane, Pane } from '../src';
33

44
export function TouchExample() {
55
const [resizeSource, setResizeSource] = useState<string | null>(null);
66
const [sizes, setSizes] = useState<number[]>([]);
7+
const [direction, setDirection] = useState<'horizontal' | 'vertical'>('horizontal');
8+
9+
// Use vertical layout on mobile for better touch experience
10+
useEffect(() => {
11+
const isMobile = window.innerWidth <= 768;
12+
if (isMobile) {
13+
setDirection('vertical');
14+
}
15+
}, []);
716

817
return (
918
<div className="example-container">
1019
<div className="example-info">
1120
<h2>Touch Support</h2>
1221
<p>
13-
Full touch support for mobile and tablet devices. Try dragging the
14-
divider with your finger on a touch device.
22+
Full touch support for mobile. Drag the divider with your finger!
1523
</p>
1624
{resizeSource && (
1725
<p className="size-display">
18-
Last resize via:{' '}
19-
<strong className={`source-${resizeSource}`}>{resizeSource}</strong>
26+
Via: <strong className={`source-${resizeSource}`}>{resizeSource}</strong>
2027
{sizes.length > 0 && (
21-
<span>
22-
{' '}
23-
| Sizes: {sizes.map((s) => Math.round(s)).join(' / ')}px
24-
</span>
28+
<span> | {sizes.map((s) => Math.round(s)).join('/')}px</span>
2529
)}
2630
</p>
2731
)}
2832
</div>
2933
<div className="example-content touch-example">
3034
<SplitPane
31-
direction="horizontal"
35+
direction={direction}
3236
onResizeStart={(event) => setResizeSource(event.source)}
3337
onResize={(newSizes) => setSizes(newSizes)}
3438
>
35-
<Pane minSize={80} defaultSize="40%">
39+
<Pane minSize={60} defaultSize="40%">
3640
<div className="pane-content touch-pane">
3741
<h2>Touch Here</h2>
3842
<div className="touch-instructions">
@@ -50,7 +54,7 @@ export function TouchExample() {
5054
</div>
5155
</div>
5256
</Pane>
53-
<Pane minSize={80}>
57+
<Pane minSize={60}>
5458
<div className="pane-content touch-pane">
5559
<h2>Resize Methods</h2>
5660
<div className="resize-methods">
@@ -72,18 +76,16 @@ export function TouchExample() {
7276
</div>
7377
<div className="code-block">
7478
<code>
75-
{`// Touch events are handled automatically
79+
{`// Touch events handled automatically
7680
<SplitPane
77-
onResizeStart={(event) => {
78-
// event.source: 'mouse' | 'touch' | 'keyboard'
79-
console.log('Resize via:', event.source);
81+
onResizeStart={(e) => {
82+
// e.source: 'mouse' | 'touch' | 'keyboard'
8083
}}
81-
onResize={(sizes, event) => {
82-
console.log('New sizes:', sizes);
84+
onResize={(sizes) => {
85+
console.log('Sizes:', sizes);
8386
}}
8487
>
85-
<Pane>...</Pane>
86-
<Pane>...</Pane>
88+
...
8789
</SplitPane>`}
8890
</code>
8991
</div>

examples/index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, user-scalable=no" />
6+
<meta name="apple-mobile-web-app-capable" content="yes" />
7+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
8+
<meta name="theme-color" content="#1a1a2e" />
69
<title>React Split Pane Examples</title>
710
</head>
811
<body>

examples/main.tsx

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,34 @@ import './styles.css';
1010

1111
type Example = 'basic' | 'nested' | 'controlled' | 'styled' | 'snap' | 'touch';
1212

13+
const examples: { id: Example; label: string; shortLabel: string }[] = [
14+
{ id: 'basic', label: 'Basic', shortLabel: 'Basic' },
15+
{ id: 'nested', label: 'Nested', shortLabel: 'Nest' },
16+
{ id: 'controlled', label: 'Controlled', shortLabel: 'Ctrl' },
17+
{ id: 'styled', label: 'Styled', shortLabel: 'Style' },
18+
{ id: 'snap', label: 'Snap Points', shortLabel: 'Snap' },
19+
{ id: 'touch', label: 'Touch', shortLabel: 'Touch' },
20+
];
21+
1322
function App() {
14-
const [example, setExample] = useState<Example>('basic');
23+
const [example, setExample] = useState<Example>('touch');
1524

1625
return (
1726
<div className="app">
1827
<nav className="nav">
1928
<h1>React Split Pane</h1>
2029
<div className="nav-buttons">
21-
<button
22-
className={example === 'basic' ? 'active' : ''}
23-
onClick={() => setExample('basic')}
24-
>
25-
Basic
26-
</button>
27-
<button
28-
className={example === 'nested' ? 'active' : ''}
29-
onClick={() => setExample('nested')}
30-
>
31-
Nested
32-
</button>
33-
<button
34-
className={example === 'controlled' ? 'active' : ''}
35-
onClick={() => setExample('controlled')}
36-
>
37-
Controlled
38-
</button>
39-
<button
40-
className={example === 'styled' ? 'active' : ''}
41-
onClick={() => setExample('styled')}
42-
>
43-
Styled
44-
</button>
45-
<button
46-
className={example === 'snap' ? 'active' : ''}
47-
onClick={() => setExample('snap')}
48-
>
49-
Snap Points
50-
</button>
51-
<button
52-
className={example === 'touch' ? 'active' : ''}
53-
onClick={() => setExample('touch')}
54-
>
55-
Touch
56-
</button>
30+
{examples.map(({ id, label, shortLabel }) => (
31+
<button
32+
key={id}
33+
className={example === id ? 'active' : ''}
34+
onClick={() => setExample(id)}
35+
aria-label={label}
36+
>
37+
<span className="label-full">{label}</span>
38+
<span className="label-short">{shortLabel}</span>
39+
</button>
40+
))}
5741
</div>
5842
</nav>
5943

0 commit comments

Comments
 (0)