@ndla/ui 41.2.5 → 41.3.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 (79) hide show
  1. package/es/Article/ArticleByline.js +5 -5
  2. package/es/Article/index.js +1 -2
  3. package/es/ContentTypeBadge/ContentTypeBadge.js +2 -2
  4. package/es/Embed/ImageEmbed.js +4 -1
  5. package/es/FrontpageArticle/FrontpageArticle.js +78 -0
  6. package/es/FrontpageArticle/index.js +10 -0
  7. package/es/Hero/Hero.js +25 -15
  8. package/es/Hero/HeroContent.js +16 -0
  9. package/es/Hero/index.js +2 -1
  10. package/es/Image/Image.js +42 -35
  11. package/es/Layout/LayoutItem.js +15 -4
  12. package/es/LearningPaths/LearningPathWrapper.js +4 -9
  13. package/es/LicenseByline/EmbedByline.js +11 -6
  14. package/es/all.css +1 -1
  15. package/es/index.js +3 -2
  16. package/es/locale/messages-en.js +1 -1
  17. package/es/locale/messages-nb.js +1 -1
  18. package/es/locale/messages-nn.js +1 -1
  19. package/es/locale/messages-se.js +1 -1
  20. package/es/locale/messages-sma.js +1 -1
  21. package/lib/Article/ArticleByline.js +5 -5
  22. package/lib/Article/index.d.ts +1 -2
  23. package/lib/Article/index.js +0 -7
  24. package/lib/ContentTypeBadge/ContentTypeBadge.js +1 -1
  25. package/lib/Embed/ImageEmbed.d.ts +2 -1
  26. package/lib/Embed/ImageEmbed.js +4 -1
  27. package/lib/FrontpageArticle/FrontpageArticle.d.ts +17 -0
  28. package/lib/FrontpageArticle/FrontpageArticle.js +84 -0
  29. package/lib/FrontpageArticle/index.d.ts +9 -0
  30. package/lib/FrontpageArticle/index.js +17 -0
  31. package/lib/Hero/Hero.d.ts +5 -7
  32. package/lib/Hero/Hero.js +25 -17
  33. package/lib/Hero/HeroContent.d.ts +12 -0
  34. package/lib/Hero/HeroContent.js +24 -0
  35. package/lib/Hero/index.d.ts +1 -0
  36. package/lib/Hero/index.js +8 -1
  37. package/lib/Image/Image.d.ts +2 -1
  38. package/lib/Image/Image.js +42 -35
  39. package/lib/Layout/LayoutItem.d.ts +3 -3
  40. package/lib/Layout/LayoutItem.js +16 -6
  41. package/lib/LearningPaths/LearningPathWrapper.js +4 -9
  42. package/lib/LicenseByline/EmbedByline.d.ts +2 -1
  43. package/lib/LicenseByline/EmbedByline.js +11 -6
  44. package/lib/all.css +1 -1
  45. package/lib/index.d.ts +3 -2
  46. package/lib/index.js +13 -6
  47. package/lib/locale/messages-en.js +1 -1
  48. package/lib/locale/messages-nb.js +1 -1
  49. package/lib/locale/messages-nn.js +1 -1
  50. package/lib/locale/messages-se.js +1 -1
  51. package/lib/locale/messages-sma.js +1 -1
  52. package/package.json +3 -3
  53. package/src/Article/ArticleByline.tsx +1 -0
  54. package/src/Article/index.ts +0 -2
  55. package/src/ContentTypeBadge/ContentTypeBadge.tsx +2 -2
  56. package/src/Embed/ImageEmbed.tsx +4 -1
  57. package/src/FrontpageArticle/FrontpageArticle.tsx +76 -0
  58. package/src/FrontpageArticle/index.ts +11 -0
  59. package/src/Hero/Hero.stories.tsx +38 -0
  60. package/src/Hero/Hero.tsx +94 -22
  61. package/src/Hero/HeroContent.tsx +43 -0
  62. package/src/Hero/index.ts +1 -0
  63. package/src/Image/Image.tsx +29 -19
  64. package/src/Image/__tests__/__snapshots__/Image-test.jsx.snap +73 -0
  65. package/src/Layout/LayoutItem.tsx +8 -4
  66. package/src/LearningPaths/LearningPathWrapper.tsx +6 -20
  67. package/src/LicenseByline/EmbedByline.tsx +15 -4
  68. package/src/index.ts +3 -1
  69. package/src/locale/messages-en.ts +1 -1
  70. package/src/locale/messages-nb.ts +1 -1
  71. package/src/locale/messages-nn.ts +1 -1
  72. package/src/locale/messages-se.ts +1 -1
  73. package/src/locale/messages-sma.ts +1 -1
  74. package/src/main.scss +0 -1
  75. package/es/Article/ArticleSideBar.js +0 -78
  76. package/lib/Article/ArticleSideBar.d.ts +0 -7
  77. package/lib/Article/ArticleSideBar.js +0 -84
  78. package/src/Article/ArticleSideBar.tsx +0 -73
  79. package/src/Hero/component.hero.scss +0 -122
package/lib/index.d.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  */
8
8
  export { default as SectionHeading } from './SectionHeading';
9
9
  export { ConceptNotionV2, ImageEmbed, AudioEmbed, H5pEmbed, ExternalEmbed, IframeEmbed, FootnoteEmbed, BrightcoveEmbed, ContentLinkEmbed, RelatedContentEmbed, ConceptEmbed, ConceptListEmbed, UnknownEmbed, } from './Embed';
10
- export { ArticleByline, ArticleContent, ArticleFootNotes, ArticleIntroduction, ArticleTitle, ArticleWrapper, ArticleHeaderWrapper, ArticleSideBar, default as Article, } from './Article';
10
+ export { ArticleByline, ArticleContent, ArticleFootNotes, ArticleIntroduction, ArticleTitle, ArticleWrapper, ArticleHeaderWrapper, default as Article, } from './Article';
11
11
  export { default as Table } from './Table';
12
12
  export { default as ResourcesWrapper, ResourcesTopicTitle } from './ResourcesWrapper';
13
13
  export { createUniversalPortal } from './utils/createUniversalPortal';
@@ -26,7 +26,7 @@ export { default as FactBox, FactBoxV2 } from './FactBox';
26
26
  export { default as Image, ImageLink, makeSrcQueryString } from './Image';
27
27
  export type { ImageCrop, ImageFocalPoint } from './Image';
28
28
  export type { HeroContentType } from './Hero';
29
- export { SubjectMaterialHero, TasksAndActivitiesHero, AssessmentResourcesHero, SubjectHero, ExternalLearningResourcesHero, SourceMaterialHero, Hero, NdlaFilmHero, } from './Hero';
29
+ export { SubjectMaterialHero, TasksAndActivitiesHero, AssessmentResourcesHero, SubjectHero, ExternalLearningResourcesHero, SourceMaterialHero, Hero, NdlaFilmHero, HeroContent, } from './Hero';
30
30
  export { FilterList, FilterListPhone, FilterButtons, ToggleItem } from './Filter';
31
31
  export { Footer, EditorName, FooterText } from './Footer';
32
32
  export { Figure, FigureCaption, FigureLicenseDialog, FigureExpandButton, FigureOpenDialogButton, FigureBylineExpandButton, } from './Figure';
@@ -98,4 +98,5 @@ export { Grid } from './Grid';
98
98
  export type { GridType } from './Grid';
99
99
  export { Heading } from './Typography';
100
100
  export type { HeadingLevel } from './types';
101
+ export { default as FrontpageArticle } from './FrontpageArticle';
101
102
  export { DefinitionTerm, DefinitionDescription } from './DefinitionList';
package/lib/index.js CHANGED
@@ -64,12 +64,6 @@ Object.defineProperty(exports, "ArticleIntroduction", {
64
64
  return _Article.ArticleIntroduction;
65
65
  }
66
66
  });
67
- Object.defineProperty(exports, "ArticleSideBar", {
68
- enumerable: true,
69
- get: function get() {
70
- return _Article.ArticleSideBar;
71
- }
72
- });
73
67
  Object.defineProperty(exports, "ArticleTitle", {
74
68
  enumerable: true,
75
69
  get: function get() {
@@ -454,6 +448,12 @@ Object.defineProperty(exports, "FootnoteEmbed", {
454
448
  return _Embed.FootnoteEmbed;
455
449
  }
456
450
  });
451
+ Object.defineProperty(exports, "FrontpageArticle", {
452
+ enumerable: true,
453
+ get: function get() {
454
+ return _FrontpageArticle.default;
455
+ }
456
+ });
457
457
  Object.defineProperty(exports, "FrontpageFilm", {
458
458
  enumerable: true,
459
459
  get: function get() {
@@ -532,6 +532,12 @@ Object.defineProperty(exports, "Hero", {
532
532
  return _Hero.Hero;
533
533
  }
534
534
  });
535
+ Object.defineProperty(exports, "HeroContent", {
536
+ enumerable: true,
537
+ get: function get() {
538
+ return _Hero.HeroContent;
539
+ }
540
+ });
535
541
  Object.defineProperty(exports, "HomeBreadcrumb", {
536
542
  enumerable: true,
537
543
  get: function get() {
@@ -1331,6 +1337,7 @@ var _ContactBlock = _interopRequireDefault(require("./ContactBlock"));
1331
1337
  var _CampaignBlock = require("./CampaignBlock");
1332
1338
  var _Grid = require("./Grid");
1333
1339
  var _Typography = require("./Typography");
1340
+ var _FrontpageArticle = _interopRequireDefault(require("./FrontpageArticle"));
1334
1341
  var _DefinitionList = require("./DefinitionList");
1335
1342
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
1336
1343
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -1165,7 +1165,7 @@ var messages = _objectSpread(_objectSpread({
1165
1165
  loginText: 'In order to use the My NDLA service you have to be a student or work at a school in a county that partakes in the NDLA collaboration. We ask you not to write offensive or personally sensitive information in text fields. Read our ',
1166
1166
  loginTextLink: 'privacy policy here',
1167
1167
  loginTerms: 'Log in with Feide to receive access. By logging on your accept your terms of service',
1168
- loginResourcePitch: 'Do you want to favorite this page?',
1168
+ loginResourcePitch: 'Do you want to favorite this resource?',
1169
1169
  loginWelcome: 'Welcome to My NDLA! This page allows you to organize your articles in your <i>own</i> way!',
1170
1170
  deleteAccount: 'Delete My NDLA',
1171
1171
  welcome: 'Welcome to my NDLA! You can now save your favourite resources from NDLA and organise them in folders with tags',
@@ -1166,7 +1166,7 @@ var messages = _objectSpread(_objectSpread({
1166
1166
  loginText: 'For å kunne bruke tjenesten Min NDLA må du være elev eller jobbe på en skole i et fylke som er med i NDLA-samarbeidet. Vi ber om at du ikke skriver noe støtende, personsensitiv informasjon eller andre persondata i tekstfelt. Les vår ',
1167
1167
  loginTextLink: 'personvernerklæring her',
1168
1168
  loginTerms: 'Logg på med Feide for å få tilgang. Ved å logge på godkjenner du våre vilkår for bruk',
1169
- loginResourcePitch: 'Ønsker du å favorittmerke denne siden?',
1169
+ loginResourcePitch: 'Ønsker du å favorittmerke denne ressursen?',
1170
1170
  loginWelcome: 'Velkommen til NDLA! Her kan du organisere fagstoffet på <i>din</i> måte!',
1171
1171
  welcome: 'Velkommen til Min NDLA! Nå kan du lagre favorittressursene dine fra NDLA og organisere dem i mapper og med emneknagger.',
1172
1172
  read: {
@@ -1166,7 +1166,7 @@ var messages = _objectSpread(_objectSpread({
1166
1166
  loginText: 'For å kunne bruke tjenesten Min NDLA må du vere elev eller jobbe på ein skule i eit fylke som er med i NDLA-samarbeidet. Vi ber om at du ikkje skriv noko støtande, personsensitiv informasjon eller andre persondata i tekstfelt. Les vår ',
1167
1167
  loginTextLink: 'personvernerklæring her',
1168
1168
  loginTerms: 'Logg på med Feide for å få tilgang. Ved å logge på godkjennar du våre vilkår for bruk',
1169
- loginResourcePitch: 'Ønsker du å favorittmerke denne sida?',
1169
+ loginResourcePitch: 'Ønsker du å favorittmerke denne resursen?',
1170
1170
  loginWelcome: 'Velkommen til NDLA! Her kan du organisere fagstoffet på <i>din</i> måte!',
1171
1171
  welcome: 'Velkommen til Min NDLA! No kan du lagre favorittressursane dine frå NDLA og organisere dei i mapper og med emneknaggar.',
1172
1172
  read: {
@@ -1166,7 +1166,7 @@ var messages = _objectSpread(_objectSpread({
1166
1166
  loginText: 'Jus galggat sáhttit geavahit bálvalusa Mu NDLA fertet leat oahppi dahje bargat muhtin skuvllas fylkkas mii lea mielde NDLA-ovttasbarggus. Mii bivdit ahte it čále maidege unohasaid, persovdnasensitiivvalaš dieđuid dahje eará persovdnadáhtaid min teakstagieddái. Loga min ',
1167
1167
  loginTextLink: 'personsuodjalusjulggaštusa dákko',
1168
1168
  loginTerms: 'Logge Feide bokte vai oaččut beassanlobi. Go logget sisa de dohkkehat min geavahaneavttuid.',
1169
- loginResourcePitch: 'Dáhtut go merket siiddu oiddohin?',
1169
+ loginResourcePitch: 'Ønsker du å favorittmerke denne ressursen?',
1170
1170
  loginWelcome: 'Bures boahtin NDLA:ii! Dáppe sáhtát fágaávdnasiid ordnet iežat vuogi mielde',
1171
1171
  welcome: 'Bures boahtin Mu NDLA:ii! Dál sáhtát vurket iežat oiddotresurssaid NDLA:s ja ordnet daid nu go dáhtut máhpaide ja fáddágilkoriiguin.',
1172
1172
  read: {
@@ -1166,7 +1166,7 @@ var messages = _objectSpread(_objectSpread({
1166
1166
  loginText: 'For å kunne bruke tjenesten Min NDLA må du vere elev eller jobbe på ein skule i eit fylke som er med i NDLA-samarbeidet. Vi ber om at du ikkje skriv noko støtande, personsensitiv informasjon eller andre persondata i tekstfelt. Les vår ',
1167
1167
  loginTextLink: 'personvernerklæring her',
1168
1168
  loginTerms: 'Logg på med Feide for å få tilgang. Ved å logge på godkjenner du våre vilkår for bruk',
1169
- loginResourcePitch: 'Ønsker du å favorittmerke denne siden?',
1169
+ loginResourcePitch: 'Ønsker du å favorittmerke denne ressursen?',
1170
1170
  loginWelcome: 'Velkommen til NDLA! Her kan du organisere fagstoffet på <i>din</i> måte!',
1171
1171
  welcome: 'Velkommen til Min NDLA! Nå kan du lagre favorittressursene dine fra NDLA og organisere dem i mapper og med emneknagger.',
1172
1172
  read: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "41.2.5",
3
+ "version": "41.3.0",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -36,7 +36,7 @@
36
36
  "@ndla/button": "^10.1.9",
37
37
  "@ndla/carousel": "^3.1.7",
38
38
  "@ndla/core": "^4.1.2",
39
- "@ndla/forms": "^4.3.9",
39
+ "@ndla/forms": "^4.3.10",
40
40
  "@ndla/hooks": "^2.0.7",
41
41
  "@ndla/icons": "^3.0.5",
42
42
  "@ndla/licenses": "^7.0.4",
@@ -83,5 +83,5 @@
83
83
  "publishConfig": {
84
84
  "access": "public"
85
85
  },
86
- "gitHead": "d5b859163608f1921fa425b333d5bbdd898c64d1"
86
+ "gitHead": "8f9e3f62713e77a08c6c27442e5567fd4e8282a4"
87
87
  }
@@ -85,6 +85,7 @@ const getSuppliersText = (suppliers: SupplierProps[], t: TFunction) => {
85
85
  const LicenseWrapper = styled.div`
86
86
  display: flex;
87
87
  gap: ${spacing.small};
88
+ padding-right: ${spacing.xsmall}}
88
89
  `;
89
90
 
90
91
  const StyledAccordionHeader = styled(AccordionHeader)`
@@ -11,14 +11,12 @@ import ArticleByline from './ArticleByline';
11
11
  import ArticleContent from './ArticleContent';
12
12
  import ArticleFootNotes from './ArticleFootNotes';
13
13
  import ArticleHeaderWrapper from './ArticleHeaderWrapper';
14
- import ArticleSideBar from './ArticleSideBar';
15
14
 
16
15
  export {
17
16
  ArticleByline,
18
17
  ArticleContent,
19
18
  ArticleFootNotes,
20
19
  ArticleHeaderWrapper,
21
- ArticleSideBar,
22
20
  ArticleTitle,
23
21
  ArticleIntroduction,
24
22
  ArticleWrapper,
@@ -13,7 +13,7 @@ import {
13
13
  } from '@ndla/icons/contentType';
14
14
 
15
15
  import { MenuBook } from '@ndla/icons/action';
16
- import { Concept, Media, SquareAudio, SquareVideo } from '@ndla/icons/editor';
16
+ import { Concept, ImageNormal, SquareAudio, SquareVideo } from '@ndla/icons/editor';
17
17
 
18
18
  import * as contentTypes from '../model/ContentType';
19
19
 
@@ -66,7 +66,7 @@ export const ContentTypeBadge = ({ type, background, title, size = 'small', bord
66
66
  icon = <MultidisciplinaryTopic />;
67
67
  break;
68
68
  case contentTypes.resourceEmbedTypeMapping.image:
69
- icon = <Media />;
69
+ icon = <ImageNormal />;
70
70
  embedResource = true;
71
71
  break;
72
72
  case contentTypes.resourceEmbedTypeMapping.audio:
@@ -22,6 +22,7 @@ interface Props {
22
22
  embed: ImageMetaData;
23
23
  previewAlt?: boolean;
24
24
  heartButton?: HeartButtonType;
25
+ inGrid?: boolean;
25
26
  }
26
27
 
27
28
  export interface Author {
@@ -98,7 +99,7 @@ const getCrop = (data: ImageEmbedData) => {
98
99
 
99
100
  const expandedSizes = '(min-width: 1024px) 1024px, 100vw';
100
101
 
101
- const ImageEmbed = ({ embed, previewAlt, heartButton: HeartButton }: Props) => {
102
+ const ImageEmbed = ({ embed, previewAlt, heartButton: HeartButton, inGrid }: Props) => {
102
103
  const [isBylineHidden, setIsBylineHidden] = useState(hideByline(embed.embedData.size));
103
104
  const [imageSizes, setImageSizes] = useState<string | undefined>(undefined);
104
105
  if (embed.status === 'error') {
@@ -133,6 +134,7 @@ const ImageEmbed = ({ embed, previewAlt, heartButton: HeartButton }: Props) => {
133
134
  sizes={imageSizes ?? sizes}
134
135
  alt={altText}
135
136
  src={data.image.imageUrl}
137
+ inGrid={inGrid}
136
138
  expandButton={
137
139
  <ExpandButton
138
140
  size={embedData.size}
@@ -151,6 +153,7 @@ const ImageEmbed = ({ embed, previewAlt, heartButton: HeartButton }: Props) => {
151
153
  description={embedData.caption ?? data.caption.caption}
152
154
  bottomRounded
153
155
  visibleAlt={previewAlt ? embed.embedData.alt : ''}
156
+ inGrid={inGrid}
154
157
  >
155
158
  {HeartButton && data.copyright.license.license.toLowerCase() !== COPYRIGHTED && <HeartButton embed={embed} />}
156
159
  </EmbedByline>
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Copyright (c) 2023-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import { ReactNode } from 'react';
10
+ import { breakpoints, fonts, mq, spacing, utils } from '@ndla/core';
11
+ import styled from '@emotion/styled';
12
+ import { Article } from '../types';
13
+ import LayoutItem from '../Layout';
14
+ import { Heading } from '../Typography';
15
+
16
+ interface Props {
17
+ article: Article;
18
+ children?: ReactNode;
19
+ id: string;
20
+ isWide?: boolean;
21
+ }
22
+
23
+ const StyledArticle = styled.article`
24
+ max-width: 773px;
25
+ &[data-wide='true'] {
26
+ max-width: 1100px;
27
+ }
28
+ `;
29
+
30
+ const StyledLayoutItem = styled(LayoutItem)`
31
+ > section {
32
+ > figure,
33
+ > iframe {
34
+ width: 100% !important;
35
+ left: 0;
36
+ }
37
+ }
38
+ `;
39
+
40
+ const StyledIntroduction = styled.div`
41
+ font-weight: ${fonts.weight.light};
42
+ font-family: ${fonts.sans};
43
+ margin-top: ${spacing.small};
44
+ ${fonts.sizes('22px', '30px')};
45
+
46
+ ${mq.range({ from: breakpoints.tablet })} {
47
+ margin-top: ${spacing.mediumlarge};
48
+ ${fonts.sizes('26px', '36px')};
49
+ }
50
+ `;
51
+
52
+ export const FrontpageArticle = ({ article, id, isWide }: Props) => {
53
+ const { title, introduction, content } = article;
54
+
55
+ if (isWide) {
56
+ return (
57
+ <StyledArticle data-wide={isWide}>
58
+ <StyledLayoutItem>{content}</StyledLayoutItem>
59
+ </StyledArticle>
60
+ );
61
+ }
62
+
63
+ return (
64
+ <StyledArticle>
65
+ <StyledLayoutItem>
66
+ <Heading id={id} headingStyle="h1" element="h1" margin="normal" tabIndex={-1}>
67
+ {title}
68
+ </Heading>
69
+ <StyledIntroduction>{introduction}</StyledIntroduction>
70
+ </StyledLayoutItem>
71
+ <StyledLayoutItem>{content}</StyledLayoutItem>
72
+ </StyledArticle>
73
+ );
74
+ };
75
+
76
+ export default FrontpageArticle;
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Copyright (c) 2023-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import FrontpageArticle from './FrontpageArticle';
10
+
11
+ export default FrontpageArticle;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Copyright (c) 2023-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import React from 'react';
10
+ import styled from '@emotion/styled';
11
+ import { Meta, StoryFn } from '@storybook/react';
12
+ import { defaultParameters } from '../../../../stories/defaults';
13
+ import { Hero } from './Hero';
14
+
15
+ const StyledDiv = styled.div`
16
+ width: 1000px;
17
+ `;
18
+
19
+ export default {
20
+ title: 'Components/Hero',
21
+ component: Hero,
22
+ tags: ['autodocs'],
23
+ parameters: {
24
+ ...defaultParameters,
25
+ layout: 'centered',
26
+ },
27
+ args: {
28
+ contentType: 'assessment-resources',
29
+ },
30
+ } as Meta<typeof Hero>;
31
+
32
+ export const HeroStory: StoryFn<typeof Hero> = ({ ...args }) => (
33
+ <Hero {...args}>
34
+ <StyledDiv />
35
+ </Hero>
36
+ );
37
+
38
+ HeroStory.storyName = 'Hero';
package/src/Hero/Hero.tsx CHANGED
@@ -6,15 +6,90 @@
6
6
  *
7
7
  */
8
8
 
9
- import React, { ReactNode } from 'react';
10
- import BEMHelper from 'react-bem-helper';
9
+ import React, { HTMLAttributes, ReactNode } from 'react';
10
+ import styled from '@emotion/styled';
11
+ import { breakpoints, colors, mq, spacing, spacingUnit } from '@ndla/core';
12
+ import {
13
+ ASSESSMENT_RESOURCES,
14
+ EXTERNAL_LEARNING_RESOURCES,
15
+ SOURCE_MATERIAL,
16
+ SUBJECT,
17
+ SUBJECT_MATERIAL,
18
+ TASKS_AND_ACTIVITIES,
19
+ } from '../model/ContentType';
11
20
 
12
- import * as contentTypes from '../model/ContentType';
21
+ const StyledDiv = styled.div`
22
+ background-repeat: repeat;
23
+ background-size: ${spacing.normal};
24
+ background-color: ${colors.brand.greyLightest};
13
25
 
14
- const classes = new BEMHelper({
15
- name: 'hero',
16
- prefix: 'c-',
17
- });
26
+ ${mq.range({ from: breakpoints.tablet })} {
27
+ min-height: 246px;
28
+ padding-bottom: ${spacingUnit * 6.5}px;
29
+ }
30
+
31
+ &[data-contenttype='subject-material'] {
32
+ background-color: ${colors.subjectMaterial.light};
33
+ }
34
+
35
+ &[data-contenttype='tasks-and-activities'] {
36
+ background-color: ${colors.tasksAndActivities.background};
37
+ }
38
+
39
+ &[data-contenttype='assessment-resources'] {
40
+ background-color: ${colors.assessmentResource.background};
41
+ }
42
+
43
+ &[data-contenttype='subject'] {
44
+ background-color: ${colors.subject.light};
45
+ }
46
+
47
+ &[data-contenttype='external-learning-resources'] {
48
+ background-color: ${colors.externalLearningResource.background};
49
+ }
50
+
51
+ &[data-contenttype='source-material'] {
52
+ background-color: ${colors.sourceMaterial.light};
53
+ }
54
+
55
+ &[data-contenttype='beta'] {
56
+ background-color: ${colors.brand.primary};
57
+ }
58
+
59
+ &[data-contenttype='ndla-film has-image'],
60
+ &[data-contenttype='ndla-film'] {
61
+ background: ${colors.ndlaFilm.filmColor};
62
+
63
+ ${mq.range({ from: breakpoints.tablet })} {
64
+ height: 2000px;
65
+ margin-bottom: -1910px;
66
+ }
67
+
68
+ &[data-contenttype='ndla-film has-image'] {
69
+ ${mq.range({ from: breakpoints.tablet })} {
70
+ margin-bottom: -1800px;
71
+ @media (min-height: 720px) {
72
+ margin-bottom: -1750px;
73
+ }
74
+ @media (min-height: 1020px) {
75
+ margin-bottom: -1700px;
76
+ }
77
+ }
78
+ }
79
+
80
+ ${mq.range({ until: breakpoints.tablet })} {
81
+ + div article.c-article {
82
+ margin-left: -${spacing.normal};
83
+ margin-right: -${spacing.normal};
84
+ margin-top: 0;
85
+ background: ${colors.white};
86
+ padding-left: ${spacing.normal};
87
+ padding-right: ${spacing.normal};
88
+ padding-top: ${spacing.large};
89
+ }
90
+ }
91
+ }
92
+ `;
18
93
 
19
94
  export type HeroContentType =
20
95
  | 'subject-material'
@@ -27,32 +102,29 @@ export type HeroContentType =
27
102
  | 'topic'
28
103
  | 'beta'
29
104
  | 'ndla-film'
30
- | 'ndla-film has-image';
105
+ | 'ndla-film has-image'
106
+ | 'frontpage-article';
31
107
 
32
- interface HeroProps {
33
- children?: ReactNode;
108
+ interface HeroProps extends HTMLAttributes<HTMLDivElement> {
34
109
  contentType?: HeroContentType;
35
110
  }
36
111
 
37
112
  export const Hero = ({ children, contentType }: HeroProps) => (
38
- <div {...classes('', contentType)}>{children || null}</div>
113
+ <StyledDiv data-contenttype={contentType}>{children || null}</StyledDiv>
39
114
  );
40
115
 
41
116
  interface Props {
42
117
  children?: ReactNode;
118
+ hasImage?: boolean;
43
119
  }
44
- export const SubjectMaterialHero = (props: Props) => <Hero contentType={contentTypes.SUBJECT_MATERIAL} {...props} />;
45
- export const TasksAndActivitiesHero = (props: Props) => (
46
- <Hero contentType={contentTypes.TASKS_AND_ACTIVITIES} {...props} />
47
- );
48
- export const AssessmentResourcesHero = (props: Props) => (
49
- <Hero contentType={contentTypes.ASSESSMENT_RESOURCES} {...props} />
50
- );
51
- export const SubjectHero = (props: Props) => <Hero contentType={contentTypes.SUBJECT} {...props} />;
120
+ export const SubjectMaterialHero = (props: Props) => <Hero contentType={SUBJECT_MATERIAL} {...props} />;
121
+ export const TasksAndActivitiesHero = (props: Props) => <Hero contentType={TASKS_AND_ACTIVITIES} {...props} />;
122
+ export const AssessmentResourcesHero = (props: Props) => <Hero contentType={ASSESSMENT_RESOURCES} {...props} />;
123
+ export const SubjectHero = (props: Props) => <Hero contentType={SUBJECT} {...props} />;
52
124
  export const ExternalLearningResourcesHero = (props: Props) => (
53
- <Hero contentType={contentTypes.EXTERNAL_LEARNING_RESOURCES} {...props} />
125
+ <Hero contentType={EXTERNAL_LEARNING_RESOURCES} {...props} />
54
126
  );
55
- export const SourceMaterialHero = (props: Props) => <Hero contentType={contentTypes.SOURCE_MATERIAL} {...props} />;
56
- export const NdlaFilmHero = ({ hasImage, ...rest }: Props & { hasImage?: boolean }) => (
127
+ export const SourceMaterialHero = (props: Props) => <Hero contentType={SOURCE_MATERIAL} {...props} />;
128
+ export const NdlaFilmHero = ({ hasImage, ...rest }: Props) => (
57
129
  <Hero {...rest} contentType={hasImage ? 'ndla-film has-image' : 'ndla-film'} />
58
130
  );
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copyright (c) 2023-present, NDLA.
3
+ *
4
+ * This source code is licensed under the GPLv3 license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ *
7
+ */
8
+
9
+ import styled from '@emotion/styled';
10
+ import { spacing, mq, breakpoints } from '@ndla/core';
11
+
12
+ export const HeroContent = styled.div`
13
+ display: flex;
14
+ flex-wrap: wrap;
15
+ align-items: flex-end;
16
+ padding: ${spacing.small} 0 ${spacing.small};
17
+ z-index: 9;
18
+
19
+ ${mq.range({ from: breakpoints.tablet })} {
20
+ min-height: 90px;
21
+ padding-bottom: ${spacing.xxsmall};
22
+
23
+ &[data-image='true'] {
24
+ min-height: 190px;
25
+ @media (min-height: 720px) {
26
+ min-height: 240px;
27
+ }
28
+ @media (min-height: 1020px) {
29
+ min-height: 290px;
30
+ }
31
+ }
32
+ }
33
+
34
+ &[data-film='true'] {
35
+ .c-breadcrumb__item,
36
+ .c-breadcrumb__item--home:after,
37
+ a,
38
+ a:focus,
39
+ a:hover {
40
+ color: #fff;
41
+ }
42
+ }
43
+ `;
package/src/Hero/index.ts CHANGED
@@ -16,5 +16,6 @@ export {
16
16
  Hero,
17
17
  NdlaFilmHero,
18
18
  } from './Hero';
19
+ export { HeroContent } from './HeroContent';
19
20
 
20
21
  export type { HeroContentType } from './Hero';
@@ -7,8 +7,8 @@
7
7
  */
8
8
 
9
9
  import React, { ReactNode } from 'react';
10
+ import { colors } from '@ndla/core';
10
11
  import styled from '@emotion/styled';
11
- import { css } from '@emotion/react';
12
12
  import LazyLoadImage from './LazyLoadImage';
13
13
 
14
14
  export interface ImageCrop {
@@ -38,22 +38,30 @@ const getSrcSet = (src: string, crop: ImageCrop | undefined, focalPoint: ImageFo
38
38
  return widths.map((width) => `${src}?${makeSrcQueryString(width, crop, focalPoint)} ${width}w`).join(', ');
39
39
  };
40
40
 
41
- interface StyledImageWrapperProps {
42
- svg?: boolean;
43
- }
44
-
45
- const StyledImageWrapper = styled.div<StyledImageWrapperProps>`
41
+ const StyledImageWrapper = styled.div`
46
42
  position: relative;
47
- ${({ svg }) => {
48
- return (
49
- svg &&
50
- css`
51
- display: flex
52
- justify-content: center;
53
- `
54
- );
55
- }}
43
+
44
+ &[data-svg='true'] {
45
+ display: flex;
46
+ justify-content: center;
47
+ }
48
+ &[data-in-grid='true'] {
49
+ border: 1px solid ${colors.brand.tertiary};
50
+ border-bottom: 0;
51
+ border-radius: 4px;
52
+ border-bottom-left-radius: 0;
53
+ border-bottom-right-radius: 0;
54
+ }
55
+ `;
56
+
57
+ const StyledImage = styled.img`
58
+ &[data-in-grid='true'] {
59
+ border-radius: 3px;
60
+ border-bottom-left-radius: 0;
61
+ border-bottom-right-radius: 0;
62
+ }
56
63
  `;
64
+
57
65
  interface Props {
58
66
  alt: string;
59
67
  src: string;
@@ -66,6 +74,7 @@ interface Props {
66
74
  expandButton?: ReactNode;
67
75
  crop?: ImageCrop;
68
76
  focalPoint?: ImageFocalPoint;
77
+ inGrid?: boolean;
69
78
  }
70
79
 
71
80
  const Image = ({
@@ -79,6 +88,7 @@ const Image = ({
79
88
  sizes = '(min-width: 1024px) 1024px, 100vw',
80
89
  expandButton,
81
90
  fallbackWidth = 1024,
91
+ inGrid,
82
92
  ...rest
83
93
  }: Props) => {
84
94
  const srcSet = rest.srcSet ?? getSrcSet(src, crop, focalPoint);
@@ -86,8 +96,8 @@ const Image = ({
86
96
 
87
97
  if (contentType && contentType === 'image/gif') {
88
98
  return (
89
- <StyledImageWrapper>
90
- <img alt={alt} src={`${src}`} {...rest} />
99
+ <StyledImageWrapper data-in-grid={inGrid}>
100
+ <StyledImage alt={alt} src={`${src}`} {...rest} data-in-grid={inGrid} />
91
101
  </StyledImageWrapper>
92
102
  );
93
103
  }
@@ -107,10 +117,10 @@ const Image = ({
107
117
  }
108
118
 
109
119
  return (
110
- <StyledImageWrapper svg={contentType === 'image/svg+xml'}>
120
+ <StyledImageWrapper data-svg={contentType === 'image/svg+xml'} data-in-grid={inGrid}>
111
121
  <picture>
112
122
  <source type={contentType} srcSet={srcSet} sizes={sizes} />
113
- <img alt={alt} src={`${src}?${queryString}`} {...rest} />
123
+ <StyledImage alt={alt} src={`${src}?${queryString}`} {...rest} data-in-grid={inGrid} />
114
124
  </picture>
115
125
  {expandButton}
116
126
  </StyledImageWrapper>