@ndla/ui 56.0.25-alpha.0 → 56.0.27-alpha.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.
@@ -34,6 +34,14 @@ interface Props {
34
34
  path?: string;
35
35
  }
36
36
 
37
+ const Wrapper = styled("div", {
38
+ base: {
39
+ width: "100%",
40
+ height: "100%",
41
+ containerType: "inline-size",
42
+ },
43
+ });
44
+
37
45
  const Container = styled("div", {
38
46
  base: {
39
47
  display: "grid",
@@ -49,14 +57,24 @@ const Container = styled("div", {
49
57
  variants: {
50
58
  imageSide: {
51
59
  left: {
52
- tabletWide: {
60
+ "@/tablet": {
53
61
  gridTemplateColumns: "minmax(230px, 455px) auto", //required for campaign block in myNdla
54
62
  },
63
+ "@supports not (container-type: inline-size)": {
64
+ tabletWide: {
65
+ gridTemplateColumns: "minmax(230px, 455px) auto",
66
+ },
67
+ },
55
68
  },
56
69
  right: {
57
- tabletWide: {
70
+ "@/tablet": {
58
71
  gridTemplateColumns: "auto minmax(230px, 455px)", //required for campaign block in myNdla
59
72
  },
73
+ "@supports not (container-type: inline-size)": {
74
+ tabletWide: {
75
+ gridTemplateColumns: "auto minmax(230px, 455px)",
76
+ },
77
+ },
60
78
  },
61
79
  },
62
80
  },
@@ -93,12 +111,17 @@ const StyledImg = styled("img", {
93
111
  objectFit: "cover",
94
112
  width: "100%",
95
113
  height: "215px",
96
- tablet: {
97
- height: "265px",
98
- },
99
- tabletWide: {
114
+ "@/tablet": {
100
115
  height: "340px",
101
116
  },
117
+ "@supports not (container-type: inline-size)": {
118
+ tablet: {
119
+ height: "265px",
120
+ },
121
+ tabletWide: {
122
+ height: "340px",
123
+ },
124
+ },
102
125
  },
103
126
  });
104
127
 
@@ -112,13 +135,12 @@ const ContentWrapper = styled("div", {
112
135
  justifyContent: "center",
113
136
  paddingBlock: "medium",
114
137
  paddingInline: "medium",
115
- minWidth: "270px", //required for campaign block in myNdla
116
138
  },
117
139
  });
118
140
 
119
141
  const StyledText = styled(Text, {
120
142
  base: {
121
- tabletWide: {
143
+ tablet: {
122
144
  display: "block",
123
145
  overflow: "hidden",
124
146
  position: "relative",
@@ -158,26 +180,28 @@ const CampaignBlock = ({
158
180
  const imageComponent = image && <StyledImg src={`${image.src}?width=455`} height={340} width={455} alt={image.alt} />;
159
181
  const HeaderComponent = url?.url ? LinkHeader : Text;
160
182
  return (
161
- <Container className={className} data-embed-type="campaign-block" imageSide={imageSide}>
162
- {imageSide === "left" && imageComponent}
163
- <ContentWrapper>
164
- <MaybeLinkText url={url?.url} path={path}>
165
- <HeaderComponent asChild consumeCss textStyle="heading.small">
166
- <InternalHeading>{parse(title)}</InternalHeading>
167
- </HeaderComponent>
168
- </MaybeLinkText>
169
- <StyledText textStyle="body.xlarge">{parse(description)}</StyledText>
170
- {!!url?.url && (
171
- <MaybeLinkText url={url.url} path={path}>
172
- <LinkText textStyle="body.medium">
173
- {parse(url.text ?? "")}
174
- <ArrowRightLine />
175
- </LinkText>
183
+ <Wrapper>
184
+ <Container className={className} data-embed-type="campaign-block" imageSide={imageSide}>
185
+ {imageSide === "left" && imageComponent}
186
+ <ContentWrapper>
187
+ <MaybeLinkText url={url?.url} path={path}>
188
+ <HeaderComponent asChild consumeCss textStyle="heading.small">
189
+ <InternalHeading>{parse(title)}</InternalHeading>
190
+ </HeaderComponent>
176
191
  </MaybeLinkText>
177
- )}
178
- </ContentWrapper>
179
- {imageSide !== "left" && imageComponent}
180
- </Container>
192
+ <StyledText textStyle="body.xlarge">{parse(description)}</StyledText>
193
+ {!!url?.url && (
194
+ <MaybeLinkText url={url.url} path={path}>
195
+ <LinkText textStyle="body.medium">
196
+ {parse(url.text ?? "")}
197
+ <ArrowRightLine />
198
+ </LinkText>
199
+ </MaybeLinkText>
200
+ )}
201
+ </ContentWrapper>
202
+ {imageSide !== "left" && imageComponent}
203
+ </Container>
204
+ </Wrapper>
181
205
  );
182
206
  };
183
207
 
@@ -22,7 +22,7 @@ export const contentTypeToHeroMap: Record<ContentType, HeroVariant> = {
22
22
  [contentTypes.LEARNING_PATH]: "primary",
23
23
  [contentTypes.TOPIC]: "neutral",
24
24
  [contentTypes.MULTIDISCIPLINARY]: "primary",
25
- [contentTypes.CONCEPT]: "brand1Subtle",
25
+ [contentTypes.CONCEPT]: "brand1Moderate",
26
26
  [contentTypes.EXTERNAL]: "primary",
27
27
  [contentTypes.IMAGE]: "primary",
28
28
  [contentTypes.AUDIO]: "primary",
@@ -31,6 +31,7 @@ const LinkedVideoButton = styled(Button, {
31
31
 
32
32
  const BrightcoveIframe = styled("iframe", {
33
33
  base: {
34
+ border: 0,
34
35
  height: "auto",
35
36
  width: "100%",
36
37
  },
@@ -86,9 +87,8 @@ const BrightcoveEmbed = ({ embed, renderContext = "article", lang }: Props) => {
86
87
  ref={iframeRef}
87
88
  title={embedData.alt ?? fallbackTitle}
88
89
  aria-label={embedData.alt ?? fallbackTitle}
89
- frameBorder="0"
90
90
  {...getIframeProps(embedData, [])}
91
- allowFullScreen
91
+ allow="fullscreen; encrypted-media"
92
92
  />
93
93
  </EmbedErrorPlaceholder>
94
94
  );
@@ -112,9 +112,8 @@ const BrightcoveEmbed = ({ embed, renderContext = "article", lang }: Props) => {
112
112
  className="original"
113
113
  title={embedData.alt ?? data.name ?? fallbackTitle}
114
114
  aria-label={embedData.alt ?? data.name ?? fallbackTitle}
115
- frameBorder="0"
116
115
  {...(alternativeVideoProps && !showOriginalVideo ? alternativeVideoProps : originalVideoProps)}
117
- allowFullScreen
116
+ allow="fullscreen; encrypted-media"
118
117
  />
119
118
  </div>
120
119
  <EmbedByline type="video" copyright={data.copyright!} description={parsedDescription}>
@@ -183,6 +183,9 @@ const ExpandButton = styled(
183
183
  transitionDuration: "normal",
184
184
  transitionTimingFunction: "ease-out",
185
185
  },
186
+ tabletDown: {
187
+ display: "none",
188
+ },
186
189
  },
187
190
  },
188
191
  { defaultProps: { type: "button" } },
@@ -221,11 +224,13 @@ const ImageEmbed = ({ embed, previewAlt, lang, renderContext = "article", childr
221
224
 
222
225
  const licenseProps = licenseAttributes(data.copyright.license.license, lang, embedData.url);
223
226
 
227
+ const figureSize = figureProps?.float ? figureProps?.size ?? "medium" : "full";
228
+
224
229
  // TODO: Check how this works with `children`. Will only be important for ED
225
230
  return (
226
231
  <StyledFigure
227
232
  float={figureProps?.float}
228
- size={imageSizes ? "full" : figureProps?.size ?? "medium"}
233
+ size={imageSizes ? "full" : figureSize}
229
234
  data-embed-type="image"
230
235
  {...licenseProps}
231
236
  >
@@ -242,7 +247,7 @@ const ImageEmbed = ({ embed, previewAlt, lang, renderContext = "article", childr
242
247
  onClick={figureProps?.float ? toggleImageSize : undefined}
243
248
  variant="rounded"
244
249
  />
245
- {!!embedData.align && (
250
+ {(embedData.align === "right" || embedData.align === "left") && (
246
251
  <ExpandButton
247
252
  aria-label={t(`license.images.itemImage.zoom${imageSizes ? "Out" : ""}ImageButtonLabel`)}
248
253
  onClick={toggleImageSize}
@@ -252,14 +257,14 @@ const ImageEmbed = ({ embed, previewAlt, lang, renderContext = "article", childr
252
257
  </ExpandButton>
253
258
  )}
254
259
  </ImageWrapper>
255
- {embedData.hideByline === "true" ? null : (
256
- <EmbedByline
257
- type="image"
258
- copyright={data.copyright}
259
- description={embedData.hideCaption === "true" ? "" : parsedDescription}
260
- visibleAlt={previewAlt ? embed.embedData.alt : ""}
261
- />
262
- )}
260
+ <EmbedByline
261
+ type="image"
262
+ copyright={data.copyright}
263
+ description={parsedDescription}
264
+ hideDescription={embedData.hideCaption === "true"}
265
+ hideCopyright={embedData.hideByline === "true"}
266
+ visibleAlt={previewAlt ? embed.embedData.alt : ""}
267
+ />
263
268
  </StyledFigure>
264
269
  );
265
270
  };
@@ -24,6 +24,8 @@ interface BaseProps {
24
24
  children?: ReactNode;
25
25
  visibleAlt?: string;
26
26
  error?: true | false;
27
+ hideDescription?: boolean;
28
+ hideCopyright?: boolean;
27
29
  }
28
30
 
29
31
  export interface EmbedBylineErrorProps extends BaseProps {
@@ -78,6 +80,7 @@ const BylineWrapper = styled("figcaption", {
78
80
  paddingBlock: "xsmall",
79
81
  background: "surface.default",
80
82
  textStyle: "label.medium",
83
+ color: "text.subtle",
81
84
  },
82
85
  });
83
86
 
@@ -114,7 +117,15 @@ const BaseDescription = styled("div", {
114
117
  },
115
118
  });
116
119
 
117
- export const EmbedByline = ({ type, description, children, visibleAlt, ...props }: Props) => {
120
+ export const EmbedByline = ({
121
+ type,
122
+ description,
123
+ children,
124
+ visibleAlt,
125
+ hideCopyright,
126
+ hideDescription,
127
+ ...props
128
+ }: Props) => {
118
129
  const { t } = useTranslation();
119
130
 
120
131
  if (props.error) {
@@ -132,14 +143,18 @@ export const EmbedByline = ({ type, description, children, visibleAlt, ...props
132
143
  }
133
144
 
134
145
  const { copyright } = props;
146
+ const bylineDescription = hideDescription ? "" : description;
135
147
 
136
148
  return (
137
149
  <>
138
150
  <BylineWrapper>
139
151
  <div>
140
- <LicenseContainerContent type={type} copyright={copyright}>
141
- {description}
142
- </LicenseContainerContent>
152
+ {hideCopyright && bylineDescription}
153
+ {!hideCopyright && (
154
+ <LicenseContainerContent type={type} copyright={copyright}>
155
+ {bylineDescription}
156
+ </LicenseContainerContent>
157
+ )}
143
158
  {children}
144
159
  </div>
145
160
  </BylineWrapper>
@@ -16,7 +16,7 @@ interface Props {
16
16
 
17
17
  const StyledSafeLink = styled(SafeLink, {
18
18
  base: {
19
- color: "primary",
19
+ color: "text.link",
20
20
  textDecoration: "underline",
21
21
  whiteSpace: "nowrap",
22
22
  _hover: {