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:
@@ -1,7 +1,6 @@
|
||||
.floatingBookingWidget {
|
||||
width: var(--max-width-content);
|
||||
margin: 0 auto;
|
||||
min-height: 88px;
|
||||
position: relative;
|
||||
|
||||
.floatingBackground {
|
||||
@@ -25,9 +24,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) and (max-width: 1366px) {
|
||||
.floatingBookingWidget {
|
||||
min-height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@ export function FloatingBookingWidgetClient(props: Props) {
|
||||
useEffect(() => {
|
||||
observerRef.current = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
const hasScrolledPastTop = entry.boundingClientRect.top < 0
|
||||
const hasScrolledPastTop = entry.boundingClientRect.bottom < 0
|
||||
setStickyTop(hasScrolledPastTop)
|
||||
},
|
||||
{ threshold: 0, rootMargin: "0px 0px -100% 0px" }
|
||||
{ threshold: 0, rootMargin: "0px 0px 0% 0px" }
|
||||
)
|
||||
|
||||
if (containerRef.current) {
|
||||
|
||||
@@ -32,6 +32,7 @@ interface SelectHotelProps {
|
||||
isBookingCodeRateAvailable?: boolean
|
||||
title: ReactNode
|
||||
lang: Lang
|
||||
topSlot?: ReactNode
|
||||
}
|
||||
|
||||
export function SelectHotel({
|
||||
@@ -42,6 +43,7 @@ export function SelectHotel({
|
||||
isBookingCodeRateAvailable = false,
|
||||
title,
|
||||
lang,
|
||||
topSlot,
|
||||
}: SelectHotelProps) {
|
||||
const isAllUnavailable = hotels.every(
|
||||
(hotel) => hotel.availability.status !== "Available"
|
||||
@@ -83,54 +85,60 @@ export function SelectHotel({
|
||||
</div>
|
||||
</header>
|
||||
<main className={styles.main}>
|
||||
{showBookingCodeFilter ? <BookingCodeFilter /> : null}
|
||||
<div className={styles.sideBar}>
|
||||
{hotels.length ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
href={
|
||||
isAlternative
|
||||
? alternativeHotelsMap(lang)
|
||||
: selectHotelMap(lang)
|
||||
}
|
||||
keepSearchParams
|
||||
>
|
||||
<MapWithButtonWrapper>
|
||||
{topSlot && <div className={styles.topSlotContainer}>{topSlot}</div>}
|
||||
<div className={styles.availabilityContainer}>
|
||||
{showBookingCodeFilter ? <BookingCodeFilter /> : null}
|
||||
<div className={styles.sideBar}>
|
||||
{hotels.length ? (
|
||||
<Link
|
||||
className={styles.link}
|
||||
href={
|
||||
isAlternative
|
||||
? alternativeHotelsMap(lang)
|
||||
: selectHotelMap(lang)
|
||||
}
|
||||
keepSearchParams
|
||||
>
|
||||
<MapWithButtonWrapper>
|
||||
<StaticMap
|
||||
city={city.name}
|
||||
country={isCityWithCountry(city) ? city.country : undefined}
|
||||
width={340}
|
||||
height={200}
|
||||
zoomLevel={11}
|
||||
mapType="roadmap"
|
||||
altText={`Map of ${city.name} city center`}
|
||||
/>
|
||||
</MapWithButtonWrapper>
|
||||
</Link>
|
||||
) : (
|
||||
<div className={styles.mapContainer}>
|
||||
<StaticMap
|
||||
city={city.name}
|
||||
country={isCityWithCountry(city) ? city.country : undefined}
|
||||
width={340}
|
||||
height={200}
|
||||
zoomLevel={11}
|
||||
mapType="roadmap"
|
||||
altText={`Map of ${city.name} city center`}
|
||||
/>
|
||||
</MapWithButtonWrapper>
|
||||
</Link>
|
||||
) : (
|
||||
<div className={styles.mapContainer}>
|
||||
<StaticMap
|
||||
city={city.name}
|
||||
width={340}
|
||||
height={200}
|
||||
zoomLevel={11}
|
||||
mapType="roadmap"
|
||||
altText={`Map of ${city.name} city center`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<HotelFilter filters={filterList} className={styles.filter} />
|
||||
</div>
|
||||
<div className={styles.hotelList}>
|
||||
<NoAvailabilityAlert
|
||||
hotelsLength={hotels.length}
|
||||
isAlternative={isAlternative}
|
||||
isAllUnavailable={isAllUnavailable}
|
||||
operaId={hotels?.[0]?.hotel.operaId}
|
||||
bookingCode={bookingCode}
|
||||
isBookingCodeRateNotAvailable={!isBookingCodeRateAvailable}
|
||||
/>
|
||||
<HotelCardListing hotelData={hotels} isAlternative={isAlternative} />
|
||||
</div>
|
||||
)}
|
||||
<HotelFilter filters={filterList} className={styles.filter} />
|
||||
</div>
|
||||
<div className={styles.hotelList}>
|
||||
<NoAvailabilityAlert
|
||||
hotelsLength={hotels.length}
|
||||
isAlternative={isAlternative}
|
||||
isAllUnavailable={isAllUnavailable}
|
||||
operaId={hotels?.[0]?.hotel.operaId}
|
||||
bookingCode={bookingCode}
|
||||
isBookingCodeRateNotAvailable={!isBookingCodeRateAvailable}
|
||||
/>
|
||||
<HotelCardListing
|
||||
hotelData={hotels}
|
||||
isAlternative={isAlternative}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</>
|
||||
|
||||
@@ -1,14 +1,38 @@
|
||||
.main {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x5);
|
||||
justify-items: center;
|
||||
padding-top: var(--Space-x4);
|
||||
}
|
||||
|
||||
.topSlotContainer {
|
||||
width: var(--max-width-page);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.availabilityContainer {
|
||||
display: flex;
|
||||
background-color: var(--Scandic-Brand-Warm-White);
|
||||
min-height: min(100dvh, 750px);
|
||||
flex-direction: column;
|
||||
max-width: var(--max-width-page);
|
||||
width: var(--max-width-page);
|
||||
margin: 0 auto;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
flex-direction: row;
|
||||
gap: var(--Space-x5);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
padding: var(--Space-x3) 0 var(--Space-x2);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
background-color: var(--Base-Surface-Subtle-Normal);
|
||||
padding: var(--Space-x4) 0 var(--Space-x3);
|
||||
}
|
||||
}
|
||||
|
||||
.headerContent {
|
||||
@@ -17,6 +41,9 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--Space-x2);
|
||||
@media (min-width: 768px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.cityInformation {
|
||||
@@ -28,19 +55,37 @@
|
||||
|
||||
.sorter {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
display: block;
|
||||
width: 339px;
|
||||
}
|
||||
}
|
||||
|
||||
.sideBar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
max-width: 340px;
|
||||
}
|
||||
}
|
||||
|
||||
.sideBarItem {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.link {
|
||||
display: none;
|
||||
|
||||
@media (min-width: 768px) {
|
||||
display: flex;
|
||||
margin-bottom: var(--Space-x6);
|
||||
}
|
||||
}
|
||||
|
||||
.hotelList {
|
||||
@@ -56,59 +101,26 @@
|
||||
|
||||
.skeletonContainer .title {
|
||||
margin-bottom: var(--Space-x3);
|
||||
|
||||
@media (min-width: 768px) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.main {
|
||||
padding: var(--Space-x5) 0;
|
||||
flex-direction: row;
|
||||
gap: var(--Space-x5);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.headerContent {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.header {
|
||||
background-color: var(--Base-Surface-Subtle-Normal);
|
||||
padding: var(--Space-x4) 0 var(--Space-x3);
|
||||
}
|
||||
|
||||
.sorter {
|
||||
display: block;
|
||||
width: 339px;
|
||||
}
|
||||
|
||||
.title {
|
||||
.title {
|
||||
@media (min-width: 768px) {
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
max-width: var(--max-width-navigation);
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
|
||||
.sideBar {
|
||||
max-width: 340px;
|
||||
}
|
||||
|
||||
.sideBarItem {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.filter {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.link {
|
||||
display: flex;
|
||||
margin-bottom: var(--Space-x6);
|
||||
}
|
||||
|
||||
.skeletonContainer .title {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.skeletonContainer .sideBar {
|
||||
gap: var(--Space-x3);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import { getSelectHotelTracking } from "../misc/selectHotelTracking"
|
||||
import { parseSelectHotelSearchParams } from "../utils/url"
|
||||
|
||||
import type { Lang } from "@scandic-hotels/common/constants/language"
|
||||
import type { ReactNode } from "react"
|
||||
|
||||
import type { NextSearchParams } from "../types"
|
||||
|
||||
@@ -23,10 +24,12 @@ export async function SelectHotelPage({
|
||||
lang,
|
||||
searchParams,
|
||||
config,
|
||||
topSlot,
|
||||
}: {
|
||||
lang: Lang
|
||||
searchParams: NextSearchParams
|
||||
config: BookingFlowConfig
|
||||
topSlot?: ReactNode
|
||||
}) {
|
||||
const booking = parseSelectHotelSearchParams(searchParams)
|
||||
|
||||
@@ -111,6 +114,7 @@ export async function SelectHotelPage({
|
||||
hotels={hotels}
|
||||
title={city.name}
|
||||
lang={lang}
|
||||
topSlot={topSlot}
|
||||
/>
|
||||
|
||||
<TrackingSDK hotelInfo={hotelsTrackingData} pageData={pageTrackingData} />
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { Alert } from './index'
|
||||
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert'
|
||||
import { expect, fn } from 'storybook/test'
|
||||
|
||||
const meta: Meta<typeof Alert> = {
|
||||
title: 'Components/Alert',
|
||||
component: Alert,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: ['banner', 'inline'],
|
||||
},
|
||||
type: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(AlertTypeEnum),
|
||||
},
|
||||
close: {
|
||||
table: {
|
||||
disable: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
type: AlertTypeEnum.Info,
|
||||
heading: 'Heading',
|
||||
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.',
|
||||
close: undefined,
|
||||
ariaRole: 'alert',
|
||||
},
|
||||
play: async ({ canvas }) => {
|
||||
canvas.findByRole('alert')
|
||||
},
|
||||
}
|
||||
|
||||
export const Closable: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
type: AlertTypeEnum.Info,
|
||||
heading: 'Heading',
|
||||
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.',
|
||||
close: fn(),
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
expect(args.close).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
|
||||
export const WithPhonenumber: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
type: AlertTypeEnum.Info,
|
||||
heading: 'Heading',
|
||||
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.',
|
||||
close: fn(),
|
||||
phoneContact: {
|
||||
displayText: 'Call us:',
|
||||
phoneNumber: '+4685551234',
|
||||
footnote: 'Available 24/7',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -192,6 +192,8 @@ export function IconByIconName({
|
||||
return <MaterialIcon icon="concierge" {...props} />
|
||||
case IconName.Cultural:
|
||||
return <MaterialIcon icon="theater_comedy" {...props} />
|
||||
case IconName.CreditCard:
|
||||
return <MaterialIcon icon="credit_card" {...props} />
|
||||
case IconName.Diamond:
|
||||
return <MaterialIcon icon="diamond" {...props} />
|
||||
case IconName.Directions:
|
||||
|
||||
@@ -7,9 +7,9 @@ export enum IconName {
|
||||
AirConditioningInRoom = 'AirConditioningInRoom',
|
||||
Airplane = 'Airplane',
|
||||
ArmChair = 'ArmChair',
|
||||
ArrowFrom = 'ArrowFrom',
|
||||
ArrowLeft = 'ArrowLeft',
|
||||
ArrowLeftSmall = 'ArrowLeftSmall',
|
||||
ArrowFrom = 'ArrowFrom',
|
||||
ArrowRight = 'ArrowRight',
|
||||
ArrowRightSmall = 'ArrowRightSmall',
|
||||
ArrowTo = 'ArrowTo',
|
||||
@@ -22,6 +22,7 @@ export enum IconName {
|
||||
Bike = 'Bike',
|
||||
Bouquet = 'Bouquet',
|
||||
Bowling = 'Bowling',
|
||||
Breakfast = 'Breakfast',
|
||||
Business = 'Business',
|
||||
BusinessCentre = 'BusinessCentre',
|
||||
Calendar = 'Calendar',
|
||||
@@ -51,6 +52,7 @@ export enum IconName {
|
||||
ConferenceRoom = 'ConferenceRoom',
|
||||
ConvenienceStore24h = 'ConvenienceStore24h',
|
||||
ConventionCentre = 'ConventionCentre',
|
||||
CreditCard = 'CreditCard',
|
||||
CroissantCoffeeEgg = 'CroissantCoffeeEgg',
|
||||
CrossCircle = 'CrossCircle',
|
||||
CrossCircleOutline = 'CrossCircleOutline',
|
||||
@@ -92,8 +94,8 @@ export enum IconName {
|
||||
HandKey = 'HandKey',
|
||||
Hanger = 'Hanger',
|
||||
HangerAlt = 'HangerAlt',
|
||||
Heat = 'Heat',
|
||||
Heart = 'Heart',
|
||||
Heat = 'Heat',
|
||||
Hiking = 'Hiking',
|
||||
HotelNight = 'HotelNight',
|
||||
House = 'House',
|
||||
@@ -108,15 +110,15 @@ export enum IconName {
|
||||
Kettle = 'Kettle',
|
||||
Kids = 'Kids',
|
||||
KidsMocktail = 'KidsMocktail',
|
||||
Landscape = 'Landscape',
|
||||
Kitchen = 'Kitchen',
|
||||
Lamp = 'Lamp',
|
||||
Landscape = 'Landscape',
|
||||
LaptopSafe = 'LaptopSafe',
|
||||
LaundryMachine = 'LaundryMachine',
|
||||
Link = 'Link',
|
||||
LocalBar = 'LocalBar',
|
||||
Location = 'Location',
|
||||
Lock = 'Lock',
|
||||
Breakfast = 'Breakfast',
|
||||
Luggage = 'Luggage',
|
||||
LuggageLockers = 'LuggageLockers',
|
||||
MagicWand = 'MagicWand',
|
||||
@@ -163,11 +165,11 @@ export enum IconName {
|
||||
StarFilled = 'StarFilled',
|
||||
Street = 'Street',
|
||||
Swim = 'Swim',
|
||||
Theatre = 'Theatre',
|
||||
Swipe = 'Swipe',
|
||||
Theatre = 'Theatre',
|
||||
Thermostat = 'Thermostat',
|
||||
Toilet = 'Toilet',
|
||||
Ticket = 'Ticket',
|
||||
Toilet = 'Toilet',
|
||||
Train = 'Train',
|
||||
Tripadvisor = 'Tripadvisor',
|
||||
Trophy = 'Trophy',
|
||||
@@ -179,5 +181,4 @@ export enum IconName {
|
||||
WarningTriangle = 'WarningTriangle',
|
||||
Wheelchair = 'Wheelchair',
|
||||
Wifi = 'Wifi',
|
||||
Kitchen = 'Kitchen',
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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',
|
||||
},
|
||||
}
|
||||
57
packages/design-system/lib/components/InfoBox/InfoBox.tsx
Normal file
57
packages/design-system/lib/components/InfoBox/InfoBox.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -137,6 +137,7 @@
|
||||
"./ImageContainer": "./lib/components/ImageContainer/index.tsx",
|
||||
"./ImageFallback": "./lib/components/ImageFallback/index.tsx",
|
||||
"./ImageGallery": "./lib/components/ImageGallery/index.tsx",
|
||||
"./InfoBox": "./lib/components/InfoBox/InfoBox.tsx",
|
||||
"./InfoCard": "./lib/components/InfoCard/index.tsx",
|
||||
"./Input": "./lib/components/Input/index.tsx",
|
||||
"./JsonToHtml": "./lib/components/JsonToHtml/JsonToHtml.tsx",
|
||||
|
||||
Reference in New Issue
Block a user