feat: SW-276 SW-565 Updated UI
This commit is contained in:
@@ -1,9 +1,15 @@
|
|||||||
.container {
|
.container {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(4, auto);
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.counterContainer {
|
||||||
.textCenter {
|
display: flex;
|
||||||
text-align: center;
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.counterBtn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import { useIntl } from "react-intl"
|
|||||||
|
|
||||||
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
||||||
|
|
||||||
|
import { MinusIcon, PlusIcon } from "@/components/Icons"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
|
||||||
import styles from "./adult-selector.module.css"
|
import styles from "./adult-selector.module.css"
|
||||||
@@ -50,26 +52,42 @@ export default function AdultSelector({ roomIndex = 0 }: AdultSelectorProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className={styles.container}>
|
<section className={styles.container}>
|
||||||
<Caption>{adultsLabel}</Caption>
|
<Caption color="uiTextHighContrast" textTransform="bold">
|
||||||
<Button
|
{adultsLabel}
|
||||||
onClick={() => {
|
</Caption>
|
||||||
decreaseAdultsCount(roomIndex)
|
<div className={styles.counterContainer}>
|
||||||
}}
|
<Button
|
||||||
intent="text"
|
className={styles.counterBtn}
|
||||||
size="small"
|
intent="elevated"
|
||||||
>
|
onClick={() => {
|
||||||
-
|
decreaseAdultsCount(roomIndex)
|
||||||
</Button>
|
}}
|
||||||
<span className={styles.textCenter}>{adults}</span>
|
size="small"
|
||||||
<Button
|
theme="base"
|
||||||
onClick={() => {
|
variant="icon"
|
||||||
increaseAdultsCount(roomIndex)
|
wrapping={true}
|
||||||
}}
|
disabled={adults == 1}
|
||||||
intent="text"
|
>
|
||||||
size="small"
|
<MinusIcon color="burgundy" />
|
||||||
>
|
</Button>
|
||||||
+
|
<Body color="textHighContrast" textAlign="center">
|
||||||
</Button>
|
{adults}
|
||||||
|
</Body>
|
||||||
|
<Button
|
||||||
|
className={styles.counterBtn}
|
||||||
|
onClick={() => {
|
||||||
|
increaseAdultsCount(roomIndex)
|
||||||
|
}}
|
||||||
|
intent="elevated"
|
||||||
|
variant="icon"
|
||||||
|
theme="base"
|
||||||
|
wrapping={true}
|
||||||
|
size="small"
|
||||||
|
disabled={adults == 6}
|
||||||
|
>
|
||||||
|
<PlusIcon color="burgundy" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,15 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
import { useFormContext } from "react-hook-form"
|
import { useFormContext } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
||||||
|
|
||||||
|
import { ErrorCircleIcon } from "@/components/Icons"
|
||||||
import Select from "@/components/TempDesignSystem/Select"
|
import Select from "@/components/TempDesignSystem/Select"
|
||||||
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
|
||||||
|
import styles from "./child-selector.module.css"
|
||||||
|
|
||||||
import { BedTypeEnum } from "@/types/components/bookingWidget/enums"
|
import { BedTypeEnum } from "@/types/components/bookingWidget/enums"
|
||||||
import {
|
import {
|
||||||
@@ -96,36 +102,43 @@ export default function ChildInfoSelector({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>
|
<div key={index} className={styles.childInfoContainer}>
|
||||||
<Select
|
<div>
|
||||||
required={true}
|
|
||||||
items={ageList}
|
|
||||||
label={ageLabel}
|
|
||||||
aria-label={ageLabel}
|
|
||||||
value={child.age}
|
|
||||||
onSelect={(key) => {
|
|
||||||
updateSelectedAge(parseInt(key.toString()))
|
|
||||||
}}
|
|
||||||
name={`rooms.${roomIndex}.children.${index}.age`}
|
|
||||||
placeholder={ageLabel}
|
|
||||||
/>
|
|
||||||
{isValidated && child.age < 0 ? <span>{ageReqdErrMsg}</span> : null}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
{child.age !== -1 ? (
|
|
||||||
<Select
|
<Select
|
||||||
items={getAvailableBeds(child.age)}
|
required={true}
|
||||||
label={bedLabel}
|
items={ageList}
|
||||||
aria-label={bedLabel}
|
label={ageLabel}
|
||||||
value={child.bed}
|
aria-label={ageLabel}
|
||||||
|
value={child.age}
|
||||||
onSelect={(key) => {
|
onSelect={(key) => {
|
||||||
updateSelectedBed(parseInt(key.toString()))
|
updateSelectedAge(parseInt(key.toString()))
|
||||||
}}
|
}}
|
||||||
name={`rooms.${roomIndex}.children.${index}.age`}
|
name={`rooms.${roomIndex}.children.${index}.age`}
|
||||||
placeholder={bedLabel}
|
placeholder={ageLabel}
|
||||||
/>
|
/>
|
||||||
) : null}
|
</div>
|
||||||
|
<div>
|
||||||
|
{child.age !== -1 ? (
|
||||||
|
<Select
|
||||||
|
items={getAvailableBeds(child.age)}
|
||||||
|
label={bedLabel}
|
||||||
|
aria-label={bedLabel}
|
||||||
|
value={child.bed}
|
||||||
|
onSelect={(key) => {
|
||||||
|
updateSelectedBed(parseInt(key.toString()))
|
||||||
|
}}
|
||||||
|
name={`rooms.${roomIndex}.children.${index}.age`}
|
||||||
|
placeholder={bedLabel}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{isValidated && child.age < 0 ? (
|
||||||
|
<Caption color="red" className={styles.error}>
|
||||||
|
<ErrorCircleIcon color="red" />
|
||||||
|
{intl.formatMessage({ id: "Child age is required" })}
|
||||||
|
</Caption>
|
||||||
|
) : null}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,21 @@
|
|||||||
.container {
|
.container {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(4, auto);
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.captionBold {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
.counterContainer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.counterBtn {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
.childInfoContainer {
|
.childInfoContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -10,6 +23,8 @@
|
|||||||
grid-template-columns: 1fr 2fr;
|
grid-template-columns: 1fr 2fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
.textCenter {
|
.error {
|
||||||
text-align: center;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: var(--Spacing-x1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
import { useFormContext } from "react-hook-form"
|
import { useFormContext } from "react-hook-form"
|
||||||
import { useIntl } from "react-intl"
|
import { useIntl } from "react-intl"
|
||||||
|
|
||||||
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
||||||
|
|
||||||
|
import { MinusIcon, PlusIcon } from "@/components/Icons"
|
||||||
import Button from "@/components/TempDesignSystem/Button"
|
import Button from "@/components/TempDesignSystem/Button"
|
||||||
|
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||||
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
import Caption from "@/components/TempDesignSystem/Text/Caption"
|
||||||
|
|
||||||
import ChildInfoSelector from "./ChildInfoSelector"
|
import ChildInfoSelector from "./ChildInfoSelector"
|
||||||
@@ -40,31 +44,50 @@ export default function ChildSelector({ roomIndex = 0 }: ChildSelectorProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<section className={styles.container}>
|
<section className={styles.container}>
|
||||||
<Caption>{childrenLabel}</Caption>
|
<Caption color="uiTextHighContrast" textTransform="bold">
|
||||||
<Button
|
{childrenLabel}
|
||||||
intent="text"
|
</Caption>
|
||||||
size="small"
|
<div className={styles.counterContainer}>
|
||||||
onClick={() => decreaseChildrenCount(roomIndex)}
|
<Button
|
||||||
>
|
className={styles.counterBtn}
|
||||||
-
|
intent="elevated"
|
||||||
</Button>
|
onClick={() => {
|
||||||
<span className={styles.textCenter}>{children.length}</span>
|
decreaseChildrenCount(roomIndex)
|
||||||
<Button
|
}}
|
||||||
intent="text"
|
size="small"
|
||||||
size="small"
|
theme="base"
|
||||||
onClick={() => increaseChildrenCount(roomIndex)}
|
variant="icon"
|
||||||
>
|
wrapping={true}
|
||||||
+
|
disabled={children.length == 0}
|
||||||
</Button>
|
>
|
||||||
|
<MinusIcon color="burgundy" />
|
||||||
|
</Button>
|
||||||
|
<Body color="textHighContrast" textAlign="center">
|
||||||
|
{children.length}
|
||||||
|
</Body>
|
||||||
|
<Button
|
||||||
|
className={styles.counterBtn}
|
||||||
|
onClick={() => {
|
||||||
|
increaseChildrenCount(roomIndex)
|
||||||
|
}}
|
||||||
|
intent="elevated"
|
||||||
|
variant="icon"
|
||||||
|
theme="base"
|
||||||
|
wrapping={true}
|
||||||
|
size="small"
|
||||||
|
disabled={children.length == 5}
|
||||||
|
>
|
||||||
|
<PlusIcon color="burgundy" />
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{children.map((child, index) => (
|
{children.map((child, index) => (
|
||||||
<div key={index} className={styles.childInfoContainer}>
|
<ChildInfoSelector
|
||||||
<ChildInfoSelector
|
roomIndex={roomIndex}
|
||||||
roomIndex={roomIndex}
|
index={index}
|
||||||
index={index}
|
child={child}
|
||||||
child={child}
|
key={index}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
))}
|
))}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { useIntl } from "react-intl"
|
|||||||
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
import { guestsRoomsStore } from "@/stores/guests-rooms"
|
||||||
|
|
||||||
import { guestRoomsSchema } from "../Forms/BookingWidget/schema"
|
import { guestRoomsSchema } from "../Forms/BookingWidget/schema"
|
||||||
|
import { CloseLarge } from "../Icons"
|
||||||
import Button from "../TempDesignSystem/Button"
|
import Button from "../TempDesignSystem/Button"
|
||||||
import Divider from "../TempDesignSystem/Divider"
|
import Divider from "../TempDesignSystem/Divider"
|
||||||
import Subtitle from "../TempDesignSystem/Text/Subtitle"
|
import Subtitle from "../TempDesignSystem/Text/Subtitle"
|
||||||
@@ -30,10 +31,15 @@ export default function GuestsRoomsPicker({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<header className={styles.header}>
|
||||||
|
<button type="button" className={styles.close} onClick={closePicker}>
|
||||||
|
<CloseLarge />
|
||||||
|
</button>
|
||||||
|
</header>
|
||||||
{guestsData.map((room, index) => (
|
{guestsData.map((room, index) => (
|
||||||
<section className={styles.roomContainer} key={index}>
|
<section className={styles.roomContainer} key={index}>
|
||||||
<section className={styles.roomDetailsContainer}>
|
<section className={styles.roomDetailsContainer}>
|
||||||
<Subtitle>
|
<Subtitle type="two" className={styles.roomHeading}>
|
||||||
{roomLabel} {index + 1}
|
{roomLabel} {index + 1}
|
||||||
</Subtitle>
|
</Subtitle>
|
||||||
<AdultSelector roomIndex={index} />
|
<AdultSelector roomIndex={index} />
|
||||||
@@ -45,7 +51,7 @@ export default function GuestsRoomsPicker({
|
|||||||
Remove Room
|
Remove Room
|
||||||
</Button>
|
</Button>
|
||||||
) : null} */}
|
) : null} */}
|
||||||
<Divider />
|
<Divider color="primaryLightSubtle" />
|
||||||
</section>
|
</section>
|
||||||
))}
|
))}
|
||||||
<footer className={styles.footer}>
|
<footer className={styles.footer}>
|
||||||
@@ -55,7 +61,24 @@ export default function GuestsRoomsPicker({
|
|||||||
Add Room
|
Add Room
|
||||||
</Button>
|
</Button>
|
||||||
) : null} */}
|
) : null} */}
|
||||||
<Button onClick={closePicker} disabled={isInValid}>
|
<Button
|
||||||
|
onClick={closePicker}
|
||||||
|
disabled={isInValid}
|
||||||
|
className={styles.hideOnMobile}
|
||||||
|
intent="tertiary"
|
||||||
|
theme="base"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
|
{doneLabel}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={closePicker}
|
||||||
|
disabled={isInValid}
|
||||||
|
className={styles.hideOnDesktop}
|
||||||
|
intent="tertiary"
|
||||||
|
theme="base"
|
||||||
|
size="large"
|
||||||
|
>
|
||||||
{doneLabel}
|
{doneLabel}
|
||||||
</Button>
|
</Button>
|
||||||
</footer>
|
</footer>
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
.container {
|
.container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 10;
|
|
||||||
&[data-isopen="true"] {
|
&[data-isopen="true"] {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.roomContainer {
|
.roomContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--Spacing-x1);
|
gap: var(--Spacing-x2);
|
||||||
}
|
}
|
||||||
.roomDetailsContainer {
|
.roomDetailsContainer {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -17,14 +16,9 @@
|
|||||||
}
|
}
|
||||||
.hideWrapper {
|
.hideWrapper {
|
||||||
background-color: var(--Main-Grey-White);
|
background-color: var(--Main-Grey-White);
|
||||||
border-radius: var(--Corner-radius-Medium);
|
}
|
||||||
box-shadow: 0px 16px 24px 0px rgba(0, 0, 0, 0.08);
|
.roomHeading {
|
||||||
padding: var(--Spacing-x-one-and-half);
|
margin-bottom: var(--Spacing-x1);
|
||||||
position: absolute;
|
|
||||||
/** BookingWidget padding + border-width */
|
|
||||||
top: calc(100% + var(--Spacing-x2) + 1px);
|
|
||||||
width: 360px;
|
|
||||||
max-width: 100vw; /* for small screens having view port width of 320px */
|
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
background: none;
|
background: none;
|
||||||
@@ -41,5 +35,83 @@
|
|||||||
display: grid;
|
display: grid;
|
||||||
gap: var(--Spacing-x1);
|
gap: var(--Spacing-x1);
|
||||||
grid-template-columns: auto;
|
grid-template-columns: auto;
|
||||||
margin-top: 10px;
|
margin-top: var(--Spacing-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1366px) {
|
||||||
|
.hideWrapper {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
overflow: auto;
|
||||||
|
position: fixed;
|
||||||
|
right: 0;
|
||||||
|
top: 100%;
|
||||||
|
transition: top 300ms ease;
|
||||||
|
z-index: 10002;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container[data-isopen="true"] .hideWrapper {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background-color: var(--Main-Grey-White);
|
||||||
|
display: grid;
|
||||||
|
padding: var(--Spacing-x3) var(--Spacing-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
justify-self: flex-end;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.roomContainer {
|
||||||
|
padding: 0 var(--Spacing-x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(255, 255, 255, 0) 7.5%,
|
||||||
|
#ffffff 82.5%
|
||||||
|
);
|
||||||
|
padding: var(--Spacing-x1) var(--Spacing-x2) var(--Spacing-x7);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer button {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .hideOnMobile {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 1367px) {
|
||||||
|
.hideWrapper {
|
||||||
|
border-radius: var(--Corner-radius-Large);
|
||||||
|
box-shadow: 0px 0px 14px 6px rgba(0, 0, 0, 0.1);
|
||||||
|
left: calc((var(--Spacing-x1) + var(--Spacing-x2)) * -1);
|
||||||
|
max-width: calc(100vw - 20px);
|
||||||
|
padding: var(--Spacing-x2) var(--Spacing-x3);
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + var(--Spacing-x2) + 1px + var(--Spacing-x4));
|
||||||
|
width: 360px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer .hideOnDesktop {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,12 @@ a.text {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.elevated,
|
||||||
|
a.elevated {
|
||||||
|
border: none;
|
||||||
|
box-shadow: 0px 0px 8px 1px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
/* VARIANTS */
|
/* VARIANTS */
|
||||||
.default,
|
.default,
|
||||||
a.default {
|
a.default {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ export const buttonVariants = cva(styles.btn, {
|
|||||||
secondary: styles.secondary,
|
secondary: styles.secondary,
|
||||||
tertiary: styles.tertiary,
|
tertiary: styles.tertiary,
|
||||||
text: styles.text,
|
text: styles.text,
|
||||||
|
elevated: styles.elevated,
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
small: styles.small,
|
small: styles.small,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ p.caption {
|
|||||||
.bold {
|
.bold {
|
||||||
font-family: var(--typography-Caption-Bold-fontFamily);
|
font-family: var(--typography-Caption-Bold-fontFamily);
|
||||||
font-size: var(--typography-Caption-Bold-fontSize);
|
font-size: var(--typography-Caption-Bold-fontSize);
|
||||||
font-weight: var(--typography-Caption-Bold-fontWeight);
|
font-weight: 500; /* var(--typography-Caption-Bold-fontWeight); /* Commented till figma values are fixed to 500 instead of medium */
|
||||||
letter-spacing: var(--typography-Caption-Bold-letterSpacing);
|
letter-spacing: var(--typography-Caption-Bold-letterSpacing);
|
||||||
line-height: var(--typography-Caption-Bold-lineHeight);
|
line-height: var(--typography-Caption-Bold-lineHeight);
|
||||||
text-decoration: var(--typography-Caption-Bold-textDecoration);
|
text-decoration: var(--typography-Caption-Bold-textDecoration);
|
||||||
|
|||||||
Reference in New Issue
Block a user