@ndla/ui 22.2.0 → 24.0.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.
- package/es/Animation/DisplayOnPageYOffset.js +1 -1
- package/es/Article/Article.js +3 -3
- package/es/Article/ArticleAuthorContent.js +2 -4
- package/es/Article/ArticleByline.js +5 -6
- package/es/AuthorInfo/AuthorInfo.js +29 -16
- package/es/Breadcrumb/ActionBreadcrumb.js +3 -3
- package/es/ContentCard/ContentCard.js +66 -25
- package/es/Figure/FigureOpenDialogButton.js +1 -2
- package/es/FileList/File.js +34 -8
- package/es/FileList/FileList.js +29 -3
- package/es/Filter/FilterListPhone.js +1 -1
- package/es/Frontpage/FrontpageProgramMenu.js +10 -11
- package/es/InfoBox/InfoBox.js +10 -3
- package/es/InfoWidget/InfoWidget.js +67 -22
- package/es/NDLAFilm/AllMoviesAlphabetically.js +12 -12
- package/es/Portrait/Portrait.js +19 -13
- package/es/ResourceBox/ResourceBox.js +7 -35
- package/es/ResourceGroup/ResourceItem.js +13 -13
- package/es/ResourceGroup/ResourceList.js +3 -3
- package/es/Search/ActiveFilterContent.js +4 -14
- package/es/Search/ActiveFilters.js +20 -31
- package/es/Search/SearchField.js +31 -52
- package/es/Search/SearchResult.js +113 -136
- package/es/Search/ToggleSearchButton.js +34 -43
- package/es/Search/index.js +2 -8
- package/es/SearchTypeResult/ActiveFilters.js +18 -18
- package/es/SearchTypeResult/SearchFieldHeader.js +5 -6
- package/es/TopicMenu/TopicMenu.js +1 -1
- package/es/all.css +1 -1
- package/es/index-javascript.js +0 -1
- package/es/index.js +2 -1
- package/es/locale/messages-en.js +2 -0
- package/es/locale/messages-nb.js +2 -0
- package/es/locale/messages-nn.js +2 -0
- package/es/locale/messages-se.js +2 -0
- package/es/locale/messages-sma.js +2 -0
- package/lib/Animation/DisplayOnPageYOffset.js +2 -2
- package/lib/Article/Article.js +4 -4
- package/lib/Article/ArticleAuthorContent.js +9 -4
- package/lib/Article/ArticleByline.js +4 -4
- package/lib/AuthorInfo/AuthorInfo.d.ts +1 -11
- package/lib/AuthorInfo/AuthorInfo.js +36 -20
- package/lib/Breadcrumb/ActionBreadcrumb.js +3 -3
- package/lib/ContentCard/ContentCard.d.ts +1 -15
- package/lib/ContentCard/ContentCard.js +60 -28
- package/lib/FileList/File.js +36 -12
- package/lib/FileList/FileList.js +28 -5
- package/lib/Filter/FilterListPhone.js +2 -2
- package/lib/Frontpage/FrontpageProgramMenu.js +9 -9
- package/lib/InfoBox/InfoBox.js +11 -4
- package/lib/InfoWidget/InfoWidget.js +61 -25
- package/lib/NDLAFilm/AllMoviesAlphabetically.js +13 -13
- package/lib/Portrait/Portrait.js +19 -14
- package/lib/ResourceBox/ResourceBox.d.ts +1 -4
- package/lib/ResourceBox/ResourceBox.js +15 -35
- package/lib/ResourceGroup/ResourceItem.js +12 -14
- package/lib/ResourceGroup/ResourceList.js +2 -4
- package/lib/Search/ActiveFilterContent.d.ts +13 -0
- package/lib/Search/ActiveFilterContent.js +4 -15
- package/lib/Search/ActiveFilters.d.ts +13 -0
- package/lib/Search/ActiveFilters.js +31 -45
- package/lib/Search/SearchField.d.ts +19 -0
- package/lib/Search/SearchField.js +32 -56
- package/lib/Search/SearchResult.d.ts +36 -0
- package/lib/Search/SearchResult.js +116 -159
- package/lib/Search/ToggleSearchButton.d.ts +16 -0
- package/lib/Search/ToggleSearchButton.js +36 -46
- package/lib/Search/index.d.ts +12 -0
- package/lib/Search/index.js +0 -54
- package/lib/SearchTypeResult/ActiveFilters.js +37 -39
- package/lib/SearchTypeResult/SearchFieldHeader.js +6 -6
- package/lib/SearchTypeResult/SearchTypeHeader.d.ts +1 -1
- package/lib/TopicMenu/TopicMenu.js +2 -2
- package/lib/all.css +1 -1
- package/lib/index-javascript.js +0 -74
- package/lib/index.d.ts +1 -0
- package/lib/index.js +38 -1
- package/lib/locale/messages-en.d.ts +2 -0
- package/lib/locale/messages-en.js +2 -0
- package/lib/locale/messages-nb.d.ts +2 -0
- package/lib/locale/messages-nb.js +2 -0
- package/lib/locale/messages-nn.d.ts +2 -0
- package/lib/locale/messages-nn.js +2 -0
- package/lib/locale/messages-se.d.ts +2 -0
- package/lib/locale/messages-se.js +2 -0
- package/lib/locale/messages-sma.d.ts +2 -0
- package/lib/locale/messages-sma.js +2 -0
- package/package.json +17 -16
- package/src/Animation/DisplayOnPageYOffset.tsx +1 -1
- package/src/Article/Article.tsx +1 -1
- package/src/Article/ArticleAuthorContent.tsx +1 -1
- package/src/Article/ArticleByline.tsx +1 -2
- package/src/AuthorInfo/AuthorInfo.tsx +53 -19
- package/src/Breadcrumb/ActionBreadcrumb.tsx +1 -2
- package/src/ContentCard/ContentCard.tsx +127 -35
- package/src/Figure/FigureOpenDialogButton.tsx +1 -2
- package/src/FileList/File.tsx +47 -17
- package/src/FileList/FileList.tsx +37 -8
- package/src/Filter/FilterListPhone.jsx +1 -1
- package/src/Frontpage/FrontpageProgramMenu.tsx +1 -2
- package/src/InfoBox/InfoBox.tsx +24 -4
- package/src/InfoWidget/InfoWidget.tsx +83 -34
- package/src/NDLAFilm/AllMoviesAlphabetically.tsx +1 -1
- package/src/Portrait/Portrait.tsx +25 -10
- package/src/ResourceBox/ResourceBox.tsx +1 -20
- package/src/ResourceGroup/ResourceItem.tsx +1 -1
- package/src/ResourceGroup/ResourceList.tsx +1 -1
- package/src/Search/{ActiveFilterContent.jsx → ActiveFilterContent.tsx} +11 -12
- package/src/Search/{ActiveFilters.jsx → ActiveFilters.tsx} +21 -18
- package/src/Search/{SearchField.jsx → SearchField.tsx} +58 -68
- package/src/Search/SearchResult.tsx +360 -0
- package/src/Search/ToggleSearchButton.tsx +73 -0
- package/src/Search/component.search.scss +0 -4
- package/src/Search/index.ts +16 -0
- package/src/SearchTypeResult/ActiveFilters.tsx +1 -1
- package/src/SearchTypeResult/SearchFieldHeader.tsx +1 -2
- package/src/TopicMenu/TopicMenu.jsx +1 -1
- package/src/all.scss +0 -1
- package/src/index-javascript.js +0 -15
- package/src/index.ts +2 -0
- package/src/locale/messages-en.ts +2 -0
- package/src/locale/messages-nb.ts +2 -0
- package/src/locale/messages-nn.ts +2 -0
- package/src/locale/messages-se.ts +2 -0
- package/src/locale/messages-sma.ts +2 -0
- package/src/main.scss +0 -7
- package/es/BackgroundImage/BackgroundImage.js +0 -27
- package/es/BackgroundImage/index.js +0 -2
- package/es/Search/SearchFilter.js +0 -72
- package/es/Search/SearchFilterList.js +0 -115
- package/es/Search/SearchOverlay.js +0 -39
- package/es/Search/SearchPage.js +0 -178
- package/es/Search/SearchPopoverFilter.js +0 -152
- package/es/Search/SearchResultAuthor.js +0 -51
- package/lib/BackgroundImage/BackgroundImage.d.ts +0 -12
- package/lib/BackgroundImage/BackgroundImage.js +0 -40
- package/lib/BackgroundImage/index.d.ts +0 -2
- package/lib/BackgroundImage/index.js +0 -13
- package/lib/Search/SearchFilter.js +0 -88
- package/lib/Search/SearchFilterList.js +0 -137
- package/lib/Search/SearchOverlay.js +0 -62
- package/lib/Search/SearchPage.js +0 -207
- package/lib/Search/SearchPopoverFilter.js +0 -172
- package/lib/Search/SearchResultAuthor.js +0 -60
- package/src/AuthorInfo/component.author-info.scss +0 -54
- package/src/BackgroundImage/BackgroundImage.tsx +0 -32
- package/src/BackgroundImage/component.background-image.scss +0 -52
- package/src/BackgroundImage/index.ts +0 -3
- package/src/ContentCard/component.content-card.scss +0 -109
- package/src/FileList/component.file-list.scss +0 -102
- package/src/InfoBox/component.info-box.scss +0 -21
- package/src/InfoWidget/component.info-widget.scss +0 -52
- package/src/Portrait/component.portrait.scss +0 -29
- package/src/Search/SearchFilter.jsx +0 -82
- package/src/Search/SearchFilterList.jsx +0 -110
- package/src/Search/SearchOverlay.jsx +0 -38
- package/src/Search/SearchPage.jsx +0 -178
- package/src/Search/SearchPopoverFilter.jsx +0 -109
- package/src/Search/SearchResult.jsx +0 -239
- package/src/Search/SearchResultAuthor.jsx +0 -54
- package/src/Search/ToggleSearchButton.jsx +0 -64
- package/src/Search/component.search-filter.scss +0 -67
- package/src/Search/component.search-overlay.scss +0 -103
- package/src/Search/component.search-page.scss +0 -125
- package/src/Search/component.search-result-author.scss +0 -65
- package/src/Search/index.js +0 -34
package/src/FileList/File.tsx
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
1
3
|
import { Download } from '@ndla/icons/common';
|
|
2
4
|
import SafeLink from '@ndla/safelink';
|
|
3
5
|
import Tooltip from '@ndla/tooltip';
|
|
4
6
|
import React from 'react';
|
|
5
|
-
import BEMHelper from 'react-bem-helper';
|
|
6
7
|
import { FileFormat, FileType } from './FileList';
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const LinkText = styled.span`
|
|
10
|
+
& > span {
|
|
11
|
+
box-shadow: inset 0 -1px;
|
|
12
|
+
}
|
|
13
|
+
`;
|
|
14
|
+
const FileLink = styled(SafeLink)`
|
|
15
|
+
box-shadow: none;
|
|
16
|
+
position: relative;
|
|
17
|
+
color: ${colors.brand.primary};
|
|
18
|
+
margin-right: ${spacing.normal};
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
|
|
22
|
+
&:last-child {
|
|
23
|
+
margin-right: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
&:hover,
|
|
27
|
+
&:focus,
|
|
28
|
+
&:active {
|
|
29
|
+
${LinkText} {
|
|
30
|
+
box-shadow: none;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
9
34
|
|
|
10
35
|
const renderFormat = (format: FileFormat, title: string, isPrimary: boolean, id: string, isDeadLink: boolean) => {
|
|
11
36
|
const titleWithFormat = `${title} (${format.fileType.toUpperCase()})`;
|
|
@@ -22,20 +47,14 @@ const renderFormat = (format: FileFormat, title: string, isPrimary: boolean, id:
|
|
|
22
47
|
}
|
|
23
48
|
|
|
24
49
|
return (
|
|
25
|
-
<
|
|
26
|
-
{...classes('link')}
|
|
27
|
-
key={format.url}
|
|
28
|
-
to={format.url}
|
|
29
|
-
target="_blank"
|
|
30
|
-
aria-label={titleWithFormat}
|
|
31
|
-
aria-describedby={formatId}>
|
|
50
|
+
<FileLink key={format.url} to={format.url} target="_blank" aria-label={titleWithFormat} aria-describedby={formatId}>
|
|
32
51
|
<Download />
|
|
33
52
|
<Tooltip tooltip={format.tooltip}>
|
|
34
|
-
<
|
|
53
|
+
<LinkText>
|
|
35
54
|
<span>{isPrimary ? titleWithFormat : `(${format.fileType.toUpperCase()})`}</span>
|
|
36
|
-
</
|
|
55
|
+
</LinkText>
|
|
37
56
|
</Tooltip>
|
|
38
|
-
</
|
|
57
|
+
</FileLink>
|
|
39
58
|
);
|
|
40
59
|
};
|
|
41
60
|
|
|
@@ -44,16 +63,27 @@ interface Props {
|
|
|
44
63
|
file: FileType;
|
|
45
64
|
}
|
|
46
65
|
|
|
66
|
+
const FileListItem = styled.li`
|
|
67
|
+
${fonts.sizes('18px', '26px')};
|
|
68
|
+
font-weight: ${fonts.weight.semibold};
|
|
69
|
+
min-height: 60px;
|
|
70
|
+
background: ${colors.brand.greyLighter};
|
|
71
|
+
display: flex;
|
|
72
|
+
align-items: center;
|
|
73
|
+
flex-wrap: wrap;
|
|
74
|
+
margin-bottom: ${spacing.xsmall};
|
|
75
|
+
padding: ${spacing.small};
|
|
76
|
+
${mq.range({ from: breakpoints.tablet })} {
|
|
77
|
+
padding: ${spacing.small} ${spacing.normal};
|
|
78
|
+
}
|
|
79
|
+
`;
|
|
80
|
+
|
|
47
81
|
const File = ({ file, id }: Props) => {
|
|
48
82
|
const formatLinks = file.formats.map((format, index) =>
|
|
49
83
|
renderFormat(format, file.title, index === 0, id, !file.fileExists),
|
|
50
84
|
);
|
|
51
85
|
|
|
52
|
-
return
|
|
53
|
-
<li {...classes('item')} key={file.title}>
|
|
54
|
-
{formatLinks}
|
|
55
|
-
</li>
|
|
56
|
-
);
|
|
86
|
+
return <FileListItem key={file.title}>{formatLinks}</FileListItem>;
|
|
57
87
|
};
|
|
58
88
|
|
|
59
89
|
export default File;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import styled from '@emotion/styled';
|
|
3
|
+
import { colors, fonts, spacing } from '@ndla/core';
|
|
3
4
|
import File from './File';
|
|
4
5
|
|
|
5
|
-
const classes = BEMHelper('c-file-list');
|
|
6
|
-
|
|
7
6
|
export interface FileType {
|
|
8
7
|
title: string;
|
|
9
8
|
formats: FileFormat[];
|
|
@@ -22,15 +21,45 @@ interface Props {
|
|
|
22
21
|
files: FileType[];
|
|
23
22
|
}
|
|
24
23
|
|
|
24
|
+
const FileListSection = styled.section`
|
|
25
|
+
margin: ${spacing.large} 0;
|
|
26
|
+
padding: ${spacing.small} 0 ${spacing.normal} ${spacing.normal};
|
|
27
|
+
border-left: 2px solid ${colors.brand.greyLightest};
|
|
28
|
+
font-family: ${fonts.sans};
|
|
29
|
+
|
|
30
|
+
.c-icon {
|
|
31
|
+
margin-top: 3px;
|
|
32
|
+
flex-shrink: 0;
|
|
33
|
+
margin-right: ${spacing.small};
|
|
34
|
+
height: 18px;
|
|
35
|
+
width: 18px;
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
const FileListHeading = styled.h1`
|
|
40
|
+
${fonts.sizes('16px', '18px')};
|
|
41
|
+
letter-spacing: 0.05em;
|
|
42
|
+
margin: 0 0 ${spacing.xsmall} 0;
|
|
43
|
+
padding-bottom: ${spacing.xsmall};
|
|
44
|
+
border-bottom: 2px solid ${colors.brand.greyLight};
|
|
45
|
+
font-weight: ${fonts.weight.bold};
|
|
46
|
+
text-transform: uppercase;
|
|
47
|
+
`;
|
|
48
|
+
|
|
49
|
+
const FilesList = styled.ul`
|
|
50
|
+
margin: 0;
|
|
51
|
+
padding: 0;
|
|
52
|
+
`;
|
|
53
|
+
|
|
25
54
|
const FileList = ({ files, heading, id }: Props) => (
|
|
26
|
-
<
|
|
27
|
-
<
|
|
28
|
-
<
|
|
55
|
+
<FileListSection>
|
|
56
|
+
<FileListHeading>{heading}</FileListHeading>
|
|
57
|
+
<FilesList>
|
|
29
58
|
{files.map((file) => (
|
|
30
59
|
<File key={`file-${id}-${file.title}`} file={file} id={id} />
|
|
31
60
|
))}
|
|
32
|
-
</
|
|
33
|
-
</
|
|
61
|
+
</FilesList>
|
|
62
|
+
</FileListSection>
|
|
34
63
|
);
|
|
35
64
|
|
|
36
65
|
export default FileList;
|
|
@@ -12,7 +12,7 @@ import { ChevronDown, ChevronUp } from '@ndla/icons/common';
|
|
|
12
12
|
import { Cross } from '@ndla/icons/action';
|
|
13
13
|
import Modal, { ModalHeader, ModalBody, ModalCloseButton } from '@ndla/modal';
|
|
14
14
|
import Button from '@ndla/button';
|
|
15
|
-
import debounce from 'lodash
|
|
15
|
+
import { debounce } from 'lodash';
|
|
16
16
|
import { classes } from './filterClasses';
|
|
17
17
|
import ToggleItem from './ToggleItem';
|
|
18
18
|
import ActiveFilters from '../Search/ActiveFilters';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import React, { useEffect, useState } from 'react';
|
|
2
2
|
import styled from '@emotion/styled';
|
|
3
3
|
import Button from '@ndla/button';
|
|
4
|
-
import { fonts } from '@ndla/core';
|
|
5
|
-
import { breakpoints, mq } from '@ndla/core';
|
|
4
|
+
import { fonts, breakpoints, mq } from '@ndla/core';
|
|
6
5
|
import { useTranslation } from 'react-i18next';
|
|
7
6
|
import NavigationBox, { ItemProps } from '../Navigation/NavigationBox';
|
|
8
7
|
import FrontpageAllSubjects, { subjectsProps } from './FrontpageAllSubjects';
|
package/src/InfoBox/InfoBox.tsx
CHANGED
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core/src';
|
|
1
3
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import BEMHelper from 'react-bem-helper';
|
|
3
|
-
|
|
4
|
-
const classes = BEMHelper('c-info-box');
|
|
5
4
|
|
|
6
5
|
interface Props {
|
|
7
6
|
children?: ReactNode;
|
|
8
7
|
}
|
|
9
|
-
|
|
8
|
+
|
|
9
|
+
const StyledInfoBox = styled.div`
|
|
10
|
+
background: ${colors.support.yellowLight};
|
|
11
|
+
padding: ${spacing.small} ${spacing.normal};
|
|
12
|
+
font-family: ${fonts.sans};
|
|
13
|
+
${fonts.sizes('14px', '18px')};
|
|
14
|
+
margin-bottom: ${spacing.medium};
|
|
15
|
+
${mq.range({ from: breakpoints.tablet })} {
|
|
16
|
+
${fonts.sizes('16px', '20px')};
|
|
17
|
+
padding: ${spacing.normal};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
& > *:first-child {
|
|
21
|
+
margin-top: 0;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
& > *:last-child {
|
|
25
|
+
margin-bottom: 0;
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
|
|
29
|
+
const InfoBox = ({ children }: Props) => <StyledInfoBox>{children}</StyledInfoBox>;
|
|
10
30
|
|
|
11
31
|
export default InfoBox;
|
|
@@ -1,13 +1,67 @@
|
|
|
1
|
+
import styled from '@emotion/styled';
|
|
2
|
+
import { css } from '@emotion/core';
|
|
1
3
|
import React, { ReactNode } from 'react';
|
|
2
|
-
import BEMHelper from 'react-bem-helper';
|
|
3
4
|
import { Forward } from '@ndla/icons/common';
|
|
4
|
-
|
|
5
5
|
import SafeLink from '@ndla/safelink';
|
|
6
|
+
import { colors, fonts, spacing } from '@ndla/core';
|
|
6
7
|
|
|
7
8
|
import SectionHeading from '../SectionHeading';
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
interface InfoWidgetSectionProps {
|
|
11
|
+
center?: boolean;
|
|
12
|
+
}
|
|
13
|
+
const InfoWidgetSection = styled.section<InfoWidgetSectionProps>`
|
|
14
|
+
max-width: 600px;
|
|
15
|
+
margin: ${(p) => p.center && '0 auto'};
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
const InfoWidgetDescription = styled.div`
|
|
19
|
+
padding: ${spacing.normal};
|
|
20
|
+
background: ${colors.brand.lighter};
|
|
21
|
+
color: ${colors.brand.dark};
|
|
22
|
+
${fonts.sizes('18px', '26px')};
|
|
23
|
+
|
|
24
|
+
p {
|
|
25
|
+
margin-top: 0;
|
|
26
|
+
&:last-child {
|
|
27
|
+
margin-bottom: 0;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
`;
|
|
31
|
+
|
|
32
|
+
const InfoWidgetLinksContainer = styled.div`
|
|
33
|
+
display: flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
justify-content: flex-end;
|
|
36
|
+
`;
|
|
37
|
+
|
|
38
|
+
const iconLinkStyle = css`
|
|
39
|
+
width: 47px;
|
|
40
|
+
height: 47px;
|
|
41
|
+
border-radius: 100%;
|
|
42
|
+
background: ${colors.brand.lighter};
|
|
43
|
+
color: ${colors.brand.dark};
|
|
44
|
+
box-shadow: none;
|
|
45
|
+
display: flex;
|
|
46
|
+
justify-content: center;
|
|
47
|
+
align-items: center;
|
|
48
|
+
margin-right: ${spacing.small};
|
|
10
49
|
|
|
50
|
+
.c-icon {
|
|
51
|
+
width: 20px;
|
|
52
|
+
height: 20px;
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const IconSafeLink = styled(SafeLink)(iconLinkStyle);
|
|
57
|
+
|
|
58
|
+
const IconAnchor = styled.a(iconLinkStyle);
|
|
59
|
+
const IconSpan = styled.span(iconLinkStyle);
|
|
60
|
+
|
|
61
|
+
const StyledMainLink = styled.a`
|
|
62
|
+
color: ${colors.brand.dark};
|
|
63
|
+
${fonts.sizes('16px', '24px')};
|
|
64
|
+
`;
|
|
11
65
|
interface Props {
|
|
12
66
|
heading: string;
|
|
13
67
|
description: string;
|
|
@@ -26,36 +80,33 @@ interface Props {
|
|
|
26
80
|
}
|
|
27
81
|
|
|
28
82
|
const InfoWidget = ({ heading, description, mainLink, iconLinks, center = false }: Props) => (
|
|
29
|
-
<
|
|
30
|
-
<SectionHeading large
|
|
31
|
-
|
|
32
|
-
</SectionHeading>
|
|
33
|
-
<div {...classes('description')}>
|
|
83
|
+
<InfoWidgetSection center={center}>
|
|
84
|
+
<SectionHeading large>{heading}</SectionHeading>
|
|
85
|
+
<InfoWidgetDescription>
|
|
34
86
|
<p>{description}</p>
|
|
35
|
-
</
|
|
36
|
-
<
|
|
37
|
-
{iconLinks
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (link.href) {
|
|
47
|
-
return (
|
|
48
|
-
<a key={link.href} href={link.href} {...classes('icon-link')} aria-label={link.name}>
|
|
49
|
-
{link.icon}
|
|
50
|
-
</a>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
87
|
+
</InfoWidgetDescription>
|
|
88
|
+
<InfoWidgetLinksContainer>
|
|
89
|
+
{iconLinks?.map((link) => {
|
|
90
|
+
if (link.url) {
|
|
91
|
+
return (
|
|
92
|
+
<IconSafeLink key={link.url} to={link.url} aria-label={link.name}>
|
|
93
|
+
{link.icon}
|
|
94
|
+
</IconSafeLink>
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
if (link.href) {
|
|
53
98
|
return (
|
|
54
|
-
<
|
|
99
|
+
<IconAnchor key={link.href} href={link.href} aria-label={link.name}>
|
|
55
100
|
{link.icon}
|
|
56
|
-
</
|
|
101
|
+
</IconAnchor>
|
|
57
102
|
);
|
|
58
|
-
}
|
|
103
|
+
}
|
|
104
|
+
return (
|
|
105
|
+
<IconSpan key={link.name} aria-label={link.name}>
|
|
106
|
+
{link.icon}
|
|
107
|
+
</IconSpan>
|
|
108
|
+
);
|
|
109
|
+
})}
|
|
59
110
|
{mainLink.url ? (
|
|
60
111
|
<div className="o-text-link__wrapper o-text-link__wrapper--right">
|
|
61
112
|
<SafeLink className="o-text-link" to={mainLink.url}>
|
|
@@ -63,12 +114,10 @@ const InfoWidget = ({ heading, description, mainLink, iconLinks, center = false
|
|
|
63
114
|
</SafeLink>
|
|
64
115
|
</div>
|
|
65
116
|
) : (
|
|
66
|
-
<
|
|
67
|
-
{mainLink.name}
|
|
68
|
-
</a>
|
|
117
|
+
<StyledMainLink href={mainLink.href}>{mainLink.name}</StyledMainLink>
|
|
69
118
|
)}
|
|
70
|
-
</
|
|
71
|
-
</
|
|
119
|
+
</InfoWidgetLinksContainer>
|
|
120
|
+
</InfoWidgetSection>
|
|
72
121
|
);
|
|
73
122
|
|
|
74
123
|
export default InfoWidget;
|
|
@@ -10,7 +10,7 @@ import React, { Fragment, RefObject, useEffect, useRef, useState } from 'react';
|
|
|
10
10
|
import { isIE, browserVersion } from 'react-device-detect';
|
|
11
11
|
import styled from '@emotion/styled';
|
|
12
12
|
import { css } from '@emotion/core';
|
|
13
|
-
import throttle from 'lodash
|
|
13
|
+
import { throttle } from 'lodash';
|
|
14
14
|
import { breakpoints, mq, spacing, spacingUnit, colors, fonts, animations } from '@ndla/core';
|
|
15
15
|
import SafeLink from '@ndla/safelink';
|
|
16
16
|
import { makeSrcQueryString } from '../Image';
|
|
@@ -6,13 +6,25 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import styled from '@emotion/styled';
|
|
9
10
|
import React from 'react';
|
|
10
|
-
import BEMHelper from 'react-bem-helper';
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
interface PortraitWrapperProps {
|
|
13
|
+
size: string;
|
|
14
|
+
}
|
|
15
|
+
const PortraitWrapper = styled.div<PortraitWrapperProps>`
|
|
16
|
+
width: ${(p) => p.size};
|
|
17
|
+
height: ${(p) => p.size};
|
|
18
|
+
span {
|
|
19
|
+
display: block;
|
|
20
|
+
border-radius: 50%;
|
|
21
|
+
background-color: rgba(0, 0, 0, 0.16);
|
|
22
|
+
background-size: cover;
|
|
23
|
+
background-position: center center;
|
|
24
|
+
width: ${(p) => p.size};
|
|
25
|
+
height: ${(p) => p.size};
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
16
28
|
|
|
17
29
|
interface Props {
|
|
18
30
|
src: string;
|
|
@@ -21,10 +33,13 @@ interface Props {
|
|
|
21
33
|
modifier?: 'small' | 'large';
|
|
22
34
|
}
|
|
23
35
|
|
|
24
|
-
const Portrait = ({ src, alt, modifier, className }: Props) =>
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
36
|
+
const Portrait = ({ src, alt, modifier, className }: Props) => {
|
|
37
|
+
const size = modifier === 'small' ? '4rem' : modifier === 'large' ? '10rem' : '7rem';
|
|
38
|
+
return (
|
|
39
|
+
<PortraitWrapper size={size} className={className}>
|
|
40
|
+
<span role="img" aria-label={alt} style={{ backgroundImage: `url(${src})` }} />
|
|
41
|
+
</PortraitWrapper>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
29
44
|
|
|
30
45
|
export default Portrait;
|
|
@@ -10,7 +10,6 @@ import React from 'react';
|
|
|
10
10
|
import { breakpoints, fonts, mq, colors, spacing } from '@ndla/core';
|
|
11
11
|
import { useTranslation } from 'react-i18next';
|
|
12
12
|
import { Launch } from '@ndla/icons/common';
|
|
13
|
-
import { LicenseByline } from '@ndla/licenses';
|
|
14
13
|
import { SafeLinkButton } from '@ndla/safelink';
|
|
15
14
|
import styled from '@emotion/styled';
|
|
16
15
|
import Image from '../Image';
|
|
@@ -81,12 +80,6 @@ const StyledImage = styled(Image)`
|
|
|
81
80
|
}
|
|
82
81
|
`;
|
|
83
82
|
|
|
84
|
-
const LincenseWrapper = styled.div`
|
|
85
|
-
position: absolute;
|
|
86
|
-
top: 9px;
|
|
87
|
-
right: 0;
|
|
88
|
-
`;
|
|
89
|
-
|
|
90
83
|
interface ImageMeta {
|
|
91
84
|
src: string;
|
|
92
85
|
alt: string;
|
|
@@ -96,25 +89,13 @@ interface Props {
|
|
|
96
89
|
image: ImageMeta;
|
|
97
90
|
title: string;
|
|
98
91
|
caption: string;
|
|
99
|
-
licenseRights: string[];
|
|
100
|
-
authors?: string[];
|
|
101
|
-
locale?: string;
|
|
102
92
|
url: string;
|
|
103
93
|
}
|
|
104
94
|
|
|
105
|
-
export const ResourceBox = ({ image, title, caption,
|
|
95
|
+
export const ResourceBox = ({ image, title, caption, url }: Props) => {
|
|
106
96
|
const { t } = useTranslation();
|
|
107
97
|
return (
|
|
108
98
|
<ResourceBoxContainer>
|
|
109
|
-
<LincenseWrapper>
|
|
110
|
-
<LicenseByline licenseRights={licenseRights} locale={locale} marginRight color={colors.brand.tertiary}>
|
|
111
|
-
{authors && authors.length > 0 && (
|
|
112
|
-
<div className="c-figure__byline-author-buttons">
|
|
113
|
-
<span className="c-figure__byline-authors">{authors.join(' ')}</span>
|
|
114
|
-
</div>
|
|
115
|
-
)}
|
|
116
|
-
</LicenseByline>
|
|
117
|
-
</LincenseWrapper>
|
|
118
99
|
<StyledImage src={image.src} alt={image.alt} />
|
|
119
100
|
<ContentWrapper>
|
|
120
101
|
<Title>{title}</Title>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
import { useTranslation } from 'react-i18next';
|
|
11
11
|
import styled from '@emotion/styled';
|
|
12
|
-
import css from '@emotion/
|
|
12
|
+
import { css } from '@emotion/core';
|
|
13
13
|
import { keyframes } from '@emotion/core';
|
|
14
14
|
import SafeLink from '@ndla/safelink';
|
|
15
15
|
import { Additional, Core, HumanMaleBoard } from '@ndla/icons/common';
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
import styled from '@emotion/styled';
|
|
11
|
-
import css from '@emotion/
|
|
11
|
+
import { css } from '@emotion/core';
|
|
12
12
|
import { keyframes } from '@emotion/core';
|
|
13
13
|
import { useTranslation } from 'react-i18next';
|
|
14
14
|
import NoContentBox from '../NoContentBox';
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
2
|
import styled from '@emotion/styled';
|
|
4
3
|
import { Cross } from '@ndla/icons/action';
|
|
5
4
|
import { spacing, mq, breakpoints, colors, misc, fonts } from '@ndla/core';
|
|
@@ -32,7 +31,17 @@ export const StyledActiveFilterTitle = styled('span')`
|
|
|
32
31
|
padding-right: ${spacing.small};
|
|
33
32
|
`;
|
|
34
33
|
|
|
35
|
-
|
|
34
|
+
interface Props {
|
|
35
|
+
filter: {
|
|
36
|
+
value: string;
|
|
37
|
+
title: string;
|
|
38
|
+
filterName?: string;
|
|
39
|
+
};
|
|
40
|
+
onFilterRemove: (value: string, filterName?: string) => void;
|
|
41
|
+
ariaLabel: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }: Props) => (
|
|
36
45
|
<StyledActiveFilter
|
|
37
46
|
aria-label={ariaLabel}
|
|
38
47
|
type="button"
|
|
@@ -42,14 +51,4 @@ const ActiveFilterContent = ({ filter, onFilterRemove, ariaLabel }) => (
|
|
|
42
51
|
</StyledActiveFilter>
|
|
43
52
|
);
|
|
44
53
|
|
|
45
|
-
ActiveFilterContent.propTypes = {
|
|
46
|
-
filter: PropTypes.shape({
|
|
47
|
-
value: PropTypes.string.isRequired,
|
|
48
|
-
title: PropTypes.string.isRequired,
|
|
49
|
-
filterName: PropTypes.string,
|
|
50
|
-
}),
|
|
51
|
-
onFilterRemove: PropTypes.func.isRequired,
|
|
52
|
-
ariaLabel: PropTypes.string.isRequired,
|
|
53
|
-
};
|
|
54
|
-
|
|
55
54
|
export default ActiveFilterContent;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
2
|
import styled from '@emotion/styled';
|
|
4
|
-
import css from '@emotion/
|
|
3
|
+
import { css } from '@emotion/core';
|
|
5
4
|
import { spacing, mq, breakpoints } from '@ndla/core';
|
|
6
5
|
import Tooltip from '@ndla/tooltip';
|
|
7
6
|
import { useTranslation } from 'react-i18next';
|
|
8
7
|
import ActiveFilterContent, { StyledActiveFilterTitle } from './ActiveFilterContent';
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
interface StyledActiveFiltersProps {
|
|
10
|
+
showOnSmallScreen?: boolean;
|
|
11
|
+
filterLength?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const StyledActiveFilters = styled('ul')<StyledActiveFiltersProps>`
|
|
11
15
|
margin: 0;
|
|
12
16
|
padding: 0;
|
|
13
17
|
flex-direction: column;
|
|
@@ -70,10 +74,22 @@ const StyledActiveFilterWrapper = styled('li')`
|
|
|
70
74
|
}
|
|
71
75
|
`;
|
|
72
76
|
|
|
73
|
-
const getFilterLength = (filters) =>
|
|
77
|
+
const getFilterLength = (filters: Filter[]) =>
|
|
74
78
|
filters.filter((filter) => filter.filterName === 'filter_subjects' && filter.title).length;
|
|
75
79
|
|
|
76
|
-
|
|
80
|
+
interface Filter {
|
|
81
|
+
title: string;
|
|
82
|
+
value: string;
|
|
83
|
+
filterName?: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
interface Props {
|
|
87
|
+
filters: Filter[];
|
|
88
|
+
onFilterRemove: (value: string, filterName?: string) => void;
|
|
89
|
+
showOnSmallScreen?: boolean;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }: Props) => {
|
|
77
93
|
const { t } = useTranslation();
|
|
78
94
|
if (filters && filters.length > 0) {
|
|
79
95
|
const filterLength = getFilterLength(filters);
|
|
@@ -90,7 +106,6 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
|
|
|
90
106
|
})}>
|
|
91
107
|
<ActiveFilterContent
|
|
92
108
|
filter={filter}
|
|
93
|
-
filterLength={filterLength}
|
|
94
109
|
ariaLabel={t('searchPage.searchFilterMessages.removeFilter', {
|
|
95
110
|
filterName: filter.title,
|
|
96
111
|
})}
|
|
@@ -100,7 +115,6 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
|
|
|
100
115
|
) : (
|
|
101
116
|
<ActiveFilterContent
|
|
102
117
|
filter={filter}
|
|
103
|
-
filterLength={filterLength}
|
|
104
118
|
onFilterRemove={onFilterRemove}
|
|
105
119
|
ariaLabel={t('searchPage.searchFilterMessages.removeFilter', {
|
|
106
120
|
filterName: filter.title,
|
|
@@ -121,15 +135,4 @@ const ActiveFilters = ({ filters, onFilterRemove, showOnSmallScreen }) => {
|
|
|
121
135
|
return null;
|
|
122
136
|
};
|
|
123
137
|
|
|
124
|
-
ActiveFilters.propTypes = {
|
|
125
|
-
filters: PropTypes.arrayOf(
|
|
126
|
-
PropTypes.shape({
|
|
127
|
-
value: PropTypes.string.isRequired,
|
|
128
|
-
title: PropTypes.string.isRequired,
|
|
129
|
-
filterName: PropTypes.string,
|
|
130
|
-
}),
|
|
131
|
-
),
|
|
132
|
-
onFilterRemove: PropTypes.func.isRequired,
|
|
133
|
-
};
|
|
134
|
-
|
|
135
138
|
export default ActiveFilters;
|