Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new banner component #651

Merged
merged 6 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions base.scss
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@
@import "./src/stories/Library/filtered-event-list/filtered-event-list";
@import "./src/stories/Library/event-list-stacked/event-list-stacked";
@import "./src/stories/Library/material-search/material-search";
@import "./src/stories/Library/banner/banner";

// Autosuggest block styling needs to be loaded before the rest of the scss for autosuggest
@import "./src/stories/Blocks/autosuggest/autosuggest";
Expand Down
3 changes: 3 additions & 0 deletions public/icons/basic/icon-underlined.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions src/stories/Library/banner/Banner.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { ComponentMeta, ComponentStory } from "@storybook/react";
import { withDesign } from "storybook-addon-designs";
import Banner from "./Banner";

export default {
title: "Library / Banner",
component: Banner,
decorators: [withDesign],
parameters: {
design: {
type: "figma",
url: "https://www.figma.com/design/Zx9GrkFA3l4ISvyZD2q0Qi/Designsystem?node-id=446-6957&t=IWAOniAbcjV2y2Hf-4",
},
},
argTypes: {
imageSrc: {
defaultValue: "images/campaign_cover.jpg",
control: { type: "text" },
},
title: {
name: "Title",
defaultValue: "Hvad skal jeg <u>høre?</u>",
control: { type: "text" },
},
description: {
name: "Description",
defaultValue:
"Om du er dedikeret musiknørd eller moderat musikinteresseret, så er dette siden til dig. Her kan du finde anbefalinger, digitale musikmagasiner, nyheder, musiklitteratur og meget mere.",
control: { type: "text" },
},
link: {
name: "Link",
defaultValue: "#",
control: { type: "text" },
},
},
} as ComponentMeta<typeof Banner>;

const Template: ComponentStory<typeof Banner> = (args) => <Banner {...args} />;

export const Default = Template.bind({});

export const NoImage = Template.bind({});
NoImage.args = {
imageSrc: undefined,
};

export const NoImageOnlyTitle = Template.bind({});
NoImageOnlyTitle.args = {
title: "Title <u>uden</u> billede",
imageSrc: undefined,
description: undefined,
};

export const NoImageOnlyDescription = Template.bind({});
NoImageOnlyDescription.args = {
title: undefined,
imageSrc: undefined,
description:
"Om du er dedikeret musiknørd eller moderat musikinteresseret, så er dette siden til dig. Her kan du finde anbefalinger, digitale musikmagasiner, nyheder, musiklitteratur og meget mere.",
};

export const WithImageOnlyTitle = Template.bind({});
WithImageOnlyTitle.args = {
title: "Banner <u>uden</u> beskrivelse",
description: undefined,
};
export const WithImageOnlyDescription = Template.bind({});
WithImageOnlyDescription.args = {
description:
"Om du er dedikeret musiknørd eller moderat musikinteresseret, så er dette siden til dig. Her kan du finde anbefalinger, digitale musikmagasiner, nyheder, musiklitteratur og meget mere.",
};
46 changes: 46 additions & 0 deletions src/stories/Library/banner/Banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import clsx from "clsx";
import { FC, ReactNode } from "react";
import { ReactComponent as ArrowLargeRight } from "../Arrows/icon-arrow-ui/icon-arrow-ui-large-right.svg";

type BannerType = {
link: string;
title: string;
imageSrc?: ReactNode;
description?: string;
};

const Banner: FC<BannerType> = ({ link, imageSrc, title, description }) => {
const backgroundImageStyle = imageSrc
? { backgroundImage: `url(${imageSrc})` }
: {};
return (
<a
href={link}
className={clsx(`banner arrow__hover--right-large`, {
"banner--has-image": imageSrc,
})}
style={backgroundImageStyle}
>
<div className="banner__content-wrapper">
<div
className={clsx("banner__content", {
"banner__content--has-image": imageSrc,
})}
>
{title && (
<h2
className="banner__title"
// We need to be able to replicate our WYSIWYG field in Drupal that makes it possible to underline (<u>) words.
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{ __html: title }}
/>
)}
{description && <p className="banner__description">{description}</p>}
<ArrowLargeRight />
</div>
</div>
</a>
);
};

export default Banner;
79 changes: 79 additions & 0 deletions src/stories/Library/banner/banner.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
$_banner-content-wrapper-width: 944px;
$_banner-content-max-width-small: 330px;
$_banner-content-max-width-medium: 569px;
$_banner-content-no-image-max-width-small: $layout__max-width--small;
$_banner-height-small: 500px;
$_banner-height-medium: 810px;

.banner {
@include layout-container($layout__max-width--large, 0);

display: grid;
align-items: center;
text-decoration: none;
box-sizing: border-box;
background-color: $color__global-secondary;
min-height: $_banner-height-small;

&--has-image {
background-repeat: no-repeat;
background-position: center;
background-size: cover;
height: 100%;
width: 100%;
}

@include media-query__small {
min-height: $_banner-height-medium;
}
}

.banner__content-wrapper {
@include layout-container($_banner-content-wrapper-width, 0);
width: 100%;
padding: $s-2xl 0;

&--has-image {
padding-right: $s-2xl;
}

@include media-query__small {
padding-right: unset;
}
}

.banner__content {
display: flex;
flex-direction: column;
align-items: center;
gap: $s-md;
text-align: center;
padding: $s-xl;
margin: 0 auto;
max-width: $_banner-content-max-width-medium;

&--has-image {
padding: $s-xl;
margin: unset;
text-align: unset;
align-items: unset;
background-color: $color__global-white;
max-width: $_banner-content-max-width-small;
}

@include media-query__small {
gap: $s-lg;
padding: calc($s-2xl + 6px);
max-width: $_banner-content-max-width-medium;
}
}

.banner__title {
@include typography($typo__h2);
@include u-extending-underline-style;
}

.banner__description {
@include typography($typo__body-placeholder);
line-height: 160%;
}
26 changes: 26 additions & 0 deletions src/styles/scss/tools/mixins.tools.scss
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,29 @@
text-overflow: ellipsis;
text-align: left;
}

/**
* Mixin `u-extending-underline-style` applies a custom underline effect to `<u>` elements.
* - Uses a pseudo-element (::after) with a positioned SVG image as the underline.
* - Removes default text underline.
*/
@mixin u-extending-underline-style {
u {
position: relative;
text-decoration: none;

&::after {
content: "";
position: absolute;
bottom: -5px;
left: 0;
width: 100%;
height: 12px;
background-repeat: no-repeat;
background-position: left;
background-size: cover;
// Underlined icon from public/icons/basic/icon-underlined.svg
background-image: url("data:image/svg+xml,%3Csvg width='205' height='8' viewBox='0 0 205 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M1.11133 6.87425C73.7223 0.129386 128.695 1.4981 203.889 1.8943' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
LasseStaus marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Loading