Merged in chore/SW-3145-move-radio-card (pull request #2533)

chore: SW-3145 Moved RadioCard to design system

* chore: SW-3145 Moved RadioCard to design system

* chore: SW-3145 Optimized code

* chore: SW-3145 Optimized code


Approved-by: Anton Gunnarsson
This commit is contained in:
Hrishikesh Vaipurkar
2025-07-08 08:25:00 +00:00
parent a68072d2f6
commit 8ae251635d
6 changed files with 18 additions and 16 deletions

View File

@@ -4,10 +4,11 @@ import { zodResolver } from "@hookform/resolvers/zod"
import { useCallback, useEffect, useState } from "react"
import { FormProvider, useForm } from "react-hook-form"
import RadioCard from "@scandic-hotels/design-system/Form/RadioCard"
import { BED_TYPE_ICONS } from "@/constants/booking"
import { useEnterDetailsStore } from "@/stores/enter-details"
import RadioCard from "@/components/TempDesignSystem/Form/RadioCard"
import { useRoomContext } from "@/contexts/Details/Room"
import { trackBedSelection } from "@/utils/tracking"

View File

@@ -6,13 +6,13 @@ import { FormProvider, useForm } from "react-hook-form"
import { useIntl } from "react-intl"
import Body from "@scandic-hotels/design-system/Body"
import RadioCard from "@scandic-hotels/design-system/Form/RadioCard"
import BreakfastBuffetIcon from "@scandic-hotels/design-system/Icons/BreakfastBuffetIcon"
import NoBreakfastBuffetIcon from "@scandic-hotels/design-system/Icons/NoBreakfastBuffetIcon"
import { BreakfastPackageEnum } from "@scandic-hotels/trpc/enums/breakfast"
import { useEnterDetailsStore } from "@/stores/enter-details"
import RadioCard from "@/components/TempDesignSystem/Form/RadioCard"
import { useRoomContext } from "@/contexts/Details/Room"
import { formatPrice } from "@/utils/numberFormatting"
import { trackBreakfastSelection } from "@/utils/tracking"

View File

@@ -1,110 +0,0 @@
"use client"
import { cx } from "class-variance-authority"
import { useFormContext } from "react-hook-form"
import { Divider } from "@scandic-hotels/design-system/Divider"
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
import { Typography } from "@scandic-hotels/design-system/Typography"
import styles from "./radioCard.module.css"
import type { RadioCardProps } from "./types"
export default function RadioCard({
Icon,
iconHeight = 32,
id,
name,
title,
subtitleSecondary,
subtitle,
value,
disabled = false,
description,
descriptionSecondary,
}: RadioCardProps) {
const { register, setValue } = useFormContext()
function onLabelClick(event: React.MouseEvent) {
// Preventing click event on label elements firing twice: https://github.com/facebook/react/issues/14295
event.preventDefault()
if (!disabled) {
setValue(name, value)
}
}
function onKeyDown(event: React.KeyboardEvent) {
if (disabled) return
if (event.key === "Enter") {
setValue(name, value)
}
}
return (
<label
className={cx(styles.label, { [styles.disabled]: disabled })}
onClick={onLabelClick}
onKeyDown={onKeyDown}
tabIndex={0}
>
<div className={styles.selectedIcon}>
<MaterialIcon icon="check" size={22} color="Icon/Inverted" />
</div>
{Icon ? (
<Icon
className={styles.icon}
color="CurrentColor"
height={iconHeight}
/>
) : null}
<Typography variant="Body/Paragraph/mdBold" className={styles.title}>
<p>{title}</p>
</Typography>
{subtitleSecondary ? (
<Typography
variant="Body/Supporting text (caption)/smRegular"
className={styles.subtitleSecondary}
>
<p>{subtitleSecondary}</p>
</Typography>
) : null}
<Typography variant="Body/Paragraph/mdBold" className={styles.subtitle}>
<p>{subtitle}</p>
</Typography>
{description || descriptionSecondary ? (
<Divider className={styles.divider} />
) : null}
{description ? (
<Typography
variant="Body/Supporting text (caption)/smRegular"
className={styles.description}
>
<p>{description}</p>
</Typography>
) : null}
{descriptionSecondary ? (
<Typography
variant="Body/Supporting text (caption)/smRegular"
className={styles.descriptionSecondary}
>
<p>{descriptionSecondary}</p>
</Typography>
) : null}
<input
{...register(name)}
aria-hidden
id={id || name}
hidden
type="radio"
disabled={disabled}
value={value}
/>
</label>
)
}

View File

@@ -1,87 +0,0 @@
.label {
position: relative;
cursor: pointer;
display: grid;
grid-template-columns: 1fr auto;
grid-auto-rows: min-content;
grid-template-areas:
"icon subtitleSecondary"
"title subtitle";
border-radius: var(--Corner-radius-md);
border: 1px solid var(--Border-Intense);
background: var(--Surface-Primary-Default);
padding: var(--Space-x2) var(--Space-x3);
gap: var(--Space-x1);
transition:
background 0.2s ease,
border-color 0.2s ease;
}
.label:hover:not(.disabled) {
background: var(--Surface-Primary-Hover);
}
.label.disabled {
background: var(--Surface-Primary-Disabled);
filter: grayscale(1);
opacity: 0.5;
cursor: not-allowed;
}
.label:has(:checked) {
border: 2px solid var(--Border-Interactive-Selected);
}
.label:not(:has(:checked)) .selectedIcon {
display: none;
}
.selectedIcon {
position: absolute;
top: calc(-1 * var(--Space-x15));
right: calc(-1 * var(--Space-x15));
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border: 2px solid var(--Base-Border-Inverted);
border-radius: var(--Corner-radius-rounded);
background-color: var(--Surface-Feedback-Succes-Accent);
}
.icon {
grid-area: icon;
}
.title {
grid-area: title;
color: var(--Text-Default);
}
.subtitle {
grid-area: subtitle;
color: var(--Text-Default);
justify-self: end;
}
.subtitleSecondary {
grid-area: subtitleSecondary;
place-self: end;
color: var(--Text-Default);
}
.divider {
grid-column: 1 / -1;
margin: var(--Space-x1) 0;
}
.description {
grid-column: 1 / -1;
color: var(--Text-Default);
}
.descriptionSecondary {
grid-column: 1 / -1;
color: var(--Text-Secondary);
}

View File

@@ -1,16 +0,0 @@
import type { IconProps } from "@scandic-hotels/design-system/Icons"
import type { JSX } from "react"
export interface RadioCardProps
extends Omit<React.LabelHTMLAttributes<HTMLLabelElement>, "title"> {
Icon?: (props: IconProps) => JSX.Element
iconHeight?: number
name: string
subtitle: React.ReactNode
subtitleSecondary?: React.ReactNode
title: React.ReactNode
value?: string
disabled?: boolean
description?: React.ReactNode
descriptionSecondary?: React.ReactNode
}