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:
@@ -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"
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user