@ndla/ui 25.0.0 → 25.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 (95) hide show
  1. package/es/Frontpage/FrontpageSearch.js +5 -3
  2. package/es/Masthead/Masthead.js +7 -7
  3. package/es/NDLAFilm/FilmSlideshow.js +7 -7
  4. package/es/NDLAFilm/NavigationArrow.js +4 -4
  5. package/es/Notion/FigureNotion.js +4 -3
  6. package/es/Notion/NotionVisualElement.js +3 -2
  7. package/es/SectionHeading/SectionHeading.js +5 -4
  8. package/es/Subject/Subject.js +109 -64
  9. package/es/Subject/SubjectAbout.js +61 -23
  10. package/es/Subject/SubjectArchive.js +109 -67
  11. package/es/Subject/SubjectCarousel.js +39 -62
  12. package/es/Subject/SubjectHeader.js +55 -25
  13. package/es/Subject/SubjectLinks.js +30 -16
  14. package/es/Subject/SubjectNewContent.js +76 -21
  15. package/es/Subject/SubjectShortcuts.js +39 -24
  16. package/es/Subject/SubjectSocial.js +20 -18
  17. package/es/all.css +1 -1
  18. package/es/index.js +1 -0
  19. package/es/locale/messages-nb.js +21 -21
  20. package/es/locale/messages-nn.js +27 -27
  21. package/es/locale/messages-se.js +22 -22
  22. package/es/locale/messages-sma.js +22 -22
  23. package/lib/Frontpage/FrontpageMultidisciplinarySubject.d.ts +5 -5
  24. package/lib/Frontpage/FrontpageSearch.js +6 -3
  25. package/lib/Frontpage/illustrations/FrontpageIllustrations.d.ts +2 -2
  26. package/lib/Masthead/Masthead.js +16 -16
  27. package/lib/MultidisciplinarySubject/Illustrations.d.ts +7 -7
  28. package/lib/NDLAFilm/FilmSlideshow.js +7 -7
  29. package/lib/NDLAFilm/NavigationArrow.js +4 -4
  30. package/lib/Notion/FigureNotion.d.ts +2 -1
  31. package/lib/Notion/FigureNotion.js +4 -3
  32. package/lib/Notion/NotionVisualElement.d.ts +1 -0
  33. package/lib/Notion/NotionVisualElement.js +3 -2
  34. package/lib/Resource/resourceComponents.d.ts +2 -2
  35. package/lib/Search/ActiveFilterContent.d.ts +1 -1
  36. package/lib/Search/ContentTypeResultStyles.d.ts +3 -3
  37. package/lib/SearchTypeResult/ActiveFilterContent.d.ts +1 -1
  38. package/lib/SectionHeading/SectionHeading.js +10 -9
  39. package/lib/Subject/Subject.d.ts +30 -82
  40. package/lib/Subject/Subject.js +90 -62
  41. package/lib/Subject/SubjectAbout.d.ts +1 -15
  42. package/lib/Subject/SubjectAbout.js +56 -25
  43. package/lib/Subject/SubjectArchive.d.ts +0 -21
  44. package/lib/Subject/SubjectArchive.js +103 -73
  45. package/lib/Subject/SubjectCarousel.d.ts +1 -31
  46. package/lib/Subject/SubjectCarousel.js +47 -76
  47. package/lib/Subject/SubjectHeader.d.ts +1 -14
  48. package/lib/Subject/SubjectHeader.js +53 -28
  49. package/lib/Subject/SubjectLinks.d.ts +1 -11
  50. package/lib/Subject/SubjectLinks.js +29 -19
  51. package/lib/Subject/SubjectNewContent.d.ts +1 -13
  52. package/lib/Subject/SubjectNewContent.js +70 -24
  53. package/lib/Subject/SubjectShortcuts.d.ts +0 -13
  54. package/lib/Subject/SubjectShortcuts.js +38 -29
  55. package/lib/Subject/SubjectSocial.d.ts +7 -22
  56. package/lib/Subject/SubjectSocial.js +19 -21
  57. package/lib/all.css +1 -1
  58. package/lib/index.d.ts +1 -0
  59. package/lib/index.js +12 -3
  60. package/lib/locale/messages-nb.js +21 -21
  61. package/lib/locale/messages-nn.js +27 -27
  62. package/lib/locale/messages-se.js +22 -22
  63. package/lib/locale/messages-sma.js +22 -22
  64. package/package.json +14 -14
  65. package/src/Frontpage/FrontpageSearch.tsx +3 -1
  66. package/src/Masthead/Masthead.tsx +1 -1
  67. package/src/NDLAFilm/FilmSlideshow.tsx +2 -0
  68. package/src/NDLAFilm/NavigationArrow.tsx +4 -4
  69. package/src/Notion/FigureNotion.tsx +5 -2
  70. package/src/Notion/NotionVisualElement.tsx +2 -0
  71. package/src/SectionHeading/SectionHeading.tsx +7 -3
  72. package/src/Subject/Subject.tsx +151 -72
  73. package/src/Subject/SubjectAbout.tsx +97 -27
  74. package/src/Subject/SubjectArchive.tsx +129 -58
  75. package/src/Subject/SubjectCarousel.tsx +42 -36
  76. package/src/Subject/SubjectHeader.tsx +75 -34
  77. package/src/Subject/SubjectLinks.tsx +21 -19
  78. package/src/Subject/SubjectNewContent.tsx +87 -32
  79. package/src/Subject/SubjectShortcuts.tsx +67 -27
  80. package/src/Subject/SubjectSocial.tsx +19 -20
  81. package/src/index.ts +2 -0
  82. package/src/locale/messages-nb.ts +21 -22
  83. package/src/locale/messages-nn.ts +27 -27
  84. package/src/locale/messages-se.ts +22 -23
  85. package/src/locale/messages-sma.ts +22 -23
  86. package/src/main.scss +0 -1
  87. package/src/Subject/component.subject-about.scss +0 -73
  88. package/src/Subject/component.subject-archive.scss +0 -92
  89. package/src/Subject/component.subject-carousel.scss +0 -32
  90. package/src/Subject/component.subject-concepts.scss +0 -37
  91. package/src/Subject/component.subject-header.scss +0 -87
  92. package/src/Subject/component.subject-links.scss +0 -14
  93. package/src/Subject/component.subject-new-content.scss +0 -82
  94. package/src/Subject/component.subject-shortcut.scss +0 -57
  95. package/src/Subject/component.subject.scss +0 -213
@@ -30,6 +30,7 @@ interface Props {
30
30
  hideFigCaption?: boolean;
31
31
  hideIconsAndAuthors?: boolean;
32
32
  figureType?: FigureType;
33
+ licenseButtons?: ReactNode;
33
34
  }
34
35
 
35
36
  const FigureNotion = ({
@@ -44,6 +45,7 @@ const FigureNotion = ({
44
45
  hideFigCaption,
45
46
  hideIconsAndAuthors,
46
47
  figureType,
48
+ licenseButtons,
47
49
  }: Props) => {
48
50
  const { t, i18n } = useTranslation();
49
51
  const license = getLicenseByAbbreviation(licenseString, i18n.language);
@@ -84,8 +86,9 @@ const FigureNotion = ({
84
86
  source: t('source'),
85
87
  learnAboutLicenses: t('license.learnMore'),
86
88
  title: t('title'),
87
- }}
88
- />
89
+ }}>
90
+ {licenseButtons}
91
+ </FigureLicenseDialog>
89
92
  </FigureCaption>
90
93
  ) : (
91
94
  <BottomBorder />
@@ -30,6 +30,7 @@ export type NotionVisualElementType = {
30
30
  src: string;
31
31
  alt?: string;
32
32
  };
33
+ licenseButtons?: ReactNode;
33
34
  };
34
35
 
35
36
  interface Props {
@@ -64,6 +65,7 @@ const NotionVisualElement = ({ visualElement, id, figureId }: Props) => {
64
65
  title={visualElement.title ?? ''}
65
66
  copyright={visualElement.copyright}
66
67
  licenseString={visualElement.copyright?.license?.license ?? ''}
68
+ licenseButtons={visualElement.licenseButtons}
67
69
  type={type}>
68
70
  {visualElement.image?.src ? (
69
71
  <img src={visualElement.image?.src} alt={visualElement.image.alt} />
@@ -1,6 +1,6 @@
1
1
  import React, { ElementType, ReactNode } from 'react';
2
2
  import { css } from '@emotion/core';
3
- import { breakpoints, fonts, mq, spacing } from '@ndla/core/src';
3
+ import { breakpoints, fonts, mq, spacing } from '@ndla/core';
4
4
  import styled from '@emotion/styled';
5
5
 
6
6
  interface StyledWrapperProps {
@@ -26,7 +26,7 @@ const StyledWrapper = styled.h2<StyledWrapperProps>`
26
26
  `};
27
27
  `;
28
28
 
29
- const LargeStyledWrapper = StyledWrapper.withComponent('h2');
29
+ const LargeStyledWrapper = StyledWrapper.withComponent('h1');
30
30
 
31
31
  interface Props {
32
32
  children: ReactNode;
@@ -36,7 +36,11 @@ interface Props {
36
36
 
37
37
  const SectionHeading = ({ children, large = false, className }: Props) => {
38
38
  const Wrapper: ElementType = large ? LargeStyledWrapper : StyledWrapper;
39
- return <Wrapper className={className}>{children}</Wrapper>;
39
+ return (
40
+ <Wrapper large={large} className={className}>
41
+ {children}
42
+ </Wrapper>
43
+ );
40
44
  };
41
45
 
42
46
  export default SectionHeading;
@@ -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;