diff --git a/components/ContentType/HotelPage/CardContainer/cardContainer.module.css b/components/ContentType/HotelPage/CardContainer/cardContainer.module.css new file mode 100644 index 000000000..9636d90d5 --- /dev/null +++ b/components/ContentType/HotelPage/CardContainer/cardContainer.module.css @@ -0,0 +1,15 @@ +.cardContainer { + display: grid; + gap: var(--Spacing-x3); + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); +} + +.cardContainer.twoColumns { + grid-template-columns: repeat(2, 1fr); +} +.cardContainer.threeColumns { + grid-template-columns: repeat(3, 1fr); +} +.cardContainer.fourColumns { + grid-template-columns: repeat(4, 1fr); +} diff --git a/components/ContentType/HotelPage/CardContainer/cardContainer.ts b/components/ContentType/HotelPage/CardContainer/cardContainer.ts new file mode 100644 index 000000000..51f0c7775 --- /dev/null +++ b/components/ContentType/HotelPage/CardContainer/cardContainer.ts @@ -0,0 +1,7 @@ +import { VariantProps } from "class-variance-authority" + +import { cardContainerVariants } from "./variants" + +export interface CardContainerProps + extends React.PropsWithChildren>, + VariantProps {} diff --git a/components/ContentType/HotelPage/CardContainer/index.tsx b/components/ContentType/HotelPage/CardContainer/index.tsx new file mode 100644 index 000000000..f65e5981d --- /dev/null +++ b/components/ContentType/HotelPage/CardContainer/index.tsx @@ -0,0 +1,18 @@ +import { CardContainerProps } from "./cardContainer" +import { cardContainerVariants } from "./variants" + +export function CardContainer({ + children, + className, + columns, + ...props +}: CardContainerProps) { + return ( +
+ {children} +
+ ) +} diff --git a/components/ContentType/HotelPage/CardContainer/variants.ts b/components/ContentType/HotelPage/CardContainer/variants.ts new file mode 100644 index 000000000..a7599adb0 --- /dev/null +++ b/components/ContentType/HotelPage/CardContainer/variants.ts @@ -0,0 +1,16 @@ +import { cva } from "class-variance-authority" + +import styles from "./cardContainer.module.css" + +export const cardContainerVariants = cva(styles.cardContainer, { + variants: { + columns: { + 2: styles.twoColumns, + 3: styles.threeColumns, + 4: styles.fourColumns, + }, + }, + defaultVariants: { + columns: 3, + }, +}) diff --git a/components/ContentType/HotelPage/RoomCard/index.tsx b/components/ContentType/HotelPage/RoomCard/index.tsx new file mode 100644 index 000000000..4e4bd5c86 --- /dev/null +++ b/components/ContentType/HotelPage/RoomCard/index.tsx @@ -0,0 +1,52 @@ +"use client" + +import { ImageIcon } from "@/components/Icons" +import Image from "@/components/Image" +import Body from "@/components/TempDesignSystem/Text/Body" +import Title from "@/components/TempDesignSystem/Text/Title" + +import { RoomCardProps } from "./roomCard" + +import styles from "./roomCard.module.css" + +export function RoomCard({ + badgeText, + title, + subtitle, + cta, + image, + imageCount, + imageClick, +}: RoomCardProps) { + return ( +
+ +
+
+ + {title} + + {subtitle} +
+ +
+
+ ) +} diff --git a/components/ContentType/HotelPage/RoomCard/roomCard.module.css b/components/ContentType/HotelPage/RoomCard/roomCard.module.css new file mode 100644 index 000000000..f616a6767 --- /dev/null +++ b/components/ContentType/HotelPage/RoomCard/roomCard.module.css @@ -0,0 +1,90 @@ +.roomCard { + border-radius: var(--Corner-radius-Medium); + background-color: var(--Base-Surface-Primary-Normal); + border: 1px solid var(--Base-Border-Subtle); + display: grid; +} + +.badge { + position: absolute; + top: var(--Spacing-x1); + left: var(--Spacing-x1); + background-color: var(--Scandic-Blue-100); + padding: var(--Spacing-x-half) var(--Spacing-x1); + border-radius: var(--Corner-radius-Medium); + color: var(--Tertiary-Dark-On-Surface-Text, #fff0c2); + text-transform: uppercase; + font-family: var(--typography-Title-5-fontFamily); + font-size: var(--typography-Footnote-Regular-fontSize); + font-weight: var(--typography-Footnote-Regular-fontWeight); +} + +.imageCount { + position: absolute; + right: var(--Spacing-x1); + bottom: var(--Spacing-x1); + display: flex; + gap: var(--Spacing-x-half); + align-items: center; + background-color: color-mix( + in srgb, + var(--Scandic-Beige-80) 80%, + transparent + ); + color: white; + padding: var(--Spacing-x-half) var(--Spacing-x1); + border-radius: var(--Corner-radius-Medium); +} + +.content { + display: grid; + justify-items: center; + gap: var(--Spacing-x-one-and-half); + padding: var(--Spacing-x2); +} + +.innerContent { + display: grid; + justify-items: center; + gap: var(--Spacing-x1); +} + +.imageWrapper { + position: relative; + background-color: transparent; + border-width: 0; + cursor: pointer; + margin: 0; + padding: 0; + display: flex; +} + +.image { + width: 100%; + object-fit: cover; + border-top-left-radius: var(--Corner-radius-Medium); + border-top-right-radius: var(--Corner-radius-Medium); +} + +.subtitle { + color: var(--UI-Text-Placeholder, #787472); +} + +.cta { + background-color: transparent; + border-width: 0; + cursor: pointer; + margin: 0; + padding: 0; + display: flex; + align-items: center; + gap: var(--Spacing-x-half); + color: var(--Base-Text-Medium-contrast, #8f4350); + font-family: var(--typography-Body-Bold-fontFamily); + font-size: var(--typography-Body-Bold-fontSize); + font-weight: 600; + text-decoration: underline; +} +.cta:hover { + color: var(--Base-Text-High-contrast, #4d001b); +} diff --git a/components/ContentType/HotelPage/RoomCard/roomCard.ts b/components/ContentType/HotelPage/RoomCard/roomCard.ts new file mode 100644 index 000000000..0d174f46f --- /dev/null +++ b/components/ContentType/HotelPage/RoomCard/roomCard.ts @@ -0,0 +1,16 @@ +import { ImageProps } from "next/image" + +interface RoomCardCtaProps { + text: string + callback: () => void +} + +export interface RoomCardProps { + image: ImageProps + imageCount: number + imageClick: () => void + title: string + subtitle: string + cta: RoomCardCtaProps + badgeText?: string +} diff --git a/components/Icons/Camera.tsx b/components/Icons/Camera.tsx new file mode 100644 index 000000000..bed8a79e6 --- /dev/null +++ b/components/Icons/Camera.tsx @@ -0,0 +1,23 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function CameraIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + ) +} diff --git a/components/Icons/Image.tsx b/components/Icons/Image.tsx new file mode 100644 index 000000000..9fcfe4a71 --- /dev/null +++ b/components/Icons/Image.tsx @@ -0,0 +1,36 @@ +import { iconVariants } from "./variants" + +import type { IconProps } from "@/types/components/icon" + +export default function ImageIcon({ className, color, ...props }: IconProps) { + const classNames = iconVariants({ className, color }) + return ( + + + + + + + + + ) +} diff --git a/components/Icons/get-icon-by-icon-name.ts b/components/Icons/get-icon-by-icon-name.ts index ae2534a5d..897ca8b28 100644 --- a/components/Icons/get-icon-by-icon-name.ts +++ b/components/Icons/get-icon-by-icon-name.ts @@ -7,6 +7,7 @@ import { BarIcon, BikingIcon, CalendarIcon, + CameraIcon, CellphoneIcon, CheckCircleIcon, CheckIcon, @@ -21,6 +22,7 @@ import { FitnessIcon, GlobeIcon, HouseIcon, + ImageIcon, InfoCircleIcon, LocationIcon, LockIcon, @@ -51,6 +53,8 @@ export function getIconByIconName(icon?: IconName): FC | null { return BikingIcon case IconName.Calendar: return CalendarIcon + case IconName.Camera: + return CameraIcon case IconName.Cellphone: return CellphoneIcon case IconName.Check: @@ -79,6 +83,8 @@ export function getIconByIconName(icon?: IconName): FC | null { return GlobeIcon case IconName.House: return HouseIcon + case IconName.Image: + return ImageIcon case IconName.InfoCircle: return InfoCircleIcon case IconName.Location: diff --git a/components/Icons/icon.module.css b/components/Icons/icon.module.css index 73b8f38a3..bc8715040 100644 --- a/components/Icons/icon.module.css +++ b/components/Icons/icon.module.css @@ -41,3 +41,8 @@ .red * { fill: var(--Scandic-Brand-Scandic-Red); } + +.white, +.white * { + fill: var(--Scandic-Opacity-White-100); +} diff --git a/components/Icons/index.tsx b/components/Icons/index.tsx index a69a2a77e..07c9b7016 100644 --- a/components/Icons/index.tsx +++ b/components/Icons/index.tsx @@ -4,6 +4,7 @@ export { default as ArrowRightIcon } from "./ArrowRight" export { default as BarIcon } from "./Bar" export { default as BikingIcon } from "./Biking" export { default as CalendarIcon } from "./Calendar" +export { default as CameraIcon } from "./Camera" export { default as CellphoneIcon } from "./Cellphone" export { default as CheckIcon } from "./Check" export { default as CheckCircleIcon } from "./CheckCircle" @@ -18,6 +19,7 @@ export { default as EmailIcon } from "./Email" export { default as FitnessIcon } from "./Fitness" export { default as GlobeIcon } from "./Globe" export { default as HouseIcon } from "./House" +export { default as ImageIcon } from "./Image" export { default as InfoCircleIcon } from "./InfoCircle" export { default as LocationIcon } from "./Location" export { default as LockIcon } from "./Lock" diff --git a/components/Icons/variants.ts b/components/Icons/variants.ts index e39422ece..39e4ff51e 100644 --- a/components/Icons/variants.ts +++ b/components/Icons/variants.ts @@ -13,6 +13,7 @@ const config = { primaryLightOnSurfaceAccent: styles.plosa, red: styles.red, green: styles.green, + white: styles.white, }, }, defaultVariants: { diff --git a/components/TempDesignSystem/Text/Body/body.module.css b/components/TempDesignSystem/Text/Body/body.module.css index 2176cf473..6a547fd9c 100644 --- a/components/TempDesignSystem/Text/Body/body.module.css +++ b/components/TempDesignSystem/Text/Body/body.module.css @@ -50,6 +50,10 @@ color: var(--Scandic-Brand-Burgundy); } +.grey { + color: var(--UI-Text-Placeholder, #787472); +} + .pale { color: var(--Scandic-Brand-Pale-Peach); } diff --git a/components/TempDesignSystem/Text/Body/variants.ts b/components/TempDesignSystem/Text/Body/variants.ts index 96d36937e..d044b4286 100644 --- a/components/TempDesignSystem/Text/Body/variants.ts +++ b/components/TempDesignSystem/Text/Body/variants.ts @@ -7,6 +7,7 @@ const config = { color: { black: styles.black, burgundy: styles.burgundy, + grey: styles.grey, pale: styles.pale, red: styles.red, textMediumContrast: styles.textMediumContrast, diff --git a/types/components/icon.ts b/types/components/icon.ts index e340e9aff..ff76c28eb 100644 --- a/types/components/icon.ts +++ b/types/components/icon.ts @@ -13,6 +13,7 @@ export enum IconName { Bar = "Bar", Biking = "Biking", Calendar = "Calendar", + Camera = "Camera", Cellphone = "Cellphone", Check = "Check", CheckCircle = "CheckCircle", @@ -27,6 +28,7 @@ export enum IconName { Fitness = "Fitness", Globe = "Globe", House = "House", + Image = "Image", InfoCircle = "InfoCircle", Location = "Location", Lock = "Lock",