@ndla/ui 50.2.1 → 50.2.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ndla/ui",
3
- "version": "50.2.1",
3
+ "version": "50.2.2",
4
4
  "description": "UI component library for NDLA.",
5
5
  "license": "GPL-3.0",
6
6
  "main": "lib/index.js",
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "6f041fcaaf82427200c03a36b4c71cb5d8416731"
84
+ "gitHead": "55f97f38adf946d72fbc513ca3a7b00301d24a8a"
85
85
  }
@@ -6,51 +6,147 @@
6
6
  *
7
7
  */
8
8
 
9
- import { ReactNode, useState } from 'react';
10
- import BEMHelper from 'react-bem-helper';
9
+ import { ComponentProps, ReactNode, forwardRef, useCallback, useEffect, useState } from 'react';
11
10
  import { useTranslation } from 'react-i18next';
12
11
  import styled from '@emotion/styled';
13
12
  import { IconButtonV2 } from '@ndla/button';
14
13
  import { ChevronDown, ChevronUp } from '@ndla/icons/common';
14
+ import { breakpoints, colors, mq, spacing } from '@ndla/core';
15
+ import { css } from '@emotion/react';
15
16
 
16
- const classes = new BEMHelper({
17
- name: 'factbox',
18
- prefix: 'c-',
19
- });
20
-
21
- interface Props {
17
+ interface Props extends ComponentProps<'aside'> {
22
18
  children?: ReactNode;
19
+ defaultOpen?: boolean;
20
+ open?: boolean;
21
+ onOpenChange?: (open: boolean) => void;
23
22
  }
24
23
 
25
24
  const StyledAside = styled.aside`
26
25
  display: flex;
27
26
  flex-direction: column;
28
27
  align-items: center;
28
+ position: relative;
29
+ z-index: 1;
30
+ margin: ${spacing.large} 0 calc(${spacing.large} - ${spacing.nsmall}) 0;
31
+ overflow: hidden;
32
+ padding-bottom: ${spacing.nsmall};
33
+
34
+ @media print {
35
+ overflow: visible;
36
+ }
37
+
38
+ h2:first-of-type {
39
+ border-bottom: 2px solid ${colors.brand.primary};
40
+ margin-top: 0;
41
+ margin-bottom: ${spacing.normal};
42
+ }
43
+
44
+ h2,
45
+ h3,
46
+ h4,
47
+ h5 {
48
+ display: block;
49
+ margin-top: ${spacing.normal};
50
+ margin-bottom: ${spacing.small};
51
+ border-bottom: 1px solid ${colors.brand.light};
52
+ }
29
53
  `;
30
54
 
31
55
  const StyledDiv = styled.div`
32
56
  width: 100%;
57
+ position: relative;
58
+ color: ${colors.brand.greyDark};
59
+ padding: ${spacing.normal} ${spacing.normal} ${spacing.large};
60
+ border: 1px solid ${colors.brand.greyLight};
61
+ max-height: 190px;
62
+ transition: max-height 0.6s ease-in-out;
63
+ overflow: hidden;
64
+
65
+ &:after {
66
+ content: '';
67
+ text-align: center;
68
+ position: absolute;
69
+ top: 0;
70
+ bottom: 0;
71
+ right: 0;
72
+ width: 99%;
73
+ margin: 0.5% 0.5% 0 0.5%;
74
+ transition: opacity 0.5s cubic-bezier(0.74, -0.04, 0.96, 0.97);
75
+ /* The 00 after our color is to set its opacity to 0 */
76
+ background: linear-gradient(${colors.brand.light}00, ${colors.white});
77
+ opacity: 1;
78
+ z-index: 0;
79
+ }
80
+
81
+ @media print {
82
+ max-height: revert;
83
+ &:after {
84
+ display: none;
85
+ }
86
+ }
87
+
88
+ & > ul:not([class]),
89
+ :not(li) > ul:not([class]) {
90
+ ${mq.range({ from: breakpoints.desktop })} {
91
+ margin-left: ${spacing.normal};
92
+ }
93
+ }
94
+
95
+ & > ol:not([class]),
96
+ :not(li) > ol:not([class]) {
97
+ ${mq.range({ from: breakpoints.desktop })} {
98
+ margin-left: ${spacing.large};
99
+ }
100
+ }
33
101
  `;
34
102
 
35
103
  const StyledIconButton = styled(IconButtonV2)`
36
104
  margin-top: -20px;
37
105
  z-index: 1;
106
+
107
+ @media print {
108
+ display: none;
109
+ }
110
+ `;
111
+
112
+ const expandedStyle = css`
113
+ max-height: 500vh;
114
+ `;
115
+
116
+ const expandedContentStyle = css`
117
+ max-height: 500vh;
118
+ &:after {
119
+ opacity: 0;
120
+ z-index: -1;
121
+ }
38
122
  `;
39
123
 
40
- const FactBox = ({ children }: Props) => {
41
- const { t } = useTranslation();
42
- const [isOpen, setIsOpen] = useState(false);
43
-
44
- const additional = isOpen ? 'expanded' : '';
45
-
46
- return (
47
- <StyledAside {...classes(undefined, undefined, additional)}>
48
- <StyledDiv {...classes('content')}>{children}</StyledDiv>
49
- <StyledIconButton onClick={() => setIsOpen((p) => !p)} aria-label={t(`factbox.${isOpen ? 'close' : 'open'}`)}>
50
- {isOpen ? <ChevronUp /> : <ChevronDown />}
51
- </StyledIconButton>
52
- </StyledAside>
53
- );
54
- };
124
+ const FactBox = forwardRef<HTMLElement, Props>(
125
+ ({ children, open, onOpenChange, defaultOpen = false, ...rest }, ref) => {
126
+ const { t } = useTranslation();
127
+ const [isOpen, setIsOpen] = useState(defaultOpen);
128
+
129
+ useEffect(() => {
130
+ if (open !== undefined) {
131
+ setIsOpen(open);
132
+ }
133
+ }, [open]);
134
+
135
+ const onClick = useCallback(() => {
136
+ const newOpen = !isOpen;
137
+ setIsOpen(newOpen);
138
+ onOpenChange?.(newOpen);
139
+ }, [isOpen, onOpenChange]);
140
+
141
+ return (
142
+ <StyledAside {...rest} css={[isOpen ? expandedStyle : undefined]} ref={ref}>
143
+ <StyledDiv css={isOpen ? expandedContentStyle : undefined}>{children}</StyledDiv>
144
+ <StyledIconButton onClick={onClick} aria-label={t(`factbox.${isOpen ? 'close' : 'open'}`)}>
145
+ {isOpen ? <ChevronUp /> : <ChevronDown />}
146
+ </StyledIconButton>
147
+ </StyledAside>
148
+ );
149
+ },
150
+ );
55
151
 
56
152
  export default FactBox;
@@ -104,7 +104,7 @@ interface MediaListCCLinkProps {
104
104
  url: string;
105
105
  }
106
106
  export const MediaListCCLink = ({ children, url }: MediaListCCLinkProps) => (
107
- <a className="c-figure-license__link" target="_blank" rel="noopener noreferrer license" href={url}>
107
+ <a rel="noopener noreferrer license" href={url}>
108
108
  {children}
109
109
  </a>
110
110
  );
package/src/main.scss CHANGED
@@ -6,8 +6,6 @@
6
6
 
7
7
  @import 'global/components/component.bodybox';
8
8
  @import 'Figure/component.figure';
9
- @import 'Figure/component.figure-license';
10
- @import 'FactBox/component.factbox';
11
9
  @import 'Aside/component.aside';
12
10
  @import 'global/components/component.logo';
13
11
  @import 'MediaList/component.medialist';
@@ -1,167 +0,0 @@
1
- $padding-bottom: 17px;
2
-
3
- .c-factbox {
4
- position: relative;
5
- z-index: 1;
6
- margin: $spacing--large 0 ($spacing--large - $padding-bottom) 0;
7
- overflow: hidden;
8
- padding-bottom: $padding-bottom;
9
-
10
- @include font-size(16px, 1.5);
11
-
12
- &__content {
13
- position: relative;
14
- color: $brand-grey-dark;
15
- padding: $spacing $spacing $spacing--large;
16
- border: 1px solid $brand-grey--light;
17
- max-height: 190px;
18
- transition: max-height 0.6s ease-in-out;
19
- overflow: hidden;
20
-
21
- &:after {
22
- content: '';
23
- text-align: center;
24
- position: absolute;
25
- top: 0;
26
- bottom: 0;
27
- right: 0;
28
- width: 99%;
29
- margin: 0.5% 0.5% 0 0.5%;
30
- transition: opacity 0.5s cubic-bezier(0.74, -0.04, 0.96, 0.97);
31
- background: linear-gradient(rgba($brand-color--light, 0), $white);
32
- opacity: 1;
33
- z-index: 0;
34
- }
35
-
36
- & > ul:not([class]),
37
- :not(li) > ul:not([class]) {
38
- @include mq(desktop) {
39
- margin-left: $spacing;
40
- }
41
- }
42
-
43
- & > ol:not([class]),
44
- :not(li) > ol:not([class]) {
45
- @include mq(desktop) {
46
- margin-left: $spacing--large;
47
- }
48
- }
49
- }
50
-
51
- @media print {
52
- overflow: visible;
53
- &__content {
54
- max-height: revert;
55
- &:after {
56
- display: none;
57
- }
58
- }
59
- }
60
-
61
- &.expanded {
62
- max-height: 500vh;
63
-
64
- .c-factbox {
65
- &__content {
66
- max-height: 500vh;
67
-
68
- > div > * {
69
- // Hack to fix links and interactions inside aside
70
- z-index: 9;
71
- position: relative;
72
- }
73
-
74
- &:after {
75
- opacity: 0;
76
- z-index: -1;
77
- }
78
- }
79
-
80
- &__button:after {
81
- transform: rotate(180deg);
82
- top: 38%;
83
- }
84
- &__button--open {
85
- visibility: visible;
86
- }
87
- &__button--collapsed {
88
- visibility: hidden;
89
- }
90
- }
91
- }
92
- &__button--open {
93
- visibility: hidden;
94
- }
95
- &__button--collapsed {
96
- visibility: visible;
97
- }
98
-
99
- &__button {
100
- position: absolute;
101
- left: 0;
102
- right: 0;
103
- bottom: 2px;
104
- z-index: 9;
105
- box-shadow: 0 0px 15px rgba(gray, 0.3);
106
- margin: auto;
107
- padding: 5px 15px !important;
108
- width: 0px;
109
- height: 33px;
110
- text-align: center;
111
- font-size: 14px;
112
- border-radius: 50% !important;
113
-
114
- &:after {
115
- content: '';
116
- display: inline-block;
117
- position: absolute;
118
- top: 45%;
119
- left: 32%;
120
- width: 0;
121
- height: 0;
122
- border-left: 5px solid transparent;
123
- border-right: 5px solid transparent;
124
- border-top: 5px solid $white;
125
- }
126
- &:hover,
127
- &:active {
128
- background: $brand-color--dark !important;
129
- }
130
- @media print {
131
- display: none !important;
132
- }
133
- }
134
-
135
- img {
136
- box-shadow: 0px 0px 9px -3px $brand-grey;
137
- }
138
-
139
- figure {
140
- // Overrule default images width
141
- width: 100% !important;
142
- left: 0 !important;
143
- padding: 0;
144
- }
145
-
146
- h2:first-child {
147
- border-bottom: 2px solid $brand-color;
148
- margin-top: 0;
149
- margin-bottom: $spacing;
150
- @include font-size(22px, 34px);
151
- font-weight: $font-weight-bold;
152
- position: relative;
153
- z-index: 2;
154
- }
155
-
156
- h2,
157
- h3,
158
- h4,
159
- h5 {
160
- display: block;
161
- @include font-size(16px, 1.5);
162
- letter-spacing: 0.1em;
163
- margin-top: $spacing;
164
- margin-bottom: $spacing--small;
165
- border-bottom: 1px solid $brand-color--light;
166
- }
167
- }
@@ -1,129 +0,0 @@
1
- /**
2
- ** FIGURE LICENSE
3
- ** Popup displaying license info
4
- **
5
- ** PRINCIPLE:
6
- **
7
- **/
8
-
9
- .c-figure-license {
10
- @include font-size(16px, 1.5);
11
- font-family: $font-serif;
12
- }
13
-
14
- .c-figure-license__cta-block {
15
- display: flex;
16
- flex-direction: column;
17
- justify-content: space-between;
18
- align-self: flex-end;
19
-
20
- > * {
21
- margin-top: $spacing--small;
22
- }
23
-
24
- @include mq(tablet) {
25
- flex-direction: row;
26
- flex-wrap: wrap;
27
- }
28
- }
29
-
30
- .c-figure-license__button {
31
- margin-bottom: $spacing--small;
32
- }
33
-
34
- .c-figure-license__link {
35
- color: $brand-color;
36
- }
37
-
38
- .c-figure-license__list {
39
- background: $white;
40
- list-style: none;
41
- padding: 0 $spacing--small $spacing--small $spacing--small;
42
- margin-top: 0;
43
- margin-bottom: 0;
44
- li {
45
- list-style: none;
46
- }
47
- }
48
-
49
- .c-figure-license__item {
50
- margin-bottom: 0;
51
- }
52
-
53
- .c-figure-license__close {
54
- position: absolute;
55
- top: $spacing;
56
- right: $spacing;
57
- background: transparent;
58
- border: none;
59
- color: $brand-color;
60
- @include font-size(18px, 1.33);
61
- font-weight: $font-weight-normal;
62
- z-index: 9;
63
- cursor: pointer;
64
- }
65
-
66
- .c-figure-license__cta-wrapper {
67
- background-color: $white;
68
- padding: $spacing;
69
- margin-top: $spacing;
70
- }
71
-
72
- .c-figure-license__title {
73
- margin: 0 0 $spacing--small;
74
- @include font-size(18px, 1.33);
75
- color: $brand-color;
76
- }
77
- .c-figure-license--fullscreen {
78
- text-align: center;
79
- }
80
- .c-figure-license__content {
81
- margin: auto;
82
- display: inline-block;
83
- text-align: left;
84
- }
85
-
86
- .c-figure-license__image-title {
87
- @include font-size(28px, 30px);
88
- margin: $spacing 0 0;
89
- text-align: left;
90
- }
91
-
92
- .c-figure-license__hidden-content {
93
- display: none;
94
- flex-wrap: wrap;
95
- > div {
96
- width: 48%;
97
- margin: 1%;
98
- }
99
- }
100
- .c-figure-license__hidden-content--active {
101
- display: flex;
102
- }
103
-
104
- .c-figure-license__image-wrapper {
105
- display: block;
106
- cursor: zoom-in;
107
- margin: 0 auto;
108
- padding: 0;
109
- background: none;
110
- border: 0;
111
- overflow: hidden;
112
- margin-top: $spacing--large;
113
-
114
- img {
115
- transition: transform 0.5s ease-out;
116
- max-width: 100%;
117
- max-height: 90vh;
118
- height: auto;
119
- margin: auto;
120
- }
121
-
122
- &--zoom {
123
- cursor: zoom-out;
124
-
125
- img {
126
- transform: scale3d(2, 2, 2);
127
- }
128
- }
129
- }