@ndla/ui 45.0.9 → 45.0.10

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 (43) hide show
  1. package/es/BannerCard/BannerCard.js +20 -10
  2. package/es/Embed/ConceptEmbed.js +44 -22
  3. package/es/Embed/ConceptListEmbed.js +5 -4
  4. package/es/Embed/conceptComponents.js +54 -41
  5. package/es/Gloss/Gloss.js +9 -8
  6. package/es/LicenseByline/EmbedByline.js +5 -5
  7. package/es/locale/messages-en.js +5 -3
  8. package/es/locale/messages-nb.js +4 -2
  9. package/es/locale/messages-nn.js +5 -3
  10. package/es/locale/messages-se.js +5 -3
  11. package/es/locale/messages-sma.js +5 -3
  12. package/lib/BannerCard/BannerCard.d.ts +1 -1
  13. package/lib/BannerCard/BannerCard.js +21 -12
  14. package/lib/Embed/ConceptEmbed.d.ts +1 -1
  15. package/lib/Embed/ConceptEmbed.js +44 -22
  16. package/lib/Embed/ConceptListEmbed.js +5 -4
  17. package/lib/Embed/conceptComponents.d.ts +5 -2
  18. package/lib/Embed/conceptComponents.js +53 -41
  19. package/lib/Gloss/Gloss.js +9 -8
  20. package/lib/LicenseByline/EmbedByline.d.ts +1 -1
  21. package/lib/LicenseByline/EmbedByline.js +5 -5
  22. package/lib/locale/messages-en.d.ts +3 -1
  23. package/lib/locale/messages-en.js +5 -3
  24. package/lib/locale/messages-nb.d.ts +3 -1
  25. package/lib/locale/messages-nb.js +4 -2
  26. package/lib/locale/messages-nn.d.ts +3 -1
  27. package/lib/locale/messages-nn.js +5 -3
  28. package/lib/locale/messages-se.d.ts +3 -1
  29. package/lib/locale/messages-se.js +5 -3
  30. package/lib/locale/messages-sma.d.ts +3 -1
  31. package/lib/locale/messages-sma.js +5 -3
  32. package/package.json +3 -3
  33. package/src/BannerCard/BannerCard.tsx +2 -2
  34. package/src/Embed/ConceptEmbed.tsx +96 -69
  35. package/src/Embed/ConceptListEmbed.tsx +2 -1
  36. package/src/Embed/conceptComponents.tsx +58 -37
  37. package/src/Gloss/Gloss.tsx +2 -2
  38. package/src/LicenseByline/EmbedByline.tsx +1 -1
  39. package/src/locale/messages-en.ts +3 -1
  40. package/src/locale/messages-nb.ts +3 -1
  41. package/src/locale/messages-nn.ts +3 -1
  42. package/src/locale/messages-se.ts +3 -1
  43. package/src/locale/messages-sma.ts +3 -1
@@ -287,6 +287,7 @@ declare const messages: {
287
287
  concept: string;
288
288
  h5p: string;
289
289
  external: string;
290
+ gloss: string;
290
291
  };
291
292
  };
292
293
  gloss: {
@@ -496,7 +497,8 @@ declare const messages: {
496
497
  notionsHeading: string;
497
498
  notionsRemove: string;
498
499
  showVideo: string;
499
- showNotion: string;
500
+ concept: string;
501
+ gloss: string;
500
502
  gridView: string;
501
503
  listView: string;
502
504
  };
@@ -213,7 +213,8 @@ var messages = _objectSpread(_objectSpread({
213
213
  notionsHeading: 'Begrepsforklaring',
214
214
  notionsRemove: 'Fjern',
215
215
  showVideo: 'Se video',
216
- showNotion: 'Se forklaring',
216
+ concept: 'Se forklaring',
217
+ gloss: 'Se glose',
217
218
  gridView: 'Gallerivisning',
218
219
  listView: 'Listevisning'
219
220
  },
@@ -1289,7 +1290,8 @@ var messages = _objectSpread(_objectSpread({
1289
1290
  podcast: 'Podkast',
1290
1291
  concept: 'Forklaring',
1291
1292
  h5p: 'H5P',
1292
- external: 'Ekstern ressurs'
1293
+ external: 'Ekstern ressurs',
1294
+ gloss: 'Glose'
1293
1295
  }
1294
1296
  },
1295
1297
  gloss: {
@@ -287,6 +287,7 @@ declare const messages: {
287
287
  concept: string;
288
288
  h5p: string;
289
289
  external: string;
290
+ gloss: string;
290
291
  };
291
292
  };
292
293
  gloss: {
@@ -496,9 +497,10 @@ declare const messages: {
496
497
  notionsHeading: string;
497
498
  notionsRemove: string;
498
499
  showVideo: string;
499
- showNotion: string;
500
+ concept: string;
500
501
  gridView: string;
501
502
  listView: string;
503
+ gloss: string;
502
504
  };
503
505
  contextModal: {
504
506
  button: string;
@@ -213,9 +213,10 @@ var messages = _objectSpread(_objectSpread({
213
213
  notionsHeading: 'Begrepsforklaring',
214
214
  notionsRemove: 'Fjern',
215
215
  showVideo: 'Sjå video',
216
- showNotion: 'Sjå forklaring',
216
+ concept: 'Sjå forklaring',
217
217
  gridView: 'Gallerivisning',
218
- listView: 'Listevisning'
218
+ listView: 'Listevisning',
219
+ gloss: 'Sjå glose'
219
220
  },
220
221
  contextModal: {
221
222
  button: '+ {{count}} fleire stader',
@@ -1289,7 +1290,8 @@ var messages = _objectSpread(_objectSpread({
1289
1290
  podcast: 'Podkast',
1290
1291
  concept: 'Forklaring',
1291
1292
  h5p: 'H5P',
1292
- external: 'Ekstern ressurs'
1293
+ external: 'Ekstern ressurs',
1294
+ gloss: 'Glose'
1293
1295
  }
1294
1296
  },
1295
1297
  gloss: {
@@ -287,6 +287,7 @@ declare const messages: {
287
287
  concept: string;
288
288
  h5p: string;
289
289
  external: string;
290
+ gloss: string;
290
291
  };
291
292
  };
292
293
  gloss: {
@@ -496,9 +497,10 @@ declare const messages: {
496
497
  notionsHeading: string;
497
498
  notionsRemove: string;
498
499
  showVideo: string;
499
- showNotion: string;
500
+ concept: string;
500
501
  gridView: string;
501
502
  listView: string;
503
+ gloss: string;
502
504
  };
503
505
  contextModal: {
504
506
  button: string;
@@ -213,9 +213,10 @@ var messages = _objectSpread(_objectSpread({
213
213
  notionsHeading: 'Doabačilgehus',
214
214
  notionsRemove: 'Sihko',
215
215
  showVideo: 'Geahča video',
216
- showNotion: 'Geahča čilgehusa',
216
+ concept: 'Geahča čilgehusa',
217
217
  gridView: 'Galleriijačájáhus',
218
- listView: 'Čájáhus listtu vuođul'
218
+ listView: 'Čájáhus listtu vuođul',
219
+ gloss: 'Se glose'
219
220
  },
220
221
  contextModal: {
221
222
  button: '+ {{count}} eanet sajiin',
@@ -1289,7 +1290,8 @@ var messages = _objectSpread(_objectSpread({
1289
1290
  podcast: 'Podkast',
1290
1291
  concept: 'Forklaring',
1291
1292
  h5p: 'H5P',
1292
- external: 'Ekstern ressurs'
1293
+ external: 'Ekstern ressurs',
1294
+ gloss: 'Glose'
1293
1295
  }
1294
1296
  },
1295
1297
  gloss: {
@@ -287,6 +287,7 @@ declare const messages: {
287
287
  concept: string;
288
288
  h5p: string;
289
289
  external: string;
290
+ gloss: string;
290
291
  };
291
292
  };
292
293
  gloss: {
@@ -496,9 +497,10 @@ declare const messages: {
496
497
  notionsHeading: string;
497
498
  notionsRemove: string;
498
499
  showVideo: string;
499
- showNotion: string;
500
+ concept: string;
500
501
  gridView: string;
501
502
  listView: string;
503
+ gloss: string;
502
504
  };
503
505
  contextModal: {
504
506
  button: string;
@@ -213,9 +213,10 @@ var messages = _objectSpread(_objectSpread({
213
213
  notionsHeading: 'Baakoebuerkiestimmie',
214
214
  notionsRemove: 'Skubph',
215
215
  showVideo: 'Gïehtjh videjovem',
216
- showNotion: 'Gïehtjh buerkiestimmiem ',
216
+ concept: 'Gïehtjh buerkiestimmiem ',
217
217
  gridView: 'Gallerivisning',
218
- listView: 'Listevisning'
218
+ listView: 'Listevisning',
219
+ gloss: 'Se glose'
219
220
  },
220
221
  contextModal: {
221
222
  button: '+ {{count}} jieniebinie sijjine',
@@ -1289,7 +1290,8 @@ var messages = _objectSpread(_objectSpread({
1289
1290
  podcast: 'Podkast',
1290
1291
  concept: 'Forklaring',
1291
1292
  h5p: 'H5P',
1292
- external: 'Ekstern ressurs'
1293
+ external: 'Ekstern ressurs',
1294
+ gloss: 'Glose'
1293
1295
  }
1294
1296
  },
1295
1297
  gloss: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "45.0.9",
3
+ "version": "45.0.10",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -42,7 +42,7 @@
42
42
  "@ndla/icons": "^4.0.6",
43
43
  "@ndla/licenses": "^7.1.4",
44
44
  "@ndla/modal": "^4.0.7",
45
- "@ndla/notion": "^5.0.24",
45
+ "@ndla/notion": "^5.0.25",
46
46
  "@ndla/safelink": "^4.1.21",
47
47
  "@ndla/select": "^2.4.12",
48
48
  "@ndla/switch": "^1.1.12",
@@ -83,5 +83,5 @@
83
83
  "publishConfig": {
84
84
  "access": "public"
85
85
  },
86
- "gitHead": "b397e4fff32cb39065d431e6a3a1a3714912a5bb"
86
+ "gitHead": "8abb4a1a790af81f4a4eb14e6c355817160c938d"
87
87
  }
@@ -79,9 +79,9 @@ type BannerProps = {
79
79
  content: { content: string; lang?: string };
80
80
  linkText: { text: string; lang?: string };
81
81
  };
82
- export const BannerCard = ({ link, title, content, linkText, image }: BannerProps) => {
82
+ export const BannerCard = ({ link, title, content, linkText, image, ...rest }: BannerProps) => {
83
83
  return (
84
- <BannerWrapper>
84
+ <BannerWrapper {...rest}>
85
85
  <ImageWrapper>
86
86
  <StyledImage alt={image.altText} src={image.imageSrc} />
87
87
  </ImageWrapper>
@@ -14,16 +14,17 @@ import { Root, Trigger, Content, Anchor, Close, Portal } from '@radix-ui/react-p
14
14
  import { IconButtonV2 } from '@ndla/button';
15
15
  import { Cross } from '@ndla/icons/action';
16
16
  import { breakpoints, colors, mq, spacing } from '@ndla/core';
17
- import { ConceptMetaData } from '@ndla/types-embed';
17
+ import { AudioMeta, ConceptMetaData } from '@ndla/types-embed';
18
18
  import Tooltip from '@ndla/tooltip';
19
19
  import { COPYRIGHTED } from '@ndla/licenses';
20
20
  import { Notion as UINotion } from '../Notion';
21
21
  import { Figure } from '../Figure';
22
22
  import { NotionImage } from '../Notion/NotionImage';
23
- import { ConceptNotionV2, ConceptNotionData } from './conceptComponents';
23
+ import { ConceptNotionV2, ConceptNotionData, ConceptType } from './conceptComponents';
24
24
  import { EmbedByline } from '../LicenseByline';
25
25
  import EmbedErrorPlaceholder from './EmbedErrorPlaceholder';
26
26
  import { HeartButtonType } from './types';
27
+ import { Gloss } from '../Gloss';
27
28
 
28
29
  const BottomBorder = styled.div`
29
30
  margin-top: ${spacing.normal};
@@ -110,7 +111,7 @@ export const ConceptEmbed = ({ embed, fullWidth, heartButton: HeartButton }: Pro
110
111
  return (
111
112
  <BlockConcept
112
113
  fullWidth={fullWidth}
113
- title={concept.title.title}
114
+ title={concept.title}
114
115
  content={concept.content?.content}
115
116
  metaImage={concept.metaImage}
116
117
  copyright={concept.copyright}
@@ -118,12 +119,14 @@ export const ConceptEmbed = ({ embed, fullWidth, heartButton: HeartButton }: Pro
118
119
  visualElement={visualElement}
119
120
  heartButton={HeartButton}
120
121
  conceptHeartButton={HeartButton && <HeartButton embed={embed} />}
122
+ conceptType={concept.conceptType}
123
+ glossData={concept.glossData}
121
124
  />
122
125
  );
123
126
  } else if (embed.embedData.type === 'inline') {
124
127
  return (
125
128
  <InlineConcept
126
- title={concept.title.title}
129
+ title={concept.title}
127
130
  content={concept.content?.content}
128
131
  metaImage={concept.metaImage}
129
132
  copyright={concept.copyright}
@@ -132,12 +135,14 @@ export const ConceptEmbed = ({ embed, fullWidth, heartButton: HeartButton }: Pro
132
135
  linkText={embed.embedData.linkText}
133
136
  heartButton={HeartButton}
134
137
  conceptHeartButton={HeartButton && <HeartButton embed={embed} />}
138
+ conceptType={concept.conceptType}
139
+ glossData={concept.glossData}
135
140
  />
136
141
  );
137
142
  } else {
138
143
  return (
139
144
  <ConceptNotionV2
140
- title={concept.title.title}
145
+ title={concept.title}
141
146
  content={concept.content?.content}
142
147
  metaImage={concept.metaImage}
143
148
  copyright={concept.copyright}
@@ -145,6 +150,8 @@ export const ConceptEmbed = ({ embed, fullWidth, heartButton: HeartButton }: Pro
145
150
  visualElement={visualElement}
146
151
  heartButton={HeartButton}
147
152
  conceptHeartButton={HeartButton && <HeartButton embed={embed} />}
153
+ conceptType={concept.conceptType}
154
+ glossData={concept.glossData}
148
155
  />
149
156
  );
150
157
  }
@@ -223,6 +230,8 @@ const InlineConcept = ({
223
230
  linkText,
224
231
  heartButton,
225
232
  conceptHeartButton,
233
+ glossData,
234
+ conceptType,
226
235
  }: InlineConceptProps) => {
227
236
  const { t } = useTranslation();
228
237
  const anchorRef = useRef<HTMLDivElement>(null);
@@ -270,6 +279,8 @@ const InlineConcept = ({
270
279
  </IconButtonV2>
271
280
  </Close>
272
281
  }
282
+ conceptType={conceptType}
283
+ glossData={glossData}
273
284
  />
274
285
  </Content>
275
286
  </PopoverWrapper>
@@ -294,6 +305,8 @@ export const BlockConcept = ({
294
305
  fullWidth,
295
306
  heartButton,
296
307
  conceptHeartButton,
308
+ glossData,
309
+ conceptType,
297
310
  }: ConceptProps) => {
298
311
  const { t } = useTranslation();
299
312
  const anchorRef = useRef<HTMLDivElement>(null);
@@ -318,71 +331,85 @@ export const BlockConcept = ({
318
331
  <Root modal={isMobile} onOpenChange={onOpenChange}>
319
332
  <StyledAnchor ref={anchorRef} />
320
333
  <Figure resizeIframe type={fullWidth ? 'full' : 'full-column'}>
321
- <UINotion
322
- id=""
323
- title={title}
324
- text={content}
325
- visualElement={
326
- visualElement?.status === 'success' && (
327
- <>
328
- <ImageWrapper>
329
- <Tooltip tooltip={t('searchPage.resultType.showNotion')}>
330
- <Trigger asChild>
331
- <StyledButton type="button" aria-label={t('concept.showDescription', { title: title })}>
332
- {visualElement.resource === 'image' ? (
333
- <NotionImage
334
- type={visualElementType}
335
- id={''}
336
- src={visualElement.data.image.imageUrl}
337
- alt={visualElement.data.alttext.alttext}
338
- />
339
- ) : metaImage ? (
340
- <NotionImage
341
- type={visualElementType}
342
- id={''}
343
- src={metaImage?.url ?? ''}
344
- alt={metaImage?.alt ?? ''}
345
- />
346
- ) : undefined}
347
- </StyledButton>
348
- </Trigger>
349
- </Tooltip>
350
- </ImageWrapper>
351
- <Portal
352
- container={
353
- typeof document !== 'undefined'
354
- ? (document.querySelector('.c-article') as HTMLElement | null) || undefined
355
- : undefined
356
- }
357
- >
358
- <PopoverWrapper top={modalPos}>
359
- <Content avoidCollisions={false} asChild side="bottom">
360
- <ConceptNotionV2
361
- title={title}
362
- content={content}
363
- copyright={copyright}
364
- source={source}
365
- visualElement={visualElement}
366
- heartButton={heartButton}
367
- conceptHeartButton={conceptHeartButton}
368
- inPopover
369
- closeButton={
370
- <Close asChild>
371
- <IconButtonV2 aria-label={t('close')} variant="ghost">
372
- <Cross />
373
- </IconButtonV2>
374
- </Close>
375
- }
376
- />
377
- </Content>
378
- </PopoverWrapper>
379
- </Portal>
380
- </>
381
- )
382
- }
383
- />
334
+ {conceptType === 'concept' ? (
335
+ <UINotion
336
+ id=""
337
+ title={title.title}
338
+ text={content}
339
+ visualElement={
340
+ visualElement?.status === 'success' && (
341
+ <>
342
+ <ImageWrapper>
343
+ <Tooltip tooltip={t(`searchPage.resultType.${conceptType}`)}>
344
+ <Trigger asChild>
345
+ <StyledButton type="button" aria-label={t('concept.showDescription', { title: title })}>
346
+ {visualElement.resource === 'image' ? (
347
+ <NotionImage
348
+ type={visualElementType}
349
+ id={''}
350
+ src={visualElement.data.image.imageUrl}
351
+ alt={visualElement.data.alttext.alttext}
352
+ />
353
+ ) : metaImage ? (
354
+ <NotionImage
355
+ type={visualElementType}
356
+ id={''}
357
+ src={metaImage?.url ?? ''}
358
+ alt={metaImage?.alt ?? ''}
359
+ />
360
+ ) : undefined}
361
+ </StyledButton>
362
+ </Trigger>
363
+ </Tooltip>
364
+ </ImageWrapper>
365
+ <Portal
366
+ container={
367
+ typeof document !== 'undefined'
368
+ ? (document.querySelector('.c-article') as HTMLElement | null) || undefined
369
+ : undefined
370
+ }
371
+ >
372
+ <PopoverWrapper top={modalPos}>
373
+ <Content avoidCollisions={false} asChild side="bottom">
374
+ <ConceptNotionV2
375
+ title={title}
376
+ content={content}
377
+ copyright={copyright}
378
+ source={source}
379
+ visualElement={visualElement}
380
+ heartButton={heartButton}
381
+ conceptHeartButton={conceptHeartButton}
382
+ inPopover
383
+ closeButton={
384
+ <Close asChild>
385
+ <IconButtonV2 aria-label={t('close')} variant="ghost">
386
+ <Cross />
387
+ </IconButtonV2>
388
+ </Close>
389
+ }
390
+ conceptType={conceptType}
391
+ glossData={glossData}
392
+ />
393
+ </Content>
394
+ </PopoverWrapper>
395
+ </Portal>
396
+ </>
397
+ )
398
+ }
399
+ />
400
+ ) : (
401
+ <Gloss
402
+ glossData={glossData!}
403
+ title={title}
404
+ audio={
405
+ visualElement?.status === 'success' && visualElement.resource === 'audio'
406
+ ? { src: visualElement.data.audioFile.url, title: visualElement.data.title.title }
407
+ : undefined
408
+ }
409
+ />
410
+ )}
384
411
  {copyright ? (
385
- <EmbedByline copyright={copyright} bottomRounded topRounded type="concept">
412
+ <EmbedByline copyright={copyright} bottomRounded topRounded type={conceptType as ConceptType}>
386
413
  {copyright.license?.license.toLowerCase() !== COPYRIGHTED && conceptHeartButton}
387
414
  </EmbedByline>
388
415
  ) : (
@@ -45,12 +45,13 @@ const ConceptListEmbed = ({ embed }: Props) => {
45
45
  {data.concepts.map(({ concept, visualElement }) => (
46
46
  <li key={concept.id}>
47
47
  <BlockConcept
48
- title={concept.title.title}
48
+ title={concept.title}
49
49
  content={concept.content.content}
50
50
  metaImage={concept.metaImage}
51
51
  copyright={concept.copyright}
52
52
  source={concept.source}
53
53
  visualElement={visualElement}
54
+ conceptType={concept.conceptType}
54
55
  />
55
56
  </li>
56
57
  ))}
@@ -7,7 +7,7 @@
7
7
  */
8
8
 
9
9
  import { forwardRef, ReactNode, RefAttributes } from 'react';
10
- import { ConceptVisualElementMeta } from '@ndla/types-embed';
10
+ import { AudioMeta, AudioMetaData, ConceptData, ConceptVisualElementMeta } from '@ndla/types-embed';
11
11
  import { useTranslation } from 'react-i18next';
12
12
  import { css } from '@emotion/react';
13
13
  import { breakpoints, colors, fonts, misc, mq, spacing } from '@ndla/core';
@@ -21,9 +21,12 @@ import BrightcoveEmbed from './BrightcoveEmbed';
21
21
  import H5pEmbed from './H5pEmbed';
22
22
  import { ExternalEmbed, HeartButtonType, IframeEmbed } from '.';
23
23
  import { EmbedByline } from '../LicenseByline';
24
+ import { Gloss } from '../Gloss';
25
+
26
+ export type ConceptType = 'concept' | 'gloss';
24
27
 
25
28
  export interface ConceptNotionData {
26
- title: string;
29
+ title: ConceptData['concept']['title'];
27
30
  content?: string;
28
31
  metaImage?: {
29
32
  url?: string;
@@ -32,6 +35,8 @@ export interface ConceptNotionData {
32
35
  copyright?: Copyright;
33
36
  source?: string;
34
37
  visualElement?: ConceptVisualElementMeta;
38
+ conceptType: ConceptData['concept']['conceptType'];
39
+ glossData?: ConceptData['concept']['glossData'];
35
40
  }
36
41
 
37
42
  interface ConceptNotionProps extends RefAttributes<HTMLDivElement>, ConceptNotionData {
@@ -151,6 +156,8 @@ export const ConceptNotionV2 = forwardRef<HTMLDivElement, ConceptNotionProps>(
151
156
  subjects,
152
157
  heartButton,
153
158
  conceptHeartButton,
159
+ conceptType,
160
+ glossData,
154
161
  ...rest
155
162
  },
156
163
  ref,
@@ -162,47 +169,61 @@ export const ConceptNotionV2 = forwardRef<HTMLDivElement, ConceptNotionProps>(
162
169
  <ContentPadding>
163
170
  <NotionHeader>
164
171
  <h1>
165
- {title} {<small>{t('searchPage.resultType.notionsHeading')}</small>}
172
+ {title.title} {<small>{t(`searchPage.resultType.${conceptType}`)}</small>}
166
173
  </h1>
167
174
  {closeButton}
168
175
  </NotionHeader>
169
- <StyledNotionDialogContent>
170
- {visualElement?.resource === 'image' ? (
171
- <ImageEmbed embed={visualElement} heartButton={heartButton} />
172
- ) : visualElement?.resource === 'brightcove' ? (
173
- <BrightcoveEmbed embed={visualElement} heartButton={heartButton} />
174
- ) : visualElement?.resource === 'h5p' ? (
175
- <H5pEmbed embed={visualElement} />
176
- ) : visualElement?.resource === 'iframe' ? (
177
- <IframeEmbed embed={visualElement} />
178
- ) : visualElement?.resource === 'external' ? (
179
- <ExternalEmbed embed={visualElement} />
180
- ) : null}
181
- <NotionDialogText>{parseMarkdown(content ?? '', 'body')}</NotionDialogText>
182
- </StyledNotionDialogContent>
183
- {tags && (
184
- <ListWrapper>
185
- {`${t('notions.tags')}:`}
186
- <StyledList>
187
- {tags.map((tag, index) => (
188
- <li key={index}>{tag}</li>
189
- ))}
190
- </StyledList>
191
- </ListWrapper>
192
- )}
193
- {subjects && (
194
- <ListWrapper>
195
- {`${t('notions.usedIn')}:`}
196
- <StyledList>
197
- {subjects.map((subject, index) => (
198
- <li key={index}>{subject}</li>
199
- ))}
200
- </StyledList>
201
- </ListWrapper>
176
+ {conceptType !== 'gloss' ? (
177
+ <>
178
+ <StyledNotionDialogContent>
179
+ {visualElement?.resource === 'image' ? (
180
+ <ImageEmbed embed={visualElement} heartButton={heartButton} />
181
+ ) : visualElement?.resource === 'brightcove' ? (
182
+ <BrightcoveEmbed embed={visualElement} heartButton={heartButton} />
183
+ ) : visualElement?.resource === 'h5p' ? (
184
+ <H5pEmbed embed={visualElement} />
185
+ ) : visualElement?.resource === 'iframe' ? (
186
+ <IframeEmbed embed={visualElement} />
187
+ ) : visualElement?.resource === 'external' ? (
188
+ <ExternalEmbed embed={visualElement} />
189
+ ) : null}
190
+ <NotionDialogText>{parseMarkdown(content ?? '', 'body')}</NotionDialogText>
191
+ </StyledNotionDialogContent>
192
+ {tags && (
193
+ <ListWrapper>
194
+ {`${t('notions.tags')}:`}
195
+ <StyledList>
196
+ {tags.map((tag, index) => (
197
+ <li key={index}>{tag}</li>
198
+ ))}
199
+ </StyledList>
200
+ </ListWrapper>
201
+ )}
202
+ {subjects && (
203
+ <ListWrapper>
204
+ {`${t('notions.usedIn')}:`}
205
+ <StyledList>
206
+ {subjects.map((subject, index) => (
207
+ <li key={index}>{subject}</li>
208
+ ))}
209
+ </StyledList>
210
+ </ListWrapper>
211
+ )}
212
+ </>
213
+ ) : (
214
+ <Gloss
215
+ title={title}
216
+ glossData={glossData!}
217
+ audio={
218
+ visualElement?.status === 'success' && visualElement.resource === 'audio'
219
+ ? { src: visualElement.data.audioFile.url, title: visualElement.data.title.title }
220
+ : undefined
221
+ }
222
+ />
202
223
  )}
203
224
  </ContentPadding>
204
225
  {copyright && (
205
- <EmbedByline copyright={copyright} type="concept">
226
+ <EmbedByline copyright={copyright} type={conceptType as ConceptType}>
206
227
  {copyright.license?.license.toLowerCase() !== COPYRIGHTED && conceptHeartButton}
207
228
  </EmbedByline>
208
229
  )}
@@ -86,7 +86,7 @@ const TranslatedText = styled.span`
86
86
  padding: ${spacing.small} ${spacing.normal};
87
87
  font-family: ${fonts.sans};
88
88
  ${fonts.sizes('18px', '24px')};
89
- :first-child {
89
+ &[data-first='true'] {
90
90
  color: ${colors.brand.dark};
91
91
  font-weight: ${fonts.weight.bold};
92
92
  background-color: ${colors.background.lightBlue};
@@ -137,7 +137,7 @@ const Gloss = ({ title, glossData, audio }: Props) => {
137
137
  <div key={index}>
138
138
  {example.map((translation, innerIndex) => (
139
139
  <div key={`${index}_${innerIndex}`}>
140
- <TranslatedText>{translation.example}</TranslatedText>
140
+ <TranslatedText data-first={innerIndex === 0}>{translation.example}</TranslatedText>
141
141
  {translation.transcriptions.pinyin && (
142
142
  <TranslatedText key={t('gloss.transcriptions.pinyin')} lang={glossData.originalLanguage}>
143
143
  {translation.transcriptions?.pinyin}
@@ -58,7 +58,7 @@ interface PodcastProps extends BaseProps {
58
58
  }
59
59
 
60
60
  interface ConceptProps extends BaseProps {
61
- type: 'concept';
61
+ type: 'concept' | 'gloss';
62
62
  copyright: ConceptCopyright | undefined;
63
63
  }
64
64
 
@@ -210,9 +210,10 @@ const messages = {
210
210
  notionsHeading: 'Explanations',
211
211
  notionsRemove: 'Remove',
212
212
  showVideo: 'Watch video',
213
- showNotion: 'Show notion',
213
+ concept: 'Show notion',
214
214
  gridView: 'Grid-view',
215
215
  listView: 'List-view',
216
+ gloss: 'Show gloss',
216
217
  },
217
218
  contextModal: {
218
219
  button: '+ {{count}} more contexts',
@@ -1336,6 +1337,7 @@ const messages = {
1336
1337
  concept: 'Concept',
1337
1338
  h5p: 'H5P',
1338
1339
  external: 'External resource',
1340
+ gloss: 'Gloss',
1339
1341
  },
1340
1342
  },
1341
1343
  gloss: {