@ndla/ui 42.0.6 → 42.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 (64) hide show
  1. package/es/Article/ArticleByline.js +9 -6
  2. package/es/CompetenceGoalTab/CompetenceGoalItem.js +7 -81
  3. package/es/CompetenceGoalTab/CompetenceGoalTab.js +2 -11
  4. package/es/CompetenceGoalTab/CompetenceItem.js +26 -51
  5. package/es/CompetenceGoalTab/CoreElementItem.js +43 -0
  6. package/es/CompetenceGoalTab/SearchButton.js +43 -0
  7. package/es/CompetenceGoalTab/styles.js +57 -0
  8. package/es/FrontpageArticle/FrontpageArticle.js +15 -3
  9. package/es/Hero/Hero.js +2 -2
  10. package/es/Layout/OneColumn.js +15 -4
  11. package/es/SearchTypeResult/SearchHeader.js +34 -17
  12. package/es/locale/messages-en.js +2 -1
  13. package/es/locale/messages-nb.js +2 -1
  14. package/es/locale/messages-nn.js +2 -1
  15. package/es/locale/messages-se.js +2 -1
  16. package/es/locale/messages-sma.js +2 -1
  17. package/lib/Article/ArticleByline.d.ts +3 -1
  18. package/lib/Article/ArticleByline.js +9 -6
  19. package/lib/CompetenceGoalTab/CompetenceGoalItem.js +20 -92
  20. package/lib/CompetenceGoalTab/CompetenceGoalTab.js +9 -18
  21. package/lib/CompetenceGoalTab/CompetenceItem.d.ts +2 -6
  22. package/lib/CompetenceGoalTab/CompetenceItem.js +25 -50
  23. package/lib/CompetenceGoalTab/CoreElementItem.d.ts +10 -0
  24. package/lib/CompetenceGoalTab/CoreElementItem.js +50 -0
  25. package/lib/CompetenceGoalTab/SearchButton.d.ts +14 -0
  26. package/lib/CompetenceGoalTab/SearchButton.js +50 -0
  27. package/lib/CompetenceGoalTab/styles.d.ts +28 -0
  28. package/lib/CompetenceGoalTab/styles.js +67 -0
  29. package/lib/FrontpageArticle/FrontpageArticle.d.ts +2 -1
  30. package/lib/FrontpageArticle/FrontpageArticle.js +15 -3
  31. package/lib/Hero/Hero.js +2 -2
  32. package/lib/Layout/OneColumn.d.ts +3 -3
  33. package/lib/Layout/OneColumn.js +16 -6
  34. package/lib/SearchTypeResult/SearchHeader.d.ts +3 -2
  35. package/lib/SearchTypeResult/SearchHeader.js +34 -17
  36. package/lib/locale/messages-en.d.ts +1 -0
  37. package/lib/locale/messages-en.js +2 -1
  38. package/lib/locale/messages-nb.d.ts +1 -0
  39. package/lib/locale/messages-nb.js +2 -1
  40. package/lib/locale/messages-nn.d.ts +1 -0
  41. package/lib/locale/messages-nn.js +2 -1
  42. package/lib/locale/messages-se.d.ts +1 -0
  43. package/lib/locale/messages-se.js +2 -1
  44. package/lib/locale/messages-sma.d.ts +1 -0
  45. package/lib/locale/messages-sma.js +2 -1
  46. package/lib/types.d.ts +9 -2
  47. package/package.json +2 -2
  48. package/src/Article/ArticleByline.tsx +12 -2
  49. package/src/CompetenceGoalTab/CompetenceGoalItem.tsx +7 -56
  50. package/src/CompetenceGoalTab/CompetenceGoalTab.tsx +2 -2
  51. package/src/CompetenceGoalTab/CompetenceItem.tsx +26 -26
  52. package/src/CompetenceGoalTab/CoreElementItem.tsx +38 -0
  53. package/src/CompetenceGoalTab/SearchButton.tsx +51 -0
  54. package/src/CompetenceGoalTab/styles.ts +36 -0
  55. package/src/FrontpageArticle/FrontpageArticle.tsx +17 -2
  56. package/src/Hero/Hero.tsx +4 -1
  57. package/src/Layout/OneColumn.tsx +8 -4
  58. package/src/SearchTypeResult/SearchHeader.tsx +24 -9
  59. package/src/locale/messages-en.ts +2 -1
  60. package/src/locale/messages-nb.ts +2 -1
  61. package/src/locale/messages-nn.ts +2 -1
  62. package/src/locale/messages-se.ts +2 -1
  63. package/src/locale/messages-sma.ts +2 -1
  64. package/src/types.ts +11 -2
@@ -458,7 +458,8 @@ var messages = _objectSpread(_objectSpread({
458
458
  useCompentenceGoalsFilter: 'Geavat filtara',
459
459
  closeCompentenceGoalsFilter: 'Govčča filtara',
460
460
  competenceGoalsNarrowBackButton: 'Ruovttoluotta',
461
- competenceGoalResourceSearchText: 'Vis ressursar til kompetansemål {{goal}}',
461
+ competenceGoalResourceSearchText: 'Vis ressursar til kompetansemål {{code}}',
462
+ coreResourceSearchText: 'Vis ressurser til kjerneelement {{code}}',
462
463
  competenceGoalShowExtra: 'Čájet oahppoplána doarjaga',
463
464
  competenceGoalCloseExtra: 'Čiega oahppoplána doarjaga',
464
465
  competenceCoreLabel: 'Guovddášelemeanta',
@@ -743,6 +743,7 @@ declare const messages: {
743
743
  closeCompentenceGoalsFilter: string;
744
744
  competenceGoalsNarrowBackButton: string;
745
745
  competenceGoalResourceSearchText: string;
746
+ coreResourceSearchText: string;
746
747
  competenceGoalShowExtra: string;
747
748
  competenceGoalCloseExtra: string;
748
749
  competenceCoreLabel: string;
@@ -458,7 +458,8 @@ var messages = _objectSpread(_objectSpread({
458
458
  useCompentenceGoalsFilter: 'Bruk filter',
459
459
  closeCompentenceGoalsFilter: 'Lukk filter',
460
460
  competenceGoalsNarrowBackButton: 'Tilbake',
461
- competenceGoalResourceSearchText: 'Ohtsh gaajhkh vierhtieh mah daan maahtoeålman sjiehtieh',
461
+ competenceGoalResourceSearchText: 'Ohtsh gaajhkh vierhtieh mah daan maahtoeålman sjiehtieh {{code}}',
462
+ coreResourceSearchText: 'Vis ressurser til kjerneelement {{code}}',
462
463
  competenceGoalShowExtra: 'Vuesehth learoesoejkesjen dåarjoem',
463
464
  competenceGoalCloseExtra: 'Tjïekh learoesoejkesjen dåarjoem',
464
465
  competenceCoreLabel: 'Jarngebiehkie',
package/lib/types.d.ts CHANGED
@@ -87,9 +87,11 @@ export type elementRectType = {
87
87
  fromY: number;
88
88
  fromScale: number;
89
89
  };
90
- export type CompetenceGoalsItemType = {
90
+ interface GrepCode {
91
91
  id: string;
92
92
  title: string;
93
+ }
94
+ export interface CompetenceGoalsItemType extends GrepCode {
93
95
  goals: {
94
96
  id: string;
95
97
  text: string;
@@ -97,7 +99,12 @@ export type CompetenceGoalsItemType = {
97
99
  }[];
98
100
  selected?: boolean;
99
101
  isOembed?: boolean;
100
- };
102
+ }
103
+ export interface CoreElementsItemType extends GrepCode {
104
+ text?: string;
105
+ url?: string;
106
+ isOembed?: boolean;
107
+ }
101
108
  export type NotionMedia = {
102
109
  type: 'video' | 'other';
103
110
  element: ReactNode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "42.0.6",
3
+ "version": "42.1.0",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -83,5 +83,5 @@
83
83
  "publishConfig": {
84
84
  "access": "public"
85
85
  },
86
- "gitHead": "5a89e0fa5877b3ad21cc5f140ebc269e0d2e2061"
86
+ "gitHead": "d2c07a70bcb59567d7d14fd40963d8b36d1f98b7"
87
87
  }
@@ -51,6 +51,8 @@ type SupplierProps = {
51
51
  name: string;
52
52
  };
53
53
 
54
+ type AccordionHeaderVariants = 'white' | 'blue';
55
+
54
56
  type Props = {
55
57
  authors?: AuthorProps[];
56
58
  suppliers?: SupplierProps[];
@@ -59,6 +61,7 @@ type Props = {
59
61
  licenseBox?: ReactNode;
60
62
  locale?: string;
61
63
  footnotes?: FootNote[];
64
+ accordionHeaderVariant?: AccordionHeaderVariants;
62
65
  };
63
66
 
64
67
  const renderContributors = (contributors: SupplierProps[] | AuthorProps[], t: TFunction) => {
@@ -85,7 +88,7 @@ const getSuppliersText = (suppliers: SupplierProps[], t: TFunction) => {
85
88
  const LicenseWrapper = styled.div`
86
89
  display: flex;
87
90
  gap: ${spacing.small};
88
- padding-right: ${spacing.xsmall}}
91
+ padding-right: ${spacing.xsmall};
89
92
  `;
90
93
 
91
94
  const StyledAccordionHeader = styled(AccordionHeader)`
@@ -93,6 +96,10 @@ const StyledAccordionHeader = styled(AccordionHeader)`
93
96
  border: 1px solid ${colors.brand.tertiary};
94
97
  font-size: ${fonts.sizes('16px', '29px')};
95
98
  font-weight: ${fonts.weight.semibold};
99
+
100
+ &[data-background-color='white'] {
101
+ background-color: ${colors.background.default};
102
+ }
96
103
  `;
97
104
 
98
105
  const refRegexp = /note\d/;
@@ -106,6 +113,7 @@ const ArticleByline = ({
106
113
  licenseBox,
107
114
  published,
108
115
  locale,
116
+ accordionHeaderVariant = 'blue',
109
117
  }: Props) => {
110
118
  const { t } = useTranslation();
111
119
  const [openAccordions, setOpenAccordions] = useState<string[]>([]);
@@ -157,7 +165,9 @@ const ArticleByline = ({
157
165
  <AccordionRoot type="multiple" onValueChange={setOpenAccordions} value={openAccordions}>
158
166
  {licenseBox && (
159
167
  <AccordionItem value="rulesForUse">
160
- <StyledAccordionHeader headingLevel="h2">{t('article.useContent')}</StyledAccordionHeader>
168
+ <StyledAccordionHeader headingLevel="h2" data-background-color={accordionHeaderVariant}>
169
+ {t('article.useContent')}
170
+ </StyledAccordionHeader>
161
171
  <AccordionContent>{licenseBox}</AccordionContent>
162
172
  </AccordionItem>
163
173
  )}
@@ -7,58 +7,10 @@
7
7
  */
8
8
 
9
9
  import React from 'react';
10
- import styled from '@emotion/styled';
11
- import { fonts, spacing, mq, breakpoints } from '@ndla/core';
12
- import { Search } from '@ndla/icons/common';
13
- import { SafeLinkButton } from '@ndla/safelink';
14
10
  import { useTranslation } from 'react-i18next';
15
11
  import { CompetenceGoalsItemType } from '../types';
16
-
17
- const GoalItem = styled.li`
18
- margin: ${spacing.medium} 0;
19
- border-bottom: 1px solid #d1d6db;
20
- `;
21
-
22
- const GoalsHeading = styled.h3`
23
- margin-top: 0;
24
- `;
25
-
26
- const StyledSearch = styled(Search)`
27
- height: 24px;
28
- width: 24px;
29
- min-width: 24px;
30
- `;
31
-
32
- const GoalList = styled.ul`
33
- padding: 0;
34
- `;
35
-
36
- const GoalText = styled.p`
37
- margin: 0;
38
- `;
39
-
40
- const ListItemContent = styled.div`
41
- display: flex;
42
- justify-content: space-between;
43
- ${fonts.sizes('22px', '32px')};
44
- ${mq.range({ until: breakpoints.tabletWide })} {
45
- flex-direction: column;
46
- }
47
- `;
48
-
49
- const GoalSearchWrapper = styled.div`
50
- margin-left: ${spacing.normal};
51
- flex: 0 0 289px;
52
- span {
53
- text-align: left;
54
- }
55
-
56
- ${mq.range({ until: breakpoints.tabletWide })} {
57
- margin-left: 0;
58
- margin-top: ${spacing.normal};
59
- flex-basis: auto;
60
- }
61
- `;
12
+ import SearchButton from './SearchButton';
13
+ import { GoalItem, GoalList, GoalText, GoalsHeading, ListItemContent } from './styles';
62
14
 
63
15
  const CompetenceGoalItem = ({ title, goals, isOembed }: CompetenceGoalsItemType) => {
64
16
  const { t } = useTranslation();
@@ -71,12 +23,11 @@ const CompetenceGoalItem = ({ title, goals, isOembed }: CompetenceGoalsItemType)
71
23
  <ListItemContent>
72
24
  <GoalText>{goal.text}</GoalText>
73
25
  {goal.url && (
74
- <GoalSearchWrapper>
75
- <SafeLinkButton variant="outline" to={goal.url} target={isOembed ? '_blank' : '_self'}>
76
- <StyledSearch size="large" />
77
- <span>{t('competenceGoals.competenceGoalResourceSearchText', { goal: goal.id })}</span>
78
- </SafeLinkButton>
79
- </GoalSearchWrapper>
26
+ <SearchButton
27
+ url={goal.url}
28
+ isOembed={isOembed}
29
+ searchText={t('competenceGoals.competenceGoalResourceSearchText', { code: goal.id })}
30
+ />
80
31
  )}
81
32
  </ListItemContent>
82
33
  </li>
@@ -30,8 +30,8 @@ const ButtonWrapper = styled.div`
30
30
  `;
31
31
 
32
32
  const LicenseIconsTextWrapper = styled.span`
33
- padding-bottom: 5px;
34
- margin-left: 5px;
33
+ padding-bottom: ${spacing.xxsmall};
34
+ margin-left: ${spacing.xxsmall};
35
35
  `;
36
36
 
37
37
  const CompetenceGoalTab = ({ list, isOembed }: CompetenceProps) => {
@@ -9,25 +9,26 @@
9
9
  import React from 'react';
10
10
  import styled from '@emotion/styled';
11
11
  import { MenuBook } from '@ndla/icons/action';
12
- import { spacing } from '@ndla/core';
12
+ import { colors, spacing } from '@ndla/core';
13
13
  import { useTranslation } from 'react-i18next';
14
14
  import CompetenceGoalItem from './CompetenceGoalItem';
15
- import { CompetenceGoalsItemType } from '../types';
15
+ import { CompetenceGoalsItemType, CoreElementsItemType } from '../types';
16
+ import CoreElementItem from './CoreElementItem';
16
17
 
17
- const GroupedGoalsWrapper = styled.div`
18
- margin: 24px 0 52px;
18
+ const GroupedElementWrapper = styled.div`
19
+ margin: ${spacing.normal} 0 ${spacing.large};
19
20
  `;
20
21
 
21
22
  const GroupedGoalsTitleWrapper = styled.div`
22
- border-bottom: 1px solid #d1d6db;
23
+ border-bottom: 1px solid ${colors.brand.neutral7};
23
24
  `;
24
25
  const GroupedGoalsTitle = styled.h2`
25
26
  display: flex;
26
27
  align-items: center;
27
28
  gap: ${spacing.xsmall};
28
29
  svg {
29
- width: 24px;
30
- height: 24px;
30
+ width: ${spacing.normal};
31
+ height: ${spacing.normal};
31
32
  }
32
33
  `;
33
34
 
@@ -42,10 +43,6 @@ const GoalList = styled.ul`
42
43
  list-style-image: none;
43
44
  `;
44
45
 
45
- const GroupedCoreItemsWrapper = styled.div`
46
- margin: 24px 0 52px;
47
- `;
48
-
49
46
  export type CompetenceTypeProps = 'competenceGoals' | 'coreElement';
50
47
  export type CompetenceGoals = {
51
48
  title: string;
@@ -53,11 +50,7 @@ export type CompetenceGoals = {
53
50
  };
54
51
  export type CoreElementItems = {
55
52
  title?: string;
56
- elements: {
57
- id: string;
58
- name: string;
59
- text: string;
60
- }[];
53
+ elements: CoreElementsItemType[];
61
54
  };
62
55
  export type ListItemProp = {
63
56
  id: string;
@@ -74,12 +67,13 @@ export type ListItemProps = {
74
67
  const CompetenceItem = ({ item, isOembed }: ListItemProps) => {
75
68
  const { t } = useTranslation();
76
69
  const { type, groupedCompetenceGoals, groupedCoreElementItems } = item;
70
+
77
71
  switch (type) {
78
72
  case 'competenceGoals':
79
73
  return (
80
74
  <>
81
75
  {groupedCompetenceGoals?.map((group) => (
82
- <GroupedGoalsWrapper key={group.title}>
76
+ <GroupedElementWrapper key={group.title}>
83
77
  <GroupedGoalsTitleWrapper>
84
78
  <hgroup>
85
79
  <GroupedGoalsTitle>
@@ -102,7 +96,7 @@ const CompetenceItem = ({ item, isOembed }: ListItemProps) => {
102
96
  ))}
103
97
  </GoalList>
104
98
  )}
105
- </GroupedGoalsWrapper>
99
+ </GroupedElementWrapper>
106
100
  ))}
107
101
  </>
108
102
  );
@@ -110,18 +104,24 @@ const CompetenceItem = ({ item, isOembed }: ListItemProps) => {
110
104
  return (
111
105
  <>
112
106
  {groupedCoreElementItems?.map((group) => (
113
- <GroupedCoreItemsWrapper key={group.title}>
107
+ <GroupedElementWrapper key={group.title}>
114
108
  <GroupedGoalsTitle>
115
109
  <MenuBook />
116
110
  {group.title}
117
111
  </GroupedGoalsTitle>
118
- {group.elements.map((coreItem) => (
119
- <div key={coreItem.id}>
120
- <h3>{coreItem.name}</h3>
121
- <p>{coreItem.text}</p>
122
- </div>
123
- ))}
124
- </GroupedCoreItemsWrapper>
112
+ <GoalList>
113
+ {group.elements.map((coreItem) => (
114
+ <CoreElementItem
115
+ key={coreItem.id}
116
+ id={coreItem.id}
117
+ title={coreItem.title}
118
+ text={coreItem.text}
119
+ url={coreItem.url}
120
+ isOembed={isOembed}
121
+ />
122
+ ))}
123
+ </GoalList>
124
+ </GroupedElementWrapper>
125
125
  ))}
126
126
  </>
127
127
  );
@@ -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 { useTranslation } from 'react-i18next';
11
+ import { CoreElementsItemType } from '../types';
12
+ import SearchButton from './SearchButton';
13
+ import { GoalItem, GoalList, GoalText, GoalsHeading, ListItemContent } from './styles';
14
+
15
+ const CoreElementItem = ({ title, text, url, id, isOembed }: CoreElementsItemType) => {
16
+ const { t } = useTranslation();
17
+ return (
18
+ <GoalItem>
19
+ <GoalsHeading>{title}</GoalsHeading>
20
+ <GoalList>
21
+ <li>
22
+ <ListItemContent>
23
+ <GoalText>{text}</GoalText>
24
+ {url && (
25
+ <SearchButton
26
+ url={url}
27
+ isOembed={isOembed}
28
+ searchText={t('competenceGoals.coreResourceSearchText', { code: id })}
29
+ />
30
+ )}
31
+ </ListItemContent>
32
+ </li>
33
+ </GoalList>
34
+ </GoalItem>
35
+ );
36
+ };
37
+
38
+ export default CoreElementItem;
@@ -0,0 +1,51 @@
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 { spacing, mq, breakpoints } from '@ndla/core';
12
+ import { Search } from '@ndla/icons/common';
13
+ import { SafeLinkButton } from '@ndla/safelink';
14
+
15
+ const StyledSearch = styled(Search)`
16
+ height: ${spacing.normal};
17
+ width: ${spacing.normal};
18
+ min-width: ${spacing.normal};
19
+ `;
20
+
21
+ const GoalSearchWrapper = styled.div`
22
+ margin-left: ${spacing.normal};
23
+ flex: 0 0 30%;
24
+ span {
25
+ text-align: left;
26
+ }
27
+
28
+ ${mq.range({ until: breakpoints.tabletWide })} {
29
+ margin-left: 0;
30
+ margin-top: ${spacing.normal};
31
+ flex-basis: auto;
32
+ }
33
+ `;
34
+
35
+ interface SearchButtonProps {
36
+ url: string;
37
+ searchText: string;
38
+ isOembed?: boolean;
39
+ }
40
+
41
+ const SearchButton = ({ url, isOembed, searchText }: SearchButtonProps) => {
42
+ return (
43
+ <GoalSearchWrapper>
44
+ <SafeLinkButton variant="outline" to={url} target={isOembed ? '_blank' : '_self'}>
45
+ <StyledSearch size="large" />
46
+ <span>{searchText}</span>
47
+ </SafeLinkButton>
48
+ </GoalSearchWrapper>
49
+ );
50
+ };
51
+ export default SearchButton;
@@ -0,0 +1,36 @@
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 { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
11
+
12
+ export const ListItemContent = styled.div`
13
+ display: flex;
14
+ justify-content: space-between;
15
+ ${fonts.sizes('22px', '32px')};
16
+ ${mq.range({ until: breakpoints.tabletWide })} {
17
+ flex-direction: column;
18
+ }
19
+ `;
20
+
21
+ export const GoalItem = styled.li`
22
+ margin: ${spacing.medium} 0;
23
+ border-bottom: 1px solid ${colors.brand.neutral7};
24
+ `;
25
+
26
+ export const GoalsHeading = styled.h3`
27
+ margin-top: 0;
28
+ `;
29
+
30
+ export const GoalList = styled.ul`
31
+ padding: 0;
32
+ `;
33
+
34
+ export const GoalText = styled.p`
35
+ margin: 0;
36
+ `;
@@ -7,17 +7,19 @@
7
7
  */
8
8
 
9
9
  import { ReactNode } from 'react';
10
- import { breakpoints, fonts, mq, spacing, utils } from '@ndla/core';
10
+ import { breakpoints, fonts, mq, spacing } from '@ndla/core';
11
11
  import styled from '@emotion/styled';
12
12
  import { Article } from '../types';
13
13
  import LayoutItem from '../Layout';
14
14
  import { Heading } from '../Typography';
15
+ import { ArticleByline } from '../Article';
15
16
 
16
17
  interface Props {
17
18
  article: Article;
18
19
  children?: ReactNode;
19
20
  id: string;
20
21
  isWide?: boolean;
22
+ licenseBox?: ReactNode;
21
23
  }
22
24
 
23
25
  const StyledArticle = styled.article`
@@ -39,7 +41,7 @@ const StyledIntroduction = styled.div`
39
41
  }
40
42
  `;
41
43
 
42
- export const FrontpageArticle = ({ article, id, isWide }: Props) => {
44
+ export const FrontpageArticle = ({ article, id, isWide, licenseBox }: Props) => {
43
45
  const { title, introduction, content } = article;
44
46
 
45
47
  if (isWide) {
@@ -50,6 +52,10 @@ export const FrontpageArticle = ({ article, id, isWide }: Props) => {
50
52
  );
51
53
  }
52
54
 
55
+ const authors =
56
+ article.copyright.creators.length || article.copyright.rightsholders.length
57
+ ? article.copyright.creators
58
+ : article.copyright.processors;
53
59
  return (
54
60
  <StyledArticle>
55
61
  <LayoutItem>
@@ -59,6 +65,15 @@ export const FrontpageArticle = ({ article, id, isWide }: Props) => {
59
65
  <StyledIntroduction>{introduction}</StyledIntroduction>
60
66
  </LayoutItem>
61
67
  <LayoutItem>{content}</LayoutItem>
68
+ <ArticleByline
69
+ authors={authors}
70
+ suppliers={article.copyright.rightsholders}
71
+ license={article.copyright.license?.license!}
72
+ published={article.published}
73
+ footnotes={article.footNotes}
74
+ accordionHeaderVariant={'white'}
75
+ licenseBox={licenseBox}
76
+ />
62
77
  </StyledArticle>
63
78
  );
64
79
  };
package/src/Hero/Hero.tsx CHANGED
@@ -56,6 +56,10 @@ const StyledDiv = styled.div`
56
56
  background-color: ${colors.brand.primary};
57
57
  }
58
58
 
59
+ &[data-contenttype='frontpage-article'] {
60
+ background-color: ${colors.background.lightBlue};
61
+ }
62
+
59
63
  &[data-contenttype='ndla-film has-image'],
60
64
  &[data-contenttype='ndla-film'] {
61
65
  background: ${colors.ndlaFilm.filmColor};
@@ -112,7 +116,6 @@ interface HeroProps extends HTMLAttributes<HTMLDivElement> {
112
116
  export const Hero = ({ children, contentType }: HeroProps) => (
113
117
  <StyledDiv data-contenttype={contentType}>{children || null}</StyledDiv>
114
118
  );
115
-
116
119
  interface Props {
117
120
  children?: ReactNode;
118
121
  hasImage?: boolean;
@@ -6,7 +6,7 @@
6
6
  *
7
7
  */
8
8
 
9
- import React, { ReactNode } from 'react';
9
+ import React, { HTMLAttributes, ReactNode } from 'react';
10
10
  import BEMHelper from 'react-bem-helper';
11
11
 
12
12
  const classes = BEMHelper({
@@ -15,7 +15,7 @@ const classes = BEMHelper({
15
15
  outputIsString: true,
16
16
  });
17
17
 
18
- interface Props {
18
+ interface Props extends HTMLAttributes<HTMLDivElement> {
19
19
  children?: ReactNode;
20
20
  className?: string;
21
21
  cssModifier?: string;
@@ -24,7 +24,7 @@ interface Props {
24
24
  extraPadding?: boolean;
25
25
  }
26
26
 
27
- export const OneColumn = ({ children, className, cssModifier, wide, noPadding, extraPadding }: Props) => {
27
+ export const OneColumn = ({ children, className, cssModifier, wide, noPadding, extraPadding, ...rest }: Props) => {
28
28
  const modifiers = [];
29
29
 
30
30
  if (cssModifier) {
@@ -43,7 +43,11 @@ export const OneColumn = ({ children, className, cssModifier, wide, noPadding, e
43
43
  modifiers.push('extra-padding');
44
44
  }
45
45
 
46
- return <div className={`${classes('', modifiers)} ${className}`}>{children}</div>;
46
+ return (
47
+ <div className={`${classes('', modifiers)} ${className}`} {...rest}>
48
+ {children}
49
+ </div>
50
+ );
47
51
  };
48
52
 
49
53
  export default OneColumn;
@@ -13,9 +13,10 @@ import { ButtonV2 } from '@ndla/button';
13
13
  import { Spinner } from '@ndla/icons';
14
14
 
15
15
  import SearchFieldHeader from './SearchFieldHeader';
16
- import { CompetenceGoalsItemType } from '../types';
16
+ import { CompetenceGoalsItemType, CoreElementsItemType } from '../types';
17
17
  import CompetenceGoalItem from '../CompetenceGoalTab/CompetenceGoalItem';
18
18
  import SubjectFilters, { SubjectFilterProps } from './components/SubjectFilters';
19
+ import CoreElementItem from '../CompetenceGoalTab/CoreElementItem';
19
20
 
20
21
  const Wrapper = styled.div`
21
22
  margin-top: ${spacing.normal};
@@ -36,13 +37,13 @@ const PhraseWrapper = styled.div`
36
37
  margin: ${spacing.normal} 0 ${spacing.medium};
37
38
  `;
38
39
 
39
- const CompetenceGoalsWrapper = styled.div`
40
+ const GrepCodesWrapper = styled.div`
40
41
  font-size: 16px;
41
42
  width: 100%;
42
43
  margin-top: ${spacing.normal};
43
44
  `;
44
45
 
45
- const CompetenceGoalsList = styled.ul`
46
+ const GrepCodesList = styled.ul`
46
47
  padding: 0;
47
48
  margin: 0;
48
49
  li {
@@ -56,7 +57,7 @@ const PhraseText = styled.div`
56
57
  `;
57
58
  const PhraseSuggestionText = styled.div``;
58
59
 
59
- const GoalsLabel = styled.div`
60
+ const GrepCodesLabel = styled.div`
60
61
  ${fonts.sizes('16px', '32px')};
61
62
  text-transform: uppercase;
62
63
  `;
@@ -69,6 +70,7 @@ type Props = {
69
70
  filters: SubjectFilterProps['filters'];
70
71
  activeFilters?: SubjectFilterProps['activeFilters'];
71
72
  competenceGoals?: CompetenceGoalsItemType[];
73
+ coreElements?: CoreElementsItemType[];
72
74
  onSearchValueChange: (value: string) => void;
73
75
  onSubmit: (event: FormEvent<HTMLFormElement>) => void;
74
76
  noResults?: boolean;
@@ -85,6 +87,7 @@ const SearchHeader = ({
85
87
  activeFilters,
86
88
  filters,
87
89
  competenceGoals,
90
+ coreElements,
88
91
  noResults,
89
92
  loading,
90
93
  }: Props) => {
@@ -143,18 +146,30 @@ const SearchHeader = ({
143
146
  </PhraseSuggestionText>
144
147
  )}
145
148
  {!!competenceGoals?.length && (
146
- <CompetenceGoalsWrapper>
149
+ <GrepCodesWrapper>
147
150
  {competenceGoals?.length && (
148
151
  <>
149
- <GoalsLabel>{t('competenceGoals.competenceGoalItem.title')}</GoalsLabel>
150
- <CompetenceGoalsList>
152
+ <GrepCodesLabel>{t('competenceGoals.competenceGoalItem.title')}</GrepCodesLabel>
153
+ <GrepCodesList>
151
154
  {competenceGoals.map((e) => (
152
155
  <CompetenceGoalItem key={e.id} id={e.id} title={e.title} goals={e.goals} />
153
156
  ))}
154
- </CompetenceGoalsList>
157
+ </GrepCodesList>
155
158
  </>
156
159
  )}
157
- </CompetenceGoalsWrapper>
160
+ </GrepCodesWrapper>
161
+ )}
162
+ {!!coreElements?.length && (
163
+ <GrepCodesWrapper>
164
+ <>
165
+ <GrepCodesLabel>{t('competenceGoals.competenceTabCorelabel')}</GrepCodesLabel>
166
+ <GrepCodesList>
167
+ {coreElements.map((e) => (
168
+ <CoreElementItem key={e.id} id={e.id} title={e.title} text={e.text} url={e.url} />
169
+ ))}
170
+ </GrepCodesList>
171
+ </>
172
+ </GrepCodesWrapper>
158
173
  )}
159
174
  </PhraseWrapper>
160
175
  {isNarrowScreen && (
@@ -490,7 +490,8 @@ const messages = {
490
490
  useCompentenceGoalsFilter: 'Use filter',
491
491
  closeCompentenceGoalsFilter: 'Close filter',
492
492
  competenceGoalsNarrowBackButton: 'Go back',
493
- competenceGoalResourceSearchText: 'View resources to competence goal {{goal}}',
493
+ competenceGoalResourceSearchText: 'View resources to competence goal {{code}}',
494
+ coreResourceSearchText: 'View resources to core element {{code}}',
494
495
  competenceGoalShowExtra: 'Show',
495
496
  competenceGoalCloseExtra: 'Hide',
496
497
  competenceCoreLabel: 'Core element',