@telus-uds/components-community.sticky 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +21 -0
- package/CHANGELOG.json +50 -0
- package/CHANGELOG.md +18 -0
- package/__fixtures__/Theme.jsx +13 -0
- package/__fixtures__/images/mountains_desktop.jpg +0 -0
- package/__fixtures__/images/pigs-allium-lo.png +0 -0
- package/__fixtures__/testTheme.js +335 -0
- package/__tests__/Sticky.test.jsx +66 -0
- package/babel.config.js +4 -0
- package/jest.config.js +20 -0
- package/jest.setup.js +5 -0
- package/lib/Sticky.js +126 -0
- package/lib/index.js +19 -0
- package/lib/styles.js +18 -0
- package/package.json +49 -0
- package/src/Sticky.jsx +83 -0
- package/src/index.js +5 -0
- package/src/styles.js +92 -0
- package/stories/Sticky.stories.jsx +222 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const base = require('../../../../eslintrc.base')
|
|
3
|
+
|
|
4
|
+
base.rules['import/no-extraneous-dependencies'] = [
|
|
5
|
+
'error',
|
|
6
|
+
{ packageDir: [__dirname, path.join(__dirname, '../..')] }
|
|
7
|
+
]
|
|
8
|
+
base.settings = {
|
|
9
|
+
...base.settings,
|
|
10
|
+
'import/resolver': {
|
|
11
|
+
node: {
|
|
12
|
+
...base.settings?.['import/resolver']?.node,
|
|
13
|
+
moduleDirectory: [
|
|
14
|
+
path.join(__dirname, '../../node_modules'),
|
|
15
|
+
path.join(__dirname, '../../../../node_modules')
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
module.exports = base
|
package/CHANGELOG.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@telus-uds/components-community.sticky",
|
|
3
|
+
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"date": "Wed, 24 May 2023 01:36:34 GMT",
|
|
6
|
+
"tag": "@telus-uds/components-community.sticky_v1.0.0",
|
|
7
|
+
"version": "1.0.0",
|
|
8
|
+
"comments": {
|
|
9
|
+
"major": [
|
|
10
|
+
{
|
|
11
|
+
"author": "oscar.palencia@telus.com",
|
|
12
|
+
"package": "@telus-uds/components-community.sticky",
|
|
13
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55",
|
|
14
|
+
"comment": "Implementation of Sticky component"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"author": "beachball",
|
|
18
|
+
"package": "@telus-uds/components-community.sticky",
|
|
19
|
+
"comment": "Bump @telus-uds/components-base to v1.43.0",
|
|
20
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"author": "beachball",
|
|
24
|
+
"package": "@telus-uds/components-community.sticky",
|
|
25
|
+
"comment": "Bump @telus-uds/components-web to v2.1.0",
|
|
26
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"author": "beachball",
|
|
30
|
+
"package": "@telus-uds/components-community.sticky",
|
|
31
|
+
"comment": "Bump @telus-uds/system-constants to v1.2.1",
|
|
32
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"author": "beachball",
|
|
36
|
+
"package": "@telus-uds/components-community.sticky",
|
|
37
|
+
"comment": "Bump @telus-uds/system-theme-tokens to v2.26.1",
|
|
38
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"author": "beachball",
|
|
42
|
+
"package": "@telus-uds/components-community.sticky",
|
|
43
|
+
"comment": "Bump @telus-uds/browserslist-config to v1.0.5",
|
|
44
|
+
"commit": "8dbd3648007f312603cb1844872ea3ff85202e55"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Change Log - @telus-uds/components-community.sticky
|
|
2
|
+
|
|
3
|
+
This log was last generated on Wed, 24 May 2023 01:36:34 GMT and should not be manually modified.
|
|
4
|
+
|
|
5
|
+
<!-- Start content -->
|
|
6
|
+
|
|
7
|
+
## 1.0.0
|
|
8
|
+
|
|
9
|
+
Wed, 24 May 2023 01:36:34 GMT
|
|
10
|
+
|
|
11
|
+
### Major changes
|
|
12
|
+
|
|
13
|
+
- Implementation of Sticky component (oscar.palencia@telus.com)
|
|
14
|
+
- Bump @telus-uds/components-base to v1.43.0
|
|
15
|
+
- Bump @telus-uds/components-web to v2.1.0
|
|
16
|
+
- Bump @telus-uds/system-constants to v1.2.1
|
|
17
|
+
- Bump @telus-uds/system-theme-tokens to v2.26.1
|
|
18
|
+
- Bump @telus-uds/browserslist-config to v1.0.5
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { ThemeProvider } from '@telus-uds/components-base'
|
|
5
|
+
import testTheme from './testTheme'
|
|
6
|
+
|
|
7
|
+
const Theme = ({ children }) => <ThemeProvider defaultTheme={testTheme}>{children}</ThemeProvider>
|
|
8
|
+
|
|
9
|
+
Theme.propTypes = {
|
|
10
|
+
children: PropTypes.node.isRequired
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export default Theme
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
import { appearances } from '@telus-uds/system-theme-tokens'
|
|
2
|
+
import systemThemeTokensPackage from '@telus-uds/system-theme-tokens/package.json'
|
|
3
|
+
|
|
4
|
+
// This is a dev-only file so we don't need to make @telus-uds/palette-allium a dependency.
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
metadata: {
|
|
8
|
+
name: 'test',
|
|
9
|
+
themeTokensVersion: systemThemeTokensPackage.version
|
|
10
|
+
},
|
|
11
|
+
components: {
|
|
12
|
+
spacingScale: {
|
|
13
|
+
tokens: {
|
|
14
|
+
size: 36
|
|
15
|
+
},
|
|
16
|
+
rules: [
|
|
17
|
+
{ if: { space: 5 }, tokens: { size: 32 } },
|
|
18
|
+
{ if: { space: 4 }, tokens: { size: 24 } },
|
|
19
|
+
{ if: { space: 3 }, tokens: { size: 16 } },
|
|
20
|
+
{ if: { space: 2 }, tokens: { size: 8 } },
|
|
21
|
+
{ if: { space: 1 }, tokens: { size: 4 } },
|
|
22
|
+
|
|
23
|
+
{ if: { compact: true }, tokens: { size: 12 } },
|
|
24
|
+
{ if: { compact: true, space: 5 }, tokens: { size: 10 } },
|
|
25
|
+
{ if: { compact: true, space: 4 }, tokens: { size: 8 } },
|
|
26
|
+
{ if: { compact: true, space: 3 }, tokens: { size: 6 } },
|
|
27
|
+
{ if: { compact: true, space: 2 }, tokens: { size: 4 } },
|
|
28
|
+
{ if: { compact: true, space: 1 }, tokens: { size: 2 } },
|
|
29
|
+
|
|
30
|
+
{ if: { responsive: true }, tokens: { size: 6 } },
|
|
31
|
+
{ if: { responsive: true, space: 5 }, tokens: { size: 5 } },
|
|
32
|
+
{ if: { responsive: true, space: 4 }, tokens: { size: 4 } },
|
|
33
|
+
{ if: { responsive: true, space: 3 }, tokens: { size: 3 } },
|
|
34
|
+
{ if: { responsive: true, space: 2 }, tokens: { size: 2 } },
|
|
35
|
+
{ if: { responsive: true, space: 1 }, tokens: { size: 1 } },
|
|
36
|
+
{ if: { responsive: true, viewport: ['sm', 'md'] }, tokens: { size: 8 } },
|
|
37
|
+
{ if: { responsive: true, viewport: ['sm', 'md'], space: 5 }, tokens: { size: 7 } },
|
|
38
|
+
{ if: { responsive: true, viewport: ['sm', 'md'], space: 4 }, tokens: { size: 6 } },
|
|
39
|
+
{ if: { responsive: true, viewport: ['sm', 'md'], space: 3 }, tokens: { size: 5 } },
|
|
40
|
+
{ if: { responsive: true, viewport: ['sm', 'md'], space: 2 }, tokens: { size: 4 } },
|
|
41
|
+
{ if: { responsive: true, viewport: ['sm', 'md'], space: 1 }, tokens: { size: 3 } },
|
|
42
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'] }, tokens: { size: 12 } },
|
|
43
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'], space: 5 }, tokens: { size: 11 } },
|
|
44
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'], space: 4 }, tokens: { size: 10 } },
|
|
45
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'], space: 3 }, tokens: { size: 9 } },
|
|
46
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'], space: 2 }, tokens: { size: 8 } },
|
|
47
|
+
{ if: { responsive: true, viewport: ['lg', 'xl'], space: 1 }, tokens: { size: 7 } },
|
|
48
|
+
|
|
49
|
+
{ if: { space: 0 }, tokens: { size: 0 } }
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
Box: {
|
|
53
|
+
tokens: {},
|
|
54
|
+
variants: {
|
|
55
|
+
lightest: {
|
|
56
|
+
backgroundColor: '#ffffff'
|
|
57
|
+
},
|
|
58
|
+
light: {
|
|
59
|
+
backgroundColor: '#f4f4f7'
|
|
60
|
+
},
|
|
61
|
+
dark: {
|
|
62
|
+
backgroundColor: '#414547'
|
|
63
|
+
},
|
|
64
|
+
darkest: {
|
|
65
|
+
backgroundColor: '#2c2e30'
|
|
66
|
+
},
|
|
67
|
+
critical: {
|
|
68
|
+
backgroundColor: '#c12335'
|
|
69
|
+
},
|
|
70
|
+
danger: {
|
|
71
|
+
backgroundColor: '#fff6f8'
|
|
72
|
+
},
|
|
73
|
+
warning: {
|
|
74
|
+
backgroundColor: '#000000'
|
|
75
|
+
},
|
|
76
|
+
positive: {
|
|
77
|
+
backgroundColor: '#f4f9f2'
|
|
78
|
+
},
|
|
79
|
+
brand: {
|
|
80
|
+
backgroundColor: '#4d80de'
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
defaultVariant: ['lightest']
|
|
84
|
+
},
|
|
85
|
+
Typography: {
|
|
86
|
+
appearances: {
|
|
87
|
+
weight: {
|
|
88
|
+
values: ['light', 'medium', 'bold'],
|
|
89
|
+
type: 'variant'
|
|
90
|
+
},
|
|
91
|
+
size: {
|
|
92
|
+
values: [
|
|
93
|
+
'micro',
|
|
94
|
+
'small',
|
|
95
|
+
'large',
|
|
96
|
+
'h1',
|
|
97
|
+
'h2',
|
|
98
|
+
'h3',
|
|
99
|
+
'h4',
|
|
100
|
+
'h5',
|
|
101
|
+
'h6',
|
|
102
|
+
'display1',
|
|
103
|
+
'display2'
|
|
104
|
+
],
|
|
105
|
+
type: 'variant'
|
|
106
|
+
},
|
|
107
|
+
colour: {
|
|
108
|
+
values: ['secondary', 'tertiary'],
|
|
109
|
+
type: 'variant'
|
|
110
|
+
},
|
|
111
|
+
inverse: {
|
|
112
|
+
description: 'Styles the link white for use on dark backgrounds.',
|
|
113
|
+
values: [true],
|
|
114
|
+
type: 'variant'
|
|
115
|
+
},
|
|
116
|
+
viewport: appearances.system.viewport
|
|
117
|
+
},
|
|
118
|
+
tokens: {
|
|
119
|
+
fontWeight: '400',
|
|
120
|
+
fontSize: 16,
|
|
121
|
+
color: '#2c2e30',
|
|
122
|
+
lineHeight: 1.5,
|
|
123
|
+
fontScaleCap: 64
|
|
124
|
+
},
|
|
125
|
+
rules: [
|
|
126
|
+
{
|
|
127
|
+
if: { inverse: true },
|
|
128
|
+
tokens: {
|
|
129
|
+
color: '#ffffff'
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
if: { colour: 'primary' },
|
|
134
|
+
tokens: {
|
|
135
|
+
color: '#2c2e30'
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
if: { colour: 'secondary' },
|
|
140
|
+
tokens: {
|
|
141
|
+
color: '#414547'
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
if: { weight: 'light' },
|
|
146
|
+
tokens: {
|
|
147
|
+
fontWeight: '300'
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
if: { weight: 'medium' },
|
|
152
|
+
tokens: {
|
|
153
|
+
fontWeight: '500'
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
if: { weight: 'bold' },
|
|
158
|
+
tokens: {
|
|
159
|
+
fontWeight: '700'
|
|
160
|
+
}
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
if: { size: 'large' },
|
|
164
|
+
tokens: {
|
|
165
|
+
fontSize: 20,
|
|
166
|
+
lineHeight: 1.6
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
if: { size: 'small' },
|
|
171
|
+
tokens: {
|
|
172
|
+
fontSize: 14,
|
|
173
|
+
lineHeight: 1.4
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
if: { size: 'micro' },
|
|
178
|
+
tokens: {
|
|
179
|
+
fontSize: 12,
|
|
180
|
+
fontWeight: '500',
|
|
181
|
+
lineHeight: 1.3
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
if: { size: 'display1' },
|
|
186
|
+
tokens: {
|
|
187
|
+
fontSize: 40,
|
|
188
|
+
fontWeight: '300',
|
|
189
|
+
lineHeight: 1.2
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
if: { size: 'display1', colour: 'primary' },
|
|
194
|
+
tokens: {
|
|
195
|
+
color: '#4d80de'
|
|
196
|
+
}
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
if: { size: 'display1', colour: 'secondary' },
|
|
200
|
+
tokens: {
|
|
201
|
+
color: '#2c2e30'
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
if: { size: 'display1', viewport: ['lg', 'xl'] },
|
|
206
|
+
tokens: {
|
|
207
|
+
fontSize: 64,
|
|
208
|
+
lineHeight: 1.1
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
if: { size: 'display2' },
|
|
213
|
+
tokens: {
|
|
214
|
+
fontSize: 40,
|
|
215
|
+
fontWeight: '300',
|
|
216
|
+
color: '#4d80de',
|
|
217
|
+
lineHeight: 1.2
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
if: { size: 'display2', colour: 'secondary' },
|
|
222
|
+
tokens: {
|
|
223
|
+
color: '#2c2e30'
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
if: { size: 'display2', viewport: ['lg', 'xl'] },
|
|
228
|
+
tokens: {
|
|
229
|
+
fontSize: 56,
|
|
230
|
+
lineHeight: 1.1
|
|
231
|
+
}
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
if: { size: 'h1' },
|
|
235
|
+
tokens: {
|
|
236
|
+
fontSize: 28,
|
|
237
|
+
lineHeight: 1.2,
|
|
238
|
+
color: '#4d80de'
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
if: { size: 'h1', colour: 'secondary' },
|
|
243
|
+
tokens: {
|
|
244
|
+
color: '#2c2e30'
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
{
|
|
248
|
+
if: { size: 'h1', viewport: ['lg', 'xl'] },
|
|
249
|
+
tokens: {
|
|
250
|
+
fontSize: 40,
|
|
251
|
+
lineHeight: 1.1
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
if: { size: 'h2' },
|
|
256
|
+
tokens: {
|
|
257
|
+
fontSize: 24,
|
|
258
|
+
color: '#4d80de',
|
|
259
|
+
fontWeight: '500',
|
|
260
|
+
lineHeight: 1.3
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
if: { size: 'h2', colour: 'secondary' },
|
|
265
|
+
tokens: {
|
|
266
|
+
color: '#2c2e30'
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
if: { size: 'h2', viewport: ['lg', 'xl'] },
|
|
271
|
+
tokens: {
|
|
272
|
+
fontSize: 28
|
|
273
|
+
}
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
if: { size: 'h3' },
|
|
277
|
+
tokens: {
|
|
278
|
+
fontSize: 20,
|
|
279
|
+
fontWeight: '500',
|
|
280
|
+
lineHeight: 1.4,
|
|
281
|
+
color: '#4d80de'
|
|
282
|
+
}
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
if: { size: 'h3', colour: 'secondary' },
|
|
286
|
+
tokens: {
|
|
287
|
+
color: '#2c2e30'
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
if: { size: 'h3', viewport: ['lg', 'xl'] },
|
|
292
|
+
tokens: {
|
|
293
|
+
fontSize: 24,
|
|
294
|
+
lineHeight: 1.3
|
|
295
|
+
}
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
if: { size: 'h4' },
|
|
299
|
+
tokens: {
|
|
300
|
+
fontSize: 16,
|
|
301
|
+
weight: '500',
|
|
302
|
+
lineHeight: 1.5
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
if: { size: 'h5' },
|
|
307
|
+
tokens: {
|
|
308
|
+
fontSize: 14,
|
|
309
|
+
fontWeight: '500',
|
|
310
|
+
lineHeight: 1.3
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
if: { size: 'h6' },
|
|
315
|
+
tokens: {
|
|
316
|
+
fontSize: 12,
|
|
317
|
+
fontWeight: '700',
|
|
318
|
+
lineHeight: 1.3
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
if: { size: 'h6', colour: 'tertiary' },
|
|
323
|
+
tokens: {
|
|
324
|
+
color: '#000000'
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
},
|
|
329
|
+
Sticky: {
|
|
330
|
+
appearances: {},
|
|
331
|
+
rules: [],
|
|
332
|
+
tokens: {}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render } from '@testing-library/react'
|
|
3
|
+
import { Typography } from '@telus-uds/components-web'
|
|
4
|
+
import Theme from '../__fixtures__/Theme'
|
|
5
|
+
import { Sticky } from '../src'
|
|
6
|
+
|
|
7
|
+
describe('Sticky', () => {
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
const mockIntersectionObserver = jest.fn()
|
|
10
|
+
mockIntersectionObserver.mockReturnValue({
|
|
11
|
+
observe: jest.fn(),
|
|
12
|
+
unobserve: jest.fn(),
|
|
13
|
+
disconnect: jest.fn()
|
|
14
|
+
})
|
|
15
|
+
window.IntersectionObserver = mockIntersectionObserver
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('is rendered with children', () => {
|
|
19
|
+
const { getByText, container } = render(
|
|
20
|
+
<Theme>
|
|
21
|
+
<Sticky>
|
|
22
|
+
<Typography>Sticky Content</Typography>
|
|
23
|
+
</Sticky>
|
|
24
|
+
</Theme>
|
|
25
|
+
)
|
|
26
|
+
const sentinelTop = container.querySelector('.sentinelTop')
|
|
27
|
+
const sentinelBottom = container.querySelector('.sentinelBottom')
|
|
28
|
+
const stickyElement = container.querySelector('.sticky-element')
|
|
29
|
+
const titleElement = getByText(/Sticky Content/i)
|
|
30
|
+
expect(sentinelTop).toBeInTheDocument()
|
|
31
|
+
expect(sentinelBottom).toBeInTheDocument()
|
|
32
|
+
expect(stickyElement).toBeInTheDocument()
|
|
33
|
+
expect(titleElement).toBeInTheDocument()
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
it('is rendered with children using alternate variant', () => {
|
|
37
|
+
const { getByText, container } = render(
|
|
38
|
+
<Theme>
|
|
39
|
+
<Sticky variant="alternate">
|
|
40
|
+
<Typography>Sticky Content</Typography>
|
|
41
|
+
</Sticky>
|
|
42
|
+
</Theme>
|
|
43
|
+
)
|
|
44
|
+
const titleElement = getByText(/Sticky Content/i)
|
|
45
|
+
const alternateSticky = container.querySelector('.alternate')
|
|
46
|
+
const stickyElement = container.querySelector('.sticky-element')
|
|
47
|
+
expect(titleElement).toBeInTheDocument()
|
|
48
|
+
expect(alternateSticky).toBeInTheDocument()
|
|
49
|
+
expect(stickyElement).toBeInTheDocument()
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
it('is rendered with children using hidden variant', () => {
|
|
53
|
+
const { getByText, container } = render(
|
|
54
|
+
<Theme>
|
|
55
|
+
<Sticky variant="hidden">
|
|
56
|
+
<Typography>Sticky Content</Typography>
|
|
57
|
+
</Sticky>
|
|
58
|
+
</Theme>
|
|
59
|
+
)
|
|
60
|
+
const titleElement = getByText(/Sticky Content/i)
|
|
61
|
+
const stickyElement = container.querySelector('.sticky-element')
|
|
62
|
+
expect(stickyElement).toBeInTheDocument()
|
|
63
|
+
expect(titleElement).toBeInTheDocument()
|
|
64
|
+
expect(stickyElement.parentNode).toHaveStyle('height: 0px')
|
|
65
|
+
})
|
|
66
|
+
})
|
package/babel.config.js
ADDED
package/jest.config.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
module.exports = () => ({
|
|
2
|
+
displayName: {
|
|
3
|
+
name: require('./package.json').name.split('@telus-uds/').pop(),
|
|
4
|
+
color: 'magenta'
|
|
5
|
+
},
|
|
6
|
+
testEnvironment: 'jsdom',
|
|
7
|
+
// __dirname here tells babel to look in ds-allium/ for babel root when running from monorepo root
|
|
8
|
+
transform: { '\\.(js|jsx)$': ['babel-jest', { cwd: __dirname }] },
|
|
9
|
+
moduleNameMapper: {
|
|
10
|
+
'.+\\.(otf|png|jpg)$': 'identity-obj-proxy',
|
|
11
|
+
// mock icon imports as in https://jestjs.io/docs/webpack#mocking-css-modules
|
|
12
|
+
'\\.icon.svg': '<rootDir>/__mocks__/iconMock.jsx',
|
|
13
|
+
'\\.css': '<rootDir>/__mocks__/styleMock.js',
|
|
14
|
+
'^styled-components':
|
|
15
|
+
'<rootDir>/../../node_modules/styled-components/dist/styled-components.browser.cjs.js'
|
|
16
|
+
},
|
|
17
|
+
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
18
|
+
// Count everything in src when calculating coverage
|
|
19
|
+
collectCoverageFrom: ['src/*.{js,jsx}']
|
|
20
|
+
})
|
package/jest.setup.js
ADDED
package/lib/Sticky.js
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
|
|
10
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
11
|
+
|
|
12
|
+
var _componentsWeb = require("@telus-uds/components-web");
|
|
13
|
+
|
|
14
|
+
var _componentsBase = require("@telus-uds/components-base");
|
|
15
|
+
|
|
16
|
+
var _styles = _interopRequireDefault(require("./styles"));
|
|
17
|
+
|
|
18
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
19
|
+
|
|
20
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
21
|
+
|
|
22
|
+
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
23
|
+
|
|
24
|
+
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
25
|
+
|
|
26
|
+
function createObserver(ref, callback) {
|
|
27
|
+
const options = {
|
|
28
|
+
threshold: [1]
|
|
29
|
+
};
|
|
30
|
+
const observer = new IntersectionObserver(_ref => {
|
|
31
|
+
let [e] = _ref;
|
|
32
|
+
const isNotVisibleInViewport = e.intersectionRatio < 1;
|
|
33
|
+
callback(isNotVisibleInViewport);
|
|
34
|
+
}, options);
|
|
35
|
+
observer.observe(ref.current);
|
|
36
|
+
return observer;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const Sticky = _ref2 => {
|
|
40
|
+
let {
|
|
41
|
+
children,
|
|
42
|
+
variant = 'default',
|
|
43
|
+
vertical = {
|
|
44
|
+
xs: 0,
|
|
45
|
+
sm: 0,
|
|
46
|
+
lg: 0,
|
|
47
|
+
xl: 0
|
|
48
|
+
},
|
|
49
|
+
horizontal = {
|
|
50
|
+
xs: 0,
|
|
51
|
+
sm: 0,
|
|
52
|
+
lg: 0,
|
|
53
|
+
xl: 0
|
|
54
|
+
}
|
|
55
|
+
} = _ref2;
|
|
56
|
+
const sentinelTopRef = (0, _react.useRef)();
|
|
57
|
+
const sentinelBottomRef = (0, _react.useRef)();
|
|
58
|
+
const stickyWrapperRef = (0, _react.useRef)();
|
|
59
|
+
const [observer, setObserver] = (0, _react.useState)();
|
|
60
|
+
(0, _react.useEffect)(() => {
|
|
61
|
+
if (observer) {
|
|
62
|
+
observer.disconnect();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (variant === 'default' || variant === 'hidden') {
|
|
66
|
+
setObserver(createObserver(sentinelTopRef, intersected => {
|
|
67
|
+
var _stickyWrapperRef$cur, _stickyWrapperRef$cur2;
|
|
68
|
+
|
|
69
|
+
(_stickyWrapperRef$cur = stickyWrapperRef.current) === null || _stickyWrapperRef$cur === void 0 ? void 0 : _stickyWrapperRef$cur.classList.toggle('sticky-mode', intersected);
|
|
70
|
+
(_stickyWrapperRef$cur2 = stickyWrapperRef.current) === null || _stickyWrapperRef$cur2 === void 0 ? void 0 : _stickyWrapperRef$cur2.classList.toggle('top', intersected);
|
|
71
|
+
}));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (variant === 'alternate') {
|
|
75
|
+
setObserver(createObserver(sentinelBottomRef, intersected => {
|
|
76
|
+
var _stickyWrapperRef$cur3, _stickyWrapperRef$cur4;
|
|
77
|
+
|
|
78
|
+
(_stickyWrapperRef$cur3 = stickyWrapperRef.current) === null || _stickyWrapperRef$cur3 === void 0 ? void 0 : _stickyWrapperRef$cur3.classList.toggle('sticky-mode', intersected);
|
|
79
|
+
(_stickyWrapperRef$cur4 = stickyWrapperRef.current) === null || _stickyWrapperRef$cur4 === void 0 ? void 0 : _stickyWrapperRef$cur4.classList.toggle('bottom', intersected);
|
|
80
|
+
}));
|
|
81
|
+
} // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
82
|
+
|
|
83
|
+
}, [variant]);
|
|
84
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
85
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
86
|
+
className: "sentinelTop",
|
|
87
|
+
ref: sentinelTopRef
|
|
88
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_styles.default, {
|
|
89
|
+
className: variant,
|
|
90
|
+
ref: stickyWrapperRef,
|
|
91
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
92
|
+
className: "sticky-element",
|
|
93
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsWeb.Box, {
|
|
94
|
+
vertical: vertical,
|
|
95
|
+
horizontal: horizontal,
|
|
96
|
+
children: children
|
|
97
|
+
})
|
|
98
|
+
})
|
|
99
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
|
|
100
|
+
className: "sentinelBottom",
|
|
101
|
+
ref: sentinelBottomRef
|
|
102
|
+
})]
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
Sticky.propTypes = {
|
|
107
|
+
/**
|
|
108
|
+
* Sets top and bottom padding using the theme's spacing scale.
|
|
109
|
+
*
|
|
110
|
+
*/
|
|
111
|
+
vertical: _componentsBase.spacingProps.types.spacingValue,
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Sets left and right padding using the theme's spacing scale.
|
|
115
|
+
*
|
|
116
|
+
*/
|
|
117
|
+
horizontal: _componentsBase.spacingProps.types.spacingValue,
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Sticky accepts any content as children.
|
|
121
|
+
*/
|
|
122
|
+
children: _propTypes.default.node.isRequired,
|
|
123
|
+
variant: _propTypes.default.oneOf(['default', 'alternate', 'hidden'])
|
|
124
|
+
};
|
|
125
|
+
var _default = Sticky;
|
|
126
|
+
exports.default = _default;
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "Sticky", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _Sticky.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
exports.default = void 0;
|
|
13
|
+
|
|
14
|
+
var _Sticky = _interopRequireDefault(require("./Sticky"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
var _default = _Sticky.default;
|
|
19
|
+
exports.default = _default;
|
package/lib/styles.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
|
|
8
|
+
var _styledComponents = _interopRequireDefault(require("styled-components"));
|
|
9
|
+
|
|
10
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
11
|
+
|
|
12
|
+
const StickyWrapper = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
13
|
+
displayName: "styles__StickyWrapper",
|
|
14
|
+
componentId: "[object Object]__sc-160gk65-0"
|
|
15
|
+
})(["top:0;&.sticky-mode{&.alternate,&.default{position:-webkit-sticky;position:sticky;top:0px;z-index:1;box-shadow:0px 7px 4px -3px rgb(0,0,0,0.08);}&.hidden{animation:0.3s animateIn forwards;.sticky-element{animation:0.3s shadowIn forwards;}}}&.alternate{}&.hidden{position:sticky;pointerevents:none;height:0px;min-height:0px;max-height:0px;animation:0.6s animateOut forwards;.sticky-element{background:white;animation:0.6s shadowOut forwards;}}.sticky-element{background:#ffffff;}@keyframes animateIn{from{height:0%;pointerevents:none;transform:translateY(-100vh);opacity:0;z-index:-1;}to{height:100%;pointerevents:all;transform:translateY(0);opacity:1;z-index:1;}}@keyframes animateOut{from{height:100%;pointerevents:all;transform:translateY(0);opacity:1;z-index:1;}to{height:0%;pointerevents:none;transform:translateY(-100vh);opacity:0;z-index:-1;}}@keyframes shadowIn{from{box-shadow:0px 7px 4px -3px rgb(0,0,0,0);}to{box-shadow:0px 7px 4px -3px rgb(0,0,0,0.08);}}@keyframes shadowOut{from{box-shadow:0px 7px 4px -3px rgb(0,0,0,0.08);}to{box-shadow:0px 7px 4px -3px rgb(0,0,0,0);}}"]);
|
|
16
|
+
|
|
17
|
+
var _default = StickyWrapper;
|
|
18
|
+
exports.default = _default;
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "TELUS Digital",
|
|
3
|
+
"browserslist": [
|
|
4
|
+
"extends @telus-uds/browserslist-config"
|
|
5
|
+
],
|
|
6
|
+
"dependencies": {
|
|
7
|
+
"@telus-uds/components-base": "^1.43.0",
|
|
8
|
+
"@telus-uds/components-web": "^2.1.0",
|
|
9
|
+
"@telus-uds/system-constants": "^1.2.1",
|
|
10
|
+
"@telus-uds/system-theme-tokens": "^2.26.1",
|
|
11
|
+
"prop-types": "^15.7.2",
|
|
12
|
+
"styled-components": "^5.3.10"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@telus-uds/browserslist-config": "^1.0.5",
|
|
16
|
+
"@testing-library/jest-dom": "^5.16.1",
|
|
17
|
+
"@testing-library/react": "^13.3.0",
|
|
18
|
+
"babel-plugin-styled-components": "^2.0.6",
|
|
19
|
+
"jest-axe": "^6.0.0",
|
|
20
|
+
"jest-styled-components": "^7.0.8"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/telus/universal-design-system#readme",
|
|
23
|
+
"license": "UNLICENSED",
|
|
24
|
+
"name": "@telus-uds/components-community.sticky",
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"react": "^17.0.2 || ^18.0.0",
|
|
27
|
+
"react-dom": "^17.0.2 || ^18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"main": "lib/index.js",
|
|
30
|
+
"module": "lib-module/index.js",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/telus/universal-design-system.git"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"format": "prettier --write .",
|
|
37
|
+
"lint": "telus-standard",
|
|
38
|
+
"lint:fix": "telus-standard --fix",
|
|
39
|
+
"test": "jest",
|
|
40
|
+
"build:main": "babel src -d lib",
|
|
41
|
+
"build:module": "babel src -d lib-module --env-name module",
|
|
42
|
+
"build": "npm run build:main && npm run build:module"
|
|
43
|
+
},
|
|
44
|
+
"sideEffects": false,
|
|
45
|
+
"standard-engine": {
|
|
46
|
+
"skip": true
|
|
47
|
+
},
|
|
48
|
+
"version": "1.0.0"
|
|
49
|
+
}
|
package/src/Sticky.jsx
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { Box } from '@telus-uds/components-web'
|
|
4
|
+
import { spacingProps } from '@telus-uds/components-base'
|
|
5
|
+
import StickyWrapper from './styles'
|
|
6
|
+
|
|
7
|
+
function createObserver(ref, callback) {
|
|
8
|
+
const options = { threshold: [1] }
|
|
9
|
+
const observer = new IntersectionObserver(([e]) => {
|
|
10
|
+
const isNotVisibleInViewport = e.intersectionRatio < 1
|
|
11
|
+
callback(isNotVisibleInViewport)
|
|
12
|
+
}, options)
|
|
13
|
+
observer.observe(ref.current)
|
|
14
|
+
return observer
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const Sticky = ({
|
|
18
|
+
children,
|
|
19
|
+
variant = 'default',
|
|
20
|
+
vertical = { xs: 0, sm: 0, lg: 0, xl: 0 },
|
|
21
|
+
horizontal = { xs: 0, sm: 0, lg: 0, xl: 0 }
|
|
22
|
+
}) => {
|
|
23
|
+
const sentinelTopRef = useRef()
|
|
24
|
+
const sentinelBottomRef = useRef()
|
|
25
|
+
const stickyWrapperRef = useRef()
|
|
26
|
+
const [observer, setObserver] = useState()
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (observer) {
|
|
29
|
+
observer.disconnect()
|
|
30
|
+
}
|
|
31
|
+
if (variant === 'default' || variant === 'hidden') {
|
|
32
|
+
setObserver(
|
|
33
|
+
createObserver(sentinelTopRef, (intersected) => {
|
|
34
|
+
stickyWrapperRef.current?.classList.toggle('sticky-mode', intersected)
|
|
35
|
+
stickyWrapperRef.current?.classList.toggle('top', intersected)
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
if (variant === 'alternate') {
|
|
40
|
+
setObserver(
|
|
41
|
+
createObserver(sentinelBottomRef, (intersected) => {
|
|
42
|
+
stickyWrapperRef.current?.classList.toggle('sticky-mode', intersected)
|
|
43
|
+
stickyWrapperRef.current?.classList.toggle('bottom', intersected)
|
|
44
|
+
})
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
48
|
+
}, [variant])
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<>
|
|
52
|
+
<div className="sentinelTop" ref={sentinelTopRef} />
|
|
53
|
+
<StickyWrapper className={variant} ref={stickyWrapperRef}>
|
|
54
|
+
<div className="sticky-element">
|
|
55
|
+
<Box vertical={vertical} horizontal={horizontal}>
|
|
56
|
+
{children}
|
|
57
|
+
</Box>
|
|
58
|
+
</div>
|
|
59
|
+
</StickyWrapper>
|
|
60
|
+
<div className="sentinelBottom" ref={sentinelBottomRef} />
|
|
61
|
+
</>
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Sticky.propTypes = {
|
|
66
|
+
/**
|
|
67
|
+
* Sets top and bottom padding using the theme's spacing scale.
|
|
68
|
+
*
|
|
69
|
+
*/
|
|
70
|
+
vertical: spacingProps.types.spacingValue,
|
|
71
|
+
/**
|
|
72
|
+
* Sets left and right padding using the theme's spacing scale.
|
|
73
|
+
*
|
|
74
|
+
*/
|
|
75
|
+
horizontal: spacingProps.types.spacingValue,
|
|
76
|
+
/**
|
|
77
|
+
* Sticky accepts any content as children.
|
|
78
|
+
*/
|
|
79
|
+
children: PropTypes.node.isRequired,
|
|
80
|
+
variant: PropTypes.oneOf(['default', 'alternate', 'hidden'])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export default Sticky
|
package/src/index.js
ADDED
package/src/styles.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import styled from 'styled-components'
|
|
2
|
+
|
|
3
|
+
const StickyWrapper = styled.div`
|
|
4
|
+
top: 0;
|
|
5
|
+
|
|
6
|
+
&.sticky-mode {
|
|
7
|
+
&.alternate,
|
|
8
|
+
&.default {
|
|
9
|
+
position: -webkit-sticky;
|
|
10
|
+
position: sticky;
|
|
11
|
+
top: 0px;
|
|
12
|
+
z-index: 1;
|
|
13
|
+
box-shadow: 0px 7px 4px -3px rgb(0, 0, 0, 0.08);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&.hidden {
|
|
17
|
+
animation: 0.3s animateIn forwards;
|
|
18
|
+
.sticky-element {
|
|
19
|
+
animation: 0.3s shadowIn forwards;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
&.alternate {
|
|
24
|
+
}
|
|
25
|
+
&.hidden {
|
|
26
|
+
position: sticky;
|
|
27
|
+
pointerevents: none;
|
|
28
|
+
height: 0px;
|
|
29
|
+
min-height: 0px;
|
|
30
|
+
max-height: 0px;
|
|
31
|
+
animation: 0.6s animateOut forwards;
|
|
32
|
+
.sticky-element {
|
|
33
|
+
background: white;
|
|
34
|
+
animation: 0.6s shadowOut forwards;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.sticky-element {
|
|
39
|
+
background: #ffffff;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@keyframes animateIn {
|
|
43
|
+
from {
|
|
44
|
+
height: 0%;
|
|
45
|
+
pointerevents: none;
|
|
46
|
+
transform: translateY(-100vh);
|
|
47
|
+
opacity: 0;
|
|
48
|
+
z-index: -1;
|
|
49
|
+
}
|
|
50
|
+
to {
|
|
51
|
+
height: 100%;
|
|
52
|
+
pointerevents: all;
|
|
53
|
+
transform: translateY(0);
|
|
54
|
+
opacity: 1;
|
|
55
|
+
z-index: 1;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
@keyframes animateOut {
|
|
59
|
+
from {
|
|
60
|
+
height: 100%;
|
|
61
|
+
pointerevents: all;
|
|
62
|
+
transform: translateY(0);
|
|
63
|
+
opacity: 1;
|
|
64
|
+
z-index: 1;
|
|
65
|
+
}
|
|
66
|
+
to {
|
|
67
|
+
height: 0%;
|
|
68
|
+
pointerevents: none;
|
|
69
|
+
transform: translateY(-100vh);
|
|
70
|
+
opacity: 0;
|
|
71
|
+
z-index: -1;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
@keyframes shadowIn {
|
|
75
|
+
from {
|
|
76
|
+
box-shadow: 0px 7px 4px -3px rgb(0, 0, 0, 0);
|
|
77
|
+
}
|
|
78
|
+
to {
|
|
79
|
+
box-shadow: 0px 7px 4px -3px rgb(0, 0, 0, 0.08);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
@keyframes shadowOut {
|
|
83
|
+
from {
|
|
84
|
+
box-shadow: 0px 7px 4px -3px rgb(0, 0, 0, 0.08);
|
|
85
|
+
}
|
|
86
|
+
to {
|
|
87
|
+
box-shadow: 0px 7px 4px -3px rgb(0, 0, 0, 0);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`
|
|
91
|
+
|
|
92
|
+
export default StickyWrapper
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Typography, FlexGrid, Box, StoryCard, Spacer, Card } from '@telus-uds/components-web'
|
|
3
|
+
import { Sticky } from '../..'
|
|
4
|
+
import pigPhoto from '../__fixtures__/images/pigs-allium-lo.png'
|
|
5
|
+
import mountainPhoto from '../__fixtures__/images/mountains_desktop.jpg'
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Community/Sticky',
|
|
9
|
+
component: Sticky
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const Default = (args) => (
|
|
13
|
+
<FlexGrid gutter={false}>
|
|
14
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
15
|
+
<FlexGrid.Col xs={12}>
|
|
16
|
+
<Box variant={{ background: 'light' }} space={4}>
|
|
17
|
+
<Typography variant={{ size: 'h3' }}>Lorem Ipsum</Typography>
|
|
18
|
+
<Spacer space={4} />
|
|
19
|
+
<Typography>
|
|
20
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
21
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
22
|
+
</Typography>
|
|
23
|
+
<Spacer space={2} />
|
|
24
|
+
<Typography>
|
|
25
|
+
Vestibulum blandit dui leo, non placerat nisi efficitur eget. Pellentesque habitant
|
|
26
|
+
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
27
|
+
</Typography>
|
|
28
|
+
</Box>
|
|
29
|
+
</FlexGrid.Col>
|
|
30
|
+
</FlexGrid.Row>
|
|
31
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
32
|
+
<FlexGrid.Col md={4}>
|
|
33
|
+
<StoryCard
|
|
34
|
+
href="https://telus.com"
|
|
35
|
+
tag="Lorem Ipsum"
|
|
36
|
+
date="Oct 28, 2023"
|
|
37
|
+
title="Lorem Ipsum"
|
|
38
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
39
|
+
fullBleedContent={{
|
|
40
|
+
alt: 'Pig photo',
|
|
41
|
+
src: pigPhoto
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
</FlexGrid.Col>
|
|
45
|
+
<FlexGrid.Col md={4}>
|
|
46
|
+
<StoryCard
|
|
47
|
+
href="https://telus.com"
|
|
48
|
+
tag="Lorem Ipsum"
|
|
49
|
+
date="Oct 28, 2023"
|
|
50
|
+
title="Lorem Ipsum"
|
|
51
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
52
|
+
fullBleedContent={{
|
|
53
|
+
alt: 'Pig photo',
|
|
54
|
+
src: pigPhoto
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
</FlexGrid.Col>
|
|
58
|
+
<FlexGrid.Col md={4}>
|
|
59
|
+
<StoryCard
|
|
60
|
+
href="https://telus.com"
|
|
61
|
+
tag="Lorem Ipsum"
|
|
62
|
+
date="Oct 28, 2023"
|
|
63
|
+
title="Lorem Ipsum"
|
|
64
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
65
|
+
fullBleedContent={{
|
|
66
|
+
alt: 'Pig photo',
|
|
67
|
+
src: pigPhoto
|
|
68
|
+
}}
|
|
69
|
+
/>
|
|
70
|
+
</FlexGrid.Col>
|
|
71
|
+
</FlexGrid.Row>
|
|
72
|
+
<Sticky {...args}>
|
|
73
|
+
<FlexGrid gutter={false}>
|
|
74
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
75
|
+
<FlexGrid.Col>
|
|
76
|
+
<Box variant={{ background: 'featurePrimary' }} space={2}>
|
|
77
|
+
<Typography block variant={{ size: 'h1', inverse: true }}>
|
|
78
|
+
Sticky Content
|
|
79
|
+
</Typography>
|
|
80
|
+
<Spacer space={4} />
|
|
81
|
+
<Typography align="center" variant={{ inverse: true }}>
|
|
82
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed euismod, diam quis
|
|
83
|
+
aliquam Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
|
84
|
+
</Typography>
|
|
85
|
+
</Box>
|
|
86
|
+
</FlexGrid.Col>
|
|
87
|
+
</FlexGrid.Row>
|
|
88
|
+
</FlexGrid>
|
|
89
|
+
</Sticky>
|
|
90
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
91
|
+
<FlexGrid.Col md={12}>
|
|
92
|
+
<Card
|
|
93
|
+
footer={
|
|
94
|
+
<Typography>
|
|
95
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
96
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
97
|
+
</Typography>
|
|
98
|
+
}
|
|
99
|
+
>
|
|
100
|
+
<Typography block variant={{ size: 'h2' }}>
|
|
101
|
+
Lorem Ipsum
|
|
102
|
+
</Typography>
|
|
103
|
+
<Box top={4}>
|
|
104
|
+
<Typography>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Typography>
|
|
105
|
+
</Box>
|
|
106
|
+
</Card>
|
|
107
|
+
</FlexGrid.Col>
|
|
108
|
+
</FlexGrid.Row>
|
|
109
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
110
|
+
<FlexGrid.Col xs={12}>
|
|
111
|
+
<Box variant={{ background: 'light' }} space={4}>
|
|
112
|
+
<Typography variant={{ size: 'h3' }}>Lorem Ipsum</Typography>
|
|
113
|
+
<Spacer space={4} />
|
|
114
|
+
<Typography>
|
|
115
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
116
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
117
|
+
</Typography>
|
|
118
|
+
<Spacer space={2} />
|
|
119
|
+
<Typography>
|
|
120
|
+
Vestibulum blandit dui leo, non placerat nisi efficitur eget. Pellentesque habitant
|
|
121
|
+
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
122
|
+
</Typography>
|
|
123
|
+
</Box>
|
|
124
|
+
</FlexGrid.Col>
|
|
125
|
+
</FlexGrid.Row>
|
|
126
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
127
|
+
<FlexGrid.Col md={4}>
|
|
128
|
+
<StoryCard
|
|
129
|
+
href="https://telus.com"
|
|
130
|
+
tag="Lorem Ipsum"
|
|
131
|
+
date="Oct 28, 2023"
|
|
132
|
+
title="Lorem Ipsum"
|
|
133
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
134
|
+
fullBleedContent={{
|
|
135
|
+
alt: 'Mountain photo',
|
|
136
|
+
src: mountainPhoto
|
|
137
|
+
}}
|
|
138
|
+
/>
|
|
139
|
+
</FlexGrid.Col>
|
|
140
|
+
<FlexGrid.Col md={4}>
|
|
141
|
+
<StoryCard
|
|
142
|
+
href="https://telus.com"
|
|
143
|
+
tag="Lorem Ipsum"
|
|
144
|
+
date="Oct 28, 2023"
|
|
145
|
+
title="Lorem Ipsum"
|
|
146
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
147
|
+
fullBleedContent={{
|
|
148
|
+
alt: 'Mountain photo',
|
|
149
|
+
src: mountainPhoto
|
|
150
|
+
}}
|
|
151
|
+
/>
|
|
152
|
+
</FlexGrid.Col>
|
|
153
|
+
<FlexGrid.Col md={4}>
|
|
154
|
+
<StoryCard
|
|
155
|
+
href="https://telus.com"
|
|
156
|
+
tag="Lorem Ipsum"
|
|
157
|
+
date="Oct 28, 2023"
|
|
158
|
+
title="Lorem Ipsum"
|
|
159
|
+
description="Lorem ipsum dolor sit amet, consectetur adipiscing elit."
|
|
160
|
+
fullBleedContent={{
|
|
161
|
+
alt: 'Mountain photo',
|
|
162
|
+
src: mountainPhoto
|
|
163
|
+
}}
|
|
164
|
+
/>
|
|
165
|
+
</FlexGrid.Col>
|
|
166
|
+
</FlexGrid.Row>
|
|
167
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
168
|
+
<FlexGrid.Col xs={12}>
|
|
169
|
+
<Box variant={{ background: 'light' }} space={4}>
|
|
170
|
+
<Typography variant={{ size: 'h3' }}>Lorem Ipsum</Typography>
|
|
171
|
+
<Spacer space={4} />
|
|
172
|
+
<Typography>
|
|
173
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
174
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
175
|
+
</Typography>
|
|
176
|
+
<Spacer space={2} />
|
|
177
|
+
<Typography>
|
|
178
|
+
Vestibulum blandit dui leo, non placerat nisi efficitur eget. Pellentesque habitant
|
|
179
|
+
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
180
|
+
</Typography>
|
|
181
|
+
</Box>
|
|
182
|
+
</FlexGrid.Col>
|
|
183
|
+
</FlexGrid.Row>
|
|
184
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
185
|
+
<FlexGrid.Col xs={12}>
|
|
186
|
+
<Box variant={{ background: 'light' }} space={4}>
|
|
187
|
+
<Typography variant={{ size: 'h3' }}>Lorem Ipsum</Typography>
|
|
188
|
+
<Spacer space={4} />
|
|
189
|
+
<Typography>
|
|
190
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
191
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
192
|
+
</Typography>
|
|
193
|
+
<Spacer space={2} />
|
|
194
|
+
<Typography>
|
|
195
|
+
Vestibulum blandit dui leo, non placerat nisi efficitur eget. Pellentesque habitant
|
|
196
|
+
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
197
|
+
</Typography>
|
|
198
|
+
</Box>
|
|
199
|
+
</FlexGrid.Col>
|
|
200
|
+
</FlexGrid.Row>
|
|
201
|
+
<FlexGrid.Row horizontalAlign="center">
|
|
202
|
+
<FlexGrid.Col xs={12}>
|
|
203
|
+
<Box variant={{ background: 'light' }} space={4}>
|
|
204
|
+
<Typography variant={{ size: 'h3' }}>Lorem Ipsum</Typography>
|
|
205
|
+
<Spacer space={4} />
|
|
206
|
+
<Typography>
|
|
207
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque rutrum dolor
|
|
208
|
+
ligula, ac placerat tortor ornare a. Praesent pellentesque accumsan nibh eu volutpat.
|
|
209
|
+
</Typography>
|
|
210
|
+
<Spacer space={2} />
|
|
211
|
+
<Typography>
|
|
212
|
+
Vestibulum blandit dui leo, non placerat nisi efficitur eget. Pellentesque habitant
|
|
213
|
+
morbi tristique senectus et netus et malesuada fames ac turpis egestas.
|
|
214
|
+
</Typography>
|
|
215
|
+
</Box>
|
|
216
|
+
</FlexGrid.Col>
|
|
217
|
+
</FlexGrid.Row>
|
|
218
|
+
</FlexGrid>
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
Default.storyName = 'Sticky'
|
|
222
|
+
Default.args = { variant: 'default' }
|