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
@@ -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