Merged in fix/BOOK-293-button-variants (pull request #3371)
fix(BOOK-293): changed variants and props on IconButton component * fix(BOOK-293): changed variants and props on IconButton component * fix(BOOK-293): inherit color for icon Approved-by: Bianca Widstam Approved-by: Christel Westerberg
This commit is contained in:
committed by
Bianca Widstam
parent
2197ab2137
commit
3f632e6031
@@ -134,13 +134,16 @@ export default function BookingCodeFilter() {
|
||||
})}
|
||||
</h3>
|
||||
</Typography>
|
||||
<IconButton variant="Muted" emphasis onPress={close}>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
size={24}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
onPress={close}
|
||||
iconName="close"
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<RadioGroup
|
||||
|
||||
@@ -8,14 +8,7 @@ export function AddToCalendarButton({ onPress }: { onPress: () => void }) {
|
||||
const intl = useIntl()
|
||||
|
||||
return (
|
||||
<Button
|
||||
variant="Text"
|
||||
size="Small"
|
||||
color="Primary"
|
||||
wrapping
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
onPress={onPress}
|
||||
>
|
||||
<Button variant="Text" size="sm" color="Primary" onPress={onPress}>
|
||||
<MaterialIcon size={20} icon="calendar_add_on" color="CurrentColor" />
|
||||
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -39,9 +39,8 @@ export default function ManageBooking({ booking }: ManageBookingProps) {
|
||||
<ButtonLink
|
||||
href={myStayURL}
|
||||
variant="Text"
|
||||
size="Small"
|
||||
size="sm"
|
||||
color="Primary"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping
|
||||
>
|
||||
<MaterialIcon size={20} icon="edit_square" color="CurrentColor" />
|
||||
|
||||
@@ -26,7 +26,7 @@ export function Promo({ buttonText, href, text, title }: PromoProps) {
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p className={styles.text}>{text}</p>
|
||||
</Typography>
|
||||
<Button size="Small" variant="Secondary" color="Inverted" wrapping>
|
||||
<Button size="sm" variant="Secondary" color="Inverted" wrapping>
|
||||
<div>{buttonText}</div>
|
||||
</Button>
|
||||
</article>
|
||||
|
||||
@@ -137,7 +137,6 @@ export function ReceiptRoom({
|
||||
<Button
|
||||
className={styles.termsButton}
|
||||
variant="Text"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -24,7 +24,7 @@ export default function Retry({ handleRefetch }: RetryProps) {
|
||||
</p>
|
||||
</Typography>
|
||||
|
||||
<Button size="Small" onPress={handleRefetch}>
|
||||
<Button size="sm" onPress={handleRefetch}>
|
||||
{intl.formatMessage({
|
||||
id: "bookingConfirmation.linkedReservation.tryAgain",
|
||||
defaultMessage: "Try again",
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
@media screen and (min-width: 768px) and (max-width: 1366px) {
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.codePopover {
|
||||
background: var(--Base-Surface-Primary-light-Normal);
|
||||
|
||||
@@ -230,13 +230,7 @@ function CodeRulesModal() {
|
||||
return (
|
||||
<Modal
|
||||
trigger={
|
||||
<IconButton variant="Muted" size="sm" emphasis>
|
||||
<MaterialIcon
|
||||
icon="info"
|
||||
color="Icon/Interactive/Placeholder"
|
||||
size={20}
|
||||
/>
|
||||
</IconButton>
|
||||
<IconButton variant="Muted" size="sm" emphasis iconName="info" />
|
||||
}
|
||||
title={codeVoucher}
|
||||
>
|
||||
@@ -264,7 +258,7 @@ function CodeRemember({ bookingCodeValue, onApplyClick }: CodeRememberProps) {
|
||||
</Checkbox>
|
||||
{bookingCodeValue ? (
|
||||
<Button
|
||||
size="Small"
|
||||
size="sm"
|
||||
className={styles.hideOnMobile}
|
||||
variant="Tertiary"
|
||||
type="button"
|
||||
|
||||
@@ -24,7 +24,7 @@ export function RemoveExtraRooms({ ...props }: ButtonProps) {
|
||||
style={{ width: "100%" }}
|
||||
type="button"
|
||||
onClick={removeExtraRooms}
|
||||
size="Small"
|
||||
size="sm"
|
||||
variant="Secondary"
|
||||
{...props}
|
||||
>
|
||||
|
||||
@@ -101,14 +101,7 @@ export default function RewardNight() {
|
||||
</Typography>
|
||||
<Modal
|
||||
trigger={
|
||||
<IconButton variant="Muted" emphasis size="sm">
|
||||
<MaterialIcon
|
||||
icon="info"
|
||||
size={20}
|
||||
color="Icon/Interactive/Placeholder"
|
||||
className={styles.errorIcon}
|
||||
/>
|
||||
</IconButton>
|
||||
<IconButton variant="Muted" emphasis size="sm" iconName="info" />
|
||||
}
|
||||
title={reward}
|
||||
>
|
||||
|
||||
@@ -181,7 +181,7 @@ export function Search({
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<Button
|
||||
variant="Text"
|
||||
size="Small"
|
||||
size="sm"
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.clear",
|
||||
defaultMessage: "Clear",
|
||||
@@ -197,7 +197,7 @@ export function Search({
|
||||
<Button
|
||||
className={styles.searchButton}
|
||||
variant="Primary"
|
||||
size="Small"
|
||||
size="sm"
|
||||
type="submit"
|
||||
onPress={() => {
|
||||
if (!searchTerm) {
|
||||
|
||||
@@ -10,7 +10,6 @@ import { hotelreservation } from "@scandic-hotels/common/constants/routes/hotelR
|
||||
import { dt } from "@scandic-hotels/common/dt"
|
||||
import { Button } from "@scandic-hotels/design-system/Button"
|
||||
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import SkeletonShimmer from "@scandic-hotels/design-system/SkeletonShimmer"
|
||||
import { Typography } from "@scandic-hotels/design-system/Typography"
|
||||
import { SEARCH_TYPE_REDEMPTION } from "@scandic-hotels/trpc/constants/booking"
|
||||
@@ -119,9 +118,8 @@ export default function FormContent({
|
||||
form={formId}
|
||||
type="submit"
|
||||
isDisabled={isSearching}
|
||||
>
|
||||
<MaterialIcon icon="search" color="CurrentColor" size={28} />
|
||||
</IconButton>
|
||||
iconName="search"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={cx(
|
||||
@@ -147,10 +145,9 @@ export default function FormContent({
|
||||
className={styles.submitButton}
|
||||
form={formId}
|
||||
variant="Primary"
|
||||
size="Medium"
|
||||
size="md"
|
||||
type="submit"
|
||||
isDisabled={isSearching}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
{isDirty && isBookingFlow
|
||||
? intl.formatMessage({
|
||||
@@ -210,9 +207,13 @@ export function BookingWidgetFormContentSkeleton() {
|
||||
</div>
|
||||
</div>
|
||||
<div className={cx(styles.buttonContainer, styles.showOnTablet)}>
|
||||
<IconButton variant="Filled" size="xl" type="submit" isDisabled>
|
||||
<MaterialIcon icon="search" color="CurrentColor" size={28} />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
variant="Filled"
|
||||
size="xl"
|
||||
type="submit"
|
||||
isDisabled
|
||||
iconName="search"
|
||||
/>
|
||||
</div>
|
||||
<div className={cx(styles.voucherContainer, styles.voucherRow)}>
|
||||
<VoucherSkeleton />
|
||||
@@ -221,10 +222,9 @@ export function BookingWidgetFormContentSkeleton() {
|
||||
<Button
|
||||
className={styles.submitButton}
|
||||
variant="Primary"
|
||||
size="Medium"
|
||||
size="md"
|
||||
type="submit"
|
||||
isDisabled
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "bookingWidget.button.search",
|
||||
|
||||
@@ -131,8 +131,7 @@ export default function GuestsRoomsPickerDialog({
|
||||
wrapping
|
||||
onPress={handleAddRoom}
|
||||
isDisabled
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" />
|
||||
{addRoomLabel}
|
||||
@@ -163,8 +162,7 @@ export default function GuestsRoomsPickerDialog({
|
||||
wrapping
|
||||
color="Primary"
|
||||
onPress={handleAddRoom}
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" />
|
||||
{addRoomLabel}
|
||||
@@ -187,9 +185,8 @@ export default function GuestsRoomsPickerDialog({
|
||||
wrapping
|
||||
color="Primary"
|
||||
isDisabled
|
||||
size="Small"
|
||||
size="sm"
|
||||
onPress={handleAddRoom}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
<MaterialIcon icon="add_circle" color="CurrentColor" />
|
||||
{addRoomLabel}
|
||||
@@ -204,9 +201,8 @@ export default function GuestsRoomsPickerDialog({
|
||||
variant="Text"
|
||||
wrapping
|
||||
color="Primary"
|
||||
size="Small"
|
||||
size="sm"
|
||||
onPress={handleAddRoom}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
<MaterialIcon icon="add_circle" color="CurrentColor" />
|
||||
{addRoomLabel}
|
||||
@@ -220,8 +216,7 @@ export default function GuestsRoomsPickerDialog({
|
||||
className={styles.hideOnDesktop}
|
||||
variant="Tertiary"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
>
|
||||
{doneLabel}
|
||||
</Button>
|
||||
@@ -231,8 +226,7 @@ export default function GuestsRoomsPickerDialog({
|
||||
className={styles.hideOnMobile}
|
||||
variant="Tertiary"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
>
|
||||
{doneLabel}
|
||||
</Button>
|
||||
|
||||
@@ -76,7 +76,7 @@ export function JoinScandicFriendsCard({ name = "join" }: Props) {
|
||||
<LoginButton
|
||||
color="Primary"
|
||||
variant="Tertiary"
|
||||
size="Small"
|
||||
size="sm"
|
||||
lang={lang}
|
||||
className={styles.login}
|
||||
loginPosition="enter-details"
|
||||
|
||||
@@ -23,9 +23,8 @@ export function GuaranteeInfo({ buttonClassName }: GuaranteeInfoProps) {
|
||||
<Button
|
||||
variant="Text"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
size="sm"
|
||||
type="button"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
className={buttonClassName}
|
||||
onPress={() => setIsOpen(true)}
|
||||
@@ -59,8 +58,7 @@ export function GuaranteeInfo({ buttonClassName }: GuaranteeInfoProps) {
|
||||
className={styles.closeButton}
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
size="md"
|
||||
onPress={() => setIsOpen(false)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -36,7 +36,6 @@ import useLang from "../../../hooks/useLang"
|
||||
import { useEnterDetailsStore } from "../../../stores/enter-details"
|
||||
import ConfirmBooking from "../Confirm"
|
||||
import PriceChangeDialog from "../PriceChangeDialog"
|
||||
import { writeGlaToSessionStorage } from "./PaymentCallback/helpers"
|
||||
import BookingAlert from "./BookingAlert"
|
||||
import { GuaranteeInfo } from "./GuaranteeInfo"
|
||||
import {
|
||||
@@ -47,6 +46,7 @@ import {
|
||||
mustGuaranteeBooking,
|
||||
writePaymentInfoToSessionStorage,
|
||||
} from "./helpers"
|
||||
import { writeGlaToSessionStorage } from "./PaymentCallback/helpers"
|
||||
import { type PaymentFormData, paymentSchema } from "./schema"
|
||||
import { getPaymentHeadingConfig } from "./utils"
|
||||
|
||||
@@ -497,8 +497,7 @@ export default function PaymentClient({
|
||||
type="submit"
|
||||
isDisabled={isSubmitting}
|
||||
isPending={isSubmitting}
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
size="md"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "enterDetails.completeBooking",
|
||||
|
||||
@@ -82,11 +82,10 @@ export default function SelectedRoom() {
|
||||
</Subtitle>
|
||||
<Button
|
||||
variant="Text"
|
||||
size="Small"
|
||||
size="sm"
|
||||
onPress={changeRoom}
|
||||
isDisabled={isPending}
|
||||
wrapping={false}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
>
|
||||
<MaterialIcon icon="edit_square" size={20} color="CurrentColor" />
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -131,9 +131,8 @@ export default function SummaryBottomSheet({
|
||||
<Button
|
||||
variant="Primary"
|
||||
color="Primary"
|
||||
size="Large"
|
||||
size="lg"
|
||||
type="submit"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
isDisabled={isSubmitting}
|
||||
isPending={isSubmitting}
|
||||
form={formId}
|
||||
|
||||
@@ -196,7 +196,6 @@ export default function Room({
|
||||
<Button
|
||||
className={styles.termsButton}
|
||||
variant="Text"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -65,12 +65,7 @@ export function HotelSidePeekContent({
|
||||
<AdditionalAmenities amenities={hotel.detailedFacilities} />
|
||||
</Accordion>
|
||||
{hotelUrl ? (
|
||||
<ButtonLink
|
||||
href={hotelUrl}
|
||||
variant="Secondary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
<ButtonLink href={hotelUrl} variant="Secondary" size="md">
|
||||
{intl.formatMessage({
|
||||
id: "hotelSidePeek.readMore.buttonText",
|
||||
defaultMessage: "Read more about the hotel",
|
||||
|
||||
@@ -30,22 +30,17 @@ interface HotelDetailsSidePeekProps {
|
||||
|
||||
const buttonPropsMap: Record<
|
||||
HotelDetailsSidePeekProps["buttonVariant"],
|
||||
Pick<
|
||||
React.ComponentProps<typeof Button>,
|
||||
"variant" | "color" | "size" | "typography"
|
||||
>
|
||||
Pick<React.ComponentProps<typeof Button>, "variant" | "color" | "size">
|
||||
> = {
|
||||
primary: {
|
||||
variant: "Text",
|
||||
color: "Primary",
|
||||
size: "Medium",
|
||||
typography: "Body/Paragraph/mdBold",
|
||||
size: "md",
|
||||
},
|
||||
secondary: {
|
||||
variant: "Secondary",
|
||||
color: "Inverted",
|
||||
size: "Small",
|
||||
typography: "Body/Supporting text (caption)/smBold",
|
||||
size: "sm",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import { HotelCardDialogImage } from "@scandic-hotels/design-system/HotelCard/Ho
|
||||
import { HotelPointsRow } from "@scandic-hotels/design-system/HotelCard/HotelPointsRow"
|
||||
import { NoPriceAvailableCard } from "@scandic-hotels/design-system/HotelCard/NoPriceAvailableCard"
|
||||
import { IconButton } from "@scandic-hotels/design-system/IconButton"
|
||||
import { MaterialIcon } from "@scandic-hotels/design-system/Icons/MaterialIcon"
|
||||
import { OldDSButton as Button } from "@scandic-hotels/design-system/OldDSButton"
|
||||
import Link from "@scandic-hotels/design-system/OldDSLink"
|
||||
import Subtitle from "@scandic-hotels/design-system/Subtitle"
|
||||
@@ -75,9 +74,8 @@ export default function ListingHotelCardDialog({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" size={22} color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.header}>
|
||||
<HotelCardDialogImage
|
||||
|
||||
@@ -11,12 +11,7 @@ import PriceDetailsTable, {
|
||||
|
||||
function Trigger({ title }: { title: string }) {
|
||||
return (
|
||||
<Button
|
||||
variant="Text"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
wrapping={false}
|
||||
>
|
||||
<Button variant="Text" size="md" wrapping={false}>
|
||||
{title}
|
||||
<MaterialIcon icon="chevron_right" color="CurrentColor" size={20} />
|
||||
</Button>
|
||||
|
||||
@@ -26,22 +26,17 @@ interface RoomDetailsSidePeekProps {
|
||||
|
||||
const buttonPropsMap: Record<
|
||||
NonNullable<RoomDetailsSidePeekProps["buttonVariant"]>,
|
||||
Pick<
|
||||
React.ComponentProps<typeof Button>,
|
||||
"variant" | "color" | "size" | "typography"
|
||||
>
|
||||
Pick<React.ComponentProps<typeof Button>, "variant" | "color" | "size">
|
||||
> = {
|
||||
primary: {
|
||||
variant: "Text",
|
||||
color: "Primary",
|
||||
size: "Medium",
|
||||
typography: "Body/Paragraph/mdBold",
|
||||
size: "md",
|
||||
},
|
||||
secondary: {
|
||||
variant: "Text",
|
||||
color: "Inverted",
|
||||
size: "Small",
|
||||
typography: "Body/Supporting text (caption)/smBold",
|
||||
size: "sm",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -135,7 +135,7 @@ export default function FilterAndSortModal({
|
||||
return (
|
||||
<>
|
||||
<DialogTrigger>
|
||||
<Button variant="Secondary" size="Small" color="Primary">
|
||||
<Button variant="Secondary" size="sm" color="Primary">
|
||||
<MaterialIcon icon="filter_alt" color="CurrentColor" />
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p>
|
||||
@@ -176,9 +176,8 @@ export default function FilterAndSortModal({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
</header>
|
||||
<div className={styles.sorter}>
|
||||
<DeprecatedSelect
|
||||
@@ -217,8 +216,8 @@ export default function FilterAndSortModal({
|
||||
<Button
|
||||
variant="Tertiary"
|
||||
color="Primary"
|
||||
size="Large"
|
||||
onClick={() => handleApplyFiltersAndSorting(close)}
|
||||
size="lg"
|
||||
onPress={() => handleApplyFiltersAndSorting(close)}
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
@@ -238,13 +237,13 @@ export default function FilterAndSortModal({
|
||||
</Typography>
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
onPress={() => {
|
||||
setSelectedFilters([])
|
||||
setFilteredCount(unfilteredResultCount)
|
||||
}}
|
||||
variant="Text"
|
||||
color="Primary"
|
||||
size="Medium"
|
||||
size="md"
|
||||
>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p>
|
||||
|
||||
@@ -14,8 +14,7 @@ export function MapWithButtonWrapper({ children }: React.PropsWithChildren) {
|
||||
<FakeButton
|
||||
variant="Primary"
|
||||
color="Inverted"
|
||||
size="Small"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
className={styles.button}
|
||||
>
|
||||
<MaterialIcon icon="map" color="CurrentColor" size={20} />
|
||||
|
||||
@@ -168,7 +168,7 @@ export function SelectHotelMapContent({
|
||||
variant="Primary"
|
||||
color="Inverted"
|
||||
wrapping
|
||||
size="Small"
|
||||
size="sm"
|
||||
className={styles.closeButton}
|
||||
>
|
||||
<Link
|
||||
@@ -216,7 +216,7 @@ export function SelectHotelMapContent({
|
||||
<Button
|
||||
variant="Text"
|
||||
type="button"
|
||||
size="Small"
|
||||
size="sm"
|
||||
className={styles.filterContainerCloseButton}
|
||||
>
|
||||
<Link href={closeMapUrl} keepSearchParams className={styles.link}>
|
||||
|
||||
@@ -91,13 +91,12 @@ export default function SummaryContent({
|
||||
onPress={toggleSummaryOpen}
|
||||
variant="Muted"
|
||||
emphasis
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_down"
|
||||
size={20}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</IconButton>
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
iconName="keyboard_arrow_down"
|
||||
/>
|
||||
</div>
|
||||
<Typography variant="Body/Paragraph/mdBold">
|
||||
<p className={styles.dates}>
|
||||
|
||||
@@ -159,7 +159,6 @@ export default function Room({
|
||||
<Button
|
||||
className={styles.termsButton}
|
||||
variant="Text"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
wrapping={false}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -137,9 +137,8 @@ export function MobileSummary() {
|
||||
<Button
|
||||
variant="Primary"
|
||||
color="Primary"
|
||||
size="Large"
|
||||
size="lg"
|
||||
type="submit"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
isDisabled={selectedRates.state !== "ALL_SELECTED"}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -56,7 +56,7 @@ export function RoomPackagesForm({
|
||||
<Divider color="Border/Divider/Subtle" className={styles.divider} />
|
||||
<div className={styles.buttonContainer}>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<Button variant="Tertiary" size="Small" type="submit">
|
||||
<Button variant="Tertiary" size="sm" type="submit">
|
||||
{intl.formatMessage({
|
||||
id: "common.apply",
|
||||
defaultMessage: "Apply",
|
||||
@@ -64,11 +64,7 @@ export function RoomPackagesForm({
|
||||
</Button>
|
||||
</Typography>
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<Button
|
||||
onPress={clearSelectedPackages}
|
||||
size="Small"
|
||||
variant="Text"
|
||||
>
|
||||
<Button onPress={clearSelectedPackages} size="sm" variant="Text">
|
||||
{intl.formatMessage({
|
||||
id: "common.clear",
|
||||
defaultMessage: "Clear",
|
||||
|
||||
@@ -64,9 +64,12 @@ export function RoomPackageFilterModal({
|
||||
variant="Muted"
|
||||
emphasis
|
||||
onPress={() => setIsOpen(false)}
|
||||
>
|
||||
<MaterialIcon icon="close" size={24} color="CurrentColor" />
|
||||
</IconButton>
|
||||
aria-label={intl.formatMessage({
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
iconName="close"
|
||||
/>
|
||||
</div>
|
||||
<RoomPackagesForm
|
||||
close={() => setIsOpen(false)}
|
||||
|
||||
@@ -100,6 +100,7 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
|
||||
{filterLabel}
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
emphasis
|
||||
onPress={() => deletePackage(pkg.code)}
|
||||
aria-label={intl.formatMessage(
|
||||
{
|
||||
@@ -111,13 +112,9 @@ export function RoomPackageFilter({ roomIndex }: { roomIndex: number }) {
|
||||
}
|
||||
)}
|
||||
className={styles.removeButton}
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
size={16}
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
size="sm"
|
||||
/>
|
||||
</span>
|
||||
</Typography>
|
||||
)
|
||||
|
||||
@@ -55,8 +55,7 @@ export default function ParkingAccordionItem({
|
||||
href={parkingPageHref}
|
||||
variant="Secondary"
|
||||
color="Primary"
|
||||
size="Medium"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
size="md"
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "sideepek.parking.aboutParking",
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
import { useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
import { Button } from '../../Button'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { JsonToHtml } from '../../JsonToHtml/JsonToHtml'
|
||||
import { Button } from '../../Button'
|
||||
import SidePeek from '../../SidePeek'
|
||||
|
||||
import styles from './sidepeek.module.css'
|
||||
@@ -26,9 +26,7 @@ export default function AlertSidepeek({
|
||||
onPress={() => setSidePeekIsOpen(true)}
|
||||
variant="Text"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
wrapping
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
size="sm"
|
||||
>
|
||||
{ctaText}
|
||||
<MaterialIcon icon="chevron_right" size={20} color="CurrentColor" />
|
||||
|
||||
@@ -110,9 +110,8 @@ export function BookingCodeChip({
|
||||
id: 'booking.removeBookingCode',
|
||||
defaultMessage: 'Remove booking code',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" size={16} color={iconColor} />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
)}
|
||||
</IconChip>
|
||||
)
|
||||
|
||||
@@ -2,9 +2,8 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
|
||||
import { expect, fn } from 'storybook/test'
|
||||
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { config as typographyConfig } from '../Typography/variants'
|
||||
import { Button } from './Button'
|
||||
import { buttonIconNames } from './types'
|
||||
import { config as buttonConfig } from './variants'
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
@@ -13,12 +12,10 @@ const meta: Meta<typeof Button> = {
|
||||
argTypes: {
|
||||
onPress: {
|
||||
table: {
|
||||
disable: true,
|
||||
type: { summary: 'function' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
control: 'select',
|
||||
options: Object.keys(typographyConfig.variants.variant),
|
||||
description: 'Callback function to handle button press events.',
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
@@ -58,7 +55,7 @@ const meta: Meta<typeof Button> = {
|
||||
},
|
||||
},
|
||||
wrapping: {
|
||||
control: 'radio',
|
||||
control: 'boolean',
|
||||
options: Object.keys(buttonConfig.variants.wrapping),
|
||||
type: 'boolean',
|
||||
table: {
|
||||
@@ -69,6 +66,47 @@ const meta: Meta<typeof Button> = {
|
||||
description:
|
||||
'Only applies to variant `Text`. If `false`, the button will use smaller padding.',
|
||||
},
|
||||
leadingIconName: {
|
||||
control: 'select',
|
||||
options: buttonIconNames,
|
||||
table: {
|
||||
type: { summary: buttonIconNames.join(' | ') },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
description: 'Name of the Material Icon to use as leading icon.',
|
||||
},
|
||||
trailingIconName: {
|
||||
control: 'select',
|
||||
options: buttonIconNames,
|
||||
table: {
|
||||
type: { summary: buttonIconNames.join(' | ') },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
description: 'Name of the Material Icon to use as trailing icon.',
|
||||
},
|
||||
isDisabled: {
|
||||
control: 'boolean',
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
},
|
||||
},
|
||||
isPending: {
|
||||
control: 'boolean',
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
},
|
||||
},
|
||||
fullWidth: {
|
||||
control: 'boolean',
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
},
|
||||
description:
|
||||
'By default, the button width adjusts to its content. Set to true to make the button take the full width of its container.',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -83,7 +121,6 @@ export const Default: Story = {
|
||||
args: {
|
||||
onPress: fn(),
|
||||
children: 'Button',
|
||||
typography: 'Body/Paragraph/mdBold',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -95,7 +132,7 @@ export const PrimaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -106,7 +143,7 @@ export const PrimaryLarge: Story = {
|
||||
export const PrimaryMedium: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -117,8 +154,7 @@ export const PrimaryMedium: Story = {
|
||||
export const PrimarySmall: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -154,7 +190,6 @@ export const PrimaryOnDarkBackground: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
onPress: fn(), // Fresh spy instance
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -166,7 +201,7 @@ export const PrimaryInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
color: 'Inverted',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -179,7 +214,7 @@ export const PrimaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -191,8 +226,7 @@ export const PrimaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -230,7 +264,7 @@ export const SecondaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -241,7 +275,7 @@ export const SecondaryLarge: Story = {
|
||||
export const SecondaryMedium: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -252,8 +286,7 @@ export const SecondaryMedium: Story = {
|
||||
export const SecondarySmall: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -291,7 +324,7 @@ export const SecondaryInvertedLarge: Story = {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
color: 'Inverted',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -303,7 +336,7 @@ export const SecondaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -315,8 +348,7 @@ export const SecondaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -354,7 +386,7 @@ export const TertiaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Tertiary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -365,7 +397,7 @@ export const TertiaryLarge: Story = {
|
||||
export const TertiaryMedium: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -376,8 +408,7 @@ export const TertiaryMedium: Story = {
|
||||
export const TertiarySmall: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -413,7 +444,7 @@ export const TextLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -424,7 +455,7 @@ export const TextLarge: Story = {
|
||||
export const TextMedium: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -436,8 +467,7 @@ export const TextMedium: Story = {
|
||||
export const TextSmall: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -475,7 +505,7 @@ export const TextInvertedLarge: Story = {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
color: 'Inverted',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -487,7 +517,7 @@ export const TextInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -499,8 +529,7 @@ export const TextInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
@@ -524,12 +553,8 @@ export const TextInvertedDisabled: Story = {
|
||||
export const TextWithIcon: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
children: (
|
||||
<>
|
||||
Text with icon
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</>
|
||||
),
|
||||
children: 'Text with icon',
|
||||
trailingIconName: 'chevron_right',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { Button as ButtonRAC } from 'react-aria-components'
|
||||
import { Loading, type LoadingProps } from '../Loading/Loading'
|
||||
import { Loading } from '../Loading/Loading'
|
||||
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
import type { ButtonProps } from './types'
|
||||
import { variants } from './variants'
|
||||
|
||||
@@ -10,7 +12,8 @@ export function Button({
|
||||
size,
|
||||
wrapping,
|
||||
fullWidth,
|
||||
typography,
|
||||
leadingIconName,
|
||||
trailingIconName,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
@@ -20,32 +23,44 @@ export function Button({
|
||||
color,
|
||||
size,
|
||||
wrapping,
|
||||
typography,
|
||||
fullWidth,
|
||||
className,
|
||||
})
|
||||
|
||||
return (
|
||||
<ButtonRAC {...props} className={classNames}>
|
||||
{({ isPending, isHovered }) => {
|
||||
let loadingType: LoadingProps['type'] = 'White'
|
||||
if (variant === 'Secondary') {
|
||||
if (isHovered || color !== 'Inverted') {
|
||||
loadingType = 'Dark'
|
||||
}
|
||||
} else {
|
||||
if (color === 'Inverted') {
|
||||
loadingType = 'Dark'
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
{isPending && <Loading size={20} type={loadingType} />}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
</ButtonRAC>
|
||||
<Typography
|
||||
variant={
|
||||
size === 'sm'
|
||||
? 'Body/Supporting text (caption)/smBold'
|
||||
: 'Body/Paragraph/mdBold'
|
||||
}
|
||||
>
|
||||
<ButtonRAC {...props} className={classNames}>
|
||||
{({ isPending }) => {
|
||||
return (
|
||||
<>
|
||||
{leadingIconName && !isPending ? (
|
||||
<MaterialIcon
|
||||
icon={leadingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{children}
|
||||
{trailingIconName && !isPending ? (
|
||||
<MaterialIcon
|
||||
icon={trailingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{isPending ? (
|
||||
<Loading size={size === 'sm' ? 18 : 20} type="CurrentColor" />
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
</ButtonRAC>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -37,15 +37,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.size-large {
|
||||
.size-lg {
|
||||
padding: calc(var(--Space-x2) - 2px) var(--Space-x3); /* Adjust for 2px border */
|
||||
}
|
||||
|
||||
.size-medium {
|
||||
.size-md {
|
||||
padding: calc(var(--Space-x15) - 2px) var(--Space-x2); /* Adjust for 2px border */
|
||||
}
|
||||
|
||||
.size-small {
|
||||
.size-sm {
|
||||
padding: var(--Space-x1) var(--Space-x2); /* Adjust for 2px border */
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,35 @@ import { Button } from 'react-aria-components'
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import type { ComponentProps } from 'react'
|
||||
|
||||
import type { SymbolCodepoints } from '../Icons/MaterialIcon/MaterialSymbol/types'
|
||||
import type { variants } from './variants'
|
||||
|
||||
export const buttonIconNames = [
|
||||
'add_circle',
|
||||
'open_in_new',
|
||||
'keyboard_arrow_down',
|
||||
'keyboard_arrow_up',
|
||||
'edit_square',
|
||||
'location_on',
|
||||
'link',
|
||||
'mail',
|
||||
'cancel',
|
||||
'calendar_month',
|
||||
'calendar_clock',
|
||||
'edit_calendar',
|
||||
'calendar_add_on',
|
||||
'delete',
|
||||
'chevron_right',
|
||||
'chevron_left',
|
||||
] as const
|
||||
|
||||
export type ButtonIconName = Extract<
|
||||
SymbolCodepoints,
|
||||
(typeof buttonIconNames)[number]
|
||||
>
|
||||
|
||||
export interface ButtonProps
|
||||
extends ComponentProps<typeof Button>,
|
||||
VariantProps<typeof variants> {}
|
||||
extends ComponentProps<typeof Button>, VariantProps<typeof variants> {
|
||||
leadingIconName?: ButtonIconName | null
|
||||
trailingIconName?: ButtonIconName | null
|
||||
}
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
|
||||
import {
|
||||
config as typographyConfig,
|
||||
withTypography,
|
||||
} from '../Typography/variants'
|
||||
|
||||
import { deepmerge } from 'deepmerge-ts'
|
||||
import styles from './button.module.css'
|
||||
@@ -14,7 +10,6 @@ export const config = {
|
||||
Primary: styles['variant-primary'],
|
||||
Secondary: styles['variant-secondary'],
|
||||
Tertiary: styles['variant-tertiary'],
|
||||
Inverted: styles['variant-inverted'],
|
||||
Text: styles['variant-text'],
|
||||
},
|
||||
color: {
|
||||
@@ -22,9 +17,9 @@ export const config = {
|
||||
Inverted: styles['color-inverted'],
|
||||
},
|
||||
size: {
|
||||
Small: styles['size-small'],
|
||||
Medium: styles['size-medium'],
|
||||
Large: styles['size-large'],
|
||||
sm: styles['size-sm'],
|
||||
md: styles['size-md'],
|
||||
lg: styles['size-lg'],
|
||||
},
|
||||
wrapping: {
|
||||
true: undefined,
|
||||
@@ -38,24 +33,21 @@ export const config = {
|
||||
defaultVariants: {
|
||||
variant: 'Primary',
|
||||
color: 'Primary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
wrapping: true,
|
||||
fullWidth: false,
|
||||
},
|
||||
} as const
|
||||
|
||||
const buttonConfig = {
|
||||
variants: {
|
||||
...config.variants,
|
||||
typography: typographyConfig.variants.variant,
|
||||
},
|
||||
defaultVariants: {
|
||||
...config.defaultVariants,
|
||||
typography: 'Body/Paragraph/mdBold',
|
||||
},
|
||||
} as const
|
||||
|
||||
export const variants = cva(styles.button, withTypography(buttonConfig))
|
||||
export const variants = cva(styles.button, buttonConfig)
|
||||
|
||||
export function withButton<T>(config: T) {
|
||||
return deepmerge(buttonConfig, config)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
|
||||
import { expect } from 'storybook/test'
|
||||
import { expect, fn } from 'storybook/test'
|
||||
|
||||
import ButtonLink from '.'
|
||||
import { config as buttonConfig } from '../Button/variants'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { config as typographyConfig } from '../Typography/variants'
|
||||
import buttonMeta from '../Button/Button.stories'
|
||||
|
||||
const meta: Meta<typeof ButtonLink> = {
|
||||
title: 'Core Components/ButtonLink',
|
||||
@@ -13,64 +11,24 @@ const meta: Meta<typeof ButtonLink> = {
|
||||
argTypes: {
|
||||
onClick: {
|
||||
table: {
|
||||
disable: true,
|
||||
type: { summary: 'function' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
description: 'Callback function to handle link click events.',
|
||||
},
|
||||
typography: {
|
||||
control: 'select',
|
||||
options: Object.keys(typographyConfig.variants.variant),
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
options: Object.keys(buttonConfig.variants.variant),
|
||||
default: 'Primary',
|
||||
variant: buttonMeta.argTypes?.variant,
|
||||
color: buttonMeta.argTypes?.color,
|
||||
size: buttonMeta.argTypes?.size,
|
||||
wrapping: buttonMeta.argTypes?.wrapping,
|
||||
leadingIconName: buttonMeta.argTypes?.leadingIconName,
|
||||
trailingIconName: buttonMeta.argTypes?.trailingIconName,
|
||||
fullWidth: buttonMeta.argTypes?.fullWidth,
|
||||
href: {
|
||||
table: {
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.variant,
|
||||
},
|
||||
type: {
|
||||
summary: 'string',
|
||||
detail: Object.keys(buttonConfig.variants.variant).join(' | '),
|
||||
},
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
},
|
||||
color: {
|
||||
control: 'select',
|
||||
options: Object.keys(buttonConfig.variants.color),
|
||||
table: {
|
||||
type: {
|
||||
summary: 'string',
|
||||
detail: Object.keys(buttonConfig.variants.color).join(' | '),
|
||||
},
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.color,
|
||||
},
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: 'select',
|
||||
options: Object.keys(buttonConfig.variants.size),
|
||||
table: {
|
||||
type: {
|
||||
summary: 'string',
|
||||
detail: Object.keys(buttonConfig.variants.size).join(' | '),
|
||||
},
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.size,
|
||||
},
|
||||
},
|
||||
},
|
||||
wrapping: {
|
||||
control: 'radio',
|
||||
options: Object.keys(buttonConfig.variants.wrapping),
|
||||
type: 'boolean',
|
||||
table: {
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.wrapping.toString(),
|
||||
},
|
||||
},
|
||||
description:
|
||||
'Only applies to variant `Text`. If `false`, the button will use smaller padding.',
|
||||
description: 'The URL that the link points to.',
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -84,13 +42,9 @@ type Story = StoryObj<typeof ButtonLink>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onClick: (event) => {
|
||||
event.preventDefault()
|
||||
alert('Button link clicked!')
|
||||
},
|
||||
onClick: fn(),
|
||||
href: '#',
|
||||
children: 'Button link',
|
||||
typography: 'Body/Paragraph/mdBold',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -103,7 +57,7 @@ export const PrimaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -115,7 +69,7 @@ export const PrimaryLarge: Story = {
|
||||
export const PrimaryMedium: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -127,8 +81,7 @@ export const PrimaryMedium: Story = {
|
||||
export const PrimarySmall: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -142,7 +95,7 @@ export const PrimaryOnDarkBackground: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -157,7 +110,7 @@ export const PrimaryInvertedLarge: Story = {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
color: 'Inverted',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
@@ -171,9 +124,8 @@ export const PrimaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -185,10 +137,8 @@ export const PrimaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -200,9 +150,8 @@ export const SecondaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -213,9 +162,8 @@ export const SecondaryLarge: Story = {
|
||||
export const SecondaryMedium: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -226,10 +174,8 @@ export const SecondaryMedium: Story = {
|
||||
export const SecondarySmall: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -243,9 +189,8 @@ export const SecondaryInvertedLarge: Story = {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
color: 'Inverted',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -257,9 +202,8 @@ export const SecondaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -271,10 +215,8 @@ export const SecondaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -286,9 +228,8 @@ export const TertiaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Tertiary',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -299,9 +240,8 @@ export const TertiaryLarge: Story = {
|
||||
export const TertiaryMedium: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -312,10 +252,8 @@ export const TertiaryMedium: Story = {
|
||||
export const TertiarySmall: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -327,9 +265,8 @@ export const TextLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -340,9 +277,8 @@ export const TextLarge: Story = {
|
||||
export const TextMedium: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -353,10 +289,8 @@ export const TextMedium: Story = {
|
||||
export const TextSmall: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -383,9 +317,8 @@ export const TextInvertedLarge: Story = {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
color: 'Inverted',
|
||||
size: 'Large',
|
||||
size: 'lg',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -397,9 +330,8 @@ export const TextInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'Medium',
|
||||
size: 'md',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -411,10 +343,8 @@ export const TextInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
typography: 'Body/Supporting text (caption)/smBold',
|
||||
size: 'Small',
|
||||
size: 'sm',
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
@@ -426,12 +356,8 @@ export const TextWithIcon: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
children: (
|
||||
<>
|
||||
Text with icon
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</>
|
||||
),
|
||||
children: 'Text with icon',
|
||||
trailingIconName: 'chevron_right',
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
@@ -445,12 +371,6 @@ export const TextWithIconInverted: Story = {
|
||||
args: {
|
||||
...TextWithIcon.args,
|
||||
color: 'Inverted',
|
||||
children: (
|
||||
<>
|
||||
Text with icon
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</>
|
||||
),
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
|
||||
@@ -7,22 +7,30 @@ import { variants } from './variants'
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import Link from 'next/link'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { ButtonIconName } from '../Button/types'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
export interface ButtonLinkProps
|
||||
extends
|
||||
Omit<ComponentProps<typeof Link>, 'color'>,
|
||||
VariantProps<typeof variants> {}
|
||||
VariantProps<typeof variants> {
|
||||
leadingIconName?: ButtonIconName | null
|
||||
trailingIconName?: ButtonIconName | null
|
||||
}
|
||||
|
||||
export default function ButtonLink({
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
typography,
|
||||
wrapping,
|
||||
fullWidth,
|
||||
className,
|
||||
href,
|
||||
target,
|
||||
leadingIconName,
|
||||
trailingIconName,
|
||||
children,
|
||||
...props
|
||||
}: ButtonLinkProps) {
|
||||
const classNames = variants({
|
||||
@@ -30,7 +38,6 @@ export default function ButtonLink({
|
||||
color,
|
||||
size,
|
||||
wrapping,
|
||||
typography,
|
||||
fullWidth,
|
||||
className,
|
||||
})
|
||||
@@ -42,12 +49,36 @@ export default function ButtonLink({
|
||||
})
|
||||
|
||||
return (
|
||||
<Link
|
||||
className={classNames}
|
||||
href={href}
|
||||
target={target}
|
||||
title={target === '_blank' ? newTabText : ''}
|
||||
{...props}
|
||||
/>
|
||||
<Typography
|
||||
variant={
|
||||
size === 'sm'
|
||||
? 'Body/Supporting text (caption)/smBold'
|
||||
: 'Body/Paragraph/mdBold'
|
||||
}
|
||||
>
|
||||
<Link
|
||||
className={classNames}
|
||||
href={href}
|
||||
target={target}
|
||||
title={target === '_blank' ? newTabText : ''}
|
||||
{...props}
|
||||
>
|
||||
{leadingIconName ? (
|
||||
<MaterialIcon
|
||||
icon={leadingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{children}
|
||||
{trailingIconName ? (
|
||||
<MaterialIcon
|
||||
icon={trailingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
</Link>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import { fn } from 'storybook/test'
|
||||
import { themes } from '../../../../.storybook/preview'
|
||||
|
||||
import { Card } from '../'
|
||||
import { Typography } from '../../Typography'
|
||||
import { Button } from '../../Button'
|
||||
import { Typography } from '../../Typography'
|
||||
|
||||
type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & {
|
||||
_onPrimaryPress?: () => void
|
||||
@@ -97,33 +97,22 @@ const meta: Meta<CompositionProps> = {
|
||||
)}
|
||||
|
||||
{showPrimaryButton && inMainArea && (
|
||||
<Button
|
||||
size="Large"
|
||||
variant="Primary"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
onPress={args._onPrimaryPress}
|
||||
>
|
||||
<Button size="lg" variant="Primary" onPress={args._onPrimaryPress}>
|
||||
Primary action
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{showPrimaryButton && !inMainArea && (
|
||||
<Button
|
||||
size="Small"
|
||||
variant="Tertiary"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
onPress={args._onPrimaryPress}
|
||||
>
|
||||
<Button size="sm" variant="Tertiary" onPress={args._onPrimaryPress}>
|
||||
Primary action
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{showSecondaryButton && (
|
||||
<Button
|
||||
size={inMainArea ? 'Large' : 'Small'}
|
||||
size={inMainArea ? 'lg' : 'sm'}
|
||||
variant="Secondary"
|
||||
onPress={args._onSecondaryPress}
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
Secondary action
|
||||
</Button>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { variants } from './variants'
|
||||
|
||||
import { cx, type VariantProps } from 'class-variance-authority'
|
||||
import type { HTMLAttributes } from 'react'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
interface FakeButtonProps
|
||||
extends
|
||||
@@ -16,7 +17,6 @@ export function FakeButton({
|
||||
variant,
|
||||
color,
|
||||
size,
|
||||
typography,
|
||||
fullWidth,
|
||||
children,
|
||||
className,
|
||||
@@ -28,19 +28,26 @@ export function FakeButton({
|
||||
color,
|
||||
size,
|
||||
variant,
|
||||
typography,
|
||||
fullWidth,
|
||||
isHovered,
|
||||
className,
|
||||
})
|
||||
|
||||
return (
|
||||
<span
|
||||
className={cx(classNames)}
|
||||
data-disabled={isDisabled || undefined}
|
||||
{...props}
|
||||
<Typography
|
||||
variant={
|
||||
size === 'sm'
|
||||
? 'Body/Supporting text (caption)/smBold'
|
||||
: 'Body/Paragraph/mdBold'
|
||||
}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
<span
|
||||
className={cx(classNames)}
|
||||
data-disabled={isDisabled || undefined}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
</Typography>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { fn } from 'storybook/test'
|
||||
import { useEffect } from 'react'
|
||||
import { FormProvider, useForm } from 'react-hook-form'
|
||||
import { zodResolver } from '@hookform/resolvers/zod'
|
||||
import { fn } from 'storybook/test'
|
||||
import { z } from 'zod'
|
||||
|
||||
import { FormInput } from '../FormInput'
|
||||
import { Button } from '../../Button'
|
||||
import { Typography } from '../../Typography'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../Typography'
|
||||
import { FormInput } from '../FormInput'
|
||||
|
||||
const createExampleFormSchema = (prefix?: string) => {
|
||||
const getKey = (key: string) => (prefix ? `${prefix}_${key}` : key)
|
||||
@@ -127,7 +127,7 @@ function ExampleFormComponent({
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
|
||||
<Button type="submit" variant="Primary" size="Large">
|
||||
<Button type="submit" variant="Primary" size="lg">
|
||||
Send message
|
||||
</Button>
|
||||
</form>
|
||||
@@ -292,7 +292,7 @@ function SignupFormComponent({
|
||||
registerOptions={{ required: true }}
|
||||
/>
|
||||
|
||||
<Button type="submit" variant="Primary" size="Large">
|
||||
<Button type="submit" variant="Primary" size="lg">
|
||||
Create account
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
@@ -76,11 +76,7 @@ export const Default: Story = {
|
||||
],
|
||||
|
||||
belowInfoSlot: (
|
||||
<Button
|
||||
onPress={() => fn()}
|
||||
variant="Text"
|
||||
typography="Body/Paragraph/mdBold"
|
||||
>
|
||||
<Button onPress={() => fn()} variant="Text">
|
||||
Read more
|
||||
<MaterialIcon icon="chevron_right" size={24} color="CurrentColor" />
|
||||
</Button>
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
import { IconButton } from '../../../IconButton'
|
||||
import { MaterialIcon } from '../../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../../Typography'
|
||||
|
||||
import { HotelCardDialogImage } from '../../HotelCardDialogImage'
|
||||
@@ -84,9 +83,8 @@ export function StandaloneHotelCardDialog({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" size={22} color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
<HotelCardDialogImage
|
||||
imageSrc={image?.url}
|
||||
altText={image?.alt}
|
||||
@@ -187,7 +185,7 @@ export function StandaloneHotelCardDialog({
|
||||
href={selectRateUrl}
|
||||
variant="Primary"
|
||||
color="Primary"
|
||||
size="Small"
|
||||
size="sm"
|
||||
onClick={onClick}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
|
||||
@@ -364,9 +364,8 @@ export const HotelCardComponent = memo(
|
||||
) : null}
|
||||
<FakeButton
|
||||
variant="Primary"
|
||||
size="Medium"
|
||||
size="md"
|
||||
isDisabled={!!isDisabled}
|
||||
typography="Body/Paragraph/mdBold"
|
||||
isHovered={isPricesHovered}
|
||||
>
|
||||
{isDisabled
|
||||
|
||||
@@ -69,11 +69,7 @@ export const Default: Story = {
|
||||
mapping: {
|
||||
none: null,
|
||||
button: (
|
||||
<Button
|
||||
variant="Text"
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
onPress={() => fn()}
|
||||
>
|
||||
<Button variant="Text" onPress={() => fn()}>
|
||||
Read more <MaterialIcon icon="chevron_right" />
|
||||
</Button>
|
||||
),
|
||||
|
||||
@@ -2,8 +2,8 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
|
||||
import { expect, fn } from 'storybook/test'
|
||||
|
||||
import { MaterialIcon, MaterialIconProps } from '../Icons/MaterialIcon'
|
||||
import { IconButton } from './IconButton'
|
||||
import { iconButtonIconNames, IconButtonProps } from './types'
|
||||
import { config } from './variants'
|
||||
|
||||
const meta: Meta<typeof IconButton> = {
|
||||
@@ -12,13 +12,10 @@ const meta: Meta<typeof IconButton> = {
|
||||
argTypes: {
|
||||
onPress: {
|
||||
table: {
|
||||
disable: true,
|
||||
},
|
||||
},
|
||||
children: {
|
||||
table: {
|
||||
disable: true,
|
||||
type: { summary: 'function' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
description: 'Callback function to handle button press events.',
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
@@ -58,43 +55,25 @@ const meta: Meta<typeof IconButton> = {
|
||||
},
|
||||
},
|
||||
},
|
||||
iconName: {
|
||||
control: 'select',
|
||||
options: iconButtonIconNames,
|
||||
table: {
|
||||
type: { summary: iconButtonIconNames.join(' | ') },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
},
|
||||
description: 'Name of the Material Icon to use as icon.',
|
||||
},
|
||||
isDisabled: {
|
||||
control: 'boolean',
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const buttonAndIconSizesMap = Object.keys(config.variants.size).map<{
|
||||
size: keyof typeof config.variants.size
|
||||
iconSize: number
|
||||
}>((key) => {
|
||||
const typedKey = key as keyof typeof config.variants.size
|
||||
switch (typedKey) {
|
||||
case 'sm':
|
||||
return {
|
||||
size: typedKey,
|
||||
iconSize: 16,
|
||||
}
|
||||
case 'md':
|
||||
return {
|
||||
size: typedKey,
|
||||
iconSize: 20,
|
||||
}
|
||||
case 'lg':
|
||||
return {
|
||||
size: typedKey,
|
||||
iconSize: 24,
|
||||
}
|
||||
case 'xl':
|
||||
return {
|
||||
size: typedKey,
|
||||
iconSize: 28,
|
||||
}
|
||||
default:
|
||||
return {
|
||||
size: typedKey,
|
||||
iconSize: 24,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const globalStoryPropsInverted = {
|
||||
backgrounds: { value: 'scandicPrimaryDark' },
|
||||
}
|
||||
@@ -104,11 +83,11 @@ type Story = StoryObj<typeof IconButton>
|
||||
|
||||
function renderAllSizesFn(
|
||||
args: Story['args'],
|
||||
iconName: MaterialIconProps['icon'] = 'search'
|
||||
iconName: IconButtonProps['iconName'] = 'search'
|
||||
) {
|
||||
return (
|
||||
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}>
|
||||
{buttonAndIconSizesMap.map(({ size, iconSize }) => (
|
||||
{Object.keys(config.variants.size).map((size) => (
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
@@ -118,13 +97,12 @@ function renderAllSizesFn(
|
||||
}}
|
||||
key={size}
|
||||
>
|
||||
<IconButton {...args} size={size} key={size}>
|
||||
<MaterialIcon
|
||||
icon={iconName}
|
||||
size={iconSize}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</IconButton>
|
||||
<IconButton
|
||||
{...args}
|
||||
iconName={iconName}
|
||||
size={size as keyof typeof config.variants.size}
|
||||
key={size}
|
||||
/>
|
||||
<span>{size}</span>
|
||||
</div>
|
||||
))}
|
||||
@@ -135,7 +113,7 @@ function renderAllSizesFn(
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onPress: fn(),
|
||||
children: <MaterialIcon icon="search" size={24} color="CurrentColor" />,
|
||||
iconName: 'search',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(canvas.getByRole('button'))
|
||||
@@ -283,6 +261,7 @@ export const Examples: Story = {
|
||||
)
|
||||
},
|
||||
}
|
||||
|
||||
export const Filled: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
@@ -319,9 +298,7 @@ export const FilledOnDarkBackground: Story = {
|
||||
export const FilledWithEmphasis: Story = {
|
||||
args: {
|
||||
...Filled.args,
|
||||
children: (
|
||||
<MaterialIcon icon="arrow_forward" size={24} color="CurrentColor" />
|
||||
),
|
||||
iconName: 'arrow_forward',
|
||||
emphasis: true,
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -344,9 +321,7 @@ export const FilledWithEmphasisDisabled: Story = {
|
||||
export const Outlined: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
children: (
|
||||
<MaterialIcon icon="arrow_forward" size={24} color="CurrentColor" />
|
||||
),
|
||||
iconName: 'arrow_forward',
|
||||
variant: 'Outlined',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -369,9 +344,7 @@ export const OutlinedDisabled: Story = {
|
||||
export const Elevated: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
children: (
|
||||
<MaterialIcon icon="arrow_forward" size={24} color="CurrentColor" />
|
||||
),
|
||||
iconName: 'arrow_forward',
|
||||
variant: 'Elevated',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -395,9 +368,7 @@ export const Faded: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
children: (
|
||||
<MaterialIcon icon="arrow_forward" size={24} color="CurrentColor" />
|
||||
),
|
||||
iconName: 'arrow_forward',
|
||||
variant: 'Faded',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
@@ -422,9 +393,7 @@ export const Muted: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
children: (
|
||||
<MaterialIcon icon="arrow_forward" size={24} color="CurrentColor" />
|
||||
),
|
||||
iconName: 'arrow_forward',
|
||||
variant: 'Muted',
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
import { Button as ButtonRAC } from 'react-aria-components'
|
||||
|
||||
import { VariantProps } from 'class-variance-authority'
|
||||
import { ComponentProps } from 'react'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { IconButtonProps } from './types'
|
||||
import { variants } from './variants'
|
||||
|
||||
interface IconButtonProps
|
||||
extends ComponentProps<typeof ButtonRAC>, VariantProps<typeof variants> {}
|
||||
|
||||
export function IconButton({
|
||||
variant,
|
||||
emphasis,
|
||||
size,
|
||||
iconName,
|
||||
className,
|
||||
...props
|
||||
}: IconButtonProps) {
|
||||
@@ -21,5 +19,27 @@ export function IconButton({
|
||||
className,
|
||||
})
|
||||
|
||||
return <ButtonRAC {...props} className={classNames} />
|
||||
return (
|
||||
<ButtonRAC {...props} className={classNames}>
|
||||
<MaterialIcon
|
||||
icon={iconName}
|
||||
size={getIconSize(size)}
|
||||
color="CurrentColor"
|
||||
/>
|
||||
</ButtonRAC>
|
||||
)
|
||||
}
|
||||
|
||||
function getIconSize(size: IconButtonProps['size']) {
|
||||
switch (size) {
|
||||
case 'sm':
|
||||
return 16
|
||||
case 'md':
|
||||
return 20
|
||||
case 'xl':
|
||||
return 28
|
||||
case 'lg':
|
||||
default:
|
||||
return 24
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@
|
||||
|
||||
&.emphasis {
|
||||
background-color: var(--Component-Button-Brand-Tertiary-Fill-Default);
|
||||
color: var(--Component-Button-Brand-Tertiary-On-fill-Default);
|
||||
color: inherit;
|
||||
|
||||
&[data-disabled] {
|
||||
background-color: var(--Component-Button-Brand-Tertiary-Fill-Disabled);
|
||||
@@ -231,7 +231,7 @@
|
||||
}
|
||||
|
||||
&.emphasis {
|
||||
color: var(--Component-Button-Muted-On-fill-Default);
|
||||
color: inherit;
|
||||
|
||||
&[data-disabled] {
|
||||
background-color: var(--Component-Button-Muted-Fill-Disabled-inverted);
|
||||
|
||||
39
packages/design-system/lib/components/IconButton/types.ts
Normal file
39
packages/design-system/lib/components/IconButton/types.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import { Button as ButtonRAC } from 'react-aria-components'
|
||||
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import type { ComponentProps } from 'react'
|
||||
|
||||
import type { SymbolCodepoints } from '../Icons/MaterialIcon/MaterialSymbol/types'
|
||||
import type { variants } from './variants'
|
||||
|
||||
export const iconButtonIconNames = [
|
||||
'arrow_forward',
|
||||
'arrow_back',
|
||||
'remove',
|
||||
'close',
|
||||
'add',
|
||||
'search',
|
||||
'info_circle',
|
||||
'help_circle',
|
||||
'info',
|
||||
'delete',
|
||||
'visibility',
|
||||
'visibility_off',
|
||||
'keyboard_arrow_down',
|
||||
'keyboard_arrow_up',
|
||||
'cancel',
|
||||
'chevron_left',
|
||||
'chevron_right',
|
||||
] as const
|
||||
|
||||
export type IconButtonIconName = Extract<
|
||||
SymbolCodepoints,
|
||||
(typeof iconButtonIconNames)[number]
|
||||
>
|
||||
|
||||
export interface IconButtonProps
|
||||
extends
|
||||
Omit<ComponentProps<typeof ButtonRAC>, 'children'>,
|
||||
VariantProps<typeof variants> {
|
||||
iconName: IconButtonIconName
|
||||
}
|
||||
@@ -71,9 +71,8 @@ export function InfoCard({
|
||||
<div className={styles.buttonContainer}>
|
||||
{primaryButton ? (
|
||||
<ButtonLink
|
||||
size="Small"
|
||||
size="sm"
|
||||
href={primaryButton.href}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
onClick={primaryButton.onClick}
|
||||
scroll={primaryButton.scrollOnClick ?? false}
|
||||
{...buttonProps.primaryButton}
|
||||
@@ -83,9 +82,8 @@ export function InfoCard({
|
||||
) : null}
|
||||
{secondaryButton ? (
|
||||
<ButtonLink
|
||||
size="Small"
|
||||
size="sm"
|
||||
href={secondaryButton.href}
|
||||
typography="Body/Supporting text (caption)/smBold"
|
||||
onClick={secondaryButton.onClick}
|
||||
scroll={secondaryButton.scrollOnClick ?? false}
|
||||
{...buttonProps.secondaryButton}
|
||||
|
||||
@@ -130,6 +130,7 @@ const meta: Meta<typeof Input> = {
|
||||
defaultValue: { summary: 'false' },
|
||||
},
|
||||
},
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any,
|
||||
}
|
||||
|
||||
@@ -147,6 +148,7 @@ export const Default: Story = {
|
||||
leftIconName: 'person',
|
||||
rightIconName: 'lock',
|
||||
showWarning: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
} as any,
|
||||
render: (args) => {
|
||||
// Extract custom Storybook args
|
||||
|
||||
@@ -13,7 +13,6 @@ import { InputLabel } from '../InputLabel'
|
||||
import styles from './input.module.css'
|
||||
|
||||
import { IconButton } from '../IconButton'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
import type { InputProps } from './types'
|
||||
import { clearInput, useInputHasValue } from './utils'
|
||||
@@ -113,9 +112,8 @@ const InputComponent = forwardRef(function AriaInputWithLabelComponent(
|
||||
onPress={onClearContent}
|
||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
aria-label="Clear content"
|
||||
>
|
||||
<MaterialIcon icon="cancel" />
|
||||
</IconButton>
|
||||
iconName="cancel"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{rightIcon && !(showClearContentIcon && hasValue) && (
|
||||
@@ -162,9 +160,8 @@ const InputComponent = forwardRef(function AriaInputWithLabelComponent(
|
||||
onPress={onClearContent}
|
||||
// eslint-disable-next-line formatjs/no-literal-string-in-jsx
|
||||
aria-label="Clear content"
|
||||
>
|
||||
<MaterialIcon icon="cancel" />
|
||||
</IconButton>
|
||||
iconName="cancel"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{rightIcon && !(showClearContentIcon && hasValue) && (
|
||||
|
||||
@@ -22,6 +22,7 @@ export function InputLabel({
|
||||
return (
|
||||
<span className={classNames} {...rest}>
|
||||
{children}
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{required && <span aria-hidden="true">{' *'}</span>}
|
||||
</span>
|
||||
)
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useIntl } from 'react-intl'
|
||||
import Image from '../../Image'
|
||||
|
||||
import { IconButton } from '../../IconButton'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../Typography'
|
||||
|
||||
import { LightboxImage } from '../index'
|
||||
@@ -94,9 +93,8 @@ export default function FullView({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" color="CurrentColor" size={24} />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
<div className={styles.header}>
|
||||
<Typography variant="Tag/sm">
|
||||
<span className={styles.imageCount}>
|
||||
@@ -141,16 +139,14 @@ export default function FullView({
|
||||
variant="Muted"
|
||||
className={`${styles.navigationButton} ${styles.prev}`}
|
||||
onPress={handlePrev}
|
||||
>
|
||||
<MaterialIcon icon="arrow_back" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="arrow_back"
|
||||
/>
|
||||
<IconButton
|
||||
variant="Muted"
|
||||
className={`${styles.navigationButton} ${styles.next}`}
|
||||
onPress={handleNext}
|
||||
>
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="arrow_forward"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,12 @@ import { Button as ButtonRAC } from 'react-aria-components'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
import { IconButton } from '../../IconButton'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../Typography'
|
||||
|
||||
import Image from '../../Image'
|
||||
|
||||
import { cx } from 'class-variance-authority'
|
||||
import { useMediaQuery } from 'usehooks-ts'
|
||||
import { LightboxImage } from '..'
|
||||
import styles from './gallery.module.css'
|
||||
|
||||
@@ -35,6 +35,7 @@ export default function Gallery({
|
||||
const [animateLeft, setAnimateLeft] = useState(true)
|
||||
const mainImage = selectedImage || images[0]
|
||||
const mainImageIndex = images.findIndex((img) => img === mainImage)
|
||||
const isMobile = useMediaQuery('(max-width: 767px)')
|
||||
|
||||
function getThumbImages() {
|
||||
const thumbs = []
|
||||
@@ -96,20 +97,8 @@ export default function Gallery({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="chevron_left"
|
||||
color="CurrentColor"
|
||||
size={24}
|
||||
className={styles.mobileCloseIcon}
|
||||
/>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
color="CurrentColor"
|
||||
size={24}
|
||||
className={styles.desktopCloseIcon}
|
||||
/>
|
||||
</IconButton>
|
||||
iconName={isMobile ? 'chevron_left' : 'close'}
|
||||
/>
|
||||
|
||||
{/* Desktop Gallery */}
|
||||
<div className={styles.desktopGallery}>
|
||||
@@ -156,9 +145,8 @@ export default function Gallery({
|
||||
id: 'lightbox.previousImage',
|
||||
defaultMessage: 'Previous image',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="arrow_back" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="arrow_back"
|
||||
/>
|
||||
<IconButton
|
||||
variant="Elevated"
|
||||
className={cx(styles.navigationButton, styles.next)}
|
||||
@@ -167,9 +155,8 @@ export default function Gallery({
|
||||
id: 'lightbox.nextImage',
|
||||
defaultMessage: 'Next image',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="arrow_forward" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="arrow_forward"
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.desktopThumbnailGrid}>
|
||||
<AnimatePresence initial={false}>
|
||||
|
||||
@@ -45,6 +45,10 @@
|
||||
&.white circle {
|
||||
fill: var(--Icon-Inverted);
|
||||
}
|
||||
|
||||
&.currentColor circle {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
|
||||
@@ -7,6 +7,7 @@ export const config = {
|
||||
type: {
|
||||
Dark: styles.dark,
|
||||
White: styles.white,
|
||||
CurrentColor: styles.currentColor,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
|
||||
@@ -5,7 +5,6 @@ import { useEffect, useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
import { IconButton } from '../../IconButton'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
|
||||
import { HOTEL_PAGE, MAP_RESTRICTIONS } from '../mapConstants'
|
||||
|
||||
@@ -150,9 +149,8 @@ export function InteractiveMap({
|
||||
defaultMessage: 'Zoom out',
|
||||
})}
|
||||
isDisabled={isMinZoom}
|
||||
>
|
||||
<MaterialIcon icon="remove" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="remove"
|
||||
/>
|
||||
|
||||
<IconButton
|
||||
variant="Elevated"
|
||||
@@ -163,9 +161,8 @@ export function InteractiveMap({
|
||||
defaultMessage: 'Zoom in',
|
||||
})}
|
||||
isDisabled={isMaxZoom}
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="add"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
} from 'react-aria-components'
|
||||
import { useIntl } from 'react-intl'
|
||||
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
|
||||
import {
|
||||
type AnimationState,
|
||||
@@ -126,13 +125,8 @@ function InnerModal({
|
||||
})}
|
||||
variant="Muted"
|
||||
emphasis
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
color="Icon/Feedback/Neutral"
|
||||
size={24}
|
||||
/>
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
</header>
|
||||
)}
|
||||
|
||||
|
||||
@@ -86,12 +86,7 @@ export default function ParkingInformation({
|
||||
</div>
|
||||
</div>
|
||||
{parking.externalParkingUrl && showExternalParkingButton && (
|
||||
<ButtonLink
|
||||
typography="Body/Paragraph/mdBold"
|
||||
size="Medium"
|
||||
href={parking.externalParkingUrl}
|
||||
target="_blank"
|
||||
>
|
||||
<ButtonLink size="md" href={parking.externalParkingUrl} target="_blank">
|
||||
{intl.formatMessage({
|
||||
id: 'parkingInformation.bookParking',
|
||||
defaultMessage: 'Book parking',
|
||||
|
||||
@@ -87,9 +87,8 @@ export default function CampaignRateCard({
|
||||
id: 'selectRate.rateCard.openReservationPolicy',
|
||||
defaultMessage: 'Open reservation policy',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="Icon/Default" />
|
||||
</IconButton>
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
|
||||
@@ -77,9 +77,8 @@ export default function CodeRateCard({
|
||||
id: 'selectRate.rateCard.openReservationPolicy',
|
||||
defaultMessage: 'Open reservation policy',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="Icon/Default" />
|
||||
</IconButton>
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
|
||||
@@ -19,7 +19,6 @@ import { fade, slideInOut } from './motionVariants'
|
||||
|
||||
import { useIntl } from 'react-intl'
|
||||
import { IconButton } from '../../IconButton'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../Typography'
|
||||
import styles from './modal.module.css'
|
||||
|
||||
@@ -98,9 +97,8 @@ function InnerModal({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="close" size={24} color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
</header>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { IconButton } from '../../IconButton'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { Typography } from '../../Typography'
|
||||
import styles from '../rate-card.module.css'
|
||||
import { variants } from '../variants'
|
||||
@@ -34,9 +33,7 @@ export default function NoRateAvailableCard({
|
||||
<header>
|
||||
<Typography variant="Tag/sm">
|
||||
<h3 className={`${styles.title} ${styles.textDisabled}`}>
|
||||
<IconButton variant="Muted" emphasis size="sm">
|
||||
<MaterialIcon icon="info" size={20} color="Icon/Default" />
|
||||
</IconButton>
|
||||
<IconButton variant="Muted" emphasis size="sm" iconName="info" />
|
||||
{/* eslint-disable-next-line formatjs/no-literal-string-in-jsx */}
|
||||
{`${rateTitle} / ${paymentTerm}`}
|
||||
</h3>
|
||||
|
||||
@@ -63,9 +63,8 @@ export default function PointsRateCard({
|
||||
id: 'selectRate.rateCard.openReservationPolicy',
|
||||
defaultMessage: 'Open reservation policy',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="Icon/Default" />
|
||||
</IconButton>
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
|
||||
@@ -72,9 +72,8 @@ export default function RegularRateCard({
|
||||
id: 'selectRate.rateCard.openReservationPolicy',
|
||||
defaultMessage: 'Open reservation policy',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon icon="info" size={20} color="Icon/Default" />
|
||||
</IconButton>
|
||||
iconName="info"
|
||||
/>
|
||||
}
|
||||
>
|
||||
{rateTermDetails.map((termGroup) => (
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useIntl } from 'react-intl'
|
||||
import usePopStateHandler from '@scandic-hotels/common/hooks/usePopStateHandler'
|
||||
|
||||
import { IconButton } from '../IconButton'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
import SidePeekSEO from './SidePeekSEO'
|
||||
@@ -72,13 +71,8 @@ export default function SidePeekSelfControlled({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
})}
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
size={24}
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className={styles.sidePeekContent}>{children}</div>
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { useCallback, useContext, useRef } from 'react'
|
||||
import { Dialog, Modal, ModalOverlay } from 'react-aria-components'
|
||||
import { IconButton } from '../IconButton'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
import { SidePeekContext } from './SidePeekContext'
|
||||
@@ -104,12 +103,8 @@ export default function SidePeek({
|
||||
emphasis
|
||||
aria-label={closeLabel}
|
||||
onPress={onClose}
|
||||
>
|
||||
<MaterialIcon
|
||||
icon="close"
|
||||
color="Icon/Interactive/Default"
|
||||
/>
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
</div>
|
||||
</header>
|
||||
<div className={styles.sidePeekContent}>{children}</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { IconButton } from '../IconButton'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Tooltip } from '../Tooltip'
|
||||
import { Typography } from '../Typography'
|
||||
|
||||
@@ -29,9 +28,8 @@ export default function Stepper({
|
||||
onPress={handleOnDecrease}
|
||||
variant="Elevated"
|
||||
isDisabled={disableDecrease}
|
||||
>
|
||||
<MaterialIcon icon="remove" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="remove"
|
||||
/>
|
||||
<div className={styles.countDisplay}>
|
||||
<Typography variant="Body/Paragraph/mdRegular">
|
||||
<p>{count}</p>
|
||||
@@ -49,9 +47,8 @@ export default function Stepper({
|
||||
onPress={handleOnIncrease}
|
||||
variant="Elevated"
|
||||
isDisabled={disableIncrease}
|
||||
>
|
||||
<MaterialIcon icon="add" color="CurrentColor" />
|
||||
</IconButton>
|
||||
iconName="add"
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -46,9 +46,8 @@ export function Toast({ children, message, onClose, variant }: ToastsProps) {
|
||||
})}
|
||||
variant="Muted"
|
||||
emphasis
|
||||
>
|
||||
<MaterialIcon icon="close" />
|
||||
</IconButton>
|
||||
iconName="close"
|
||||
/>
|
||||
) : null}
|
||||
</div>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user