@ndla/ui 25.0.1 → 25.2.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 (159) hide show
  1. package/es/Article/ArticleFavoritesButton.js +2 -1
  2. package/es/Frontpage/FrontpageHeader.js +7 -5
  3. package/es/Frontpage/FrontpageProgramMenu.js +12 -10
  4. package/es/Frontpage/FrontpageSearch.js +5 -3
  5. package/es/Image/Image.js +5 -4
  6. package/es/LanguageSelector/LanguageSelector.js +31 -26
  7. package/es/Masthead/Masthead.js +8 -8
  8. package/es/Masthead/MastheadAuthModal.js +11 -11
  9. package/es/Masthead/MastheadSearchModal.js +9 -11
  10. package/es/NDLAFilm/AboutNdlaFilm.js +3 -3
  11. package/es/NDLAFilm/FilmSlideshow.js +7 -7
  12. package/es/NDLAFilm/NavigationArrow.js +4 -4
  13. package/es/Navigation/NavigationHeading.js +9 -6
  14. package/es/Navigation/NavigationTopicAbout.js +15 -14
  15. package/es/Notion/FigureNotion.js +4 -3
  16. package/es/Notion/NotionVisualElement.js +3 -2
  17. package/es/Programme/Programme.js +10 -7
  18. package/es/Search/SearchField.js +4 -3
  19. package/es/Search/SearchFieldForm.js +4 -3
  20. package/es/Search/ToggleSearchButton.js +3 -3
  21. package/es/SectionHeading/SectionHeading.js +4 -3
  22. package/es/Subject/Subject.js +109 -64
  23. package/es/Subject/SubjectAbout.js +61 -23
  24. package/es/Subject/SubjectArchive.js +109 -67
  25. package/es/Subject/SubjectCarousel.js +39 -62
  26. package/es/Subject/SubjectHeader.js +55 -25
  27. package/es/Subject/SubjectLinks.js +30 -16
  28. package/es/Subject/SubjectNewContent.js +76 -21
  29. package/es/Subject/SubjectShortcuts.js +39 -24
  30. package/es/Subject/SubjectSocial.js +20 -18
  31. package/es/TagSelector/SuggestionInput.js +8 -8
  32. package/es/Topic/Topic.js +21 -20
  33. package/es/TopicMenu/TopicMenu.js +22 -13
  34. package/es/TopicMenu/TopicMenuButton.js +5 -5
  35. package/es/all.css +1 -1
  36. package/es/index.js +1 -0
  37. package/es/locale/messages-nb.js +23 -23
  38. package/es/locale/messages-nn.js +29 -29
  39. package/es/locale/messages-se.js +24 -24
  40. package/es/locale/messages-sma.js +24 -24
  41. package/lib/Article/ArticleFavoritesButton.js +2 -1
  42. package/lib/Frontpage/FrontpageHeader.js +7 -5
  43. package/lib/Frontpage/FrontpageMultidisciplinarySubject.d.ts +5 -5
  44. package/lib/Frontpage/FrontpageProgramMenu.js +12 -10
  45. package/lib/Frontpage/FrontpageSearch.js +6 -3
  46. package/lib/Frontpage/illustrations/FrontpageIllustrations.d.ts +2 -2
  47. package/lib/Image/Image.d.ts +1 -1
  48. package/lib/Image/Image.js +5 -4
  49. package/lib/LanguageSelector/LanguageSelector.d.ts +1 -1
  50. package/lib/LanguageSelector/LanguageSelector.js +31 -26
  51. package/lib/Masthead/Masthead.js +8 -8
  52. package/lib/Masthead/MastheadAuthModal.js +11 -11
  53. package/lib/Masthead/MastheadSearchModal.js +9 -11
  54. package/lib/MultidisciplinarySubject/Illustrations.d.ts +7 -7
  55. package/lib/NDLAFilm/AboutNdlaFilm.js +4 -4
  56. package/lib/NDLAFilm/FilmSlideshow.js +7 -7
  57. package/lib/NDLAFilm/NavigationArrow.js +4 -4
  58. package/lib/Navigation/NavigationHeading.d.ts +2 -1
  59. package/lib/Navigation/NavigationHeading.js +9 -6
  60. package/lib/Navigation/NavigationTopicAbout.js +15 -14
  61. package/lib/Notion/FigureNotion.d.ts +2 -1
  62. package/lib/Notion/FigureNotion.js +4 -3
  63. package/lib/Notion/NotionVisualElement.d.ts +1 -0
  64. package/lib/Notion/NotionVisualElement.js +3 -2
  65. package/lib/Programme/Programme.d.ts +2 -1
  66. package/lib/Programme/Programme.js +10 -7
  67. package/lib/Resource/resourceComponents.d.ts +2 -2
  68. package/lib/Search/ActiveFilterContent.d.ts +1 -1
  69. package/lib/Search/ContentTypeResultStyles.d.ts +3 -3
  70. package/lib/Search/SearchField.js +4 -3
  71. package/lib/Search/SearchFieldForm.js +4 -3
  72. package/lib/Search/ToggleSearchButton.js +3 -3
  73. package/lib/SearchTypeResult/ActiveFilterContent.d.ts +1 -1
  74. package/lib/SectionHeading/SectionHeading.js +4 -3
  75. package/lib/Subject/Subject.d.ts +30 -82
  76. package/lib/Subject/Subject.js +90 -62
  77. package/lib/Subject/SubjectAbout.d.ts +1 -15
  78. package/lib/Subject/SubjectAbout.js +56 -25
  79. package/lib/Subject/SubjectArchive.d.ts +0 -21
  80. package/lib/Subject/SubjectArchive.js +103 -73
  81. package/lib/Subject/SubjectCarousel.d.ts +1 -31
  82. package/lib/Subject/SubjectCarousel.js +47 -76
  83. package/lib/Subject/SubjectHeader.d.ts +1 -14
  84. package/lib/Subject/SubjectHeader.js +53 -28
  85. package/lib/Subject/SubjectLinks.d.ts +1 -11
  86. package/lib/Subject/SubjectLinks.js +29 -19
  87. package/lib/Subject/SubjectNewContent.d.ts +1 -13
  88. package/lib/Subject/SubjectNewContent.js +70 -24
  89. package/lib/Subject/SubjectShortcuts.d.ts +0 -13
  90. package/lib/Subject/SubjectShortcuts.js +38 -29
  91. package/lib/Subject/SubjectSocial.d.ts +7 -22
  92. package/lib/Subject/SubjectSocial.js +19 -21
  93. package/lib/TagSelector/SuggestionInput.js +8 -8
  94. package/lib/Topic/Topic.js +21 -20
  95. package/lib/TopicMenu/TopicMenu.js +47 -39
  96. package/lib/TopicMenu/TopicMenuButton.js +6 -6
  97. package/lib/all.css +1 -1
  98. package/lib/index.d.ts +1 -0
  99. package/lib/index.js +12 -3
  100. package/lib/locale/messages-nb.js +23 -23
  101. package/lib/locale/messages-nn.js +29 -29
  102. package/lib/locale/messages-se.js +24 -24
  103. package/lib/locale/messages-sma.js +24 -24
  104. package/package.json +14 -14
  105. package/src/Article/ArticleFavoritesButton.tsx +2 -1
  106. package/src/Frontpage/FrontpageHeader.tsx +1 -1
  107. package/src/Frontpage/FrontpageProgramMenu.tsx +1 -1
  108. package/src/Frontpage/FrontpageSearch.tsx +3 -1
  109. package/src/Image/Image.tsx +1 -1
  110. package/src/LanguageSelector/LanguageSelector.tsx +21 -23
  111. package/src/Masthead/Masthead.tsx +2 -0
  112. package/src/Masthead/MastheadAuthModal.tsx +16 -16
  113. package/src/Masthead/MastheadSearchModal.tsx +6 -23
  114. package/src/NDLAFilm/AboutNdlaFilm.tsx +2 -2
  115. package/src/NDLAFilm/FilmSlideshow.tsx +2 -0
  116. package/src/NDLAFilm/NavigationArrow.tsx +4 -4
  117. package/src/Navigation/NavigationHeading.tsx +3 -2
  118. package/src/Navigation/NavigationTopicAbout.tsx +1 -0
  119. package/src/Notion/FigureNotion.tsx +5 -2
  120. package/src/Notion/NotionVisualElement.tsx +2 -0
  121. package/src/Programme/Programme.tsx +11 -2
  122. package/src/Search/SearchField.tsx +6 -1
  123. package/src/Search/SearchFieldForm.tsx +1 -1
  124. package/src/Search/ToggleSearchButton.tsx +2 -2
  125. package/src/SectionHeading/SectionHeading.tsx +6 -2
  126. package/src/Subject/Subject.tsx +151 -72
  127. package/src/Subject/SubjectAbout.tsx +97 -27
  128. package/src/Subject/SubjectArchive.tsx +129 -58
  129. package/src/Subject/SubjectCarousel.tsx +42 -36
  130. package/src/Subject/SubjectHeader.tsx +75 -34
  131. package/src/Subject/SubjectLinks.tsx +21 -19
  132. package/src/Subject/SubjectNewContent.tsx +87 -32
  133. package/src/Subject/SubjectShortcuts.tsx +67 -27
  134. package/src/Subject/SubjectSocial.tsx +19 -20
  135. package/src/TagSelector/SuggestionInput.tsx +1 -1
  136. package/src/Topic/Topic.tsx +1 -0
  137. package/src/TopicMenu/TopicMenu.jsx +23 -17
  138. package/src/TopicMenu/TopicMenuButton.jsx +6 -7
  139. package/src/index.ts +2 -0
  140. package/src/locale/messages-nb.ts +22 -23
  141. package/src/locale/messages-nn.ts +28 -28
  142. package/src/locale/messages-se.ts +23 -24
  143. package/src/locale/messages-sma.ts +23 -24
  144. package/src/main.scss +0 -2
  145. package/es/Article/ArticleAuthorContent.js +0 -71
  146. package/lib/Article/ArticleAuthorContent.d.ts +0 -28
  147. package/lib/Article/ArticleAuthorContent.js +0 -88
  148. package/src/.DS_Store +0 -0
  149. package/src/Article/ArticleAuthorContent.tsx +0 -107
  150. package/src/Article/component.article-author-popup.scss +0 -90
  151. package/src/Subject/component.subject-about.scss +0 -73
  152. package/src/Subject/component.subject-archive.scss +0 -92
  153. package/src/Subject/component.subject-carousel.scss +0 -32
  154. package/src/Subject/component.subject-concepts.scss +0 -37
  155. package/src/Subject/component.subject-header.scss +0 -87
  156. package/src/Subject/component.subject-links.scss +0 -14
  157. package/src/Subject/component.subject-new-content.scss +0 -82
  158. package/src/Subject/component.subject-shortcut.scss +0 -57
  159. package/src/Subject/component.subject.scss +0 -213
@@ -1,11 +1,76 @@
1
1
  import React, { ReactNode } from 'react';
2
- import PropTypes from 'prop-types';
3
- import BEMHelper from 'react-bem-helper';
4
-
2
+ import styled from '@emotion/styled';
3
+ import { css } from '@emotion/core';
4
+ import { breakpoints, colors, mq, spacing, spacingUnit } from '@ndla/core';
5
5
  import SectionHeading from '../SectionHeading';
6
6
 
7
- const classes = BEMHelper('c-subject-content');
8
-
7
+ const SubjectContentWrapper = styled.div`
8
+ ${mq.range({ from: breakpoints.tablet })} {
9
+ margin-bottom: 100px;
10
+ }
11
+ `;
12
+
13
+ const StyledBreadcrumb = styled.div`
14
+ display: none;
15
+ margin: ${spacing.medium} 0 0 0;
16
+ ${mq.range({ from: breakpoints.tablet })} {
17
+ display: block;
18
+ margin-left: ${spacingUnit * 3}px;
19
+ }
20
+ `;
21
+
22
+ interface StyledSubjectContentProps {
23
+ twoColumns: boolean;
24
+ }
25
+ const StyledSubjectContent = styled.div<StyledSubjectContentProps>`
26
+ display: block;
27
+ flex-flow: column;
28
+ margin-top: ${spacing.small};
29
+ ${mq.range({ from: breakpoints.tablet })} {
30
+ display: flex;
31
+ flex-flow: row;
32
+ margin-top: ${spacing.large};
33
+ > *:not(:only-child):last-child {
34
+ padding-left: ${spacingUnit * 3}px;
35
+ }
36
+ }
37
+
38
+ & > *:first-child {
39
+ margin-bottom: ${spacing.large};
40
+ ${mq.range({ from: breakpoints.tablet })} {
41
+ margin-right: 80px;
42
+ }
43
+ }
44
+
45
+ ${(p) =>
46
+ !p.twoColumns &&
47
+ css`
48
+ ${mq.range({ from: breakpoints.desktop })} {
49
+ > *:not(:only-child) {
50
+ max-width: 50%;
51
+ }
52
+ }
53
+ ${mq.range({ until: breakpoints.desktop })} {
54
+ flex-direction: column;
55
+ }
56
+ ${mq.range({ from: breakpoints.tablet, until: breakpoints.desktop })} {
57
+ > *:not(:only-child):last-child {
58
+ padding-left: $subject-margin;
59
+ }
60
+ }
61
+ `};
62
+
63
+ ${(p) =>
64
+ p.twoColumns &&
65
+ css`
66
+ flex-flow: column;
67
+ & > *:first-child {
68
+ ${mq.range({ from: breakpoints.tablet })} {
69
+ margin-right: 0;
70
+ }
71
+ }
72
+ `};
73
+ `;
9
74
  export const SubjectContent = ({
10
75
  children,
11
76
  breadcrumb,
@@ -15,102 +80,116 @@ export const SubjectContent = ({
15
80
  breadcrumb: ReactNode;
16
81
  twoColumns?: boolean;
17
82
  }) => (
18
- <div {...classes()}>
19
- <div {...classes('breadcrumb')}>{breadcrumb}</div>
20
- <div {...classes('content', { twoColumns })}>{children}</div>
21
- </div>
83
+ <SubjectContentWrapper>
84
+ <StyledBreadcrumb>{breadcrumb}</StyledBreadcrumb>
85
+ <StyledSubjectContent twoColumns={twoColumns}>{children}</StyledSubjectContent>
86
+ </SubjectContentWrapper>
22
87
  );
23
88
 
24
- SubjectContent.propTypes = {
25
- children: PropTypes.node.isRequired,
26
- breadcrumb: PropTypes.node.isRequired,
27
- twoColumns: PropTypes.bool,
28
- };
89
+ const StyledSecondaryContent = styled.div`
90
+ background: ${colors.brand.greyLightest};
91
+ padding: ${spacing.large} 0;
92
+ margin-top: ${spacing.large};
29
93
 
30
- const secondaryContentClass = BEMHelper('c-subject-secondary-content');
94
+ ${mq.range({ from: breakpoints.tablet })} {
95
+ padding: ${spacingUnit * 3}px 0 ${spacing.large};
96
+ margin-bottom: 100px;
97
+ margin-top: 0;
98
+ }
99
+ `;
31
100
 
32
101
  export const SubjectSecondaryContent = ({ children }: { children: ReactNode }) => (
33
- <div {...secondaryContentClass()}>{children}</div>
102
+ <StyledSecondaryContent>{children}</StyledSecondaryContent>
34
103
  );
35
104
 
36
- SubjectSecondaryContent.propTypes = {
37
- children: PropTypes.node.isRequired,
38
- };
39
-
40
- const childContentClasses = BEMHelper('c-subject-child-content');
105
+ const StyledChildContent = styled.div`
106
+ padding: 0 ${spacing.normal};
107
+ `;
41
108
 
42
109
  export const SubjectChildContent = ({ children }: { children: ReactNode }) => (
43
- <div {...childContentClasses()}>{children}</div>
110
+ <StyledChildContent>{children}</StyledChildContent>
44
111
  );
45
112
 
46
- SubjectChildContent.propTypes = {
47
- children: PropTypes.node.isRequired,
48
- };
49
-
50
- const topicClasses = BEMHelper('c-subject-topics');
51
-
52
113
  export const SubjectTopics = ({ messages, children }: { messages: { heading: string }; children: ReactNode }) => (
53
- <section {...topicClasses()}>
54
- <header {...topicClasses('header')}>
55
- <h1 {...topicClasses('heading')}>{messages.heading}</h1>
114
+ <section>
115
+ <header>
116
+ <h1>{messages.heading}</h1>
56
117
  </header>
57
- <div {...topicClasses('content')}>{children}</div>
118
+ <div>{children}</div>
58
119
  </section>
59
120
  );
60
121
 
61
- SubjectTopics.propTypes = {
62
- messages: PropTypes.shape({
63
- heading: PropTypes.string.isRequired,
64
- }),
65
- children: PropTypes.node.isRequired,
66
- };
122
+ const SidebarWrapper = styled.div`
123
+ display: block;
124
+ margin: 0 ${spacing.normal};
125
+
126
+ & > *:last-child {
127
+ margin-bottom: 0;
128
+ }
67
129
 
68
- const sidebarClasses = BEMHelper('c-subject-sidebar-wrapper');
130
+ ${mq.range({ from: breakpoints.tablet })} {
131
+ flex-basis: 390px;
132
+ flex-shrink: 0;
133
+ margin: 0px 0 0 0;
134
+ }
135
+ `;
69
136
 
70
137
  export const SubjectSidebarWrapper = ({ children }: { children: ReactNode }) => (
71
- <div {...sidebarClasses()}>{children}</div>
138
+ <SidebarWrapper>{children}</SidebarWrapper>
72
139
  );
73
140
 
74
- SubjectSidebarWrapper.propTypes = {
75
- children: PropTypes.node.isRequired,
76
- };
141
+ interface StyledSubjectFlexWrapperProps {
142
+ noMargin: boolean;
143
+ }
144
+ const StyledSubjectFlexWrapper = styled.div<StyledSubjectFlexWrapperProps>`
145
+ display: flex;
146
+ flex-direction: column;
147
+ margin-bottom: ${(p) => !p.noMargin && spacing.large};
77
148
 
78
- const subjectFlexWrapperClasses = BEMHelper('c-subject-flex');
149
+ ${mq.range({ from: breakpoints.tablet })} {
150
+ flex-direction: row;
151
+ }
152
+ `;
79
153
 
80
154
  export const SubjectFlexWrapper = ({ children, noMargin = false }: { children: ReactNode; noMargin?: boolean }) => (
81
- <div {...subjectFlexWrapperClasses('', { noMargin })}>{children}</div>
155
+ <StyledSubjectFlexWrapper noMargin={noMargin}>{children}</StyledSubjectFlexWrapper>
82
156
  );
83
157
 
84
- SubjectFlexWrapper.propTypes = {
85
- children: PropTypes.node.isRequired,
86
- noMargin: PropTypes.bool,
87
- };
158
+ const StyledSubjectFlexChild = styled.div`
159
+ box-sizing: border-box;
160
+ padding: 0 ${spacing.small};
161
+ ${mq.range({ from: breakpoints.tablet })} {
162
+ flex-basis: 50%;
163
+ flex-grow: 1;
164
+ flex-direction: row;
165
+ }
166
+
167
+ &:last-child {
168
+ & > * {
169
+ ${mq.range({ until: breakpoints.tablet })} {
170
+ margin-bottom: 0;
171
+ }
172
+ }
173
+ }
174
+ & > * {
175
+ ${mq.range({ from: breakpoints.tablet })} {
176
+ margin-bottom: o;
177
+ }
178
+ }
179
+ `;
88
180
 
89
181
  export const SubjectFlexChild = ({ children }: { children: ReactNode }) => (
90
- <div className="c-subject-flex__child">{children}</div>
182
+ <StyledSubjectFlexChild>{children}</StyledSubjectFlexChild>
91
183
  );
92
184
 
93
- SubjectFlexChild.propTypes = {
94
- children: PropTypes.node.isRequired,
95
- };
185
+ const StyledSectionHeading = styled(SectionHeading)`
186
+ margin: 0 0 ${spacing.small} 0;
96
187
 
97
- export const SubjectSectionTitle = ({
98
- children,
99
- className = null,
100
- }: {
101
- children: ReactNode;
102
- className?: string | null;
103
- }) => (
104
- <SectionHeading large className={`c-subject-section-title ${className}`}>
105
- {children}
106
- </SectionHeading>
107
- );
108
-
109
- SubjectSectionTitle.propTypes = {
110
- children: PropTypes.string.isRequired,
111
- className: PropTypes.string,
112
- };
188
+ ${mq.range({ from: breakpoints.tablet })} {
189
+ margin: 0 0 ${spacing.normal} 0;
190
+ }
191
+ `;
113
192
 
114
- SubjectSectionTitle.defaultProps = {
115
- className: null,
116
- };
193
+ export const SubjectSectionTitle = ({ children }: { children: ReactNode }) => (
194
+ <StyledSectionHeading large>{children}</StyledSectionHeading>
195
+ );
@@ -1,10 +1,9 @@
1
1
  import React, { ReactNode } from 'react';
2
- import PropTypes from 'prop-types';
3
- import BEMHelper from 'react-bem-helper';
2
+ import { css } from '@emotion/core';
3
+ import styled from '@emotion/styled';
4
+ import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
4
5
  import SectionHeading from '../SectionHeading';
5
6
 
6
- const classes = BEMHelper('c-subject-about');
7
-
8
7
  interface Props {
9
8
  fixedWidth?: boolean;
10
9
  wide?: boolean;
@@ -13,30 +12,101 @@ interface Props {
13
12
  description: string;
14
13
  }
15
14
 
15
+ interface SubjectAboutSectionProps {
16
+ fixedWidth: boolean;
17
+ wide: boolean;
18
+ }
19
+
20
+ const SubjectAboutSection = styled.section<SubjectAboutSectionProps>`
21
+ margin-bottom: ${spacing.large};
22
+ max-width: ${(p) => p.fixedWidth && '350px'};
23
+
24
+ ${(p) =>
25
+ p.wide &&
26
+ css`
27
+ margin: 40px 0;
28
+ ${mq.range({ from: breakpoints.tablet })} {
29
+ display: flex;
30
+ margin: 80px 0;
31
+ }
32
+ `};
33
+ ${mq.range({ from: breakpoints.tablet })} {
34
+ border: 1px solid ${colors.brand.greyLight};
35
+ }
36
+ `;
37
+
38
+ const StyledSectionHeading = styled(SectionHeading)`
39
+ margin: 0 0 ${spacing.small} 0;
40
+ ${mq.range({ from: breakpoints.tablet })} {
41
+ display: none;
42
+ }
43
+ `;
44
+
45
+ interface MediaWrapperProps {
46
+ wide?: boolean;
47
+ }
48
+
49
+ const MediaWrapper = styled.div<MediaWrapperProps>`
50
+ width: 100%;
51
+ display: flex;
52
+ justify-content: center;
53
+ align-items: center;
54
+ text-align: center;
55
+ & > *,
56
+ img {
57
+ width: 100%;
58
+ }
59
+ ${mq.range({ from: breakpoints.tablet })} {
60
+ width: 50%;
61
+ min-width: 50%;
62
+ }
63
+ ${mq.range({ from: breakpoints.desktop })} {
64
+ width: 40%;
65
+ min-width: 40%;
66
+ }
67
+ ${(p) =>
68
+ p.wide &&
69
+ css`
70
+ margin: 40px 0;
71
+ ${mq.range({ from: breakpoints.tablet })} {
72
+ display: flex;
73
+ margin: 80px 0;
74
+ }
75
+ `};
76
+ `;
77
+
78
+ const StyledContent = styled.div`
79
+ padding: ${spacing.small} 0 0 0;
80
+ ${mq.range({ from: breakpoints.tablet })} {
81
+ padding: ${spacing.normal};
82
+ }
83
+ `;
84
+
85
+ const StyledMainHeading = styled.h1`
86
+ margin: 0 0 ${spacing.small} 0;
87
+ ${fonts.sizes('14px', '32px')};
88
+ text-transform: uppercase;
89
+ font-weight: ${fonts.weight.bold};
90
+ display: none;
91
+ ${mq.range({ from: breakpoints.tablet })} {
92
+ display: block;
93
+ }
94
+ `;
95
+
96
+ const StyledDescription = styled.p`
97
+ margin: 0;
98
+ ${fonts.sizes('16px', '26px')};
99
+ `;
100
+
16
101
  const SubjectAbout = ({ fixedWidth = false, media, heading, description, wide = false }: Props) => (
17
- <section {...classes('', { fixedWidth, wide })}>
18
- <SectionHeading large className={classes('top-heading').className}>
19
- {heading}
20
- </SectionHeading>
21
- <div {...classes('media-wrapper', { wide })}>{media}</div>
22
- <div {...classes('content')}>
23
- <h1 {...classes('main-heading')}>{heading}</h1>
24
- <p {...classes('description')}>{description}</p>
25
- </div>
26
- </section>
102
+ <SubjectAboutSection wide={wide} fixedWidth={fixedWidth}>
103
+ <StyledSectionHeading large>{heading}</StyledSectionHeading>
104
+ <MediaWrapper>{media}</MediaWrapper>
105
+ <StyledContent>
106
+ <StyledMainHeading>{heading}</StyledMainHeading>
107
+ <StyledDescription>{description}</StyledDescription>
108
+ </StyledContent>
109
+ </SubjectAboutSection>
27
110
  );
28
111
 
29
- SubjectAbout.propTypes = {
30
- fixedWidth: PropTypes.bool,
31
- wide: PropTypes.bool,
32
- media: PropTypes.node.isRequired,
33
- heading: PropTypes.string.isRequired,
34
- description: PropTypes.string.isRequired,
35
- };
36
-
37
- SubjectAbout.defaultProps = {
38
- fixedWidth: false,
39
- wide: false,
40
- };
41
-
42
112
  export default SubjectAbout;
@@ -1,13 +1,11 @@
1
- import React, { ReactNode, Component, createRef, Fragment, RefObject } from 'react';
2
- import PropTypes from 'prop-types';
3
- import BEMHelper from 'react-bem-helper';
1
+ import React, { ReactNode, Component, createRef, RefObject } from 'react';
2
+ import styled from '@emotion/styled';
4
3
  import { Forward } from '@ndla/icons/common';
5
4
  import { Cross } from '@ndla/icons/action';
5
+ import { breakpoints, colors, fonts, mq, spacing, utils } from '@ndla/core';
6
6
  import SafeLink from '@ndla/safelink';
7
7
  import SectionHeading from '../SectionHeading';
8
8
 
9
- const classes = BEMHelper('c-subject-archive');
10
-
11
9
  interface Props {
12
10
  featuringArticle: {
13
11
  media: ReactNode;
@@ -26,6 +24,109 @@ interface State {
26
24
  minHeight: number | null;
27
25
  }
28
26
 
27
+ interface SubjectArchiveSectionProps {
28
+ fixedWidth: boolean;
29
+ animate: boolean;
30
+ }
31
+
32
+ const ArchiveWrapper = styled.div`
33
+ display: flex;
34
+ flex-flow: column;
35
+ `;
36
+
37
+ const StyledSectionHeading = styled(SectionHeading)`
38
+ margin: 0 0 ${spacing.small} 0;
39
+ ${mq.range({ from: breakpoints.tablet })} {
40
+ ${utils.visuallyHidden};
41
+ }
42
+ `;
43
+
44
+ const ArchiveButon = styled.button`
45
+ display: inline-flex;
46
+ align-items: center;
47
+ cursor: pointer;
48
+ margin: ${spacing.small} 0 0 0;
49
+ padding: ${spacing.xsmall} 0;
50
+ border: 0;
51
+ color: ${colors.brand.primary};
52
+ ${fonts.sizes('16px', '24px')};
53
+ font-weight: ${fonts.weight.semibold};
54
+ ${mq.range({ from: breakpoints.tablet })} {
55
+ margin: ${spacing.xsmall} ${spacing.normal} ${spacing.normal};
56
+ }
57
+ c-icon {
58
+ width: 18px;
59
+ height: 18px;
60
+ margin-right: ${spacing.small};
61
+ }
62
+ `;
63
+
64
+ interface StyledNavProps {
65
+ animate: boolean;
66
+ }
67
+ const StyledNav = styled.nav<StyledNavProps>`
68
+ padding: 0;
69
+ animation: ${(p) => p.animate && 'fadeIn 0.3s ease-in-out'};
70
+ ${mq.range({ from: breakpoints.tablet })} {
71
+ padding: ${spacing.large} ${spacing.large} 0 ${spacing.large};
72
+ }
73
+ `;
74
+
75
+ const StyledArchiveList = styled.ul`
76
+ list-style: none;
77
+ margin: 0;
78
+ padding: 0;
79
+
80
+ li {
81
+ ${fonts.sizes('16px', '24px')};
82
+ margin-bottom: ${spacing.small};
83
+ }
84
+ `;
85
+
86
+ const MediaWrapper = styled.div`
87
+ width: 100%;
88
+ & > * {
89
+ width: 100%;
90
+ }
91
+ `;
92
+
93
+ const StyledContent = styled.div`
94
+ padding: ${spacing.small} 0 0 0;
95
+ ${mq.range({ from: breakpoints.tablet })} {
96
+ padding: ${spacing.normal};
97
+ }
98
+ `;
99
+
100
+ const StyledHeading = styled.h1`
101
+ ${fonts.sizes('20px', '32px')};
102
+ margin: 0 0 ${spacing.small} 0;
103
+ flex: 0 0 auto;
104
+ `;
105
+
106
+ const StyledDescription = styled.p`
107
+ margin: 0;
108
+ ${fonts.sizes('16px', '26px')}
109
+ `;
110
+
111
+ const SubjectArchiveSection = styled.section<SubjectArchiveSectionProps>`
112
+ margin-bottom: ${spacing.large};
113
+ display: flex;
114
+ flex-direction: column;
115
+ max-width: ${(p) => p.fixedWidth && '350px'};
116
+ animation: ${(p) => p.animate && 'fadeIn 0.3s ease-in-out'};
117
+
118
+ ${mq.range({ from: breakpoints.tablet })} {
119
+ border: 1px solid ${colors.brand.greyLight};
120
+ }
121
+ `;
122
+
123
+ interface FeaturingSectionProps {
124
+ animate: boolean;
125
+ }
126
+ const FeaturingSection = styled.section<FeaturingSectionProps>`
127
+ animation: ${(p) => p.animate && 'fadeIn 0.3s ease-in-out'};
128
+ `;
129
+
29
130
  class SubjectArchive extends Component<Props, State> {
30
131
  wrapperRef: RefObject<HTMLElement> | null = createRef<HTMLElement>();
31
132
  constructor(props: Props) {
@@ -59,81 +160,51 @@ class SubjectArchive extends Component<Props, State> {
59
160
  const archiveId = 'subject-archive';
60
161
 
61
162
  const section = this.state.archiveOpen ? (
62
- <nav id={archiveId} {...classes('archive')}>
63
- <ul {...classes('archive-articles')}>
163
+ <StyledNav id={archiveId} animate={!!this.state.minHeight}>
164
+ <StyledArchiveList>
64
165
  {archiveArticles.map((article) => (
65
166
  <li key={article.heading}>
66
167
  <SafeLink to={article.url}>{article.heading}</SafeLink>
67
168
  </li>
68
169
  ))}
69
- </ul>
70
- </nav>
170
+ </StyledArchiveList>
171
+ </StyledNav>
71
172
  ) : (
72
- <section {...classes('featuring')}>
73
- <div {...classes('media-wrapper')}>{featuringArticle.media}</div>
74
- <div {...classes('content')}>
75
- <h1 {...classes('heading')}>
173
+ <FeaturingSection animate={!!this.state.minHeight}>
174
+ <MediaWrapper>{featuringArticle.media}</MediaWrapper>
175
+ <StyledContent>
176
+ <StyledHeading>
76
177
  <SafeLink to={featuringArticle.url}>{featuringArticle.heading}</SafeLink>
77
- </h1>
78
- <p {...classes('description')}>{featuringArticle.description}</p>
79
- </div>
80
- </section>
178
+ </StyledHeading>
179
+ <StyledDescription>{featuringArticle.description}</StyledDescription>
180
+ </StyledContent>
181
+ </FeaturingSection>
81
182
  );
82
183
 
83
- const subClasses = Object.entries({ fixedWidth, animate: !!this.state.minHeight })
84
- .filter(([_, include]) => include)
85
- .map(([className, _]) => className);
86
-
87
184
  return (
88
- <section {...classes('', subClasses)} ref={this.wrapperRef}>
89
- <SectionHeading large className={classes('section-heading').className}>
90
- {sectionHeading}
91
- </SectionHeading>
92
- <div {...classes('wrapper')}>
185
+ <SubjectArchiveSection animate={!!this.state.minHeight} fixedWidth={fixedWidth} ref={this.wrapperRef}>
186
+ <StyledSectionHeading large>{sectionHeading}</StyledSectionHeading>
187
+ <ArchiveWrapper>
93
188
  {section}
94
- <button
189
+ <ArchiveButon
95
190
  type="button"
96
191
  aria-expanded={this.state.archiveOpen}
97
192
  aria-controls={archiveId}
98
- className={classes('archive-button').className}
99
193
  onClick={this.handleToggleArchive}>
100
194
  {this.state.archiveOpen ? (
101
- <Fragment>
195
+ <>
102
196
  <Cross /> <span>{messages.close}</span>
103
- </Fragment>
197
+ </>
104
198
  ) : (
105
- <Fragment>
199
+ <>
106
200
  <Forward /> <span>{messages.archive}</span>
107
- </Fragment>
201
+ </>
108
202
  )}
109
- </button>
110
- </div>
111
- </section>
203
+ </ArchiveButon>
204
+ </ArchiveWrapper>
205
+ </SubjectArchiveSection>
112
206
  );
113
207
  }
114
- static propTypes = {
115
- featuringArticle: PropTypes.shape({
116
- media: PropTypes.node.isRequired,
117
- heading: PropTypes.string.isRequired,
118
- description: PropTypes.string.isRequired,
119
- url: PropTypes.string.isRequired,
120
- }).isRequired,
121
- archiveArticles: PropTypes.arrayOf(
122
- PropTypes.shape({
123
- url: PropTypes.string.isRequired,
124
- heading: PropTypes.string.isRequired,
125
- }),
126
- ).isRequired,
127
- sectionHeading: PropTypes.string.isRequired,
128
- fixedWidth: PropTypes.bool,
129
- messages: PropTypes.shape({
130
- archive: PropTypes.string.isRequired,
131
- }),
132
- };
133
-
134
- static defaultProps = {
135
- fixedWidth: false,
136
- };
137
208
  }
138
209
 
139
210
  export default SubjectArchive;