@ndla/ui 42.1.2 → 43.0.1
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/Article/ArticleNotions.js +46 -53
- package/es/AudioPlayer/Controls.js +41 -39
- package/es/Breadcrumb/index.js +0 -1
- package/es/Filter/FilterButtons.js +49 -53
- package/es/Filter/FilterListPhone.js +78 -71
- package/es/LanguageSelector/LanguageSelector.js +31 -36
- package/es/LearningPaths/LearningPathMenuModalWrapper.js +39 -28
- package/es/Masthead/MastheadSearchModal.js +31 -35
- package/es/MyNdla/Resource/Folder.js +10 -16
- package/es/MyNdla/index.js +1 -3
- package/es/NDLAFilm/AboutNdlaFilm.js +16 -20
- package/es/NDLAFilm/FilmMovieSearch.js +43 -11
- package/es/Resource/BlockResource.js +8 -11
- package/es/Resource/ListResource.js +8 -11
- package/es/Resource/resourceComponents.js +46 -35
- package/es/ResourcesWrapper/ResourcesTopicTitle.js +36 -44
- package/es/Search/ToggleSearchButton.js +7 -6
- package/es/SearchTypeResult/PopupFilter.js +55 -69
- package/es/SearchTypeResult/SearchNotionsResult.js +9 -7
- package/es/SearchTypeResult/components/ItemContexts.js +41 -45
- package/es/SearchTypeResult/components/SubjectFilters.js +16 -17
- package/es/Topic/Topic.js +41 -45
- package/es/TreeStructure/FolderItem.js +7 -11
- package/es/index.js +2 -2
- package/es/locale/messages-en.js +1 -0
- package/es/locale/messages-nb.js +1 -0
- package/es/locale/messages-nn.js +1 -0
- package/es/locale/messages-se.js +1 -0
- package/es/locale/messages-sma.js +1 -0
- package/lib/Article/ArticleNotions.js +45 -52
- package/lib/AudioPlayer/Controls.js +40 -38
- package/lib/Breadcrumb/index.d.ts +0 -1
- package/lib/Breadcrumb/index.js +0 -7
- package/lib/Filter/FilterButtons.js +48 -52
- package/lib/Filter/FilterListPhone.js +76 -69
- package/lib/LanguageSelector/LanguageSelector.js +31 -36
- package/lib/LearningPaths/LearningPathMenuModalWrapper.js +47 -35
- package/lib/Masthead/MastheadSearchModal.js +29 -32
- package/lib/MyNdla/Resource/Folder.d.ts +3 -4
- package/lib/MyNdla/Resource/Folder.js +10 -16
- package/lib/MyNdla/index.d.ts +1 -3
- package/lib/MyNdla/index.js +0 -14
- package/lib/NDLAFilm/AboutNdlaFilm.js +15 -18
- package/lib/NDLAFilm/FilmMovieSearch.d.ts +1 -2
- package/lib/NDLAFilm/FilmMovieSearch.js +46 -11
- package/lib/Resource/BlockResource.d.ts +3 -3
- package/lib/Resource/BlockResource.js +8 -11
- package/lib/Resource/ListResource.d.ts +3 -3
- package/lib/Resource/ListResource.js +8 -11
- package/lib/Resource/resourceComponents.js +45 -34
- package/lib/ResourcesWrapper/ResourcesTopicTitle.js +35 -42
- package/lib/Search/ToggleSearchButton.d.ts +2 -1
- package/lib/Search/ToggleSearchButton.js +9 -6
- package/lib/SearchTypeResult/PopupFilter.d.ts +1 -3
- package/lib/SearchTypeResult/PopupFilter.js +54 -68
- package/lib/SearchTypeResult/SearchNotionsResult.js +9 -7
- package/lib/SearchTypeResult/components/ItemContexts.js +40 -44
- package/lib/SearchTypeResult/components/SubjectFilters.js +16 -17
- package/lib/Topic/Topic.js +40 -44
- package/lib/TreeStructure/FolderItem.js +7 -11
- package/lib/index.d.ts +2 -2
- package/lib/index.js +0 -12
- package/lib/locale/messages-en.d.ts +1 -0
- package/lib/locale/messages-en.js +1 -0
- package/lib/locale/messages-nb.d.ts +1 -0
- package/lib/locale/messages-nb.js +1 -0
- package/lib/locale/messages-nn.d.ts +1 -0
- package/lib/locale/messages-nn.js +1 -0
- package/lib/locale/messages-se.d.ts +1 -0
- package/lib/locale/messages-se.js +1 -0
- package/lib/locale/messages-sma.d.ts +1 -0
- package/lib/locale/messages-sma.js +1 -0
- package/package.json +11 -12
- package/src/Article/ArticleNotions.tsx +29 -35
- package/src/AudioPlayer/Controls.tsx +22 -26
- package/src/Breadcrumb/index.ts +0 -2
- package/src/Filter/FilterButtons.tsx +28 -34
- package/src/Filter/FilterListPhone.tsx +63 -62
- package/src/LanguageSelector/LanguageSelector.tsx +26 -32
- package/src/LearningPaths/LearningPathMenuModalWrapper.tsx +19 -18
- package/src/Masthead/MastheadSearchModal.tsx +21 -29
- package/src/MyNdla/Resource/Folder.stories.tsx +27 -5
- package/src/MyNdla/Resource/Folder.tsx +4 -19
- package/src/MyNdla/index.ts +1 -3
- package/src/NDLAFilm/AboutNdlaFilm.tsx +11 -10
- package/src/NDLAFilm/FilmMovieSearch.tsx +32 -9
- package/src/Resource/BlockResource.stories.tsx +1 -1
- package/src/Resource/BlockResource.tsx +4 -6
- package/src/Resource/ListResource.tsx +4 -6
- package/src/Resource/Resource.stories.tsx +32 -2
- package/src/Resource/resourceComponents.tsx +34 -24
- package/src/ResourcesWrapper/ResourcesTopicTitle.tsx +23 -27
- package/src/Search/ToggleSearchButton.tsx +15 -12
- package/src/SearchTypeResult/PopupFilter.tsx +55 -70
- package/src/SearchTypeResult/SearchNotionsResult.tsx +5 -2
- package/src/SearchTypeResult/components/ItemContexts.tsx +23 -28
- package/src/SearchTypeResult/components/SubjectFilters.tsx +9 -12
- package/src/Topic/Topic.tsx +15 -17
- package/src/TreeStructure/FolderItem.tsx +2 -4
- package/src/index.ts +2 -2
- package/src/locale/messages-en.ts +1 -0
- package/src/locale/messages-nb.ts +1 -0
- package/src/locale/messages-nn.ts +1 -0
- package/src/locale/messages-se.ts +1 -0
- package/src/locale/messages-sma.ts +1 -0
- package/es/Breadcrumb/ActionBreadcrumb.js +0 -74
- package/es/MyNdla/Resource/FolderMenu.js +0 -74
- package/es/MyNdla/SettingsMenu.js +0 -98
- package/es/NDLAFilm/CategorySelect.js +0 -135
- package/lib/Breadcrumb/ActionBreadcrumb.d.ts +0 -15
- package/lib/Breadcrumb/ActionBreadcrumb.js +0 -82
- package/lib/MyNdla/Resource/FolderMenu.d.ts +0 -16
- package/lib/MyNdla/Resource/FolderMenu.js +0 -81
- package/lib/MyNdla/SettingsMenu.d.ts +0 -15
- package/lib/MyNdla/SettingsMenu.js +0 -102
- package/lib/NDLAFilm/CategorySelect.d.ts +0 -16
- package/lib/NDLAFilm/CategorySelect.js +0 -144
- package/src/Breadcrumb/ActionBreadcrumb.tsx +0 -87
- package/src/MyNdla/Resource/FolderMenu.tsx +0 -102
- package/src/MyNdla/SettingsMenu.tsx +0 -96
- package/src/NDLAFilm/CategorySelect.tsx +0 -197
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import React, { ReactNode, useState } from 'react';
|
|
2
|
-
import { Drawer } from '@ndla/modal';
|
|
1
|
+
import React, { ReactNode, useCallback, useState } from 'react';
|
|
2
|
+
import { Drawer, Modal, ModalTrigger } from '@ndla/modal';
|
|
3
3
|
import { IconButtonV2 as IconButton } from '@ndla/button';
|
|
4
4
|
import { Cross } from '@ndla/icons/action';
|
|
5
5
|
import styled from '@emotion/styled';
|
|
@@ -63,42 +63,34 @@ const StyledHeader = styled.div`
|
|
|
63
63
|
const MastheadSearchModal = ({ onClose: onSearchClose, children, hideOnNarrowScreen, ndlaFilm }: Props) => {
|
|
64
64
|
const { t } = useTranslation();
|
|
65
65
|
const [isOpen, setIsOpen] = useState(false);
|
|
66
|
+
|
|
67
|
+
const closeModal = useCallback(() => {
|
|
68
|
+
onSearchClose();
|
|
69
|
+
setIsOpen(false);
|
|
70
|
+
}, [onSearchClose]);
|
|
71
|
+
|
|
66
72
|
return (
|
|
67
|
-
|
|
68
|
-
<
|
|
69
|
-
{
|
|
70
|
-
|
|
73
|
+
<Modal open={isOpen} onOpenChange={setIsOpen}>
|
|
74
|
+
<ModalTrigger>
|
|
75
|
+
<ToggleSearchButton hideOnNarrowScreen={hideOnNarrowScreen} onClick={() => setIsOpen(true)} ndlaFilm={ndlaFilm}>
|
|
76
|
+
{t('masthead.menu.search')}
|
|
77
|
+
</ToggleSearchButton>
|
|
78
|
+
</ModalTrigger>
|
|
71
79
|
<StyledDrawer
|
|
72
|
-
controlled
|
|
73
80
|
aria-label={t('searchPage.searchFieldPlaceholder')}
|
|
74
81
|
position="top"
|
|
75
82
|
expands
|
|
76
83
|
size="small"
|
|
77
|
-
animation="slideIn"
|
|
78
84
|
animationDuration={200}
|
|
79
|
-
isOpen={isOpen}
|
|
80
|
-
onClose={() => {
|
|
81
|
-
setIsOpen(false);
|
|
82
|
-
onSearchClose();
|
|
83
|
-
}}
|
|
84
85
|
>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
variant="ghost"
|
|
92
|
-
colorTheme="light"
|
|
93
|
-
onClick={closeModal}
|
|
94
|
-
>
|
|
95
|
-
<Cross className="c-icon--medium" />
|
|
96
|
-
</IconButton>
|
|
97
|
-
</StyledHeader>
|
|
98
|
-
</>
|
|
99
|
-
)}
|
|
86
|
+
<StyledHeader>
|
|
87
|
+
{children(closeModal)}
|
|
88
|
+
<IconButton aria-label={t('welcomePage.closeSearch')} variant="ghost" colorTheme="light" onClick={closeModal}>
|
|
89
|
+
<Cross className="c-icon--medium" />
|
|
90
|
+
</IconButton>
|
|
91
|
+
</StyledHeader>
|
|
100
92
|
</StyledDrawer>
|
|
101
|
-
|
|
93
|
+
</Modal>
|
|
102
94
|
);
|
|
103
95
|
};
|
|
104
96
|
|
|
@@ -2,6 +2,9 @@ import React from 'react';
|
|
|
2
2
|
import { Meta, StoryFn } from '@storybook/react';
|
|
3
3
|
import { Pencil } from '@ndla/icons/action';
|
|
4
4
|
import { DeleteForever } from '@ndla/icons/editor';
|
|
5
|
+
import { DropdownMenu, DropdownTrigger, DropdownContent, DropdownItem } from '@ndla/dropdown-menu';
|
|
6
|
+
import { ButtonV2, IconButtonV2 } from '@ndla/button';
|
|
7
|
+
import { HorizontalMenu } from '@ndla/icons/contentType';
|
|
5
8
|
import { defaultParameters } from '../../../../../stories/defaults';
|
|
6
9
|
|
|
7
10
|
import Folder from './Folder';
|
|
@@ -14,7 +17,7 @@ export default {
|
|
|
14
17
|
...defaultParameters,
|
|
15
18
|
},
|
|
16
19
|
argTypes: {
|
|
17
|
-
|
|
20
|
+
menu: {
|
|
18
21
|
control: false,
|
|
19
22
|
},
|
|
20
23
|
},
|
|
@@ -26,10 +29,29 @@ export default {
|
|
|
26
29
|
description: '',
|
|
27
30
|
link: '',
|
|
28
31
|
type: 'list',
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
menu: (
|
|
33
|
+
<DropdownMenu>
|
|
34
|
+
<DropdownTrigger>
|
|
35
|
+
<IconButtonV2 aria-label="Show more" title="Show more" variant="ghost" colorTheme="light">
|
|
36
|
+
<HorizontalMenu />
|
|
37
|
+
</IconButtonV2>
|
|
38
|
+
</DropdownTrigger>
|
|
39
|
+
<DropdownContent>
|
|
40
|
+
<DropdownItem>
|
|
41
|
+
<ButtonV2 variant="ghost" colorTheme="light" shape="sharp" size="small" fontWeight="normal">
|
|
42
|
+
<Pencil />
|
|
43
|
+
Rediger
|
|
44
|
+
</ButtonV2>
|
|
45
|
+
</DropdownItem>
|
|
46
|
+
<DropdownItem>
|
|
47
|
+
<ButtonV2 variant="ghost" colorTheme="danger" shape="sharp" size="small" fontWeight="normal">
|
|
48
|
+
<DeleteForever />
|
|
49
|
+
Slett
|
|
50
|
+
</ButtonV2>
|
|
51
|
+
</DropdownItem>
|
|
52
|
+
</DropdownContent>
|
|
53
|
+
</DropdownMenu>
|
|
54
|
+
),
|
|
33
55
|
isShared: true,
|
|
34
56
|
},
|
|
35
57
|
} as Meta<typeof Folder>;
|
|
@@ -7,14 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import styled from '@emotion/styled';
|
|
10
|
-
import React from 'react';
|
|
10
|
+
import React, { ReactNode } from 'react';
|
|
11
11
|
import { FolderOutlined, FolderShared } from '@ndla/icons/contentType';
|
|
12
12
|
import { FileDocumentOutline, Share } from '@ndla/icons/common';
|
|
13
13
|
import { fonts, spacing, colors, mq, breakpoints } from '@ndla/core';
|
|
14
14
|
import { useTranslation } from 'react-i18next';
|
|
15
|
-
import { MenuItemProps } from '@ndla/button';
|
|
16
15
|
import { ResourceTitleLink } from '../../Resource/resourceComponents';
|
|
17
|
-
import FolderMenu from './FolderMenu';
|
|
18
16
|
|
|
19
17
|
export type LayoutType = 'list' | 'listLarger' | 'block';
|
|
20
18
|
|
|
@@ -151,22 +149,11 @@ interface Props {
|
|
|
151
149
|
description?: string;
|
|
152
150
|
link: string;
|
|
153
151
|
type?: LayoutType;
|
|
154
|
-
|
|
155
|
-
menuItems?: MenuItemProps[];
|
|
152
|
+
menu?: ReactNode;
|
|
156
153
|
isShared?: boolean;
|
|
157
154
|
}
|
|
158
155
|
|
|
159
|
-
const Folder = ({
|
|
160
|
-
id,
|
|
161
|
-
link,
|
|
162
|
-
title,
|
|
163
|
-
subFolders,
|
|
164
|
-
subResources,
|
|
165
|
-
type = 'list',
|
|
166
|
-
menuItems,
|
|
167
|
-
isShared,
|
|
168
|
-
onViewTypeChange,
|
|
169
|
-
}: Props) => {
|
|
156
|
+
const Folder = ({ id, link, title, subFolders, subResources, type = 'list', menu, isShared }: Props) => {
|
|
170
157
|
const { t } = useTranslation();
|
|
171
158
|
const Icon = isShared ? FolderShared : FolderOutlined;
|
|
172
159
|
|
|
@@ -196,9 +183,7 @@ const Folder = ({
|
|
|
196
183
|
<Count layoutType={type} type={'folder'} count={subFolders} />
|
|
197
184
|
<Count layoutType={type} type={'resource'} count={subResources} />
|
|
198
185
|
</CountContainer>
|
|
199
|
-
{
|
|
200
|
-
<FolderMenu menuItems={menuItems} viewType={type} onViewTypeChange={onViewTypeChange} />
|
|
201
|
-
)}
|
|
186
|
+
{menu}
|
|
202
187
|
</MenuWrapper>
|
|
203
188
|
</FolderWrapper>
|
|
204
189
|
);
|
package/src/MyNdla/index.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
1
|
import Folder from './Resource/Folder';
|
|
2
2
|
import FolderInput from './Resource/FolderInput';
|
|
3
|
-
|
|
4
|
-
import SettingsMenu from './SettingsMenu';
|
|
5
|
-
export { Folder, FolderInput, SettingsMenu, FolderMenu };
|
|
3
|
+
export { Folder, FolderInput };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { ReactNode } from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import styled from '@emotion/styled';
|
|
4
|
-
import { ModalHeader, ModalBody, ModalCloseButton, Modal } from '@ndla/modal';
|
|
4
|
+
import { ModalHeader, ModalBody, ModalCloseButton, Modal, ModalTrigger, ModalContent } from '@ndla/modal';
|
|
5
5
|
import { colors, spacing, mq, breakpoints } from '@ndla/core';
|
|
6
6
|
import { ButtonV2 as Button } from '@ndla/button';
|
|
7
7
|
import VisualElement from './VisualElement';
|
|
@@ -64,15 +64,16 @@ const AboutNdlaFilm = ({ aboutNDLAVideo, moreAboutNdlaFilm }: Props) => {
|
|
|
64
64
|
<div>
|
|
65
65
|
<h2 id={titleId}>{aboutNDLAVideo.title}</h2>
|
|
66
66
|
<p>{aboutNDLAVideo.description}</p>
|
|
67
|
-
<Modal
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
<
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
<Modal>
|
|
68
|
+
<ModalTrigger>
|
|
69
|
+
<Button variant="link">{t('ndlaFilm.about.more')}</Button>
|
|
70
|
+
</ModalTrigger>
|
|
71
|
+
<ModalContent size="full">
|
|
72
|
+
<ModalHeader>
|
|
73
|
+
<ModalCloseButton />
|
|
74
|
+
</ModalHeader>
|
|
75
|
+
<ModalBody>{moreAboutNdlaFilm}</ModalBody>
|
|
76
|
+
</ModalContent>
|
|
76
77
|
</Modal>
|
|
77
78
|
</div>
|
|
78
79
|
</StyledAside>
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React from 'react';
|
|
9
|
+
import React, { useCallback, useMemo } from 'react';
|
|
10
10
|
import SafeLink from '@ndla/safelink';
|
|
11
11
|
import { useTranslation } from 'react-i18next';
|
|
12
12
|
import styled from '@emotion/styled';
|
|
13
13
|
import { spacing, mq, breakpoints, colors } from '@ndla/core';
|
|
14
|
-
import
|
|
14
|
+
import { Option, Select, SingleValue } from '@ndla/select';
|
|
15
15
|
import { MovieResourceType } from './types';
|
|
16
16
|
import { OneColumn } from '..';
|
|
17
17
|
import { StyledHeadingH2 } from './filmStyles';
|
|
@@ -59,7 +59,6 @@ interface Props {
|
|
|
59
59
|
onChangeResourceType: (resourceType?: string) => void;
|
|
60
60
|
resourceTypeSelected?: MovieResourceType;
|
|
61
61
|
resourceTypes: MovieResourceType[];
|
|
62
|
-
ariaControlId: string;
|
|
63
62
|
skipToContentId?: string;
|
|
64
63
|
}
|
|
65
64
|
|
|
@@ -68,10 +67,32 @@ const FilmMovieSearch = ({
|
|
|
68
67
|
onChangeResourceType,
|
|
69
68
|
resourceTypes,
|
|
70
69
|
resourceTypeSelected,
|
|
71
|
-
ariaControlId,
|
|
72
70
|
skipToContentId,
|
|
73
71
|
}: Props) => {
|
|
74
72
|
const { t } = useTranslation();
|
|
73
|
+
const selectedOption = useMemo(() => {
|
|
74
|
+
if (resourceTypeSelected) {
|
|
75
|
+
return { value: resourceTypeSelected.id, label: resourceTypeSelected.name };
|
|
76
|
+
}
|
|
77
|
+
return { value: 'fromNdla', label: t('ndlaFilm.search.categoryFromNdla') };
|
|
78
|
+
}, [resourceTypeSelected, t]);
|
|
79
|
+
|
|
80
|
+
const options: Option[] = useMemo(() => {
|
|
81
|
+
const fromNdla = { value: 'fromNdla', label: t('ndlaFilm.search.categoryFromNdla') };
|
|
82
|
+
return [fromNdla].concat(resourceTypes.map((rt) => ({ value: rt.id, label: rt.name })));
|
|
83
|
+
}, [resourceTypes, t]);
|
|
84
|
+
|
|
85
|
+
const onChange = useCallback(
|
|
86
|
+
(value: SingleValue) => {
|
|
87
|
+
if (value?.value === 'fromNdla') {
|
|
88
|
+
onChangeResourceType();
|
|
89
|
+
} else {
|
|
90
|
+
onChangeResourceType(value?.value);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
[onChangeResourceType],
|
|
94
|
+
);
|
|
95
|
+
|
|
75
96
|
return (
|
|
76
97
|
<FilmMovieSearchContainer>
|
|
77
98
|
<OneColumn>
|
|
@@ -91,11 +112,13 @@ const FilmMovieSearch = ({
|
|
|
91
112
|
</StyledUl>
|
|
92
113
|
</nav>
|
|
93
114
|
</TopicNavigation>
|
|
94
|
-
<
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
115
|
+
<Select<false>
|
|
116
|
+
options={options}
|
|
117
|
+
value={selectedOption}
|
|
118
|
+
onChange={onChange}
|
|
119
|
+
colorTheme="white"
|
|
120
|
+
placeholder={t('ndlaFilm.search.chooseCategory')}
|
|
121
|
+
prefix={`${t('ndlaFilm.search.chooseCategory')} `}
|
|
99
122
|
/>
|
|
100
123
|
</OneColumn>
|
|
101
124
|
</FilmMovieSearchContainer>
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import styled from '@emotion/styled';
|
|
10
|
-
import React from 'react';
|
|
10
|
+
import React, { ReactNode } from 'react';
|
|
11
11
|
import { colors, fonts, spacing } from '@ndla/core';
|
|
12
|
-
import { MenuItemProps } from '@ndla/button';
|
|
13
12
|
import ContentTypeBadge from '../ContentTypeBadge';
|
|
14
13
|
import Image from '../Image';
|
|
15
14
|
import {
|
|
@@ -23,7 +22,6 @@ import {
|
|
|
23
22
|
} from './resourceComponents';
|
|
24
23
|
import ContentLoader from '../ContentLoader';
|
|
25
24
|
import { contentTypeMapping, resourceEmbedTypeMapping } from '../model/ContentType';
|
|
26
|
-
import { SettingsMenu } from '../MyNdla';
|
|
27
25
|
|
|
28
26
|
const BlockElementWrapper = styled.div`
|
|
29
27
|
display: flex;
|
|
@@ -149,7 +147,7 @@ interface Props {
|
|
|
149
147
|
tags?: string[];
|
|
150
148
|
description?: string;
|
|
151
149
|
headingLevel?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
152
|
-
|
|
150
|
+
menu?: ReactNode;
|
|
153
151
|
isLoading?: boolean;
|
|
154
152
|
targetBlank?: boolean;
|
|
155
153
|
resourceTypes?: { id: string; name: string }[];
|
|
@@ -163,7 +161,7 @@ const BlockResource = ({
|
|
|
163
161
|
tags,
|
|
164
162
|
resourceImage,
|
|
165
163
|
description,
|
|
166
|
-
|
|
164
|
+
menu,
|
|
167
165
|
isLoading,
|
|
168
166
|
headingLevel: Heading = 'h2',
|
|
169
167
|
targetBlank,
|
|
@@ -196,7 +194,7 @@ const BlockResource = ({
|
|
|
196
194
|
</ContentWrapper>
|
|
197
195
|
<TagsAndActionMenu>
|
|
198
196
|
{tags && tags.length > 0 && <CompressedTagList tagLinkPrefix={tagLinkPrefix} tags={tags} />}
|
|
199
|
-
{
|
|
197
|
+
{menu}
|
|
200
198
|
</TagsAndActionMenu>
|
|
201
199
|
</BlockInfoWrapper>
|
|
202
200
|
</BlockElementWrapper>
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import styled from '@emotion/styled';
|
|
10
|
-
import React from 'react';
|
|
10
|
+
import React, { ReactNode } from 'react';
|
|
11
11
|
import { fonts, spacing, colors, breakpoints, mq } from '@ndla/core';
|
|
12
|
-
import { MenuItemProps } from '@ndla/button';
|
|
13
12
|
import Image from '../Image';
|
|
14
13
|
import {
|
|
15
14
|
CompressedTagList,
|
|
@@ -23,7 +22,6 @@ import {
|
|
|
23
22
|
import ContentLoader from '../ContentLoader';
|
|
24
23
|
import ContentTypeBadge from '../ContentTypeBadge';
|
|
25
24
|
import { contentTypeMapping, resourceEmbedTypeMapping } from '../model/ContentType';
|
|
26
|
-
import { SettingsMenu } from '../MyNdla';
|
|
27
25
|
|
|
28
26
|
const ListResourceWrapper = styled.div`
|
|
29
27
|
flex: 1;
|
|
@@ -204,7 +202,7 @@ export interface ListResourceProps {
|
|
|
204
202
|
resourceTypes: { id: string; name: string }[];
|
|
205
203
|
tags?: string[];
|
|
206
204
|
description?: string;
|
|
207
|
-
|
|
205
|
+
menu?: ReactNode;
|
|
208
206
|
isLoading?: boolean;
|
|
209
207
|
targetBlank?: boolean;
|
|
210
208
|
}
|
|
@@ -218,7 +216,7 @@ const ListResource = ({
|
|
|
218
216
|
resourceImage,
|
|
219
217
|
resourceTypes,
|
|
220
218
|
description,
|
|
221
|
-
|
|
219
|
+
menu,
|
|
222
220
|
isLoading = false,
|
|
223
221
|
targetBlank,
|
|
224
222
|
}: ListResourceProps) => {
|
|
@@ -251,7 +249,7 @@ const ListResource = ({
|
|
|
251
249
|
{showDescription && <Description description={description} loading={isLoading} />}
|
|
252
250
|
<TagsandActionMenu>
|
|
253
251
|
{tags && tags.length > 0 && <CompressedTagList tagLinkPrefix={tagLinkPrefix} tags={tags} />}
|
|
254
|
-
{
|
|
252
|
+
{menu}
|
|
255
253
|
</TagsandActionMenu>
|
|
256
254
|
</ListResourceWrapper>
|
|
257
255
|
);
|
|
@@ -8,8 +8,37 @@
|
|
|
8
8
|
|
|
9
9
|
import React from 'react';
|
|
10
10
|
import { Meta, StoryFn } from '@storybook/react';
|
|
11
|
-
import {
|
|
11
|
+
import { DropdownMenu, DropdownContent, DropdownItem, DropdownTrigger } from '@ndla/dropdown-menu';
|
|
12
|
+
import { ButtonV2, IconButtonV2 } from '@ndla/button';
|
|
13
|
+
import { HorizontalMenu } from '@ndla/icons/contentType';
|
|
14
|
+
import { Pencil } from '@ndla/icons/action';
|
|
15
|
+
import { DeleteForever } from '@ndla/icons/editor';
|
|
12
16
|
import ListResource from './ListResource';
|
|
17
|
+
import { defaultParameters } from '../../../../stories/defaults';
|
|
18
|
+
|
|
19
|
+
const StoryResourceMenu = () => (
|
|
20
|
+
<DropdownMenu>
|
|
21
|
+
<DropdownTrigger>
|
|
22
|
+
<IconButtonV2 aria-label="Show more" title="Show more" variant="ghost" colorTheme="light">
|
|
23
|
+
<HorizontalMenu />
|
|
24
|
+
</IconButtonV2>
|
|
25
|
+
</DropdownTrigger>
|
|
26
|
+
<DropdownContent>
|
|
27
|
+
<DropdownItem>
|
|
28
|
+
<ButtonV2 variant="ghost" colorTheme="light" shape="sharp" size="small" fontWeight="normal">
|
|
29
|
+
<Pencil />
|
|
30
|
+
Rediger
|
|
31
|
+
</ButtonV2>
|
|
32
|
+
</DropdownItem>
|
|
33
|
+
<DropdownItem>
|
|
34
|
+
<ButtonV2 variant="ghost" colorTheme="danger" shape="sharp" size="small" fontWeight="normal">
|
|
35
|
+
<DeleteForever />
|
|
36
|
+
Slett
|
|
37
|
+
</ButtonV2>
|
|
38
|
+
</DropdownItem>
|
|
39
|
+
</DropdownContent>
|
|
40
|
+
</DropdownMenu>
|
|
41
|
+
);
|
|
13
42
|
|
|
14
43
|
export default {
|
|
15
44
|
title: 'Components/Resources/ListResource',
|
|
@@ -28,7 +57,7 @@ export default {
|
|
|
28
57
|
headingLevel: {
|
|
29
58
|
control: false,
|
|
30
59
|
},
|
|
31
|
-
|
|
60
|
+
menu: {
|
|
32
61
|
control: false,
|
|
33
62
|
},
|
|
34
63
|
},
|
|
@@ -41,6 +70,7 @@ export default {
|
|
|
41
70
|
alt: '',
|
|
42
71
|
},
|
|
43
72
|
resourceTypes: [{ id: 'urn:resourcetype:learningPath', name: 'Læringssti' }],
|
|
73
|
+
menu: <StoryResourceMenu />,
|
|
44
74
|
tags: ['tag', 'tag', 'tag', 'tag'],
|
|
45
75
|
},
|
|
46
76
|
} as Meta<typeof ListResource>;
|
|
@@ -10,11 +10,11 @@ import styled from '@emotion/styled';
|
|
|
10
10
|
import { colors, fonts, spacing } from '@ndla/core';
|
|
11
11
|
import React, { CSSProperties, HTMLAttributes, ReactNode, useMemo } from 'react';
|
|
12
12
|
import { useTranslation } from 'react-i18next';
|
|
13
|
-
import {
|
|
14
|
-
import SafeLink from '@ndla/safelink';
|
|
15
|
-
import { useNavigate } from 'react-router-dom';
|
|
13
|
+
import { IconButtonV2 } from '@ndla/button';
|
|
14
|
+
import SafeLink, { SafeLinkButton } from '@ndla/safelink';
|
|
16
15
|
import { HashTag } from '@ndla/icons/common';
|
|
17
16
|
import { css } from '@emotion/react';
|
|
17
|
+
import { DropdownMenu, DropdownContent, DropdownTrigger, DropdownItem } from '@ndla/dropdown-menu';
|
|
18
18
|
import resourceTypeColor from '../utils/resourceTypeColor';
|
|
19
19
|
import { resourceEmbedTypeMapping } from '../model/ContentType';
|
|
20
20
|
|
|
@@ -38,6 +38,10 @@ export const ResourceTitleLink = styled(SafeLink)`
|
|
|
38
38
|
}
|
|
39
39
|
`;
|
|
40
40
|
|
|
41
|
+
const StyledTrigger = styled(IconButtonV2)`
|
|
42
|
+
margin: 0px ${spacing.xsmall};
|
|
43
|
+
`;
|
|
44
|
+
|
|
41
45
|
export const resourceHeadingStyle = css`
|
|
42
46
|
margin: 0;
|
|
43
47
|
overflow: hidden;
|
|
@@ -173,34 +177,40 @@ interface CompressedTagListProps {
|
|
|
173
177
|
}
|
|
174
178
|
|
|
175
179
|
export const CompressedTagList = ({ tags, tagLinkPrefix }: CompressedTagListProps) => {
|
|
176
|
-
const navigate = useNavigate();
|
|
177
180
|
const { t } = useTranslation();
|
|
178
181
|
const visibleTags = useMemo(() => tags.slice(0, 3), [tags]);
|
|
179
|
-
const remainingTags = useMemo(
|
|
180
|
-
() =>
|
|
181
|
-
tags.slice(3, tags.length).map((tag) => {
|
|
182
|
-
return {
|
|
183
|
-
icon: <HashTag />,
|
|
184
|
-
text: tag,
|
|
185
|
-
onClick: () => {
|
|
186
|
-
navigate(`${tagLinkPrefix ? tagLinkPrefix : ''}/${encodeURIComponent(tag)}`);
|
|
187
|
-
},
|
|
188
|
-
};
|
|
189
|
-
}),
|
|
190
|
-
[navigate, tagLinkPrefix, tags],
|
|
191
|
-
);
|
|
182
|
+
const remainingTags = useMemo(() => tags.slice(3, tags.length), [tags]);
|
|
192
183
|
|
|
193
184
|
return (
|
|
194
185
|
<>
|
|
195
186
|
<TagList tagLinkPrefix={tagLinkPrefix} tags={visibleTags} />
|
|
196
187
|
{remainingTags.length > 0 && (
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
188
|
+
<DropdownMenu>
|
|
189
|
+
<DropdownTrigger>
|
|
190
|
+
<StyledTrigger
|
|
191
|
+
size="xsmall"
|
|
192
|
+
variant="ghost"
|
|
193
|
+
colorTheme="light"
|
|
194
|
+
aria-label={t('myNdla.moreTags', { count: remainingTags.length })}
|
|
195
|
+
>
|
|
196
|
+
{<TagCounterWrapper>{`+${remainingTags.length}`}</TagCounterWrapper>}
|
|
197
|
+
</StyledTrigger>
|
|
198
|
+
</DropdownTrigger>
|
|
199
|
+
<DropdownContent showArrow>
|
|
200
|
+
{remainingTags.map((tag, i) => (
|
|
201
|
+
<DropdownItem key={`tag-${i}`}>
|
|
202
|
+
<SafeLinkButton
|
|
203
|
+
to={`${tagLinkPrefix ?? ''}/${encodeURIComponent(tag)}`}
|
|
204
|
+
variant="ghost"
|
|
205
|
+
colorTheme="light"
|
|
206
|
+
>
|
|
207
|
+
<HashTag />
|
|
208
|
+
{tag}
|
|
209
|
+
</SafeLinkButton>
|
|
210
|
+
</DropdownItem>
|
|
211
|
+
))}
|
|
212
|
+
</DropdownContent>
|
|
213
|
+
</DropdownMenu>
|
|
204
214
|
)}
|
|
205
215
|
</>
|
|
206
216
|
);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import { useTranslation } from 'react-i18next';
|
|
3
3
|
import { css } from '@emotion/react';
|
|
4
4
|
import styled from '@emotion/styled';
|
|
5
5
|
import { breakpoints, colors, fonts, mq, spacing } from '@ndla/core';
|
|
6
|
-
import { ModalBody, ModalHeader, ModalCloseButton, Modal, ModalTitle } from '@ndla/modal';
|
|
6
|
+
import { ModalBody, ModalHeader, ModalCloseButton, Modal, ModalTitle, ModalTrigger, ModalContent } from '@ndla/modal';
|
|
7
7
|
import Tooltip from '@ndla/tooltip';
|
|
8
8
|
import { Switch } from '@ndla/switch';
|
|
9
9
|
import { LearningPathQuiz } from '@ndla/icons/contentType';
|
|
@@ -185,31 +185,27 @@ const ResourcesTopicTitle = ({
|
|
|
185
185
|
onChange={toggleAdditionalResources}
|
|
186
186
|
css={invertedStyle ? invertedSwitchCSS : switchCSS}
|
|
187
187
|
/>
|
|
188
|
-
<Modal
|
|
189
|
-
|
|
190
|
-
<
|
|
191
|
-
<
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
</
|
|
206
|
-
<
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
<p>{t('resource.dialogText2')}</p>
|
|
210
|
-
</ModalBody>
|
|
211
|
-
</>
|
|
212
|
-
)}
|
|
188
|
+
<Modal>
|
|
189
|
+
<TooltipWrapper>
|
|
190
|
+
<Tooltip tooltip={t('resource.dialogTooltip')}>
|
|
191
|
+
<ModalTrigger>
|
|
192
|
+
<TooltipButton aria-label={t('resource.dialogTooltip')}>
|
|
193
|
+
<HelpIcon invertedStyle={invertedStyle} />
|
|
194
|
+
</TooltipButton>
|
|
195
|
+
</ModalTrigger>
|
|
196
|
+
</Tooltip>
|
|
197
|
+
</TooltipWrapper>
|
|
198
|
+
<ModalContent>
|
|
199
|
+
<ModalHeader>
|
|
200
|
+
<ModalTitle>{t('resource.dialogHeading')}</ModalTitle>
|
|
201
|
+
<ModalCloseButton />
|
|
202
|
+
</ModalHeader>
|
|
203
|
+
<ModalBody>
|
|
204
|
+
<hr />
|
|
205
|
+
<p>{t('resource.dialogText1')}</p>
|
|
206
|
+
<p>{t('resource.dialogText2')}</p>
|
|
207
|
+
</ModalBody>
|
|
208
|
+
</ModalContent>
|
|
213
209
|
</Modal>
|
|
214
210
|
</StyledRow>
|
|
215
211
|
)}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import React from 'react';
|
|
9
|
+
import React, { forwardRef } from 'react';
|
|
10
10
|
import { spacing, spacingUnit, breakpoints, mq, misc, fonts, colors } from '@ndla/core';
|
|
11
11
|
import { Search } from '@ndla/icons/common';
|
|
12
12
|
import { ButtonProps, ButtonV2 } from '@ndla/button';
|
|
@@ -62,17 +62,20 @@ const StyledSpan = styled.span`
|
|
|
62
62
|
font-weight: ${fonts.weight.normal};
|
|
63
63
|
`;
|
|
64
64
|
|
|
65
|
-
const ToggleSearchButton =
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
65
|
+
const ToggleSearchButton = forwardRef<HTMLButtonElement, Props>(
|
|
66
|
+
({ children, ndlaFilm, hideOnNarrowScreen, hideOnWideScreen, ...rest }, ref) => (
|
|
67
|
+
<StyledButton
|
|
68
|
+
ndlaFilm={ndlaFilm}
|
|
69
|
+
hideOnNarrowScreen={hideOnNarrowScreen}
|
|
70
|
+
hideOnWideScreen={hideOnWideScreen}
|
|
71
|
+
type="button"
|
|
72
|
+
ref={ref}
|
|
73
|
+
{...rest}
|
|
74
|
+
>
|
|
75
|
+
<StyledSpan>{children}</StyledSpan>
|
|
76
|
+
<Search />
|
|
77
|
+
</StyledButton>
|
|
78
|
+
),
|
|
76
79
|
);
|
|
77
80
|
|
|
78
81
|
export default ToggleSearchButton;
|