Merged in fix/SW-415-ui-fixes (pull request #867)

Fix/SW-415 ui fixes on Room Card

Approved-by: Niclas Edenvin
This commit is contained in:
Pontus Dreij
2024-11-10 20:00:55 +00:00
10 changed files with 111 additions and 83 deletions

View File

@@ -114,7 +114,7 @@ export default function RoomFilter({
/>
))}
<Tooltip text={tooltipText} position="bottom" arrow="right">
<InfoCircleIcon className={styles.infoIcon} />
<InfoCircleIcon color="uiTextPlaceholder" />
</Tooltip>
</div>
</form>

View File

@@ -12,11 +12,6 @@
align-items: center;
}
.roomsFilter .infoIcon,
.roomsFilter .infoIcon path {
stroke: var(--UI-Text-Medium-contrast);
fill: transparent;
}
.filterInfo {
display: flex;
flex-direction: row;

View File

@@ -1,6 +1,11 @@
.priceList {
margin: 0;
}
.priceRow {
display: flex;
justify-content: space-between;
align-items: baseline;
padding: var(--Spacing-x-quarter) 0;
}

View File

@@ -3,6 +3,7 @@
border-radius: var(--Corner-radius-Large);
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
background-color: var(--Base-Surface-Secondary-light-Normal);
border: 1px solid var(--Base-Surface-Secondary-light-Normal);
position: relative;
display: flex;
flex-direction: column;
@@ -22,6 +23,13 @@
background-color: var(--Base-Surface-Primary-light-Hover-alt);
}
.checkIcon {
width: 24px;
height: 24px;
border-radius: 100px;
background-color: var(--UI-Input-Controls-Fill-Selected);
border: 2px solid var(--Base-Border-Inverted);
justify-content: center;
align-items: center;
display: none;
}
input[type="radio"]:checked + .card {
@@ -29,7 +37,7 @@ input[type="radio"]:checked + .card {
background-color: var(--Base-Surface-Primary-light-Hover-alt);
}
input[type="radio"]:checked + .card .checkIcon {
display: block;
display: flex;
position: absolute;
top: -10px;
right: -10px;
@@ -40,12 +48,6 @@ input[type="radio"]:checked + .card .checkIcon {
gap: var(--Spacing-x-half);
}
.header .infoIcon,
.header .infoIcon path {
stroke: var(--UI-Text-Medium-contrast);
fill: transparent;
}
.button {
background: none;
border: none;
@@ -53,7 +55,11 @@ input[type="radio"]:checked + .card .checkIcon {
grid-area: chevron;
height: 100%;
justify-self: flex-end;
padding: 0;
padding: 1px 0 0 0;
}
.button:focus {
outline: none;
}
.popover {

View File

@@ -1,8 +1,8 @@
"use client"
import { useState } from "react"
import { Button, DialogTrigger } from "react-aria-components"
import { useRef, useState } from "react"
import { Button } from "react-aria-components"
import { CheckCircleIcon, InfoCircleIcon } from "@/components/Icons"
import { CheckIcon, InfoCircleIcon } from "@/components/Icons"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import PricePopover from "./Popover"
@@ -25,6 +25,8 @@ export default function FlexibilityOption({
}: FlexibilityOptionProps) {
const [rootDiv, setRootDiv] = useState<Element | undefined>(undefined)
const [isPopoverOpen, setIsPopoverOpen] = useState(false)
let triggerRef = useRef<HTMLButtonElement>(null)
const buttonClickedRef = useRef(false)
function setRef(node: Element | null) {
if (node) {
@@ -36,7 +38,7 @@ export default function FlexibilityOption({
return (
<div className={styles.disabledCard}>
<div className={styles.header}>
<InfoCircleIcon className={styles.infoIcon} />
<InfoCircleIcon width={16} height={16} color="uiTextMediumContrast" />
<Caption color="disabled">{name}</Caption>
<Caption color="disabled">({paymentTerm})</Caption>
</div>
@@ -59,6 +61,15 @@ export default function FlexibilityOption({
handleSelectRate(rate)
}
function togglePopover() {
buttonClickedRef.current = !buttonClickedRef.current
setIsPopoverOpen(buttonClickedRef.current)
}
function handlePopoverChange(isOpen: boolean) {
setIsPopoverOpen(isOpen)
}
return (
<label>
<input
@@ -69,48 +80,54 @@ export default function FlexibilityOption({
/>
<div className={styles.card}>
<div className={styles.header} ref={setRef}>
<DialogTrigger>
<Button
aria-label="Help"
className={styles.button}
onPress={() => setIsPopoverOpen(true)}
>
<InfoCircleIcon className={styles.infoIcon} />
</Button>
<PricePopover
placement="bottom"
className={styles.popover}
isNonModal
shouldFlip={false}
shouldUpdatePosition={false}
/**
* react-aria uses portals to render Popover in body
* unless otherwise specified. We need it to be contained
* by this component to both access css variables assigned
* on the container as well as to not overflow it at any time.
*/
UNSTABLE_portalContainer={rootDiv}
isOpen={isPopoverOpen}
onOpenChange={setIsPopoverOpen}
<Button
aria-label="Help"
className={styles.button}
onPress={() => {
togglePopover()
}}
ref={triggerRef}
>
<InfoCircleIcon
width={16}
height={16}
color="uiTextMediumContrast"
/>
</Button>
<PricePopover
placement="bottom"
className={styles.popover}
isNonModal
shouldFlip={false}
shouldUpdatePosition={false}
/**
* react-aria uses portals to render Popover in body
* unless otherwise specified. We need it to be contained
* by this component to both access css variables assigned
* on the container as well as to not overflow it at any time.
*/
UNSTABLE_portalContainer={rootDiv}
triggerRef={triggerRef}
isOpen={isPopoverOpen}
onOpenChange={handlePopoverChange}
>
<Caption
color="uiTextHighContrast"
type="bold"
className={styles.popoverHeading}
>
{name}
</Caption>
{priceInformation?.map((info) => (
<Caption
key={info}
color="uiTextHighContrast"
type="bold"
className={styles.popoverHeading}
className={styles.popoverText}
>
{name}
{info}
</Caption>
{priceInformation?.map((info) => (
<Caption
key={info}
color="uiTextHighContrast"
className={styles.popoverText}
>
{info}
</Caption>
))}
</PricePopover>
</DialogTrigger>
))}
</PricePopover>
<Caption color="uiTextHighContrast">{name}</Caption>
<Caption color="uiTextPlaceholder">({paymentTerm})</Caption>
</div>
@@ -119,13 +136,10 @@ export default function FlexibilityOption({
memberPrice={memberPrice}
petRoomPackage={petRoomPackage}
/>
<CheckCircleIcon
color="blue"
className={styles.checkIcon}
width={24}
height={24}
stroke="white"
/>
<div className={styles.checkIcon}>
<CheckIcon color="white" height="16" width="16" />
</div>
</div>
</label>
)

View File

@@ -88,25 +88,30 @@ export default function RoomCard({
: `${roomSize?.min}-${roomSize?.max}`}
m²
</Caption>
{roomConfiguration.roomTypeCode && (
<ToggleSidePeek
hotelId={hotelId}
roomTypeCode={roomConfiguration.roomTypeCode}
/>
)}
<div className={styles.toggleSidePeek}>
{roomConfiguration.roomTypeCode && (
<ToggleSidePeek
hotelId={hotelId}
roomTypeCode={roomConfiguration.roomTypeCode}
/>
)}
</div>
</div>
<div className={styles.container}>
<div className={styles.roomDetails}>
<Subtitle className={styles.name} type="two">
{roomConfiguration.roomType}
</Subtitle>
{/* Out of scope for now
<Body>{descriptions?.short}</Body>
*/}
<Caption color="uiTextHighContrast" type="bold">
{intl.formatMessage({
id: "Breakfast selection in next step.",
})}
</Caption>
</div>
<Caption color="uiTextHighContrast">
{intl.formatMessage({
id: "Breakfast selection in next step.",
})}
</Caption>
<div className={styles.flexibilityOptions}>
{Object.entries(rates).map(([key, rate]) => (
<FlexibilityOption

View File

@@ -27,24 +27,21 @@
padding-right: var(--Spacing-x1);
}
.specification .button {
.toggleSidePeek {
margin-left: auto;
padding: 0 0 0 var(--Spacing-x-half);
text-decoration: none;
}
.container {
padding: var(--Spacing-x1) var(--Spacing-x2) var(--Spacing-x2);
display: flex;
flex-direction: column;
gap: var(--Spacing-x2);
gap: var(--Spacing-x-one-and-half);
}
.roomDetails {
display: flex;
flex-direction: column;
gap: var(--Spacing-x1);
margin-bottom: var(--Spacing-x2);
gap: var(--Spacing-x2);
}
.name {