Merged in feature/SW-3595-sas-info-boxes (pull request #3177)

Feature/SW-3595 Add info boxes to SAS start page & Eurobonus alert to select-hotel page on SAS

* wip

* feat(SW-3595): Add info boxes to SAS start page

* Add InfoBox to design-system
* Add background gradient to SAS start page

* update variable naming and conditionalize the eurobonus message on select-hotel

* SAS startpage update default message

* make select-hotel a bit more generic with slot={} instead of alert={}


Approved-by: Anton Gunnarsson
This commit is contained in:
Joakim Jäderberg
2025-11-19 10:50:04 +00:00
parent 32e5c8d357
commit db30588f63
15 changed files with 459 additions and 105 deletions

View File

@@ -0,0 +1,40 @@
.infoBox {
display: grid;
grid-template-columns: auto 1fr;
gap: 1rem;
padding: var(--Space-x2) var(--Space-x3);
border-radius: var(--Corner-radius-Medium);
align-items: center;
background: var(--Background-Secondary);
&.sasBlue {
background: var(--SAS-Blue-90);
}
.iconContainer {
display: flex;
width: 24px;
padding: var(--Space-x05);
border-radius: 100%;
aspect-ratio: 1 / 1;
box-sizing: content-box;
align-items: center;
justify-content: center;
color: white;
background: var(--Surface-Brand-Accent-OnAccent-Accent);
&.sasBlue {
color: white;
background: var(--SAS-Blue-Default);
}
}
.content {
display: flex;
flex-direction: column;
gap: var(--Space-x05);
}
}

View File

@@ -0,0 +1,53 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
import { expect } from 'storybook/test'
import { InfoBox, Props } from './InfoBox'
import { IconName } from '../Icons/iconName'
const meta: Meta<typeof InfoBox> = {
title: 'Components/InfoBox',
component: InfoBox,
parameters: {
layout: 'padded',
},
tags: ['autodocs'],
}
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
args: {
theme: 'Default',
icon: IconName.Accessibility,
heading: 'Heading',
text: 'This is an informational message',
},
argTypes: {
icon: {
control: { type: 'select' },
options: Object.values(IconName),
},
theme: {
control: { type: 'select' },
options: ['Default', 'SAS-Blue'] satisfies Props['theme'][],
},
},
play: async ({ canvas, args }) => {
const article = await canvas.findByRole('article')
await expect(article).toBeVisible()
const heading = await canvas.findByRole('heading', { name: args.heading })
await expect(heading).toBeVisible()
const paragraph = await canvas.findByText(args.text)
await expect(paragraph).toBeVisible()
},
}
export const WithoutIcon: Story = {
args: {
heading: 'Heading',
text: 'This is an informational message',
},
}

View File

@@ -0,0 +1,57 @@
import { cva } from 'class-variance-authority'
import { IconByIconName } from '../Icons/IconByIconName'
import { IconName } from '../Icons/iconName'
import { Typography } from '../Typography'
import styles from './InfoBox.module.css'
import type { VariantProps } from 'class-variance-authority'
const infoBoxVariants = cva(styles.infoBox, {
variants: {
theme: {
'SAS-Blue': styles.sasBlue,
Default: styles.default,
},
},
defaultVariants: {
theme: 'Default',
},
})
const iconVariants = cva(styles.iconContainer, {
variants: {
theme: {
'SAS-Blue': styles.sasBlue,
Default: styles.default,
},
},
defaultVariants: {
theme: 'Default',
},
})
export type Props = {
heading: string
text: string
theme?: VariantProps<typeof infoBoxVariants>['theme']
icon?: IconName
}
export function InfoBox({ heading, text, theme, icon }: Props) {
return (
<article className={infoBoxVariants({ theme })}>
{icon && (
<div className={iconVariants({ theme })}>
<IconByIconName iconName={icon} color={'CurrentColor'} />
</div>
)}
<div className={styles.content}>
<Typography variant="Body/Paragraph/mdBold">
<h2>{heading}</h2>
</Typography>
<Typography variant="Body/Supporting text (caption)/smRegular">
<p>{text}</p>
</Typography>
</div>
</article>
)
}