-
Notifications
You must be signed in to change notification settings - Fork 29.8k
/
ModalGallery.tsx
176 lines (162 loc) · 4.44 KB
/
ModalGallery.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
import * as React from 'react';
import {
BrowserRouter as Router,
Switch,
RouteComponentProps,
Route,
Link
} from 'react-router-dom';
// This example shows how to render two different screens
// (or the same screen in a different context) at the same url,
// depending on you got there.
//
// Click the colors and see them full screen, then "visit the
// gallery" and click on the colors. Note the URL and the component
// are the same as before but now we see them inside a modal
// on top of the old screen.
class ModalSwitch extends React.Component<RouteComponentProps> {
// We can pass a location to <Switch/> that will tell it to
// ignore the router's current location and use the location
// prop instead.
//
// We can also use "location state" to tell the app the user
// wants to go to `/images/2` in a modal, rather than as the
// main page, keeping the gallery visible behind it.
//
// Normally, `/images/2` wouldn't match the gallery at `/`.
// So, to get both screens to render, we can save the old
// location and pass it to Switch, so it will think the location
// is still `/` even though its `/images/2`.
previousLocation = this.props.location;
componentWillUpdate(nextProps: RouteComponentProps) {
const { location } = this.props;
// set previousLocation if props.location is not modal
if (
nextProps.history.action !== 'POP' &&
(!location.state || !location.state.modal)
) {
this.previousLocation = this.props.location;
}
}
render() {
const { location } = this.props;
const isModal = !!(
location.state &&
location.state.modal &&
this.previousLocation !== location // not initial render
);
return (
<div>
<Switch location={isModal ? this.previousLocation : location}>
<Route exact path='/' component={Home} />
<Route path='/gallery' component={Gallery} />
<Route path='/img/:id' component={ImageView} />
</Switch>
{isModal ? <Route path='/img/:id' component={Modal} /> : null}
</div>
);
}
}
const IMAGES = [
{ id: 0, title: 'Dark Orchid', color: 'DarkOrchid' },
{ id: 1, title: 'Lime Green', color: 'LimeGreen' },
{ id: 2, title: 'Tomato', color: 'Tomato' },
{ id: 3, title: 'Seven Ate Nine', color: '#789' },
{ id: 4, title: 'Crimson', color: 'Crimson' }
];
const Thumbnail: React.SFC<{ color: string }> = ({ color }) =>
<div style={{
width: 50,
height: 50,
background: color
}} />;
const Image: React.SFC<{ color: string }> = ({ color }) =>
<div style={{
width: '100%',
height: 400,
background: color
}}></div>;
const Home = () => (
<div>
<Link to='/gallery'>Visit the Gallery</Link>
<h2>Featured Images</h2>
<ul>
<li><Link to='/img/2'>Tomato</Link></li>
<li><Link to='/img/4'>Crimson</Link></li>
</ul>
</div>
);
const Gallery = () => (
<div>
{IMAGES.map(i => (
<Link
key={i.id}
to={{
pathname: `/img/${i.id}`,
// this is the trick!
state: { modal: true }
}}
>
<Thumbnail color={i.color} />
<p>{i.title}</p>
</Link>
))}
</div>
);
const ImageView: React.SFC<RouteComponentProps<{ id: string }>> = ({ match }) => {
const image = IMAGES[parseInt(match.params.id, 10)];
if (!image) {
return <div>Image not found</div>;
}
return (
<div>
<h1>{image.title}</h1>
<Image color={image.color} />
</div>
);
};
const Modal: React.SFC<RouteComponentProps<{ id: string }>> = ({ match, history }) => {
const image = IMAGES[parseInt(match.params.id, 10)];
if (!image) {
return null;
}
const back = (e: React.MouseEvent<HTMLElement>) => {
e.stopPropagation();
history.goBack();
};
return (
<div
onClick={back}
style={{
position: 'absolute',
top: 0,
left: 0,
bottom: 0,
right: 0,
background: 'rgba(0, 0, 0, 0.15)'
}}
>
<div className='modal' style={{
position: 'absolute',
background: '#fff',
top: 25,
left: '10%',
right: '10%',
padding: 15,
border: '2px solid #444'
}}>
<h1>{image.title}</h1>
<Image color={image.color} />
<button type='button' onClick={back}>
Close
</button>
</div>
</div>
);
};
const ModalGallery = () => (
<Router>
<Route component={ModalSwitch} />
</Router>
);
export default ModalGallery;