@ndla/ui 22.0.3 → 22.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 (108) hide show
  1. package/es/Animation/DisplayOnPageYOffset.js +1 -1
  2. package/es/Article/Article.js +3 -3
  3. package/es/Article/ArticleByline.js +5 -6
  4. package/es/Breadcrumb/ActionBreadcrumb.js +3 -3
  5. package/es/CompetenceGoalTab/CompetenceGoalItem.js +12 -10
  6. package/es/CompetenceGoalTab/CompetenceGoalTab.js +11 -9
  7. package/es/CompetenceGoalTab/CompetenceItem.js +14 -12
  8. package/es/CompetenceGoalTab/SearchButton.js +7 -4
  9. package/es/Figure/FigureOpenDialogButton.js +1 -2
  10. package/es/Filter/FilterListPhone.js +1 -1
  11. package/es/Frontpage/FrontpageProgramMenu.js +10 -11
  12. package/es/NDLAFilm/AllMoviesAlphabetically.js +12 -12
  13. package/es/Resource/BlockResource.js +9 -5
  14. package/es/Resource/ListResource.js +8 -6
  15. package/es/Resource/resourceComponents.js +36 -25
  16. package/es/ResourceGroup/ResourceItem.js +13 -13
  17. package/es/ResourceGroup/ResourceList.js +3 -3
  18. package/es/Search/ActiveFilters.js +18 -18
  19. package/es/Search/SearchPage.js +1 -1
  20. package/es/SearchTypeResult/ActiveFilters.js +18 -18
  21. package/es/SearchTypeResult/SearchFieldHeader.js +5 -6
  22. package/es/TopicMenu/TopicMenu.js +1 -1
  23. package/es/TreeStructure/FolderItem.js +34 -29
  24. package/es/TreeStructure/TreeStructure.js +5 -3
  25. package/es/TreeStructure/TreeStructureWrapper.js +2 -2
  26. package/es/locale/messages-en.js +5 -1
  27. package/es/locale/messages-nb.js +5 -1
  28. package/es/locale/messages-nn.js +5 -1
  29. package/es/locale/messages-se.js +5 -1
  30. package/es/locale/messages-sma.js +5 -1
  31. package/lib/Animation/DisplayOnPageYOffset.js +2 -2
  32. package/lib/Article/Article.js +4 -4
  33. package/lib/Article/ArticleByline.js +4 -4
  34. package/lib/Breadcrumb/ActionBreadcrumb.js +3 -3
  35. package/lib/CompetenceGoalTab/CompetenceGoalItem.d.ts +1 -1
  36. package/lib/CompetenceGoalTab/CompetenceGoalItem.js +12 -10
  37. package/lib/CompetenceGoalTab/CompetenceGoalTab.d.ts +2 -1
  38. package/lib/CompetenceGoalTab/CompetenceGoalTab.js +11 -9
  39. package/lib/CompetenceGoalTab/CompetenceItem.d.ts +2 -1
  40. package/lib/CompetenceGoalTab/CompetenceItem.js +14 -12
  41. package/lib/CompetenceGoalTab/SearchButton.d.ts +2 -1
  42. package/lib/CompetenceGoalTab/SearchButton.js +7 -4
  43. package/lib/Filter/FilterListPhone.js +2 -2
  44. package/lib/Frontpage/FrontpageProgramMenu.js +9 -9
  45. package/lib/NDLAFilm/AllMoviesAlphabetically.js +13 -13
  46. package/lib/Resource/BlockResource.d.ts +2 -1
  47. package/lib/Resource/BlockResource.js +9 -5
  48. package/lib/Resource/ListResource.d.ts +2 -1
  49. package/lib/Resource/ListResource.js +8 -6
  50. package/lib/Resource/resourceComponents.d.ts +4 -2
  51. package/lib/Resource/resourceComponents.js +38 -19
  52. package/lib/ResourceGroup/ResourceItem.js +12 -14
  53. package/lib/ResourceGroup/ResourceList.js +2 -4
  54. package/lib/Search/ActiveFilters.js +30 -32
  55. package/lib/Search/SearchPage.js +2 -2
  56. package/lib/SearchTypeResult/ActiveFilters.js +37 -39
  57. package/lib/SearchTypeResult/SearchFieldHeader.js +6 -6
  58. package/lib/TopicMenu/TopicMenu.js +2 -2
  59. package/lib/TreeStructure/FolderItem.d.ts +1 -1
  60. package/lib/TreeStructure/FolderItem.js +34 -29
  61. package/lib/TreeStructure/TreeStructure.d.ts +0 -1
  62. package/lib/TreeStructure/TreeStructure.js +5 -3
  63. package/lib/TreeStructure/TreeStructureWrapper.js +2 -2
  64. package/lib/TreeStructure/types.d.ts +1 -0
  65. package/lib/locale/messages-en.d.ts +4 -0
  66. package/lib/locale/messages-en.js +5 -1
  67. package/lib/locale/messages-nb.d.ts +4 -0
  68. package/lib/locale/messages-nb.js +5 -1
  69. package/lib/locale/messages-nn.d.ts +4 -0
  70. package/lib/locale/messages-nn.js +5 -1
  71. package/lib/locale/messages-se.d.ts +4 -0
  72. package/lib/locale/messages-se.js +5 -1
  73. package/lib/locale/messages-sma.d.ts +4 -0
  74. package/lib/locale/messages-sma.js +5 -1
  75. package/lib/types.d.ts +1 -0
  76. package/package.json +19 -17
  77. package/src/Animation/DisplayOnPageYOffset.tsx +1 -1
  78. package/src/Article/Article.tsx +1 -1
  79. package/src/Article/ArticleByline.tsx +1 -2
  80. package/src/Breadcrumb/ActionBreadcrumb.tsx +1 -2
  81. package/src/CompetenceGoalTab/CompetenceGoalItem.tsx +6 -2
  82. package/src/CompetenceGoalTab/CompetenceGoalTab.tsx +5 -4
  83. package/src/CompetenceGoalTab/CompetenceItem.tsx +9 -2
  84. package/src/CompetenceGoalTab/SearchButton.tsx +3 -2
  85. package/src/Figure/FigureOpenDialogButton.tsx +1 -2
  86. package/src/Filter/FilterListPhone.jsx +1 -1
  87. package/src/Frontpage/FrontpageProgramMenu.tsx +1 -2
  88. package/src/NDLAFilm/AllMoviesAlphabetically.tsx +1 -1
  89. package/src/Resource/BlockResource.tsx +4 -2
  90. package/src/Resource/ListResource.tsx +3 -1
  91. package/src/Resource/resourceComponents.tsx +25 -9
  92. package/src/ResourceGroup/ResourceItem.tsx +1 -1
  93. package/src/ResourceGroup/ResourceList.tsx +1 -1
  94. package/src/Search/ActiveFilters.jsx +1 -1
  95. package/src/Search/SearchPage.jsx +1 -1
  96. package/src/SearchTypeResult/ActiveFilters.tsx +1 -1
  97. package/src/SearchTypeResult/SearchFieldHeader.tsx +1 -2
  98. package/src/TopicMenu/TopicMenu.jsx +1 -1
  99. package/src/TreeStructure/FolderItem.tsx +7 -2
  100. package/src/TreeStructure/TreeStructure.tsx +2 -1
  101. package/src/TreeStructure/TreeStructureWrapper.tsx +9 -12
  102. package/src/TreeStructure/types.ts +1 -0
  103. package/src/locale/messages-en.ts +4 -0
  104. package/src/locale/messages-nb.ts +4 -0
  105. package/src/locale/messages-nn.ts +4 -0
  106. package/src/locale/messages-se.ts +4 -0
  107. package/src/locale/messages-sma.ts +4 -0
  108. package/src/types.ts +1 -0
@@ -387,7 +387,9 @@ var messages = _objectSpread(_objectSpread({
387
387
  competenceTabCorelabel: 'Kjerneelement',
388
388
  competenceGoalItem: {
389
389
  title: 'Kompetansemål og vurdering'
390
- }
390
+ },
391
+ licenseData: 'Inneholder data under',
392
+ licenseFrom: 'tilgjengeliggjort på'
391
393
  },
392
394
  subject: {
393
395
  associatedTopics: 'Tilhørende emner'
@@ -985,6 +987,8 @@ var messages = _objectSpread(_objectSpread({
985
987
  detailView: 'Detaljrik listevisning',
986
988
  shortView: 'Kort visning',
987
989
  myPage: {
990
+ confirmDeleteAccount: 'Er du sikker på at du vil slette kontoen?',
991
+ confirmDeleteAccountButton: 'Slett konto',
988
992
  myPage: 'Min side',
989
993
  deleteAccount: 'Slett Min NDLA',
990
994
  logout: 'Logg ut av Min NDLA',
@@ -86,6 +86,8 @@ declare const messages: {
86
86
  detailView: string;
87
87
  shortView: string;
88
88
  myPage: {
89
+ confirmDeleteAccount: string;
90
+ confirmDeleteAccountButton: string;
89
91
  myPage: string;
90
92
  deleteAccount: string;
91
93
  logout: string;
@@ -552,6 +554,8 @@ declare const messages: {
552
554
  competenceGoalItem: {
553
555
  title: string;
554
556
  };
557
+ licenseData: string;
558
+ licenseFrom: string;
555
559
  };
556
560
  subject: {
557
561
  associatedTopics: string;
@@ -387,7 +387,9 @@ var messages = _objectSpread(_objectSpread({
387
387
  competenceTabCorelabel: 'Kjerneelement',
388
388
  competenceGoalItem: {
389
389
  title: 'Kompetansemål og vurdering'
390
- }
390
+ },
391
+ licenseData: 'Inneholder data under',
392
+ licenseFrom: 'tilgjengeliggjort på'
391
393
  },
392
394
  subject: {
393
395
  associatedTopics: 'Tilhørende emner'
@@ -985,6 +987,8 @@ var messages = _objectSpread(_objectSpread({
985
987
  detailView: 'Detaljrik listevisning',
986
988
  shortView: 'Kort visning',
987
989
  myPage: {
990
+ confirmDeleteAccount: 'Er du sikker på at du vil slette kontoen?',
991
+ confirmDeleteAccountButton: 'Slett konto',
988
992
  myPage: 'Min side',
989
993
  deleteAccount: 'Slett Min NDLA',
990
994
  logout: 'Logg ut av Min NDLA',
package/lib/types.d.ts CHANGED
@@ -96,6 +96,7 @@ export declare type CompetenceGoalsItemType = {
96
96
  type: 'LK06' | 'LK20';
97
97
  }[];
98
98
  selected?: boolean;
99
+ isOembed?: boolean;
99
100
  };
100
101
  export declare type NotionMedia = {
101
102
  type: 'video' | 'other';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "22.0.3",
3
+ "version": "22.3.0",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -31,21 +31,22 @@
31
31
  "types"
32
32
  ],
33
33
  "dependencies": {
34
- "@ndla/button": "^3.2.1",
35
- "@ndla/carousel": "^1.2.15",
36
- "@ndla/core": "^2.3.3",
37
- "@ndla/forms": "^3.1.3",
38
- "@ndla/hooks": "^1.1.4",
39
- "@ndla/icons": "^1.11.3",
40
- "@ndla/licenses": "^5.0.6",
41
- "@ndla/modal": "^1.2.17",
42
- "@ndla/notion": "^3.1.28",
43
- "@ndla/safelink": "^2.2.5",
44
- "@ndla/switch": "^0.1.10",
45
- "@ndla/tabs": "^1.1.14",
46
- "@ndla/tooltip": "^2.1.5",
34
+ "@ndla/article-scripts": "^3.0.1",
35
+ "@ndla/button": "^3.3.1",
36
+ "@ndla/carousel": "^1.2.16",
37
+ "@ndla/core": "^2.3.4",
38
+ "@ndla/forms": "^3.1.4",
39
+ "@ndla/hooks": "^1.1.5",
40
+ "@ndla/icons": "^1.11.4",
41
+ "@ndla/licenses": "^5.0.7",
42
+ "@ndla/modal": "^1.2.18",
43
+ "@ndla/notion": "^3.1.30",
44
+ "@ndla/safelink": "^2.2.7",
45
+ "@ndla/switch": "^0.1.11",
46
+ "@ndla/tabs": "^1.1.15",
47
+ "@ndla/tooltip": "^2.1.6",
47
48
  "@ndla/types-learningpath-api": "^0.0.12",
48
- "@ndla/util": "^3.0.0",
49
+ "@ndla/util": "^3.0.1",
49
50
  "@reach/menu-button": "^0.16.2",
50
51
  "@reach/slider": "^0.16.0",
51
52
  "focus-trap-react": "^8.9.2",
@@ -68,7 +69,8 @@
68
69
  "i18next": "^20.3.1",
69
70
  "prop-types": "^15.8.1",
70
71
  "react": "^16.8.4 || ^17.0.0",
71
- "react-i18next": "^11.11.0"
72
+ "react-i18next": "^11.11.0",
73
+ "react-router-dom": "^6.3.0"
72
74
  },
73
75
  "devDependencies": {
74
76
  "@babel/plugin-proposal-optional-chaining": "^7.11.0",
@@ -83,5 +85,5 @@
83
85
  "publishConfig": {
84
86
  "access": "public"
85
87
  },
86
- "gitHead": "7a872c80b02640a49da4f6343a032c1c242f5aed"
88
+ "gitHead": "1c8439d413eefda014a9438d78a34c1639194321"
87
89
  }
@@ -8,7 +8,7 @@
8
8
 
9
9
  import React, { Component, ReactNode } from 'react';
10
10
  import PropTypes from 'prop-types';
11
- import throttle from 'lodash/throttle';
11
+ import { throttle } from 'lodash';
12
12
  import Fade from './Fade';
13
13
 
14
14
  interface Props {
@@ -8,7 +8,7 @@
8
8
 
9
9
  import React, { ComponentType, ReactNode, useEffect, useRef, useState, forwardRef } from 'react';
10
10
  import BEMHelper from 'react-bem-helper';
11
- import isString from 'lodash/isString';
11
+ import { isString } from 'lodash';
12
12
  import parse from 'html-react-parser';
13
13
  import styled from '@emotion/styled';
14
14
 
@@ -13,8 +13,7 @@ import Button, { CopyButton } from '@ndla/button';
13
13
  import { colors, fonts, spacing } from '@ndla/core';
14
14
  import { copyTextToClipboard, printPage } from '@ndla/util';
15
15
  import { useTranslation } from 'react-i18next';
16
- import { LicenseByline } from '@ndla/licenses';
17
- import { getLicenseByAbbreviation } from '@ndla/licenses';
16
+ import { LicenseByline, getLicenseByAbbreviation } from '@ndla/licenses';
18
17
  import { TFunction } from 'i18next';
19
18
 
20
19
  const Wrapper = styled.div`
@@ -11,8 +11,7 @@ import { colors, fonts, spacing } from '@ndla/core';
11
11
  import { ChevronRight } from '@ndla/icons/common';
12
12
  import SafeLink from '@ndla/safelink';
13
13
  import React from 'react';
14
- import { MenuButton } from '@ndla/button';
15
- import { MenuItemProps } from '@ndla/button';
14
+ import { MenuButton, MenuItemProps } from '@ndla/button';
16
15
  import Breadcrumb from './Breadcrumb';
17
16
  import { IndexedBreadcrumbItem, SimpleBreadcrumbItem } from './BreadcrumbItem';
18
17
 
@@ -60,7 +60,7 @@ const GoalSearchWrapper = styled.div`
60
60
  }
61
61
  `;
62
62
 
63
- const CompetenceGoalItem = ({ title, goals }: CompetenceGoalsItemType) => {
63
+ const CompetenceGoalItem = ({ title, goals, isOembed }: CompetenceGoalsItemType) => {
64
64
  const { t } = useTranslation();
65
65
  return (
66
66
  <GoalItem>
@@ -73,7 +73,11 @@ const CompetenceGoalItem = ({ title, goals }: CompetenceGoalsItemType) => {
73
73
  <GoalListInnerTextWrapper>{goal.text}</GoalListInnerTextWrapper>
74
74
  {goal.url && goal.type !== 'LK06' && (
75
75
  <GoalSearchWrapper>
76
- <SearchButton to={goal.url} text={t('competenceGoals.competenceGoalResourceSearchText')} />
76
+ <SearchButton
77
+ to={goal.url}
78
+ text={t('competenceGoals.competenceGoalResourceSearchText')}
79
+ target={isOembed ? '_blank' : '_self'}
80
+ />
77
81
  </GoalSearchWrapper>
78
82
  )}
79
83
  </GoalListElementInnerWrapper>
@@ -19,6 +19,7 @@ import CompetenceItem, { ListItemProp } from './CompetenceItem';
19
19
  type CompetenceProps = {
20
20
  list: ListItemProp[];
21
21
  highlightSearchBox?: boolean;
22
+ isOembed?: boolean;
22
23
  };
23
24
 
24
25
  const Wrapper = styled.div`
@@ -79,7 +80,7 @@ const HighlightText = styled.span`
79
80
  font-family: 'Shadows Into Light Two', cursive;
80
81
  `;
81
82
 
82
- const CompetenceGoalTab = ({ list, highlightSearchBox }: CompetenceProps) => {
83
+ const CompetenceGoalTab = ({ list, highlightSearchBox, isOembed }: CompetenceProps) => {
83
84
  const [currentTabItem, setCurrentTab] = useState(list[0]);
84
85
  const { t } = useTranslation();
85
86
 
@@ -106,15 +107,15 @@ const CompetenceGoalTab = ({ list, highlightSearchBox }: CompetenceProps) => {
106
107
  <ArrowFeatureTips />
107
108
  </HighlightWrapper>
108
109
  )}
109
- <CompetenceItem item={currentTabItem} />
110
+ <CompetenceItem item={currentTabItem} isOembed={isOembed} />
110
111
  <LicenseByline licenseRights={[CC, BY]}>
111
112
  <LicenseIconsTextWrapper>UDIR</LicenseIconsTextWrapper>
112
113
  </LicenseByline>
113
- Inneholder data under{' '}
114
+ {`${t('competenceGoals.licenseData')} `}
114
115
  <SafeLink to="https://data.norge.no/nlod/no" target="_blank">
115
116
  NLOD
116
117
  </SafeLink>
117
- , tilgjengeliggjort på{' '}
118
+ {`, ${t('competenceGoals.licenseFrom')} `}
118
119
  <SafeLink to="https://data.udir.no/" target="_blank">
119
120
  data.udir.no
120
121
  </SafeLink>
@@ -79,9 +79,10 @@ export type ListItemProp = {
79
79
  };
80
80
  export type ListItemProps = {
81
81
  item: ListItemProp;
82
+ isOembed?: boolean;
82
83
  };
83
84
 
84
- const CompetenceItem = ({ item }: ListItemProps) => {
85
+ const CompetenceItem = ({ item, isOembed }: ListItemProps) => {
85
86
  const { t } = useTranslation();
86
87
  const { type, groupedCompetenceGoals, groupedCoreElementItems } = item;
87
88
  switch (type) {
@@ -105,7 +106,13 @@ const CompetenceItem = ({ item }: ListItemProps) => {
105
106
  {group.elements.length > 0 && (
106
107
  <Goals>
107
108
  {group.elements.map((goal) => (
108
- <CompetenceGoalItem key={goal.id} id={goal.id} title={goal.title} goals={goal.goals} />
109
+ <CompetenceGoalItem
110
+ key={goal.id}
111
+ id={goal.id}
112
+ title={goal.title}
113
+ goals={goal.goals}
114
+ isOembed={isOembed}
115
+ />
109
116
  ))}
110
117
  </Goals>
111
118
  )}
@@ -37,11 +37,12 @@ const IconWrapper = styled.span`
37
37
  type Props = {
38
38
  to: string;
39
39
  text: string;
40
+ target?: string;
40
41
  };
41
42
 
42
- const SearchButton = ({ to, text }: Props) => (
43
+ const SearchButton = ({ to, text, target = '_self' }: Props) => (
43
44
  <Wrapper>
44
- <SafeLink to={to}>
45
+ <SafeLink to={to} target={target}>
45
46
  <IconWrapper>
46
47
  <Search style={{ width: '24px', height: '24px' }} />
47
48
  </IconWrapper>
@@ -8,8 +8,7 @@
8
8
 
9
9
  import React from 'react';
10
10
  import { Play } from '@ndla/icons/common';
11
- import { ExpandTwoArrows } from '@ndla/icons/action';
12
- import { CursorClick } from '@ndla/icons/action';
11
+ import { ExpandTwoArrows, CursorClick } from '@ndla/icons/action';
13
12
 
14
13
  interface Props {
15
14
  type?: 'image' | 'video' | 'h5p' | 'iframe' | 'external';
@@ -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/debounce';
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';
@@ -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/throttle';
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';
@@ -17,6 +17,7 @@ import ContentLoader from '../ContentLoader';
17
17
 
18
18
  interface BlockResourceProps {
19
19
  link: string;
20
+ tagLinkPrefix?: string;
20
21
  title: string;
21
22
  resourceImage: ResourceImageProps;
22
23
  topics: string[];
@@ -47,7 +48,7 @@ const BlockDescription = styled.p`
47
48
  overflow: hidden;
48
49
  text-overflow: ellipsis;
49
50
  transition: height 0.2s ease-out;
50
- ${() => BlockElementWrapper}:hover & {
51
+ ${() => BlockElementWrapper}:hover &, ${() => BlockElementWrapper}:focus & {
51
52
  // Unfortunate css needed for multi-line text overflow ellipsis.
52
53
  height: 3.1em;
53
54
  -webkit-line-clamp: 2;
@@ -132,6 +133,7 @@ const BlockTopicList = ({ topics, loading }: BlockTopicListProps) => {
132
133
 
133
134
  const BlockResource = ({
134
135
  link,
136
+ tagLinkPrefix,
135
137
  title,
136
138
  tags,
137
139
  resourceImage,
@@ -152,7 +154,7 @@ const BlockResource = ({
152
154
  <BlockTopicList topics={topics} loading={isLoading} />
153
155
  <BlockDescription>{description}</BlockDescription>
154
156
  <RightRow>
155
- {tags && <CompressedTagList tags={tags} />}
157
+ {tags && <CompressedTagList tagLinkPrefix={tagLinkPrefix} tags={tags} />}
156
158
  {menuItems && menuItems.length > 0 && <MenuButton alignRight size="small" menuItems={menuItems} />}
157
159
  </RightRow>
158
160
  </BlockInfoWrapper>
@@ -109,6 +109,7 @@ interface StyledImageProps {
109
109
 
110
110
  export interface ListResourceProps {
111
111
  link: string;
112
+ tagLinkPrefix?: string;
112
113
  title: string;
113
114
  resourceImage: ResourceImageProps;
114
115
  topics: string[];
@@ -184,6 +185,7 @@ const ResourceDescription = ({ description, loading }: ResourceDescriptionProps)
184
185
 
185
186
  const ListResource = ({
186
187
  link,
188
+ tagLinkPrefix,
187
189
  title,
188
190
  tags,
189
191
  resourceImage,
@@ -205,7 +207,7 @@ const ListResource = ({
205
207
  </TopicAndTitleWrapper>
206
208
  {showDescription && <ResourceDescription description={description} loading={isLoading} />}
207
209
  <TagsandActionMenu>
208
- {tags && <CompressedTagList tags={tags} />}
210
+ {tags && <CompressedTagList tagLinkPrefix={tagLinkPrefix} tags={tags} />}
209
211
  {menuItems && menuItems.length > 0 && <MenuButton alignRight size="small" menuItems={menuItems} />}
210
212
  </TagsandActionMenu>
211
213
  </ResourceWrapper>
@@ -6,11 +6,13 @@
6
6
  *
7
7
  */
8
8
 
9
- import React from 'react';
10
9
  import styled from '@emotion/styled';
11
- import { fonts, colors, spacing } from '@ndla/core';
10
+ import { colors, fonts, spacing } from '@ndla/core';
11
+ import React, { MouseEvent } from 'react';
12
12
 
13
13
  import { MenuButton } from '@ndla/button';
14
+ import SafeLink from '@ndla/safelink';
15
+ import { useNavigate } from 'react-router-dom';
14
16
 
15
17
  export interface ResourceImageProps {
16
18
  alt: string;
@@ -42,9 +44,13 @@ const StyledTagList = styled.ul`
42
44
  `;
43
45
 
44
46
  const StyledTagListElement = styled.li`
45
- color: ${colors.brand.grey};
46
47
  margin: 0;
47
48
  ${fonts.sizes(14)};
49
+ `;
50
+
51
+ const StyledSafeLink = styled(SafeLink)`
52
+ box-shadow: none;
53
+ color: ${colors.brand.grey};
48
54
  ::before {
49
55
  content: '#';
50
56
  }
@@ -90,14 +96,20 @@ const TagCounterWrapper = styled.p`
90
96
 
91
97
  interface TagListProps {
92
98
  tags?: string[];
99
+ tagLinkPrefix?: string;
93
100
  }
94
-
95
- export const TagList = ({ tags }: TagListProps) => {
101
+ export const TagList = ({ tags, tagLinkPrefix }: TagListProps) => {
96
102
  if (!tags) return null;
97
103
  return (
98
104
  <StyledTagList>
99
105
  {tags.map((tag, i) => (
100
- <StyledTagListElement key={`tag-${i}`}>{tag}</StyledTagListElement>
106
+ <StyledTagListElement key={`tag-${i}`}>
107
+ <StyledSafeLink
108
+ onClick={(e: MouseEvent<HTMLAnchorElement | HTMLElement>) => e.stopPropagation()}
109
+ to={`${tagLinkPrefix ? tagLinkPrefix : ''}/${tag}`}>
110
+ {tag}
111
+ </StyledSafeLink>
112
+ </StyledTagListElement>
101
113
  ))}
102
114
  </StyledTagList>
103
115
  );
@@ -105,20 +117,24 @@ export const TagList = ({ tags }: TagListProps) => {
105
117
 
106
118
  interface CompressedTagListProps {
107
119
  tags: string[];
120
+ tagLinkPrefix?: string;
108
121
  }
109
122
 
110
- export const CompressedTagList = ({ tags }: CompressedTagListProps) => {
123
+ export const CompressedTagList = ({ tags, tagLinkPrefix }: CompressedTagListProps) => {
124
+ const navigate = useNavigate();
111
125
  const visibleTags = tags.slice(0, 3);
112
126
  const remainingTags = tags.slice(3, tags.length).map((tag) => {
113
127
  return {
114
128
  text: '#' + tag,
115
- onClick: () => {},
129
+ onClick: () => {
130
+ navigate(`${tagLinkPrefix ? tagLinkPrefix : ''}/${tag}`);
131
+ },
116
132
  };
117
133
  });
118
134
 
119
135
  return (
120
136
  <>
121
- <TagList tags={visibleTags} />
137
+ <TagList tagLinkPrefix={tagLinkPrefix} tags={visibleTags} />
122
138
  {remainingTags.length > 0 && (
123
139
  <MenuButton hideMenuIcon={true} menuItems={remainingTags}>
124
140
  <TagCounterWrapper>{`+${remainingTags.length}`}</TagCounterWrapper>
@@ -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/css';
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/css';
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,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import styled from '@emotion/styled';
4
- import css from '@emotion/css';
4
+ import { css } from '@emotion/core';
5
5
  import { spacing, mq, breakpoints } from '@ndla/core';
6
6
  import Tooltip from '@ndla/tooltip';
7
7
  import { useTranslation } from 'react-i18next';
@@ -2,7 +2,7 @@ import React, { Component, Fragment, createRef } from 'react';
2
2
  import BEMHelper from 'react-bem-helper';
3
3
  import PropTypes from 'prop-types';
4
4
  import { Back } from '@ndla/icons/common';
5
- import debounce from 'lodash/debounce';
5
+ import { debounce } from 'lodash';
6
6
  import { getCurrentBreakpoint, breakpoints } from '@ndla/util';
7
7
  import Modal, { ModalHeader, ModalBody, ModalCloseButton } from '@ndla/modal';
8
8
  import Button from '@ndla/button';
@@ -9,7 +9,7 @@
9
9
  import React, { ReactElement } from 'react';
10
10
  import { useTranslation } from 'react-i18next';
11
11
  import styled from '@emotion/styled';
12
- import css from '@emotion/css';
12
+ import { css } from '@emotion/core';
13
13
  import { spacing, mq, breakpoints } from '@ndla/core';
14
14
  import Tooltip from '@ndla/tooltip';
15
15
  import Button from '@ndla/button';
@@ -7,9 +7,8 @@
7
7
  */
8
8
  import React, { FormEvent, useRef, useState } from 'react';
9
9
  import styled from '@emotion/styled';
10
- import { colors } from '@ndla/core';
11
10
  import { Search as SearchIcon } from '@ndla/icons/common';
12
- import { spacing } from '@ndla/core';
11
+ import { spacing, colors } from '@ndla/core';
13
12
  import { Cross as CrossIcon } from '@ndla/icons/action';
14
13
 
15
14
  import { useTranslation } from 'react-i18next';
@@ -12,7 +12,7 @@
12
12
  import React, { Fragment, useEffect, useState } from 'react';
13
13
  import PropTypes from 'prop-types';
14
14
  import BEMHelper from 'react-bem-helper';
15
- import debounce from 'lodash/debounce';
15
+ import { debounce } from 'lodash';
16
16
 
17
17
  import { Home, Back, Additional, ChevronRight } from '@ndla/icons/common';
18
18
  import { Cross } from '@ndla/icons/action';
@@ -49,19 +49,22 @@ const WrapperForFolderChild = styled.div`
49
49
  gap: ${spacing.xsmall};
50
50
  `;
51
51
 
52
- const shouldForwardProp = (name: string) => !['selected', 'noArrow'].includes(name);
52
+ const shouldForwardProp = (name: string) => !['selected', 'noArrow', 'fullWidth'].includes(name);
53
53
 
54
54
  interface FolderNameProps {
55
55
  selected?: boolean;
56
56
  noArrow?: boolean;
57
+ fullWidth?: boolean;
57
58
  }
58
59
 
59
60
  const FolderName = styled('button', { shouldForwardProp })<FolderNameProps>`
60
61
  cursor: pointer;
61
62
  padding: ${spacing.xsmall};
62
63
  margin: 0;
64
+ outline-offset: -2px;
65
+ outline-color: ${colors.brand.primary};
63
66
  margin-left: ${({ noArrow }) => (noArrow ? `29px` : `0px`)};
64
- flex-grow: 1;
67
+ flex-grow: ${({ fullWidth }) => fullWidth && 1};
65
68
  display: grid;
66
69
  grid-template-columns: auto 1fr auto;
67
70
  align-items: center;
@@ -116,6 +119,7 @@ const FolderItem = ({
116
119
  setSelectedFolder,
117
120
  targetResource,
118
121
  visibleFolders,
122
+ framed,
119
123
  }: Props) => {
120
124
  const { t } = useTranslation();
121
125
  const { id, icon, name } = folder;
@@ -173,6 +177,7 @@ const FolderItem = ({
173
177
  {onSelectFolder ? (
174
178
  <>
175
179
  <FolderName
180
+ fullWidth={framed}
176
181
  ref={ref}
177
182
  onKeyDown={(e) => arrowNavigation(e, id, visibleFolders, setFocusedId, onOpenFolder, onCloseFolder)}
178
183
  noArrow={hideArrow && !noPaddingWhenArrowIsHidden}
@@ -34,7 +34,6 @@ export interface TreeStructureProps extends CommonTreeStructureProps {
34
34
  defaultOpenFolders?: string[];
35
35
  folders: FolderType[];
36
36
  editable?: boolean;
37
- framed?: boolean;
38
37
  label?: string;
39
38
  maximumLevelsOfFoldersAllowed?: number;
40
39
  onNewFolder?: (name: string, parentId: string) => Promise<IFolder>;
@@ -118,6 +117,7 @@ const TreeStructure = ({
118
117
  onNewFolder?.(name, parentId).then((newFolder) => {
119
118
  if (newFolder) {
120
119
  setSelectedFolder(newFolder);
120
+ onSelectFolder?.(newFolder.id);
121
121
  setFocusedId(newFolder.id);
122
122
  setOpenFolders(uniq(openFolders.concat(parentId)));
123
123
  }
@@ -156,6 +156,7 @@ const TreeStructure = ({
156
156
  setSelectedFolder={setSelectedFolder}
157
157
  targetResource={targetResource}
158
158
  visibleFolders={visibleFolderIds}
159
+ framed={framed}
159
160
  />
160
161
  </TreeStructureStyledWrapper>
161
162
  {editable && (
@@ -13,18 +13,15 @@ import { colors, misc, spacing } from '@ndla/core';
13
13
  const TreeStructureWrapper = styled.div<{ framed?: boolean }>`
14
14
  padding: ${spacing.xsmall};
15
15
  ${({ framed }) =>
16
- framed
17
- ? css`
18
- border: 1px solid ${colors.brand.neutral7};
19
- border-radius: ${misc.borderRadius};
20
- max-height: 400px;
21
- overflow-y: scroll;
22
- scroll-behavior: smooth;
23
- padding: ${spacing.small};
24
- `
25
- : css`
26
- margin-left: -${spacing.medium};
27
- `}
16
+ framed &&
17
+ css`
18
+ border: 1px solid ${colors.brand.neutral7};
19
+ border-radius: ${misc.borderRadius};
20
+ max-height: 400px;
21
+ overflow-y: scroll;
22
+ scroll-behavior: smooth;
23
+ padding: ${spacing.small};
24
+ `}
28
25
  transition: ${misc.transition.default};
29
26
  &:focus-within {
30
27
  border-color: ${colors.brand.primary};
@@ -24,6 +24,7 @@ export interface CommonTreeStructureProps {
24
24
  openOnFolderClick?: boolean;
25
25
  menuItems?: TreeStructureMenuProps[];
26
26
  targetResource?: IResource;
27
+ framed?: boolean;
27
28
  }
28
29
 
29
30
  export interface CommonFolderItemsProps extends CommonTreeStructureProps {