Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into chore/a11y/career/form
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/components/forms/checkbox/checkbox.tsx
  • Loading branch information
noa.santo committed Sep 19, 2024
2 parents 453e55d + 56c9a58 commit fd281f5
Show file tree
Hide file tree
Showing 16 changed files with 273 additions and 96 deletions.
6 changes: 6 additions & 0 deletions src/assets/locales/de/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
"navigation.contact": "Kontakt",
"navigation.about-us": "Über Uns",
"blog.share": "Artikel teilen",
"blog.share.facebook": "Teilen auf Facebook",
"blog.share.whatsapp": "Teilen auf WhatsApp",
"blog.share.email": "Teilen per E-Mail",
"blog.share.twitter": "Teilen auf X",
"blog.share.linkedin": "Teilen auf LinkedIn",
"blog.copy": "Kopieren",
"blog.copied": "Kopiert",
"blog.follow": "Blog abonnieren",
"blog.pagination": "Seite",
Expand Down
6 changes: 6 additions & 0 deletions src/assets/locales/en/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
"navigation.contact": "Contact",
"navigation.about-us": "About",
"blog.share": "Share article",
"blog.share.facebook": "Share on Facebook",
"blog.share.whatsapp": "Share on WhatsApp",
"blog.share.email": "Share via email",
"blog.share.twitter": "Share on X",
"blog.share.linkedin": "Share on LinkedIn",
"blog.copy": "Copy",
"blog.copied": "Copied",
"blog.follow": "Subscribe to blog",
"blog.pagination": "Page",
Expand Down
14 changes: 10 additions & 4 deletions src/components/content/rich-text/rich-text.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,19 @@ export const ContentfulRichText = ({ data }: ContentfulRichTextProps) => {
[MARKS.CODE]: (text) => <code className="language-text">{text}</code>,
},
renderNode: {
[INLINES.HYPERLINK]: (props, children) =>
customComponents.a({
[INLINES.HYPERLINK]: (props, children) => {
const uri = props.data.uri;
if (uri.startsWith('youtube://')) {
const videoId = uri.split('//')[1];
return customComponents.youtube({ videoId });
}
return customComponents.a({
children,
href: props.data.uri,
href: uri,
target: '_blank',
rel: 'nofollow noopener noreferrer',
}),
});
},
[INLINES.EMBEDDED_ENTRY]: (node) => {
const { __typename } = node.data.target;
switch (__typename) {
Expand Down
54 changes: 19 additions & 35 deletions src/components/forms/checkbox/checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React from 'react';
import { useController, UseControllerProps } from 'react-hook-form';
import styled, { css } from 'styled-components';
import { theme } from '../../layout/theme';
Expand All @@ -23,38 +23,35 @@ const CheckboxLabelText = styled.span`
}
`;

const StyledCheckbox = styled.div<{ checked: boolean; hasError: boolean }>`
const StyledCheckbox = styled.input.attrs({
type: 'checkbox',
})<{ $hasError: boolean }>`
display: inline-block;
width: 24px;
height: 24px;
margin: 0;
padding: 0;
background: #f7f8fa;
border-radius: 4px;
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
cursor: pointer;
${({ hasError }) =>
hasError &&
${({ $hasError }) =>
$hasError &&
css`
border: 2px solid ${theme.palette.text.errorMessage};
`}
&:hover {
border: 1px solid ${theme.palette.text.default};
}
svg {
visibility: ${({ checked }) => (checked ? 'visible' : 'hidden')};
}
`;

const HiddenCheckbox = styled.input.attrs({
type: 'checkbox',
})`
height: 1px;
width: 1px;
margin: -1px;
overflow: hidden;
const StyledIcon = styled(Icon)`
position: absolute;
visibility: hidden;
pointer-events: none;
`;

const CheckboxLabelTextWrapper = ({ label, required, id }) => {
Expand All @@ -66,38 +63,25 @@ const CheckboxLabelTextWrapper = ({ label, required, id }) => {
};

export const Checkbox = (
props: UseControllerProps<any> & {
label: string | JSX.Element;
},
props: UseControllerProps<any> & { label: string | JSX.Element },
) => {
const { field, fieldState, formState } = useController(props);
const errorMessage = fieldState?.error?.message;
const [checked, setChecked] = useState(field?.value || false);

const handleChange = () => {
const newChecked = !checked;
setChecked(newChecked);
field.onChange(newChecked);
};

return (
<div>
<div style={{ position: 'relative' }}>
<CheckboxLabel>
<HiddenCheckbox
<StyledCheckbox
aria-required={Boolean(props.rules?.required)}
aria-describedby={errorMessage && `${props.name}-error`}
aria-labelledby={props.label && `${props.name}-label`}
aria-invalid={Boolean(errorMessage)}
disabled={formState.isSubmitting}
{...field}
value={field?.value || false}
{...props}
id={props.name}
onChange={handleChange}
$hasError={Boolean(fieldState?.error)}
/>
<StyledCheckbox checked={checked} hasError={Boolean(fieldState?.error)}>
<Icon show="checkmark_bold" />
</StyledCheckbox>
{field.value && <StyledIcon show="checkmark_bold" />}
{props.label && (
<CheckboxLabelTextWrapper
id={`${props.name}-label`}
Expand Down
6 changes: 5 additions & 1 deletion src/components/layout/header/menu-flyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,11 @@ interface NavigationFlyoutProp {
export const NavigationFlyout: React.FC<NavigationFlyoutProp> = (props) => {
return (
<>
<FullscreenOverlay $visible={props.visible} onClick={props.onClick}>
<FullscreenOverlay
$visible={props.visible}
onClick={props.onClick}
aria-hidden={!props.visible}
>
<ScrollContainer>
<FullHeightNavigation
translation={props.translation}
Expand Down
2 changes: 2 additions & 0 deletions src/components/layout/navigation/navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ const SocialLink = styled.a`
svg {
vertical-align: middle;
}
display: inline-block;
`;

const LegalLink = styled(Link)<{ $isSelected: boolean }>`
Expand Down
4 changes: 4 additions & 0 deletions src/components/legacy/markdown/custom-components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { TextStyles } from '../../typography';
import { Quote } from '../../ui/quote/quote';
import { Link } from '../links/links';
import { WithAnchorHOC } from '../../layout/with-anchor-hoc';
import { YoutubeEmbed } from './youtube-embed';

/**
* Override markdown generated html content with custom React components (for us mostly to pass in custom styling)
Expand Down Expand Up @@ -235,6 +236,9 @@ const customSatellytesComponents = {
const { children, ...rest } = props;
return <Figcaption {...rest}>{children}</Figcaption>;
},
youtube(props) {
return <YoutubeEmbed {...props} />;
},
};

export default customSatellytesComponents;
96 changes: 96 additions & 0 deletions src/components/legacy/markdown/youtube-embed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useContext } from 'react';
import styled from 'styled-components';
import { theme } from '../../layout/theme';
import { Button } from '../../ui/buttons/button';
import { TextStyles } from '../../typography';
import YouTubeConsentContext from '../../../context/youtube-consent-context';
import { Link } from '../links/links';

interface YoutubeEmbedProps {
videoId: string;
}

// how to make iframe responsive: https://stackoverflow.com/questions/17838607/making-an-iframe-responsive
const StyledIframe = styled.iframe`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
`;

const YoutubeEmbedWrapper = styled.div`
position: relative;
padding-bottom: 56.25%; /* 16:9 */
padding-top: 25px;
height: 0;
`;

const YouTubePrivacyBannerWrapper = styled.div`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
padding: 16px;
gap: 16px;
background-color: ${theme.palette.background.card};
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
`;

const LegalText = styled.p`
${TextStyles.label}
text-align: center;
`;

const StyledButton = styled(Button)`
width: fit-content;
`;

const SyledLink = styled(Link)`
color: ${theme.palette.text.link.default};
&:hover {
border-bottom: 1px solid ${theme.palette.text.link.default};
}
`;

export const YoutubeEmbed = ({ videoId }: YoutubeEmbedProps) => {
const { consentGiven, giveConsent } = useContext(YouTubeConsentContext);

return (
<YoutubeEmbedWrapper>
{consentGiven ? (
<StyledIframe
title="YouTube video player"
width="560"
height="315"
src={`https://www.youtube-nocookie.com/embed/${videoId}`}
frameBorder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
></StyledIframe>
) : (
<YouTubePrivacyBanner giveConsent={giveConsent} />
)}
</YoutubeEmbedWrapper>
);
};

const YouTubePrivacyBanner = ({ giveConsent }) => {
return (
<YouTubePrivacyBannerWrapper>
<LegalText>
By clicking on &quot;Show YouTube Content&quot; you accept{' '}
<SyledLink to={'https://policies.google.com/privacy?hl=en'}>
YouTube&apos;s privacy policy
</SyledLink>
.
</LegalText>
<StyledButton onClick={giveConsent}>Show YouTube Content</StyledButton>
</YouTubePrivacyBannerWrapper>
);
};
71 changes: 37 additions & 34 deletions src/components/pages/blog-post/blog-post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import FollowPanel from './follow-panel';
import SharePanel from './share-panel';
import { ContentfulRichText } from '../../content/rich-text/rich-text';
import { TextStyles } from '../../typography';
import { YouTubeConsentProvider } from '../../../context/youtube-consent-context';

interface BlogPostPageProps {
blogPost: BlogArticleQueryData;
Expand Down Expand Up @@ -63,41 +64,43 @@ export const BlogPostPage = ({
const heroByLine = `${formattedDate}${readingTime}${byLine}`;

return (
<Layout
transparentHeader
siteTitleUrl={'/blog'}
light
contentAs={'article'}
hero={
<BlogHero
attribution={blogPost.heroImage}
image={blogPost.heroImage.fullImage}
naturalHeight={blogPost.heroImage.naturalHeight}
/>
}
leadbox={leadbox}
showLanguageSwitch={false}
breadcrumb={breadcrumb}
>
<BlogHeader headline={blogPost.title} byline={heroByLine}>
{blogPost.introRichText && (
<RichTextContainer>
<ContentfulRichText
data={{
...blogPost.introRichText,
references: [],
}}
/>
</RichTextContainer>
)}
</BlogHeader>
<YouTubeConsentProvider>
<Layout
transparentHeader
siteTitleUrl={'/blog'}
light
contentAs={'article'}
hero={
<BlogHero
attribution={blogPost.heroImage}
image={blogPost.heroImage.fullImage}
naturalHeight={blogPost.heroImage.naturalHeight}
/>
}
leadbox={leadbox}
showLanguageSwitch={false}
breadcrumb={breadcrumb}
>
<BlogHeader headline={blogPost.title} byline={heroByLine}>
{blogPost.introRichText && (
<RichTextContainer>
<ContentfulRichText
data={{
...blogPost.introRichText,
references: [],
}}
/>
</RichTextContainer>
)}
</BlogHeader>

<ContentfulRichText data={blogPost.content} />
<ContentfulRichText data={blogPost.content} />

<PanelContainer>
<SharePanel title={blogPost.title} />
<FollowPanel />
</PanelContainer>
</Layout>
<PanelContainer>
<SharePanel title={blogPost.title} />
<FollowPanel />
</PanelContainer>
</Layout>
</YouTubeConsentProvider>
);
};
Loading

0 comments on commit fd281f5

Please sign in to comment.