@ndla/ui 15.1.4 → 16.1.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.
Files changed (71) hide show
  1. package/es/Article/ArticleContent.js +2 -0
  2. package/es/Breadcrumb/ActionBreadcrumb.js +9 -4
  3. package/es/Breadcrumb/Breadcrumb.js +6 -5
  4. package/es/FileList/File.js +7 -12
  5. package/es/Filter/FilterButtons.js +13 -13
  6. package/es/MyNdla/Resource/Folder.js +9 -7
  7. package/es/NDLAFilm/CategorySelect.js +51 -25
  8. package/es/NDLAFilm/FilmMovieList.js +14 -10
  9. package/es/NDLAFilm/FilmMovieSearch.js +23 -10
  10. package/es/NDLAFilm/FilmSlideshow.js +117 -19
  11. package/es/NDLAFilm/MovieGrid.js +23 -14
  12. package/es/NDLAFilm/NavigationArrow.js +33 -7
  13. package/es/NDLAFilm/SlideshowIndicator.js +27 -11
  14. package/es/NDLAFilm/filmStyles.js +23 -0
  15. package/es/RadioButtonGroup/RadioButtonGroup.js +28 -9
  16. package/es/Resource/BlockResource.js +7 -7
  17. package/es/Resource/ListResource.js +38 -25
  18. package/es/Resource/resourceComponents.js +17 -18
  19. package/es/all.css +1 -1
  20. package/lib/Article/ArticleContent.js +3 -0
  21. package/lib/Breadcrumb/ActionBreadcrumb.js +9 -4
  22. package/lib/Breadcrumb/Breadcrumb.d.ts +2 -1
  23. package/lib/Breadcrumb/Breadcrumb.js +6 -5
  24. package/lib/FileList/File.js +10 -14
  25. package/lib/Filter/FilterButtons.js +13 -13
  26. package/lib/Frontpage/FrontpageMultidisciplinarySubject.d.ts +5 -5
  27. package/lib/Frontpage/illustrations/FrontpageIllustrations.d.ts +2 -2
  28. package/lib/MultidisciplinarySubject/Illustrations.d.ts +7 -7
  29. package/lib/MyNdla/Resource/Folder.js +8 -6
  30. package/lib/NDLAFilm/CategorySelect.js +52 -30
  31. package/lib/NDLAFilm/FilmMovieList.js +17 -13
  32. package/lib/NDLAFilm/FilmMovieSearch.js +29 -17
  33. package/lib/NDLAFilm/FilmSlideshow.js +113 -24
  34. package/lib/NDLAFilm/MovieGrid.js +25 -15
  35. package/lib/NDLAFilm/NavigationArrow.d.ts +5 -1
  36. package/lib/NDLAFilm/NavigationArrow.js +34 -10
  37. package/lib/NDLAFilm/SlideshowIndicator.js +34 -13
  38. package/lib/NDLAFilm/filmStyles.d.ts +8 -0
  39. package/lib/NDLAFilm/filmStyles.js +38 -0
  40. package/lib/RadioButtonGroup/RadioButtonGroup.js +28 -13
  41. package/lib/Resource/BlockResource.js +6 -6
  42. package/lib/Resource/ListResource.js +34 -23
  43. package/lib/Resource/resourceComponents.d.ts +3 -3
  44. package/lib/Resource/resourceComponents.js +19 -20
  45. package/lib/Search/ContentTypeResultStyles.d.ts +3 -3
  46. package/lib/SearchTypeResult/ActiveFilterContent.d.ts +1 -1
  47. package/lib/all.css +1 -1
  48. package/package.json +11 -11
  49. package/src/Article/ArticleContent.tsx +2 -0
  50. package/src/Breadcrumb/ActionBreadcrumb.tsx +15 -3
  51. package/src/Breadcrumb/Breadcrumb.tsx +10 -2
  52. package/src/FileList/File.tsx +8 -11
  53. package/src/Filter/FilterButtons.tsx +3 -4
  54. package/src/MyNdla/Resource/Folder.tsx +5 -1
  55. package/src/NDLAFilm/CategorySelect.tsx +110 -23
  56. package/src/NDLAFilm/FilmMovieList.tsx +13 -11
  57. package/src/NDLAFilm/FilmMovieSearch.tsx +45 -14
  58. package/src/NDLAFilm/FilmSlideshow.tsx +186 -25
  59. package/src/NDLAFilm/MovieGrid.tsx +33 -25
  60. package/src/NDLAFilm/NavigationArrow.tsx +76 -10
  61. package/src/NDLAFilm/SlideshowIndicator.tsx +53 -11
  62. package/src/NDLAFilm/component.film-movielist.scss +0 -46
  63. package/src/NDLAFilm/filmStyles.ts +33 -0
  64. package/src/RadioButtonGroup/RadioButtonGroup.tsx +82 -11
  65. package/src/Resource/BlockResource.tsx +2 -2
  66. package/src/Resource/ListResource.tsx +56 -31
  67. package/src/Resource/resourceComponents.tsx +8 -9
  68. package/src/main.scss +0 -3
  69. package/src/NDLAFilm/component.film-moviesearch.scss +0 -127
  70. package/src/NDLAFilm/component.film-slideshow.scss +0 -258
  71. package/src/RadioButtonGroup/component.radio-button-group.scss +0 -67
@@ -8,11 +8,13 @@
8
8
 
9
9
  import React, { useCallback, useEffect, useRef, useState } from 'react';
10
10
  import { SwipeEventData, useSwipeable } from 'react-swipeable';
11
- import BEMHelper from 'react-bem-helper';
11
+ import styled from '@emotion/styled';
12
+ import { css } from '@emotion/core';
13
+ import { breakpoints, mq, spacing, spacingUnit, fonts, colors } from '@ndla/core';
12
14
  import SafeLink from '@ndla/safelink';
13
15
  import { OneColumn } from '../Layout';
14
16
  import Spinner from '../Spinner';
15
- import NavigationArrow from './NavigationArrow';
17
+ import NavigationArrow, { StyledNavigationArrow } from './NavigationArrow';
16
18
  import SlideshowIndicator from './SlideshowIndicator';
17
19
  import { MovieType } from './types';
18
20
 
@@ -23,17 +25,180 @@ interface Props {
23
25
  slideInterval?: number;
24
26
  }
25
27
 
26
- const classes = new BEMHelper({
27
- name: 'film-slideshow',
28
- prefix: 'c-',
29
- });
28
+ const SlideLinkWrapper = styled.div`
29
+ margin: 0 auto;
30
+ display: flex;
31
+ justify-content: flex-start;
32
+ align-items: flex-end;
33
+ position: absolute;
34
+ z-index: 2;
35
+ height: 100vw;
36
+ width: 100%;
37
+ ${mq.range({ from: breakpoints.mobileWide })} {
38
+ height: 100vw;
39
+ }
40
+ ${mq.range({ from: breakpoints.tablet })} {
41
+ height: 75vw;
42
+ }
43
+ ${mq.range({ from: breakpoints.desktop })} {
44
+ height: 55vw;
45
+ }
46
+ ${mq.range({ from: breakpoints.wide })} {
47
+ height: 40vw;
48
+ }
49
+ ${mq.range({ from: breakpoints.ultraWide })} {
50
+ height: 36vw;
51
+ }
52
+ `;
53
+
54
+ const itemWrapperCSS = css`
55
+ display: flex;
56
+ box-shadow: none;
57
+ `;
58
+
59
+ interface SlideshowItemProps {
60
+ fadeOver?: boolean;
61
+ }
62
+
63
+ const SlideshowItem = styled.div<SlideshowItemProps>`
64
+ width: 100vw;
65
+ height: 100vw;
66
+ /* aspect ratios */
67
+ ${mq.range({ from: breakpoints.mobileWide })} {
68
+ height: 100vw;
69
+ }
70
+ ${mq.range({ from: breakpoints.tablet })} {
71
+ height: 75vw;
72
+ }
73
+ ${mq.range({ from: breakpoints.desktop })} {
74
+ height: 55vw;
75
+ }
76
+ ${mq.range({ from: breakpoints.wide })} {
77
+ height: 40vw;
78
+ }
79
+ ${mq.range({ from: breakpoints.ultraWide })} {
80
+ height: 36vw;
81
+ }
82
+ background-color: '#222';
83
+ background-size: cover;
84
+ background-position-x: center;
85
+ background-position-y: center;
86
+ border: 0;
87
+ position: ${(props) => (props.fadeOver ? 'absolute' : 'relative')};
88
+ animation: ${(props) => props.fadeOver && 'fadeIn 400ms ease'};
89
+ z-index: ${(props) => props.fadeOver && 1};
90
+ &:before {
91
+ content: '';
92
+ opacity: 0.4;
93
+ background: #091a2a;
94
+ top: 0;
95
+ left: 0;
96
+ bottom: 0;
97
+ right: 0;
98
+ position: absolute;
99
+ z-index: 1;
100
+ }
101
+ `;
102
+
103
+ interface SlideshowLinkProps {
104
+ out?: boolean;
105
+ }
106
+
107
+ const SlideshowLink = styled(SafeLink)<SlideshowLinkProps>`
108
+ display: flex;
109
+ box-shadow: none;
110
+ transition: all 400ms ease;
111
+ opacity: ${(props) => props.out && 0};
112
+ animation: ${(props) => !props.out && 'fadeInBottomFixed 600ms ease'};
113
+ ${mq.range({ from: breakpoints.mobileWide })} {
114
+ padding-bottom: ${spacing.medium};
115
+ }
116
+ ${mq.range({ from: breakpoints.tablet })} {
117
+ padding-bottom: ${spacing.large};
118
+ }
119
+ ${mq.range({ from: breakpoints.desktop })} {
120
+ padding-bottom: ${spacingUnit * 3}px;
121
+ }
122
+ &:hover {
123
+ h1 {
124
+ text-decoration: underline;
125
+ }
126
+ }
127
+ `;
128
+
129
+ const SlideshowWrapper = styled.section`
130
+ &:hover {
131
+ ${StyledNavigationArrow} {
132
+ opacity: 1;
133
+ transform: translate(0, 0);
134
+ }
135
+ }
136
+ `;
137
+
138
+ const SlideshowInfo = styled.div`
139
+ border: 0;
140
+ background: none;
141
+ background-color: rgba(3, 23, 43, 0.7);
142
+ border-radius: 4px;
143
+ padding: ${spacing.medium} ${spacing.medium} ${spacing.medium} ${spacing.normal};
144
+ margin: 0 -20px;
145
+ width: 100vw;
146
+ ${mq.range({ from: breakpoints.mobileWide })} {
147
+ margin: 0;
148
+ width: 100%;
149
+ padding: ${spacing.medium} ${spacingUnit * 2}px ${spacing.medium} ${spacing.normal};
150
+ }
151
+ h1 {
152
+ ${fonts.sizes('22px', '30px')};
153
+ color: ${colors.white};
154
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
155
+ margin: 0;
156
+ font-weight: ${fonts.weight.semibold};
157
+ ${mq.range({ from: breakpoints.mobileWide })} {
158
+ margin: 0 0 ${spacing.small};
159
+ ${fonts.sizes('26px', '30px')};
160
+ }
161
+ ${mq.range({ from: breakpoints.tablet })} {
162
+ ${fonts.sizes('40px', '44px')};
163
+ }
164
+ ${mq.range({ from: breakpoints.desktop })} {
165
+ ${fonts.sizes('48px', '54px')};
166
+ }
167
+ }
168
+
169
+ p {
170
+ color: ${colors.white};
171
+ display: inline-block;
172
+ margin: 0;
173
+ padding: 0;
174
+ border-radius: 4px;
175
+ ${fonts.sizes('12px', '18px')};
176
+ ${mq.range({ from: breakpoints.mobileWide })} {
177
+ ${fonts.sizes('15px', '20px')};
178
+ }
179
+ ${mq.range({ from: breakpoints.tablet })} {
180
+ ${fonts.sizes('18px', '24px')};
181
+ }
182
+ ${mq.range({ from: breakpoints.wide })} {
183
+ ${fonts.sizes('20px', '32px')};
184
+ }
185
+ }
186
+ `;
187
+
188
+ const EmptySlideshow = styled.div`
189
+ background: rgba(255, 255, 255, 0.08);
190
+ margin-bottom: $spacing--large * 4;
191
+ display: flex;
192
+ align-items: center;
193
+ justify-content: center;
194
+ height: 40vw;
195
+ `;
30
196
 
31
197
  const defaultTransitionSwipeEnd = 'transform 600ms cubic-bezier(0, 0.76, 0.09, 1)';
32
198
  const defaultTransitionText = 'opacity 600ms ease';
33
199
 
34
200
  const renderSlideItem = (slide: MovieType) => (
35
- <div
36
- {...classes('item')}
201
+ <SlideshowItem
37
202
  key={slide.id}
38
203
  role="img"
39
204
  aria-label={(slide.metaImage && slide.metaImage.alt) || ''}
@@ -190,9 +355,9 @@ const FilmSlideshow = ({ autoSlide = false, slideshow = [], slideInterval = 5000
190
355
  if (slideshow.length === 0) {
191
356
  return (
192
357
  <div>
193
- <div {...classes('slideshow')}>
358
+ <EmptySlideshow>
194
359
  <Spinner inverted />
195
- </div>
360
+ </EmptySlideshow>
196
361
  </div>
197
362
  );
198
363
  }
@@ -208,22 +373,18 @@ const FilmSlideshow = ({ autoSlide = false, slideshow = [], slideInterval = 5000
208
373
  const backgroundImage = slideshow[activeSlide].metaImage;
209
374
 
210
375
  return (
211
- <section {...classes('')} {...handlers}>
376
+ <SlideshowWrapper {...handlers}>
212
377
  <>
213
- <div {...classes('slide-link-wrapper')}>
378
+ <SlideLinkWrapper>
214
379
  <OneColumn>
215
- <SafeLink
216
- to={slideshow[activeSlide].path}
217
- {...classes('item-wrapper', 'text', {
218
- out: !animationComplete,
219
- })}>
220
- <div {...classes('slide-info')} ref={slideText}>
380
+ <SlideshowLink to={slideshow[activeSlide].path} out={!animationComplete}>
381
+ <SlideshowInfo ref={slideText}>
221
382
  <h1>{slideshow[activeSlide].title}</h1>
222
383
  <p>{slideshow[activeSlide].metaDescription}</p>
223
- </div>
224
- </SafeLink>
384
+ </SlideshowInfo>
385
+ </SlideshowLink>
225
386
  </OneColumn>
226
- </div>
387
+ </SlideLinkWrapper>
227
388
  <NavigationArrow
228
389
  slideIndexTarget={slideIndexTarget > 0 ? slideIndexTarget - 1 : slideshow.length - 1}
229
390
  gotoSlide={gotoSlide}
@@ -234,8 +395,8 @@ const FilmSlideshow = ({ autoSlide = false, slideshow = [], slideInterval = 5000
234
395
  rightArrow
235
396
  />
236
397
  {!animationComplete && (
237
- <div
238
- {...classes('item', 'fade-over')}
398
+ <SlideshowItem
399
+ fadeOver
239
400
  role="img"
240
401
  onAnimationEnd={onChangedSlide}
241
402
  style={{
@@ -245,7 +406,7 @@ const FilmSlideshow = ({ autoSlide = false, slideshow = [], slideInterval = 5000
245
406
  )}
246
407
  <div
247
408
  ref={slideRef}
248
- {...classes('item-wrapper')}
409
+ css={itemWrapperCSS}
249
410
  onTransitionEnd={onTransitionEnd}
250
411
  style={{
251
412
  width: slideshowWidth,
@@ -257,7 +418,7 @@ const FilmSlideshow = ({ autoSlide = false, slideshow = [], slideInterval = 5000
257
418
  </div>
258
419
  <SlideshowIndicator slideshow={slideshow} activeSlide={activeSlide} gotoSlide={gotoSlide} />
259
420
  </>
260
- </section>
421
+ </SlideshowWrapper>
261
422
  );
262
423
  };
263
424
 
@@ -1,15 +1,37 @@
1
1
  import React from 'react';
2
- import BEMHelper from 'react-bem-helper';
3
- import { css } from '@emotion/core';
2
+ import styled from '@emotion/styled';
3
+ import { spacing } from '@ndla/core/src';
4
4
  import { CalculatedCarouselProps } from '@ndla/carousel';
5
5
  import { useTranslation } from 'react-i18next';
6
6
  import FilmContentCard from './FilmContentCard';
7
7
  import { MovieResourceType, MovieType } from './types';
8
+ import { setAnimations, StyledHeadingH1 } from './filmStyles';
8
9
 
9
- const movieListClasses = new BEMHelper({
10
- name: 'film-movielist',
11
- prefix: 'c-',
12
- });
10
+ interface MovieListingProps {
11
+ marginLeft?: number;
12
+ }
13
+
14
+ const MovieListing = styled.div<MovieListingProps>`
15
+ display: flex;
16
+ flex-wrap: wrap;
17
+ margin: ${spacing.small} 0;
18
+ margin-left: ${(props) => props.marginLeft && `${props.marginLeft}px`};
19
+ ${setAnimations()};
20
+ > div {
21
+ opacity: 0;
22
+ animation-fill-mode: forwards;
23
+ animation-name: fadeIn;
24
+ animation-duration: 300ms;
25
+ }
26
+ `;
27
+
28
+ interface LoadingPlaceholderProps {
29
+ height?: string;
30
+ }
31
+
32
+ const LoadingPlaceholder = styled.div<LoadingPlaceholderProps>`
33
+ height: ${(props) => props.height};
34
+ `;
13
35
 
14
36
  interface Props {
15
37
  autoSizedProps: CalculatedCarouselProps;
@@ -33,30 +55,16 @@ const MovieGrid = ({
33
55
  const { t } = useTranslation();
34
56
  return (
35
57
  <section>
36
- <h1
37
- {...movieListClasses('heading')}
38
- css={css`
39
- margin-left: ${autoSizedProps.margin}px;
40
- `}>
58
+ <StyledHeadingH1 marginLeft={autoSizedProps.margin}>
41
59
  {resourceTypeName && resourceTypeName.name}
42
60
  <small>
43
61
  {fetchingMoviesByType
44
62
  ? t('ndlaFilm.loadingMovies')
45
63
  : `${moviesByType.length} ${t('ndlaFilm.movieMatchInCategory')}`}
46
64
  </small>
47
- </h1>
48
- <div
49
- {...movieListClasses('movie-listing')}
50
- css={css`
51
- margin-left: ${autoSizedProps.margin}px;
52
- `}>
53
- {fetchingMoviesByType && (
54
- <div
55
- css={css`
56
- height: ${loadingPlaceholderHeight};
57
- `}
58
- />
59
- )}
65
+ </StyledHeadingH1>
66
+ <MovieListing marginLeft={autoSizedProps.margin}>
67
+ {fetchingMoviesByType && <LoadingPlaceholder height={loadingPlaceholderHeight} />}
60
68
  {!fetchingMoviesByType &&
61
69
  moviesByType.map((movie) => (
62
70
  <FilmContentCard
@@ -68,7 +76,7 @@ const MovieGrid = ({
68
76
  resizeThumbnailImages={resizeThumbnailImages}
69
77
  />
70
78
  ))}
71
- </div>
79
+ </MovieListing>
72
80
  </section>
73
81
  );
74
82
  };
@@ -7,8 +7,10 @@
7
7
  */
8
8
 
9
9
  import React from 'react';
10
- import BEMHelper from 'react-bem-helper';
11
10
  import { ChevronRight, ChevronLeft } from '@ndla/icons/common';
11
+ import styled from '@emotion/styled';
12
+ import { breakpoints, colors, mq, spacing } from '@ndla/core';
13
+ import { css } from '@emotion/core';
12
14
 
13
15
  interface Props {
14
16
  slideIndexTarget: number;
@@ -17,25 +19,89 @@ interface Props {
17
19
  rightArrow?: boolean;
18
20
  }
19
21
 
20
- const classes = new BEMHelper({
21
- name: 'film-slideshow',
22
- prefix: 'c-',
23
- });
22
+ interface StyledNavigationArrowProps {
23
+ right?: boolean;
24
+ }
25
+
26
+ export const StyledNavigationArrow = styled.div<StyledNavigationArrowProps>`
27
+ opacity: 0;
28
+ transition: transform 800ms ease, opacity 800ms ease;
29
+ display: flex;
30
+ justify-content: center;
31
+ flex-direction: column;
32
+ position: absolute;
33
+ align-items: center;
34
+ z-index: 2;
35
+ height: 70vw;
36
+ ${mq.range({ from: breakpoints.tablet })} {
37
+ height: 60vw;
38
+ }
39
+ ${mq.range({ from: breakpoints.desktop })} {
40
+ height: 55vw;
41
+ }
42
+ ${mq.range({ from: breakpoints.wide })} {
43
+ height: 40vw;
44
+ }
45
+ ${mq.range({ from: breakpoints.ultraWide })} {
46
+ height: 36vw;
47
+ }
48
+ transform: translate(${spacing.xsmall}, 0);
49
+ ${(props) =>
50
+ props.right &&
51
+ `
52
+ right: 0;
53
+ transform: translate(${spacing.xsmall}, 0);
54
+ `}
55
+ `;
56
+
57
+ const NavigationArrowButton = styled.button`
58
+ padding: ${spacing.normal} 0;
59
+ border-radius: 4px;
60
+ outline: none;
61
+ background: transparent;
62
+ color: ${colors.white};
63
+ border: 0;
64
+ &:hover,
65
+ &:focus {
66
+ .c-icon {
67
+ opacity: 1;
68
+ }
69
+ background: rgba(0, 0, 0, 0.1);
70
+ }
71
+ `;
72
+
73
+ const chevronCss = css`
74
+ fill: ${colors.white};
75
+ width: 52px;
76
+ height: 52px;
77
+ ${mq.range({ from: breakpoints.desktop })} {
78
+ width: 78px;
79
+ height: 78px;
80
+ }
81
+ opacity: 0.7;
82
+ transition: transform 400ms ease, opacity 400ms ease;
83
+ ${NavigationArrowButton}:focus {
84
+ opacity: 1;
85
+ }
86
+ ${NavigationArrowButton}:hover {
87
+ opacity: 1;
88
+ }
89
+ `;
24
90
 
25
91
  const NavigationArrow = ({ slideIndexTarget, gotoSlide, rightArrow }: Props) => {
26
92
  const Chevron = rightArrow ? ChevronRight : ChevronLeft;
27
93
 
28
94
  return (
29
- <div {...classes('navigation-arrows', rightArrow ? 'right' : '')}>
30
- <button
95
+ <StyledNavigationArrow right={rightArrow}>
96
+ <NavigationArrowButton
31
97
  type="button"
32
98
  tabIndex={-1}
33
99
  onClick={() => {
34
100
  gotoSlide(slideIndexTarget, true);
35
101
  }}>
36
- <Chevron />
37
- </button>
38
- </div>
102
+ <Chevron css={chevronCss} />
103
+ </NavigationArrowButton>
104
+ </StyledNavigationArrow>
39
105
  );
40
106
  };
41
107
 
@@ -7,7 +7,8 @@
7
7
  */
8
8
 
9
9
  import React from 'react';
10
- import BEMHelper from 'react-bem-helper';
10
+ import styled from '@emotion/styled';
11
+ import { breakpoints, colors, mq, spacing } from '@ndla/core';
11
12
  import { MovieType } from './types';
12
13
 
13
14
  interface Props {
@@ -16,24 +17,65 @@ interface Props {
16
17
  gotoSlide: (indexTarget: number, useAnimation: boolean) => void;
17
18
  }
18
19
 
19
- const classes = new BEMHelper({
20
- name: 'film-slideshow',
21
- prefix: 'c-',
22
- });
20
+ const SlideshowIndicatorWrapper = styled.div`
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ margin: ${spacing.small} 0;
25
+ ${mq.range({ from: breakpoints.mobileWide })} {
26
+ margin: ${spacing.normal} 0;
27
+ }
28
+ `;
29
+
30
+ interface SlideshowIndicatorDotProps {
31
+ active?: boolean;
32
+ }
33
+
34
+ const SlideshowIndicatorDot = styled.button<SlideshowIndicatorDotProps>`
35
+ border: 0;
36
+ display: flex;
37
+ justify-content: center;
38
+ background: transparent;
39
+ span {
40
+ background: ${(props) => (props.active ? colors.white : colors.ndlaFilm.filmColorBright)};
41
+ transition: background 100ms ease;
42
+ height: 8px;
43
+ width: 8px;
44
+ ${mq.range({ from: breakpoints.mobileWide })} {
45
+ height: 10px;
46
+ width: 10px;
47
+ }
48
+ ${mq.range({ from: breakpoints.tablet })} {
49
+ height: ${spacing.small};
50
+ width: ${spacing.small};
51
+ }
52
+ border-radius: 100%;
53
+ }
54
+ padding: ${spacing.xsmall};
55
+ ${mq.range({ from: breakpoints.tablet })} {
56
+ padding: ${spacing.small};
57
+ }
58
+ &:hover,
59
+ &:focus {
60
+ span {
61
+ background: ${colors.white};
62
+ }
63
+ }
64
+ `;
23
65
 
24
66
  const SlideshowIndicator = ({ slideshow, activeSlide, gotoSlide }: Props) => {
25
67
  return (
26
- <div {...classes('indicator-wrapper')}>
27
- {slideshow.map((slide, index) => (
28
- <button
68
+ <SlideshowIndicatorWrapper>
69
+ {slideshow.map((_, index) => (
70
+ <SlideshowIndicatorDot
71
+ active={index === activeSlide}
29
72
  key={`indicator_${index}`}
30
73
  type="button"
31
- {...classes('indicator-dot', index === activeSlide ? 'active' : '')}
32
74
  onClick={() => gotoSlide(index, true)}>
33
75
  <span />
34
- </button>
76
+ </SlideshowIndicatorDot>
35
77
  ))}
36
- </div>
78
+ </SlideshowIndicatorWrapper>
37
79
  );
38
80
  };
39
81
 
@@ -7,52 +7,6 @@
7
7
  }
8
8
 
9
9
  .c-film-movielist {
10
- margin-bottom: $spacing;
11
- @include mq(tablet) {
12
- margin-bottom: $spacing--large;
13
- }
14
- &__heading {
15
- @include font-size(22px, 26px);
16
- font-weight: $font-weight-semibold;
17
- text-transform: uppercase;
18
- letter-spacing: 0.05em;
19
- color: #fff;
20
- margin: $spacing--small 0;
21
- small {
22
- font-weight: normal;
23
- padding-left: $spacing--small;
24
- color: $brand-grey--light;
25
- }
26
- }
27
- &__movie-listing {
28
- display: flex;
29
- flex-wrap: wrap;
30
- margin: $spacing--small 0;
31
- @include set-animations();
32
- > div {
33
- opacity: 0;
34
- animation-fill-mode: forwards;
35
- animation-name: fadeIn;
36
- animation-duration: 300ms;
37
- }
38
- }
39
- &__movie-item {
40
- box-shadow: none;
41
- padding: $spacing--small / 2;
42
- @include mq(tablet) {
43
- margin-bottom: $spacing--large;
44
- }
45
- @include mq($from: tablet) {
46
- width: 25%;
47
- }
48
- @include mq($from: mobileWide, $until: tablet) {
49
- width: 33.3%;
50
- }
51
- @include mq($until: mobileWide) {
52
- width: 50%;
53
- }
54
- }
55
-
56
10
  &__carousel-wrapper-buttons {
57
11
  > div {
58
12
  @include set-animations();
@@ -0,0 +1,33 @@
1
+ import styled from '@emotion/styled';
2
+ import { fonts, spacing, colors } from '@ndla/core';
3
+
4
+ export const setAnimations = () => {
5
+ const styles: any = {};
6
+ for (let i = 1; i < 20; i++) {
7
+ styles[`> div:nth-child(${i + 1})`] = {
8
+ 'animation-delay': `${i * 50}ms`,
9
+ };
10
+ }
11
+ return styles;
12
+ };
13
+
14
+ interface StyledHeadingProps {
15
+ marginLeft?: number;
16
+ }
17
+
18
+ export const StyledHeadingH1 = styled.h1<StyledHeadingProps>`
19
+ ${fonts.sizes('22px', '26px')};
20
+ font-weight: ${fonts.weight.semibold};
21
+ text-transform: uppercase;
22
+ letter-spacing: 0.05em;
23
+ color: ${colors.white};
24
+ margin: ${spacing.small} 0;
25
+ margin-left: ${(props) => props.marginLeft && `${props.marginLeft}px`};
26
+ small {
27
+ font-weight: normal;
28
+ padding-left: ${spacing.small};
29
+ color: ${colors.brand.grey};
30
+ }
31
+ `;
32
+
33
+ export const StyledHeadingH2 = StyledHeadingH1.withComponent('h2');