diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/index.tsx index c473d261d..9fe6abb65 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/index.tsx +++ b/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/index.tsx @@ -40,7 +40,7 @@ export default async function MembershipOverviewCard({ return (
- {sasMembership && ( + {sasMembership?.boostedTierExpires && ( )} diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/membershipOverviewCard.module.css b/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/membershipOverviewCard.module.css index 6b093862d..5fd69599f 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/membershipOverviewCard.module.css +++ b/apps/scandic-web/components/Blocks/DynamicContent/Overview/MembershipOverviewCard/membershipOverviewCard.module.css @@ -34,7 +34,7 @@ color: var(--Text-Brand-OnPrimary-3-Accent); } -@media (min-width: 1367px) { +@media screen and (min-width: 1367px) { .card { padding: var(--Space-x3) var(--Space-x4); } diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Overview/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/Overview/index.tsx index 9fff16ae3..81da66825 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Overview/index.tsx +++ b/apps/scandic-web/components/Blocks/DynamicContent/Overview/index.tsx @@ -7,6 +7,7 @@ import { getProfileWithExtendedPartnerData } from "@/lib/trpc/memoizedRequests" import { TeamMemberCardTrigger } from "@/components/DigitalTeamMemberCard/Trigger" import DigitalTeamMemberCard from "@/components/MyPages/DigitalTeamMemberCard" import DigitalTeamMemberCardAlert from "@/components/MyPages/DigitalTeamMemberCard/Alert" +import LevelProgressCard from "@/components/MyPages/LevelProgressCard" import SectionContainer from "@/components/Section/Container" import SectionHeader from "@/components/Section/Header" import SectionLink from "@/components/Section/Link" @@ -64,19 +65,19 @@ export default async function Overview({
- {/* LevelProgressCard will be added here in the next iteration */} +
- ) : null} + ) : ( + + + + + + + + )} - {/*TODO: Replace hero section with new section above. */} - - - - - - - ) diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Overview/overview.module.css b/apps/scandic-web/components/Blocks/DynamicContent/Overview/overview.module.css index cbb022963..afc4fdd57 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Overview/overview.module.css +++ b/apps/scandic-web/components/Blocks/DynamicContent/Overview/overview.module.css @@ -15,6 +15,7 @@ .membershipCardsContainer { display: grid; gap: var(--Space-x2); + grid-template-columns: 1fr; } @media screen and (min-width: 768px) { diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/index.tsx b/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/index.tsx index b1922c765..3b6d127d6 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/index.tsx +++ b/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/index.tsx @@ -1,7 +1,9 @@ import { Divider } from "@scandic-hotels/design-system/Divider" +import { env } from "@/env/server" import { getProfile } from "@/lib/trpc/memoizedRequests" +import LevelProgressCard from "@/components/MyPages/LevelProgressCard" import SectionContainer from "@/components/Section/Container" import SectionHeader from "@/components/Section/Header" import SectionLink from "@/components/Section/Link" @@ -34,6 +36,16 @@ export default async function PointsOverview({ headingAs={"h3"} headingLevel={"h1"} /> + {env.ENABLE_NEW_OVERVIEW_SECTION && ( +
+ {/*TODO: Add PointsToSpendCard */} + +
+ )} + {/*TODO: Once the PointsToSpendCard is added hide the Hero Section under the flag above. */} diff --git a/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/overview.module.css b/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/overview.module.css index 30729ba5f..beede3a70 100644 --- a/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/overview.module.css +++ b/apps/scandic-web/components/Blocks/DynamicContent/Points/Overview/overview.module.css @@ -2,8 +2,20 @@ margin-top: var(--Spacing-x2); } +.membershipCardsContainer { + display: grid; + gap: var(--Space-x2); + grid-template-columns: 1fr; +} + @media screen and (min-width: 768px) { .divider { display: none; } } + +@media screen and (min-width: 1367px) { + .membershipCardsContainer { + grid-template-columns: 1fr 1fr; + } +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/highestLevelCard.module.css b/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/highestLevelCard.module.css new file mode 100644 index 000000000..f7c231a2d --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/highestLevelCard.module.css @@ -0,0 +1,37 @@ +.card { + background: var(--Surface-Primary-Default); + border-radius: var(--Corner-radius-lg); + padding: var(--Space-x2) var(--Space-x4) var(--Space-x4); + display: grid; + justify-items: center; + text-align: center; + grid-template-areas: + "icon" + "content"; +} + +.title { + color: var(--Text-Heading); +} + +.content { + grid-area: content; + display: grid; + gap: var(--Space-x1); +} + +.icon { + grid-area: icon; +} + +@media screen and (min-width: 768px) { + .card { + grid-template-columns: auto 1fr; + grid-template-areas: "icon content"; + padding: var(--Space-x1) var(--Space-x4); + justify-items: start; + text-align: left; + align-items: center; + gap: var(--Space-x4); + } +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/index.tsx b/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/index.tsx new file mode 100644 index 000000000..e60ab68b3 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/HighestLevelCard/index.tsx @@ -0,0 +1,55 @@ +import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels" +import TrophyIcon from "@scandic-hotels/design-system/Icons/TrophyIcon" +import { Typography } from "@scandic-hotels/design-system/Typography" + +import { serverClient } from "@/lib/trpc/server" + +import styles from "./highestLevelCard.module.css" + +import type { HighestLevelCardProps } from "../types" + +export default async function HighestLevelCard({ + membershipLevel, + intl, +}: HighestLevelCardProps) { + const caller = await serverClient() + + const highestLevel = await caller.contentstack.loyaltyLevels.byLevel({ + level: MembershipLevelEnum[membershipLevel], + }) + + const pointsEarned = highestLevel?.required_points + + return ( +
+ +
+ +

+ {intl.formatMessage({ + defaultMessage: "Hello Best Friend!", + })} +

+
+ {pointsEarned && ( + +

+ {intl.formatMessage( + { + defaultMessage: + "you've made it to the top by earning {pointAmount} points! Continue earning points for more points to spend.", + }, + { + pointAmount: ( + {intl.formatNumber(pointsEarned)} + ), + strong: (str) => {str}, + } + )} +

+
+ )} +
+
+ ) +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/index.tsx b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/index.tsx new file mode 100644 index 000000000..46970be47 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/index.tsx @@ -0,0 +1,144 @@ +"use client" + +import { useIntl } from "react-intl" + +import { Progress } from "@scandic-hotels/design-system/Progress" +import { Typography } from "@scandic-hotels/design-system/Typography" + +import styles from "./progressLevelCard.module.css" + +import type { ProgressLevelCardProps } from "../types" + +export default function ProgressLevelCard({ + pointsEarned, + pointsToNextLevel, + pointsNeededToKeepLevel, +}: ProgressLevelCardProps) { + const intl = useIntl() + + // TODO: Awaiting proper UX/UI specs on missing point data scenarios. + if ( + typeof pointsEarned !== "number" || + typeof pointsToNextLevel !== "number" + ) { + return null + } + + const totalPointsForCurrentLevel = pointsEarned + pointsToNextLevel + const progressPercentage = (pointsEarned / totalPointsForCurrentLevel) * 100 + + // Calculate marker position (minimum threshold to keep current level) + const markerPosition = pointsNeededToKeepLevel + ? ((pointsEarned + pointsNeededToKeepLevel) / totalPointsForCurrentLevel) * + 100 + : null + + return ( +
+
+
+ + + {intl.formatMessage({ + defaultMessage: "Points Earned", + })} + + + + + + {intl.formatNumber(pointsEarned)} + + +
+ +
+ + + {intl.formatMessage({ + defaultMessage: "Left to level up", + })} + + + + + + {intl.formatNumber(pointsToNextLevel)} + + +
+
+ +
+
+ + + {markerPosition !== null && pointsNeededToKeepLevel && ( +
+
+
+
+ )} +
+ + {markerPosition !== null && pointsNeededToKeepLevel && ( +
+ + {intl.formatMessage( + { + defaultMessage: + "{pointsAmount} POINTS left to keep level", + }, + { + pointsAmount: ( + + {intl.formatNumber(pointsNeededToKeepLevel)} + + ), + points: (str) => ( + + {str} + + ), + support: (str) => ( + + {str} + + ), + } + )} + +
+ )} +
+
+ ) +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/progressLevelCard.module.css b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/progressLevelCard.module.css new file mode 100644 index 000000000..c6bcbbdf1 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelCard/progressLevelCard.module.css @@ -0,0 +1,102 @@ +.card { + background: var(--Surface-Primary-Default); + border-radius: var(--Corner-radius-lg); + display: flex; + flex-direction: column; + gap: var(--Space-x2); + padding: var(--Space-x3) 0; +} + +.statsContainer { + display: flex; + padding: 0 var(--Space-x3); + justify-content: space-between; + align-items: center; + align-self: stretch; +} + +.statItem { + display: flex; + flex-direction: column; + gap: var(--Space-x05); +} + +.statItem:last-child { + text-align: right; +} + +.label { + color: var(--Text-Secondary); +} + +.value { + color: var(--Text-Accent-Primary); + word-break: break-all; +} + +.progressSection { + padding: 0 var(--Space-x3); + display: flex; + flex-direction: column; + gap: var(--Space-x1); +} + +.progressSection.hasMarker { + padding-bottom: var(--Space-x1); +} + +.progressContainer { + position: relative; +} + +.levelMarker { + position: absolute; + top: 50%; + transform: translateX(-50%); + z-index: 2; + display: flex; + flex-direction: column; + align-items: center; + pointer-events: none; +} + +.markerPin { + width: 6px; + height: 6px; + background: var(--Surface-Brand-Primary-1-OnSurface-Default); + border-radius: 50%; + transform: translateY(-50%); +} + +.markerLine { + width: 1px; + height: 21px; + background: var(--Surface-Brand-Primary-1-OnSurface-Default); + margin-top: -3px; +} + +.markerLabelContainer { + position: relative; + height: var(--Space-x3); + margin-top: var(--Space-x15); +} + +.markerLabel { + position: absolute; + top: 0; + + /* Define both edges - let browser calculate width automatically */ + inset-inline-start: var(--Space-x3); /* respects card padding */ + inset-inline-end: calc(100% - var(--marker-pos)); /* right edge under pin */ + + white-space: normal; + overflow-wrap: anywhere; + color: var(--Text-Secondary); + text-align: right; +} + +@media screen and (min-width: 521px) { + .markerLabelContainer { + height: var(--Space-x2); + } +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelWrapper.tsx b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelWrapper.tsx new file mode 100644 index 000000000..ed235e485 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/ProgressLevelWrapper.tsx @@ -0,0 +1,58 @@ +import { MembershipLevelEnum } from "@scandic-hotels/common/constants/membershipLevels" + +import { serverClient } from "@/lib/trpc/server" + +import ProgressLevelCard from "./ProgressLevelCard" + +import type { ProgressLevelWrapperProps } from "./types" + +export default async function ProgressLevelWrapper({ + user, +}: ProgressLevelWrapperProps) { + const caller = await serverClient() + + if (!user.membership || !user.membership.membershipLevel) { + return null + } + + // NOTE: We currently rely on the CMS to get "required_points" for a given level, + // but API is working on including them in the Profile endpoint. + const [currentLevel, nextLevel] = await Promise.all([ + caller.contentstack.loyaltyLevels.byLevel({ + level: MembershipLevelEnum[user.membership.membershipLevel], + }), + + user.membership.nextLevel && MembershipLevelEnum[user.membership.nextLevel] + ? caller.contentstack.loyaltyLevels.byLevel({ + level: MembershipLevelEnum[user.membership.nextLevel], + }) + : null, + ]) + + const pointsToNextLevel = user.membership.pointsRequiredToNextlevel + + // Relying on user.loyalty.points.earned isn't suffice here as it isn't limited to loyalty-level specific earnings, + // nor limited to earnings in the current member year. + // TODO: API is working on adding a tierEarnings field which we'll be able to use for this. + // Once that's out we won't need the nextLevel call above. + const currentEarnings = + nextLevel?.required_points && pointsToNextLevel + ? nextLevel?.required_points - pointsToNextLevel + : null + + let pointsNeededToKeepLevel = null + + if (currentEarnings !== null && currentLevel?.required_points) { + if (currentEarnings < currentLevel.required_points) { + pointsNeededToKeepLevel = currentLevel.required_points - currentEarnings + } + } + + return ( + + ) +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx b/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx new file mode 100644 index 000000000..c71871162 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/index.tsx @@ -0,0 +1,73 @@ +import { dt } from "@scandic-hotels/common/dt" +import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon" +import { Typography } from "@scandic-hotels/design-system/Typography" + +import { getIntl } from "@/i18n" +import { getLang } from "@/i18n/serverContext" +import { isHighestMembership } from "@/utils/user" + +import HighestLevelCard from "./HighestLevelCard" +import ProgressLevelWrapper from "./ProgressLevelWrapper" +import { levelProgressCardVariants } from "./variants" + +import styles from "./levelProgressCard.module.css" + +import type { levelProgressCardProps } from "./types" + +export default async function LevelProgressCard({ + user, + className, + color = "Surface/Brand/Primary 1/OnSurface/Default", +}: levelProgressCardProps) { + const intl = await getIntl() + const lang = await getLang() + + if (!user.membership?.membershipLevel) { + return null + } + + const classNames = levelProgressCardVariants({ className, color }) + + return ( +
+
+ +

+ {intl.formatMessage({ + defaultMessage: "Your Level Progress", + })} +

+
+ +

+ {intl.formatMessage( + { defaultMessage: "Valid until {date}" }, + { + date: dt(user.membership.tierExpirationDate) + .locale(lang) + .format("D MMM YYYY"), + } + )} +

+
+ +
+ {isHighestMembership(user.membership.membershipLevel) ? ( + + ) : ( + + )} +
+ ) +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/levelProgressCard.module.css b/apps/scandic-web/components/MyPages/LevelProgressCard/levelProgressCard.module.css new file mode 100644 index 000000000..680d78a5d --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/levelProgressCard.module.css @@ -0,0 +1,61 @@ +.Surface-Brand-Primary-1-OnSurface-Default { + background: var(--Surface-Brand-Primary-1-OnSurface-Default); +} + +.Surface-Brand-Primary-1-Default { + background: var(--Surface-Brand-Primary-1-Default); +} + +.Surface-Brand-Primary-1-OnSurface-Default .title { + color: var(--Text-Brand-OnPrimary-3-Heading); +} + +.Surface-Brand-Primary-1-OnSurface-Default .date { + color: var(--Text-Brand-OnPrimary-2-Accent); +} + +.Surface-Brand-Primary-1-Default .title, +.Surface-Brand-Primary-1-Default .date { + color: var(--Text-Brand-OnPrimary-1-Heading); +} + +.levelProgressCard { + border-radius: var(--Corner-radius-lg); + padding: var(--Space-x3) var(--Space-x2); + position: relative; + min-height: 200px; + display: flex; + flex-direction: column; + justify-content: space-between; + gap: var(--Space-x3); +} + +.progressHeader { + display: grid; + grid-template-columns: 1fr auto; + grid-template-rows: auto auto; + gap: var(--Space-x05); + align-items: start; +} + +.title { + grid-column: 1; + grid-row: 1; +} + +.date { + grid-column: 1; + grid-row: 2; +} + +.infoButton { + grid-column: 2; + grid-row: 1 / 3; + align-self: start; +} + +@media screen and (min-width: 1367px) { + .levelProgressCard { + padding: var(--Space-x3) var(--Space-x4); + } +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/types.ts b/apps/scandic-web/components/MyPages/LevelProgressCard/types.ts new file mode 100644 index 000000000..f039bb12a --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/types.ts @@ -0,0 +1,27 @@ +import type { MembershipLevel } from "@scandic-hotels/common/constants/membershipLevels" +import type { User } from "@scandic-hotels/trpc/types/user" +import type { VariantProps } from "class-variance-authority" +import type { IntlShape } from "react-intl" + +import type { levelProgressCardVariants } from "./variants" + +export interface levelProgressCardProps + extends Omit, "color">, + VariantProps { + user: User +} + +export interface ProgressLevelWrapperProps { + user: User +} + +export interface ProgressLevelCardProps { + pointsEarned?: number | null + pointsToNextLevel?: number | null + pointsNeededToKeepLevel: number | null +} + +export interface HighestLevelCardProps { + membershipLevel: MembershipLevel + intl: IntlShape +} diff --git a/apps/scandic-web/components/MyPages/LevelProgressCard/variants.ts b/apps/scandic-web/components/MyPages/LevelProgressCard/variants.ts new file mode 100644 index 000000000..24be4bc84 --- /dev/null +++ b/apps/scandic-web/components/MyPages/LevelProgressCard/variants.ts @@ -0,0 +1,17 @@ +import { cva } from "class-variance-authority" + +import styles from "./levelProgressCard.module.css" + +export const levelProgressCardVariants = cva(styles.levelProgressCard, { + variants: { + color: { + "Surface/Brand/Primary 1/OnSurface/Default": + styles["Surface-Brand-Primary-1-OnSurface-Default"], + "Surface/Brand/Primary 1/Default": + styles["Surface-Brand-Primary-1-Default"], + }, + }, + defaultVariants: { + color: "Surface/Brand/Primary 1/OnSurface/Default", + }, +}) diff --git a/packages/design-system/lib/components/Icons/IllustrationByIconName.ts b/packages/design-system/lib/components/Icons/IllustrationByIconName.ts index e72a57ae9..aa48e03ba 100644 --- a/packages/design-system/lib/components/Icons/IllustrationByIconName.ts +++ b/packages/design-system/lib/components/Icons/IllustrationByIconName.ts @@ -10,6 +10,7 @@ import KidsIcon from './Illustrations/Kids' import KidsMocktailIcon from './Illustrations/KidsMocktail' import MagicWandIcon from './Illustrations/MagicWand' import MoneyHandIcon from './Illustrations/MoneyHand' +import TrophyIcon from './Illustrations/Trophy' import VoucherIcon from './Illustrations/Voucher' import { IconName } from './iconName' @@ -40,6 +41,8 @@ export function IllustrationByIconName(iconName: IconName | null) { return CoinIcon case IconName.Bed: return BedIcon + case IconName.Trophy: + return TrophyIcon case IconName.Voucher: return VoucherIcon default: diff --git a/packages/design-system/lib/components/Icons/Illustrations/Trophy.tsx b/packages/design-system/lib/components/Icons/Illustrations/Trophy.tsx new file mode 100644 index 000000000..442899ca6 --- /dev/null +++ b/packages/design-system/lib/components/Icons/Illustrations/Trophy.tsx @@ -0,0 +1,55 @@ +import type { IllustrationProps } from '../icon' + +export default function TrophyIcon(props: IllustrationProps) { + return ( + + + + + + + + + + + + + ) +} diff --git a/packages/design-system/lib/components/Icons/iconName.ts b/packages/design-system/lib/components/Icons/iconName.ts index 695ece883..5227efa2d 100644 --- a/packages/design-system/lib/components/Icons/iconName.ts +++ b/packages/design-system/lib/components/Icons/iconName.ts @@ -169,6 +169,7 @@ export enum IconName { Ticket = 'Ticket', Train = 'Train', Tripadvisor = 'Tripadvisor', + Trophy = 'Trophy', Tshirt = 'Tshirt', TshirtWash = 'TshirtWash', TvCasting = 'TvCasting', diff --git a/packages/design-system/lib/components/Progress/Progress.stories.tsx b/packages/design-system/lib/components/Progress/Progress.stories.tsx new file mode 100644 index 000000000..16948491e --- /dev/null +++ b/packages/design-system/lib/components/Progress/Progress.stories.tsx @@ -0,0 +1,58 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite' + +import { Progress } from './index' + +const meta: Meta = { + title: 'Components/Progress', + component: Progress, + parameters: { + backgrounds: { disable: true }, + }, + argTypes: { + value: { + control: { type: 'range', min: 0, max: 100, step: 1 }, + description: 'The current progress value (0-100)', + }, + 'aria-label': { + control: 'text', + description: 'Accessible label for the progress bar', + }, + }, + args: { + 'aria-label': 'Loading progress', + }, +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + args: { + value: 65, + }, +} + +export const LowProgress: Story = { + args: { + value: 15, + }, +} + +export const HighProgress: Story = { + args: { + value: 90, + }, +} + +export const Complete: Story = { + args: { + value: 100, + }, +} + +export const Empty: Story = { + args: { + value: 0, + }, +} diff --git a/packages/design-system/lib/components/Progress/index.tsx b/packages/design-system/lib/components/Progress/index.tsx new file mode 100644 index 000000000..29ed6c9fe --- /dev/null +++ b/packages/design-system/lib/components/Progress/index.tsx @@ -0,0 +1,30 @@ +import { ProgressBar } from 'react-aria-components' +import { cx } from 'class-variance-authority' +import styles from './progress.module.css' +import { ProgressProps } from './types' + +export function Progress({ + value, + minValue = 0, + maxValue = 100, + 'aria-label': ariaLabel, + className, +}: ProgressProps) { + return ( + + {({ percentage }) => ( + <> +
+
+
+ + )} + + ) +} diff --git a/packages/design-system/lib/components/Progress/progress.module.css b/packages/design-system/lib/components/Progress/progress.module.css new file mode 100644 index 000000000..e585bd4a0 --- /dev/null +++ b/packages/design-system/lib/components/Progress/progress.module.css @@ -0,0 +1,19 @@ +.progress { + width: 100%; +} + +.track { + height: var(--Space-x2); + border-radius: var(--Corner-radius-md); + padding: var(--Space-x05); + background: var(--Surface-Secondary-Default); + position: relative; + overflow: hidden; +} + +.fill { + height: 100%; + background: var(--Surface-Brand-Primary-1-OnSurface-Accent); + border-radius: var(--Corner-radius-md); + transition: width 0.3s ease; +} diff --git a/packages/design-system/lib/components/Progress/types.ts b/packages/design-system/lib/components/Progress/types.ts new file mode 100644 index 000000000..d4dfcceba --- /dev/null +++ b/packages/design-system/lib/components/Progress/types.ts @@ -0,0 +1,7 @@ +export interface ProgressProps { + value: number + minValue?: number + maxValue?: number + 'aria-label'?: string + className?: string +} diff --git a/packages/design-system/lib/components/Progress/variants.ts b/packages/design-system/lib/components/Progress/variants.ts new file mode 100644 index 000000000..c34833f1e --- /dev/null +++ b/packages/design-system/lib/components/Progress/variants.ts @@ -0,0 +1,10 @@ +import { cva } from 'class-variance-authority' + +import styles from './progress.module.css' + +export const config = { + variants: {}, + defaultVariants: {}, +} as const + +export const variants = cva(styles.progress, config) diff --git a/packages/design-system/package.json b/packages/design-system/package.json index 654476fb3..9aeb900eb 100644 --- a/packages/design-system/package.json +++ b/packages/design-system/package.json @@ -121,6 +121,7 @@ "./Icons/ToiletIcon": "./lib/components/Icons/Nucleo/Amenities_Facilities/toilet-2.tsx", "./Icons/TowelIcon": "./lib/components/Icons/Customised/Amenities_Facilities/Towel.tsx", "./Icons/TripadvisorIcon": "./lib/components/Icons/Customised/Socials/Tripadvisor.tsx", + "./Icons/TrophyIcon": "./lib/components/Icons/Illustrations/Trophy.tsx", "./Icons/UserPoliceIcon": "./lib/components/Icons/Nucleo/Amenities_Facilities/user-police-2.tsx", "./Icons/ViewIcon": "./lib/components/Icons/Customised/Amenities_Facilities/View.tsx", "./Icons/VoucherIcon": "./lib/components/Icons/Illustrations/Voucher.tsx", @@ -152,6 +153,7 @@ "./Payment/PaymentMethodIcon": "./lib/components/Payment/PaymentMethodIcon.tsx", "./PointsRateCard": "./lib/components/RateCard/Points/index.tsx", "./Preamble": "./lib/components/Preamble/index.tsx", + "./Progress": "./lib/components/Progress/index.tsx", "./RegularRateCard": "./lib/components/RateCard/Regular/index.tsx", "./Select": "./lib/components/Select/index.tsx", "./SidePeek": "./lib/components/SidePeek/index.tsx",