@ndla/ui 34.0.0 → 34.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 (94) hide show
  1. package/es/Figure/Figure.js +3 -2
  2. package/es/FileList/File.js +6 -6
  3. package/es/LanguageSelector/LanguageSelector.js +67 -99
  4. package/es/NDLAFilm/AboutNdlaFilm.js +13 -12
  5. package/es/NDLAFilm/AllMoviesAlphabetically.js +79 -144
  6. package/es/NDLAFilm/FilmContentCard.js +41 -26
  7. package/es/NDLAFilm/FilmContentCardTags.js +5 -3
  8. package/es/NDLAFilm/FilmMovieList.js +13 -8
  9. package/es/NDLAFilm/FilmMovieSearch.js +6 -5
  10. package/es/NDLAFilm/FilmSlideshow.js +44 -20
  11. package/es/NDLAFilm/filmStyles.js +2 -2
  12. package/es/ResourceGroup/ResourceItem.js +72 -48
  13. package/es/ResourceGroup/ResourceList.js +4 -3
  14. package/es/Search/ActiveFilterContent.js +6 -5
  15. package/es/Search/ContentTypeResult.js +6 -3
  16. package/es/SearchTypeResult/ActiveFilterContent.js +9 -10
  17. package/es/Topic/Topic.js +171 -213
  18. package/es/all.css +1 -1
  19. package/es/locale/messages-en.js +3 -1
  20. package/es/locale/messages-nb.js +3 -1
  21. package/es/locale/messages-nn.js +7 -5
  22. package/es/locale/messages-se.js +2 -0
  23. package/es/locale/messages-sma.js +3 -1
  24. package/lib/Figure/Figure.d.ts +2 -1
  25. package/lib/Figure/Figure.js +3 -2
  26. package/lib/FileList/File.js +6 -6
  27. package/lib/LanguageSelector/LanguageSelector.d.ts +6 -15
  28. package/lib/LanguageSelector/LanguageSelector.js +64 -99
  29. package/lib/NDLAFilm/AboutNdlaFilm.js +11 -14
  30. package/lib/NDLAFilm/AllMoviesAlphabetically.d.ts +1 -2
  31. package/lib/NDLAFilm/AllMoviesAlphabetically.js +77 -142
  32. package/lib/NDLAFilm/FilmContentCard.d.ts +7 -0
  33. package/lib/NDLAFilm/FilmContentCard.js +41 -26
  34. package/lib/NDLAFilm/FilmContentCardTags.d.ts +2 -1
  35. package/lib/NDLAFilm/FilmContentCardTags.js +5 -3
  36. package/lib/NDLAFilm/FilmMovieList.js +12 -7
  37. package/lib/NDLAFilm/FilmMovieSearch.js +5 -4
  38. package/lib/NDLAFilm/FilmSlideshow.js +44 -20
  39. package/lib/NDLAFilm/filmStyles.js +2 -2
  40. package/lib/Resource/resourceComponents.d.ts +1 -1
  41. package/lib/ResourceGroup/ResourceItem.d.ts +2 -2
  42. package/lib/ResourceGroup/ResourceItem.js +72 -48
  43. package/lib/ResourceGroup/ResourceList.js +4 -3
  44. package/lib/Search/ActiveFilterContent.d.ts +1 -1
  45. package/lib/Search/ActiveFilterContent.js +9 -5
  46. package/lib/Search/ContentTypeResult.js +6 -3
  47. package/lib/SearchTypeResult/ActiveFilterContent.d.ts +1 -1
  48. package/lib/SearchTypeResult/ActiveFilterContent.js +12 -10
  49. package/lib/Topic/Topic.js +170 -215
  50. package/lib/all.css +1 -1
  51. package/lib/locale/messages-en.d.ts +2 -0
  52. package/lib/locale/messages-en.js +3 -1
  53. package/lib/locale/messages-nb.d.ts +2 -0
  54. package/lib/locale/messages-nb.js +3 -1
  55. package/lib/locale/messages-nn.d.ts +4 -2
  56. package/lib/locale/messages-nn.js +7 -5
  57. package/lib/locale/messages-se.d.ts +2 -0
  58. package/lib/locale/messages-se.js +2 -0
  59. package/lib/locale/messages-sma.d.ts +2 -0
  60. package/lib/locale/messages-sma.js +3 -1
  61. package/package.json +15 -14
  62. package/src/Figure/Figure.tsx +6 -2
  63. package/src/FileList/File.tsx +4 -4
  64. package/src/LanguageSelector/LanguageSelector.stories.tsx +48 -0
  65. package/src/LanguageSelector/LanguageSelector.tsx +70 -149
  66. package/src/NDLAFilm/AboutNdlaFilm.tsx +11 -14
  67. package/src/NDLAFilm/AllMoviesAlphabetically.tsx +44 -160
  68. package/src/NDLAFilm/FilmContentCard.tsx +40 -21
  69. package/src/NDLAFilm/FilmContentCardTags.tsx +3 -2
  70. package/src/NDLAFilm/FilmMovieList.tsx +14 -7
  71. package/src/NDLAFilm/FilmMovieSearch.tsx +2 -2
  72. package/src/NDLAFilm/FilmSlideshow.tsx +49 -40
  73. package/src/NDLAFilm/filmStyles.ts +1 -1
  74. package/src/ResourceGroup/ResourceItem.tsx +79 -94
  75. package/src/ResourceGroup/ResourceList.tsx +2 -0
  76. package/src/Search/ActiveFilterContent.tsx +4 -3
  77. package/src/Search/ContentTypeResult.tsx +3 -1
  78. package/src/SearchTypeResult/ActiveFilterContent.tsx +7 -8
  79. package/src/Topic/Topic.tsx +166 -193
  80. package/src/locale/messages-en.ts +3 -1
  81. package/src/locale/messages-nb.ts +3 -1
  82. package/src/locale/messages-nn.ts +5 -4
  83. package/src/locale/messages-se.ts +2 -0
  84. package/src/locale/messages-sma.ts +3 -1
  85. package/src/main.scss +0 -1
  86. package/es/LanguageSelector/LanguageSelectorContent.js +0 -61
  87. package/es/Subject/SubjectCarousel.js +0 -133
  88. package/lib/LanguageSelector/LanguageSelectorContent.d.ts +0 -15
  89. package/lib/LanguageSelector/LanguageSelectorContent.js +0 -68
  90. package/lib/Subject/SubjectCarousel.d.ts +0 -18
  91. package/lib/Subject/SubjectCarousel.js +0 -138
  92. package/src/LanguageSelector/LanguageSelectorContent.tsx +0 -80
  93. package/src/NDLAFilm/component.film-movielist.scss +0 -105
  94. package/src/Subject/SubjectCarousel.tsx +0 -162
@@ -21,7 +21,7 @@ export const StyledHeadingH1 = styled.h1<StyledHeadingProps>`
21
21
  text-transform: uppercase;
22
22
  letter-spacing: 0.05em;
23
23
  color: ${colors.white};
24
- margin: ${spacing.small} 0;
24
+ margin: ${spacing.xsmall} 0;
25
25
  margin-left: ${(props) => props.marginLeft && `${props.marginLeft}px`};
26
26
  small {
27
27
  font-weight: normal;
@@ -59,13 +59,14 @@ const fadeInAdditionalsKeyframe = keyframes`
59
59
  }
60
60
  `;
61
61
 
62
- type ListElementProps = {
62
+ interface ListElementProps {
63
63
  additional?: boolean;
64
64
  extraBottomMargin?: boolean;
65
65
  contentType?: string;
66
66
  active?: boolean;
67
67
  hidden?: boolean;
68
- };
68
+ }
69
+
69
70
  const ListElement = styled.li<ListElementProps>`
70
71
  border: 1px solid #d1d6db;
71
72
  border-radius: 5px;
@@ -74,7 +75,7 @@ const ListElement = styled.li<ListElementProps>`
74
75
  display: flex;
75
76
  justify-content: space-between;
76
77
  align-items: center;
77
- padding-right: 1rem;
78
+ padding: ${spacing.small};
78
79
 
79
80
  ${(props) =>
80
81
  props.additional &&
@@ -108,48 +109,12 @@ const ListElement = styled.li<ListElementProps>`
108
109
  ${({ hidden }) => hidden && `display:none; opacity:0;`}
109
110
  `;
110
111
 
111
- const LinkStyle = css`
112
- display: flex;
113
- color: ${colors.brand.dark};
114
- align-items: center;
115
- width: auto;
116
- padding: ${spacing.small};
117
- box-shadow: none;
118
- min-height: 70px;
119
- `;
120
-
121
- const ActiveWrapper = styled.div`
122
- ${LinkStyle}
123
- `;
124
112
  const ResourceLink = styled(SafeLink)`
125
- ${LinkStyle}
126
- &:hover .c-content-type-badge {
127
- width: 38px;
128
- height: 38px;
129
-
130
- svg {
131
- width: 20px;
132
- height: 20px;
133
- }
134
- &.c-content-type-badge--subject-material,
135
- &.c-content-type-badge--learning-path,
136
- &.c-content-type-badge--source-material,
137
- &.c-content-type-badge--external-learning-resources {
138
- svg {
139
- width: 26px;
140
- height: 26px;
141
- }
142
- }
143
- }
144
- `;
145
-
146
- const headingStyle = css`
147
113
  font-weight: ${fonts.weight.semibold};
148
- transform: translateY(-1px);
149
- text-transform: none;
150
- letter-spacing: 0;
151
- margin: 0;
152
- display: inline;
114
+ box-shadow: none;
115
+ text-decoration: underline;
116
+ text-underline-offset: 5px;
117
+ color: ${colors.brand.dark};
153
118
  ${fonts.sizes('16px', '26px')};
154
119
  ${mq.range({ from: breakpoints.tablet })} {
155
120
  ${fonts.sizes('18px', '26px')};
@@ -157,25 +122,12 @@ const headingStyle = css`
157
122
  ${mq.range({ from: breakpoints.desktop })} {
158
123
  ${fonts.sizes('20px', '26px')};
159
124
  }
160
-
161
- box-shadow: ${colors.link};
162
-
163
- ${ResourceLink}:hover &,
164
- ${ResourceLink}:focus & {
165
- box-shadow: ${colors.linkHover};
166
- }
167
- `;
168
-
169
- const activeHeadingStyle = css`
170
- color: ${colors.brand.greyDark};
171
- box-shadow: none;
172
- small {
173
- padding-left: ${spacing.small};
174
- font-weight: ${fonts.weight.normal};
125
+ &:hover {
126
+ text-decoration: none;
175
127
  }
176
128
  `;
177
129
 
178
- const IconWrapper = styled.div`
130
+ const ContentBadgeWrapper = styled.div`
179
131
  display: flex;
180
132
  flex: 0 0 auto;
181
133
  text-align: center;
@@ -208,7 +160,41 @@ const ContentTypeName = styled.span`
208
160
  text-align: right;
209
161
  `;
210
162
 
211
- type Props = {
163
+ const InlineContainer = styled.div`
164
+ display: inline;
165
+ `;
166
+
167
+ const ResourceWrapper = styled.div`
168
+ display: flex;
169
+ gap: ${spacing.xsmall};
170
+ align-items: center;
171
+ :hover {
172
+ .c-content-type-badge {
173
+ width: 38px;
174
+ height: 38px;
175
+
176
+ svg {
177
+ width: 20px;
178
+ height: 20px;
179
+ }
180
+ &.c-content-type-badge--subject-material,
181
+ &.c-content-type-badge--learning-path,
182
+ &.c-content-type-badge--source-material,
183
+ &.c-content-type-badge--external-learning-resources {
184
+ svg {
185
+ width: 26px;
186
+ height: 26px;
187
+ }
188
+ }
189
+ }
190
+ }
191
+ `;
192
+
193
+ const CurrentSmall = styled.small`
194
+ margin-left: ${spacing.xsmall};
195
+ `;
196
+
197
+ interface Props {
212
198
  id: string;
213
199
  showContentTypeDescription?: boolean;
214
200
  contentTypeName?: string;
@@ -217,7 +203,16 @@ type Props = {
217
203
  showAdditionalResources?: boolean;
218
204
  access?: 'teacher';
219
205
  heartButton?: (path: string) => ReactNode;
220
- };
206
+ }
207
+
208
+ const IconWrapper = styled.div`
209
+ display: flex;
210
+ flex-grow: 1;
211
+ svg {
212
+ width: 26px;
213
+ height: 26px;
214
+ }
215
+ `;
221
216
 
222
217
  const ResourceItem = ({
223
218
  id,
@@ -234,6 +229,10 @@ const ResourceItem = ({
234
229
  heartButton,
235
230
  }: Props & Resource) => {
236
231
  const { t } = useTranslation();
232
+ const accessId = `${id}-teacher`;
233
+ const coreId = `${id}-core`;
234
+ const additionalId = `${id}-additional`;
235
+ const describedBy = `${coreId} ${additionalId} ${accessId}`;
237
236
  const hidden = additional ? !showAdditionalResources : false;
238
237
  return (
239
238
  <ListElement
@@ -243,54 +242,40 @@ const ResourceItem = ({
243
242
  active={active}
244
243
  additional={additional}
245
244
  extraBottomMargin={extraBottomMargin}>
246
- {active ? (
247
- <ActiveWrapper>
248
- <IconWrapper>
249
- <ContentTypeBadge type={contentType ?? ''} background border={false} />
250
- </IconWrapper>
251
- <span css={[headingStyle, activeHeadingStyle]}>
245
+ <ResourceWrapper>
246
+ <ContentBadgeWrapper>
247
+ <ContentTypeBadge type={contentType ?? ''} background border={false} />
248
+ </ContentBadgeWrapper>
249
+ <InlineContainer>
250
+ <ResourceLink to={path} aria-current={active ? 'page' : undefined} aria-describedby={describedBy}>
252
251
  {name}
253
- <small>{t('resource.youAreHere')}</small>
254
- </span>
255
- </ActiveWrapper>
256
- ) : (
257
- <ResourceLink to={path}>
258
- <IconWrapper>
259
- <ContentTypeBadge type={contentType ?? ''} background border={false} />
260
- </IconWrapper>
261
- <span css={headingStyle}>{name}</span>
262
- </ResourceLink>
263
- )}
252
+ </ResourceLink>
253
+ {active ? <CurrentSmall>{t('resource.youAreHere')}</CurrentSmall> : undefined}
254
+ </InlineContainer>
255
+ </ResourceWrapper>
264
256
  <TypeWrapper>
265
257
  {contentTypeName && <ContentTypeName>{contentTypeName}</ContentTypeName>}
266
258
  {access && access === 'teacher' && (
267
259
  <Tooltip tooltip={t('article.access.onlyTeacher')}>
268
- <HumanMaleBoard
269
- className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons"
270
- aria-label={t('article.access.onlyTeacher')}
271
- />
260
+ <IconWrapper>
261
+ <HumanMaleBoard id={accessId} aria-label={t('article.access.onlyTeacher')} />
262
+ </IconWrapper>
272
263
  </Tooltip>
273
264
  )}
274
265
  {showAdditionalResources && contentTypeDescription && (
275
266
  <>
276
267
  {additional && (
277
268
  <Tooltip tooltip={contentTypeDescription}>
278
- <div>
279
- <Additional
280
- className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons"
281
- aria-label={contentTypeDescription}
282
- />
283
- </div>
269
+ <IconWrapper>
270
+ <Additional id={additionalId} aria-label={contentTypeDescription} />
271
+ </IconWrapper>
284
272
  </Tooltip>
285
273
  )}
286
274
  {!additional && (
287
275
  <Tooltip tooltip={contentTypeDescription}>
288
- <div>
289
- <Core
290
- className="c-icon--20 u-margin-left-tiny c-topic-resource__list__additional-icons"
291
- aria-label={contentTypeDescription}
292
- />
293
- </div>
276
+ <IconWrapper>
277
+ <Core id={coreId} aria-label={contentTypeDescription} />
278
+ </IconWrapper>
294
279
  </Tooltip>
295
280
  )}
296
281
  </>
@@ -10,6 +10,7 @@ import React, { ReactNode } from 'react';
10
10
  import styled from '@emotion/styled';
11
11
  import { css, keyframes } from '@emotion/react';
12
12
  import { useTranslation } from 'react-i18next';
13
+ import { fonts } from '@ndla/core';
13
14
  import NoContentBox from '../NoContentBox';
14
15
  import ResourceItem from './ResourceItem';
15
16
  import { Resource } from '../types';
@@ -33,6 +34,7 @@ const StyledResourceList = styled.ul<StyledListProps>`
33
34
  list-style: none;
34
35
  margin: 0;
35
36
  padding: 0;
37
+ font-family: ${fonts.sans};
36
38
  ${({ showAdditionalResources }) =>
37
39
  showAdditionalResources &&
38
40
  css`
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
2
  import styled from '@emotion/styled';
3
3
  import { Cross } from '@ndla/icons/action';
4
4
  import { spacing, mq, breakpoints, colors, misc, fonts } from '@ndla/core';
@@ -41,14 +41,15 @@ interface Props {
41
41
  ariaLabel: string;
42
42
  }
43
43
 
44
- const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }: Props) => (
44
+ const ActiveFilterContent = forwardRef<HTMLButtonElement, Props>(({ filter, onFilterRemove, ariaLabel }, ref) => (
45
45
  <StyledActiveFilter
46
46
  aria-label={ariaLabel}
47
47
  type="button"
48
+ ref={ref}
48
49
  onClick={() => onFilterRemove(filter.value, filter.filterName)}>
49
50
  <StyledActiveFilterTitle>{filter.title}</StyledActiveFilterTitle>
50
51
  <Cross />
51
52
  </StyledActiveFilter>
52
- );
53
+ ));
53
54
 
54
55
  export default ActiveFilterContent;
@@ -23,7 +23,9 @@ const renderAdditionalIcon = (label: string, isAdditional?: boolean): ReactEleme
23
23
  if (isAdditional && label) {
24
24
  return (
25
25
  <Tooltip tooltip={label}>
26
- <Additional className="c-icon--20" />
26
+ <div>
27
+ <Additional className="c-icon--20" aria-hidden={false} />
28
+ </div>
27
29
  </Tooltip>
28
30
  );
29
31
  }
@@ -6,11 +6,11 @@
6
6
  *
7
7
  */
8
8
 
9
- import React from 'react';
9
+ import React, { forwardRef } from 'react';
10
10
  import styled from '@emotion/styled';
11
11
  import { Cross } from '@ndla/icons/action';
12
12
  import { spacing, fonts } from '@ndla/core';
13
- import Button from '@ndla/button';
13
+ import { ButtonV2 } from '@ndla/button';
14
14
  import { useTranslation } from 'react-i18next';
15
15
 
16
16
  export const StyledActiveFilterTitle = styled.span`
@@ -19,7 +19,7 @@ export const StyledActiveFilterTitle = styled.span`
19
19
  font-weight: ${fonts.weight.semibold};
20
20
  `;
21
21
 
22
- const StyledButton = styled(Button)`
22
+ const StyledButton = styled(ButtonV2)`
23
23
  display: grid;
24
24
  grid-template-columns: 1fr auto;
25
25
  `;
@@ -35,21 +35,20 @@ type Props = {
35
35
  onFilterRemove: (value: string, name: string) => void;
36
36
  };
37
37
 
38
- const ActiveFilterContent = ({ filter, onFilterRemove }: Props) => {
38
+ const ActiveFilterContent = forwardRef<HTMLButtonElement, Props>(({ filter, onFilterRemove }, ref) => {
39
39
  const { t } = useTranslation();
40
40
  return (
41
41
  <StyledButton
42
42
  aria-label={t('searchPage.searchFilterMessages.removeFilter', {
43
43
  filterName: filter.title,
44
44
  })}
45
- type="button"
46
- size="normal"
47
- borderShape="rounded"
45
+ ref={ref}
46
+ shape="pill"
48
47
  onClick={() => onFilterRemove(filter.value, filter.name)}>
49
48
  <StyledActiveFilterTitle>{filter.title}</StyledActiveFilterTitle>
50
49
  <Cross />
51
50
  </StyledButton>
52
51
  );
53
- };
52
+ });
54
53
 
55
54
  export default ActiveFilterContent;