diff --git a/packages/orbit-components/src/Seat/README.md b/packages/orbit-components/src/Seat/README.md index 446801b06b..e07c76f3bb 100644 --- a/packages/orbit-components/src/Seat/README.md +++ b/packages/orbit-components/src/Seat/README.md @@ -24,7 +24,8 @@ Table below contains all types of the props available in Seat component. | type | [`enum`](#modal-enum) | `default` | Visual type of Seat. If `unavailable`, the element becomes disabled. | | price | `string` | | Price of Seat. Displayed as text underneath the svg. | | label | `string` | | Label text inside of a Seat. Not announced by screen readers. | -| selected | `boolean` | | Displays Seat as selected. | +| selected | `boolean` | | **Deprecated.** Use `status="selected"` instead. | +| status | [`enum`](#status-enum) | `default` | Visual status of the seat (default, selected, processing, done). | | onClick | `() => void \| Promise` | | Function for handling onClick event. | | aria-labelledby | `string` | | Id(s) of elements that announce the component to screen readers. | | title | `string` | | Adds title title to svg element. Announced by screen readers. | @@ -44,8 +45,40 @@ Table below contains all types of the props available in Seat/SeatLegend compone ### enum -| size | type | -| :--------- | :-------------- | -| `"small"` | `"default"` | -| `"medium"` | `"legroom"` | -| | `"unavailable"` | +| size | type | status | +| :--------- | :-------------- | :------------- | +| `"small"` | `"default"` | `"default"` | +| `"medium"` | `"legroom"` | `"selected"` | +| | `"unavailable"` | `"processing"` | +| | | `"done"` | + +### Status States + +The `status` prop determines the visual appearance of the seat: + +- `default`: Default state of the seat +- `selected`: Shows the seat as selected (replaces the deprecated `selected` prop) +- `processing`: Shows a processing state with: + - Background color: product light active + - Label: bold text in product darker color + - Icon: Reload icon in the top-right corner +- `done`: Shows a completed state with: + - Background color: product light active + - Label: bold text in product darker color + - Icon: Check icon in the top-right corner + +Example usage: + +```jsx +// Processing state + + +// Done state + + +// Selected state (new way) + + +// Selected state (deprecated way) + +``` diff --git a/packages/orbit-components/src/Seat/components/SeatCircle.tsx b/packages/orbit-components/src/Seat/components/SeatCircle.tsx index c03d8ef304..fd489f36d8 100644 --- a/packages/orbit-components/src/Seat/components/SeatCircle.tsx +++ b/packages/orbit-components/src/Seat/components/SeatCircle.tsx @@ -3,7 +3,9 @@ import cx from "clsx"; import { useRandomIdSeed } from "../../hooks/useRandomId"; import { SIZE_OPTIONS, TYPES } from "../consts"; -import type { Type, Size } from "../types"; +import type { Type, Size, SeatStatus } from "../types"; +import Icon from "../../Icon"; +import { ICON_SIZES, ICON_COLORS } from "../../Icon/consts"; const defaultClasses = { [TYPES.LEGROOM]: "fill-blue-dark-hover", @@ -20,15 +22,50 @@ const hoverClasses = { interface Props { type: Type; size: Size; + /** + * @deprecated Use `status="selected"` instead + */ + selected?: boolean; + status?: SeatStatus; } -const SeatCircle = ({ size, type }: Props) => { +const SeatCircle = ({ size, type, selected, status }: Props) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + const renderIcon = () => { + switch (effectiveStatus) { + case "processing": + return ( + + + + ); + case "done": + return ( + + + + ); + default: + return null; + } + }; const randomId = useRandomIdSeed(); const circleSmallId = randomId("circleSmallId"); const circleNormalId = randomId("circleNormalId"); return (
+ {renderIcon()} {size === SIZE_OPTIONS.SMALL ? ( { - if (selected && type === TYPES.UNAVAILABLE) return null; +const SeatNormal = ({ selected, status, type, label }: SeatVariantProps) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + if (effectiveStatus === "selected" && type === TYPES.UNAVAILABLE) return null; return ( <> {type === TYPES.UNAVAILABLE ? ( ) : ( - + )} - {!selected && ( + {effectiveStatus === "default" && ( { diff --git a/packages/orbit-components/src/Seat/components/SeatSmall.tsx b/packages/orbit-components/src/Seat/components/SeatSmall.tsx index dc7bd20559..b09db060b9 100644 --- a/packages/orbit-components/src/Seat/components/SeatSmall.tsx +++ b/packages/orbit-components/src/Seat/components/SeatSmall.tsx @@ -8,27 +8,30 @@ import SymbolUnavailable from "./primitives/SymbolUnavailable"; import Text from "./primitives/Text"; import Edge from "./primitives/Edge"; -const SeatSmall = ({ type, selected, label }: SeatVariantProps) => { - if (selected && type === TYPES.UNAVAILABLE) return null; +const SeatSmall = ({ type, selected, status, label }: SeatVariantProps) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + if (effectiveStatus === "selected" && type === TYPES.UNAVAILABLE) return null; return ( <> {type === TYPES.UNAVAILABLE ? ( ) : ( - + )} - {!selected && ( + {effectiveStatus === "default" && ( )} diff --git a/packages/orbit-components/src/Seat/components/primitives/Text.tsx b/packages/orbit-components/src/Seat/components/primitives/Text.tsx index 89c4a73e68..90768a2071 100644 --- a/packages/orbit-components/src/Seat/components/primitives/Text.tsx +++ b/packages/orbit-components/src/Seat/components/primitives/Text.tsx @@ -2,19 +2,23 @@ import * as React from "react"; import cx from "clsx"; import { TYPES } from "../../consts"; -import type { SeatVariantProps } from "../../types"; +import type { SeatVariantProps, SeatStatus } from "../../types"; type Props = { fontSize: number; } & SeatVariantProps; -const Text = ({ selected, type, label, fontSize }: Props) => { +const Text = ({ selected, status, type, label, fontSize }: Props) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + const isSelected = effectiveStatus === "selected"; + const isProcessingOrDone = effectiveStatus === "processing" || effectiveStatus === "done"; + return ( & React.PropsWithChildren; -const TransitionPathFill = ({ children, type, selected, ...props }: Props) => { +const TransitionPathFill = ({ children, type, selected, status, ...props }: Props) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + const isSelected = effectiveStatus === "selected"; + const isProcessingOrDone = effectiveStatus === "processing" || effectiveStatus === "done"; + return ( & React.PropsWithChildren; -const TransitionPathStroke = ({ children, type, selected, ...props }: Props) => { +const TransitionPathStroke = ({ children, type, selected, status, ...props }: Props) => { + const effectiveStatus = status ?? (selected ? "selected" : "default"); + const isSelected = effectiveStatus === "selected"; + const isProcessingOrDone = effectiveStatus === "processing" || effectiveStatus === "done"; + return ( { + const effectiveStatus = status ?? (selected ? "selected" : "default"); const randomId = useRandomIdSeed(); const titleId = title ? randomId("title") : ""; const descrId = description ? randomId("descr") : ""; @@ -55,12 +57,24 @@ const Seat = ({ {description && {description}} {size === SIZE_OPTIONS.SMALL ? ( - + ) : ( - + )} - {selected && clickable && } + {effectiveStatus !== "default" && clickable && ( + + )} {price && !(selected && type === TYPES.UNAVAILABLE) && ( diff --git a/packages/orbit-components/src/Seat/types.d.ts b/packages/orbit-components/src/Seat/types.d.ts index 888bb75fc9..92a7b69556 100644 --- a/packages/orbit-components/src/Seat/types.d.ts +++ b/packages/orbit-components/src/Seat/types.d.ts @@ -7,9 +7,11 @@ import type * as Common from "../common/types"; export type Size = "small" | "medium"; export type Type = "default" | "legroom" | "unavailable"; +export type SeatStatus = "default" | "selected" | "processing" | "done"; export interface SeatVariantProps { - selected: boolean; + selected?: boolean; + status?: SeatStatus; type: Type; label?: React.ReactNode; } @@ -21,7 +23,11 @@ export interface Props extends Common.Globals { readonly description?: string; readonly "aria-labelledby"?: string; readonly onClick?: Common.Callback; + /** + * @deprecated Use `status="selected"` instead. + */ readonly selected?: boolean; + readonly status?: SeatStatus; readonly label?: string; readonly price?: string; }