Merged in feat/svg-instead-of-fonts (pull request #3411)
feat(SW-3695): use svg icons instead of font icons * feat(icons): use svg instead of font icons * feat(icons): use webpack/svgr for inlined svgs. Now support for isFilled again * Merge master * Remove old font icon Approved-by: Joakim Jäderberg
This commit is contained in:
@@ -3,8 +3,8 @@ 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"
|
||||
import { MaterialIconName } from "../Icons/MaterialIcon/generated"
|
||||
|
||||
export const buttonIconNames = [
|
||||
"add_circle",
|
||||
@@ -25,13 +25,8 @@ export const buttonIconNames = [
|
||||
"chevron_left",
|
||||
] as const
|
||||
|
||||
export type ButtonIconName = Extract<
|
||||
SymbolCodepoints,
|
||||
(typeof buttonIconNames)[number]
|
||||
>
|
||||
|
||||
export interface ButtonProps
|
||||
extends ComponentProps<typeof Button>, VariantProps<typeof variants> {
|
||||
leadingIconName?: ButtonIconName | null
|
||||
trailingIconName?: ButtonIconName | null
|
||||
leadingIconName?: MaterialIconName | null
|
||||
trailingIconName?: MaterialIconName | null
|
||||
}
|
||||
|
||||
@@ -7,16 +7,16 @@ 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"
|
||||
import { MaterialIconName } from "../Icons/MaterialIcon/generated"
|
||||
|
||||
export interface ButtonLinkProps
|
||||
extends
|
||||
Omit<ComponentProps<typeof Link>, "color">,
|
||||
VariantProps<typeof variants> {
|
||||
leadingIconName?: ButtonIconName | null
|
||||
trailingIconName?: ButtonIconName | null
|
||||
leadingIconName?: MaterialIconName | null
|
||||
trailingIconName?: MaterialIconName | null
|
||||
}
|
||||
|
||||
export default function ButtonLink({
|
||||
|
||||
@@ -2,9 +2,9 @@ import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
|
||||
import { fn } from "storybook/test"
|
||||
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon/MaterialIcon.tsx"
|
||||
import { ChipButton } from "./ChipButton.tsx"
|
||||
import { config as chipButtonConfig } from "./variants"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon/index.tsx"
|
||||
|
||||
const meta: Meta<typeof ChipButton> = {
|
||||
title: "Core Components/ChipButton",
|
||||
|
||||
@@ -5,7 +5,6 @@ import { FormProvider, useForm } from "react-hook-form"
|
||||
import { fn } from "storybook/test"
|
||||
import { z } from "zod"
|
||||
|
||||
import { FormTextArea } from "../FormTextArea"
|
||||
import { Button } from "../../Button"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { Typography } from "../../Typography"
|
||||
@@ -44,9 +43,8 @@ function ExampleFormComponent({
|
||||
labelPosition = "floating",
|
||||
defaultValues,
|
||||
fieldPrefix = "",
|
||||
textAreaDescription,
|
||||
textAreaError,
|
||||
textAreaLabel = "Message",
|
||||
textAreaDescription,
|
||||
}: ExampleFormProps) {
|
||||
const getFieldName = (name: string) =>
|
||||
fieldPrefix ? `${fieldPrefix}_${name}` : name
|
||||
@@ -140,9 +138,10 @@ function ExampleFormComponent({
|
||||
labelPosition={labelPosition}
|
||||
/>
|
||||
|
||||
<FormTextArea
|
||||
<FormInput
|
||||
name={getFieldName("message")}
|
||||
label={textAreaLabel || undefined}
|
||||
label="Message"
|
||||
labelPosition={labelPosition}
|
||||
registerOptions={{ required: true }}
|
||||
descriptionIcon="info"
|
||||
description={textAreaDescription}
|
||||
@@ -201,9 +200,6 @@ export const Default: Story = {
|
||||
args: {
|
||||
onSubmit: fn(),
|
||||
labelPosition: "floating",
|
||||
textAreaLabel: "Message",
|
||||
textAreaDescription: "This is a custom description",
|
||||
textAreaError: "",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -531,7 +527,7 @@ function InputShowcase() {
|
||||
name="emailIcon"
|
||||
label="Email"
|
||||
type="email"
|
||||
leftIcon={<MaterialIcon icon="email" />}
|
||||
leftIcon={<MaterialIcon icon="mail" />}
|
||||
/>
|
||||
<FormInput
|
||||
name="searchIcon"
|
||||
@@ -562,7 +558,7 @@ function InputShowcase() {
|
||||
name="emailIconTop"
|
||||
label="Email"
|
||||
type="email"
|
||||
leftIcon={<MaterialIcon icon="email" />}
|
||||
leftIcon={<MaterialIcon icon="mail" />}
|
||||
labelPosition="top"
|
||||
/>
|
||||
<FormInput
|
||||
@@ -615,7 +611,7 @@ function InputShowcase() {
|
||||
<FormInput
|
||||
name="clearLeftRight"
|
||||
label="Clear with Left Icon"
|
||||
leftIcon={<MaterialIcon icon="phone" />}
|
||||
leftIcon={<MaterialIcon icon="phone_enabled" />}
|
||||
showClearContentIcon
|
||||
/>
|
||||
<FormInput
|
||||
@@ -627,7 +623,7 @@ function InputShowcase() {
|
||||
<FormInput
|
||||
name="clearBothIcons"
|
||||
label="Clear with Both Icon"
|
||||
leftIcon={<MaterialIcon icon="email" />}
|
||||
leftIcon={<MaterialIcon icon="mail" />}
|
||||
rightIcon={<MaterialIcon icon="lock" />}
|
||||
showClearContentIcon
|
||||
/>
|
||||
|
||||
@@ -3,8 +3,8 @@ 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"
|
||||
import { MaterialIconName } from "../Icons/MaterialIcon/generated"
|
||||
|
||||
export const iconButtonIconNames = [
|
||||
"arrow_forward",
|
||||
@@ -26,14 +26,9 @@ export const iconButtonIconNames = [
|
||||
"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
|
||||
iconName: MaterialIconName
|
||||
}
|
||||
|
||||
@@ -29,8 +29,8 @@ import WindowNotAvailableIcon from "./Customised/Amenities_Facilities/WindowNotA
|
||||
import WoodFloorIcon from "./Customised/Amenities_Facilities/WoodFloor"
|
||||
|
||||
import type { IconProps, NucleoIconProps } from "."
|
||||
import type { MaterialSymbolProps } from "./MaterialIcon/MaterialSymbol"
|
||||
import type { JSX } from "react"
|
||||
import { MaterialIconName } from "./MaterialIcon/generated"
|
||||
|
||||
interface FacilityIconProps {
|
||||
name: string | undefined
|
||||
@@ -67,7 +67,7 @@ export function FacilityIcon({
|
||||
}
|
||||
|
||||
const MaterialIconMappings: {
|
||||
icon: MaterialSymbolProps["icon"]
|
||||
icon: MaterialIconName
|
||||
name: string
|
||||
}[] = [
|
||||
{ icon: "air_purifier_gen", name: "aircondition" },
|
||||
@@ -112,7 +112,7 @@ const MaterialIconMappings: {
|
||||
{ icon: "water_full", name: "complimentarycoldrefreshments" },
|
||||
{ icon: "groups", name: "conventioncentre" },
|
||||
{ icon: "accessible", name: "disabledparking" },
|
||||
{ icon: "charging_station", name: "dockingstationforipodipad" },
|
||||
{ icon: "mobile_charge", name: "dockingstationforipodipad" },
|
||||
{ icon: "cool_to_dry", name: "dryingcabinet" },
|
||||
{ icon: "assistant_navigation", name: "easyaccess" },
|
||||
{ icon: "laundry", name: "garmentsteamer" },
|
||||
@@ -172,7 +172,7 @@ const MaterialIconMappings: {
|
||||
{ icon: "local_parking", name: "parking" },
|
||||
{ icon: "local_parking", name: "parkingfreeparking" },
|
||||
{ icon: "pets", name: "petfriendlyrooms" },
|
||||
{ icon: "phone", name: "directdialphoneandvoicemail" },
|
||||
{ icon: "phone_enabled", name: "directdialphoneandvoicemail" },
|
||||
{ icon: "restaurant", name: "restaurant" },
|
||||
{ icon: "room_service", name: "roomservice" },
|
||||
{ icon: "sauna", name: "sauna" },
|
||||
|
||||
@@ -11,7 +11,7 @@ import HairdryerIcon from "./Customised/Amenities_Facilities/Hairdryer"
|
||||
import IceMachineIcon from "./Customised/Amenities_Facilities/IceMachine"
|
||||
import InstagramIcon from "./Customised/Socials/Instagram"
|
||||
import MassageIcon from "./Customised/Amenities_Facilities/Massage"
|
||||
import { MaterialIcon, type MaterialIconSetIconProps } from "./MaterialIcon"
|
||||
|
||||
import PalmTreeIcon from "./Nucleo/Experiences/palm-tree-2"
|
||||
import PopcornIcon from "./Nucleo/Food/popcorn-2"
|
||||
import RecordPlayerIcon from "./Nucleo/Amenities_Facilities/record-player-3"
|
||||
@@ -25,6 +25,7 @@ import { IconName } from "./iconName"
|
||||
|
||||
import type { IconProps, NucleoIconProps } from "./icon"
|
||||
import type { JSX } from "react"
|
||||
import { MaterialIcon, MaterialIconSetIconProps } from "./MaterialIcon"
|
||||
|
||||
interface IconByIconNameProps {
|
||||
iconName: IconName | null
|
||||
@@ -136,7 +137,7 @@ export function IconByIconName({
|
||||
return <MaterialIcon icon="photo_camera" {...props} />
|
||||
case IconName.Cellphone:
|
||||
case IconName.Phone:
|
||||
return <MaterialIcon icon="phone" {...props} />
|
||||
return <MaterialIcon icon="phone_enabled" {...props} />
|
||||
case IconName.HairdryerInRoomAllScandic:
|
||||
return <HairdryerIcon {...props} />
|
||||
case IconName.ComplimentaryColdRefreshments:
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import { MaterialSymbol, type MaterialSymbolProps } from "./MaterialSymbol"
|
||||
|
||||
import { iconVariants } from "../variants"
|
||||
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import { HTMLAttributes } from "react"
|
||||
import { getIconAriaProps } from "../utils"
|
||||
|
||||
export interface MaterialIconProps
|
||||
extends
|
||||
Pick<MaterialSymbolProps, "size" | "icon" | "className" | "style">,
|
||||
Omit<HTMLAttributes<HTMLSpanElement>, "color" | "id">,
|
||||
VariantProps<typeof iconVariants> {
|
||||
isFilled?: boolean
|
||||
}
|
||||
export type MaterialIconSetIconProps = Omit<MaterialIconProps, "icon">
|
||||
export function MaterialIcon({
|
||||
color,
|
||||
size = 24,
|
||||
className,
|
||||
isFilled = false,
|
||||
...props
|
||||
}: MaterialIconProps) {
|
||||
const classNames = iconVariants({ className, color })
|
||||
const ariaProps = getIconAriaProps(props)
|
||||
|
||||
return (
|
||||
// The span is used to prevent the MaterialSymbol from being underlined when used inside a link or button
|
||||
<span>
|
||||
<MaterialSymbol
|
||||
{...props}
|
||||
className={classNames}
|
||||
data-testid="MaterialIcon"
|
||||
size={size}
|
||||
fill={isFilled}
|
||||
{...ariaProps}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// This is adapted from https://github.com/edjonesdev/react-material-symbols
|
||||
// since it doesn't support React 19 and is not maintained anymore.
|
||||
// We should probably move to a different solution in the future.
|
||||
|
||||
import type { ElementType, CSSProperties, ReactElement, Ref } from "react"
|
||||
import type {
|
||||
MaterialSymbolWeight,
|
||||
PolymorphicComponentProps,
|
||||
SymbolCodepoints,
|
||||
} from "./types"
|
||||
import { cx } from "class-variance-authority"
|
||||
export type { MaterialSymbolWeight, SymbolCodepoints } from "./types"
|
||||
|
||||
export type MaterialSymbolProps = {
|
||||
/** Required. The name of the icon to render. */
|
||||
icon: SymbolCodepoints
|
||||
/** Default `false`.
|
||||
*
|
||||
* Fill gives you the ability to modify the default icon style. A single icon can render both unfilled and filled states. */
|
||||
fill?: boolean
|
||||
/** Weight defines the symbol’s stroke weight, with a range of weights between thin (100) and heavy (900). Weight can also affect the overall size of the symbol. */
|
||||
weight?: MaterialSymbolWeight
|
||||
/** Weight and grade affect a symbol’s thickness. Adjustments to grade are more granular than adjustments to weight and have a small impact on the size of the symbol. */
|
||||
grade?: number
|
||||
/** Default `'inherit'`.
|
||||
*
|
||||
* Size defines the icon width and height in pixels. For the image to look the same at different sizes, the stroke weight (thickness) changes as the icon size scales. */
|
||||
size?: number
|
||||
/** Default `'inherit'`
|
||||
*
|
||||
* Color accepts key values (`'red'`, `'blue'`, `'indigo'`, etc.), `<hex-color>`, `<rgb()>`, `<hsl()>` and `<hwb()>` values. */
|
||||
color?: CSSProperties["color"]
|
||||
className?: string
|
||||
style?: CSSProperties
|
||||
}
|
||||
|
||||
export type PolymorphicMaterialSymbolProps<C extends ElementType> =
|
||||
PolymorphicComponentProps<C, MaterialSymbolProps>
|
||||
|
||||
export const MaterialSymbol = (<C extends ElementType>(
|
||||
{
|
||||
icon,
|
||||
onClick,
|
||||
as,
|
||||
weight,
|
||||
fill = false,
|
||||
grade,
|
||||
size,
|
||||
style: propStyle,
|
||||
color,
|
||||
className,
|
||||
...props
|
||||
}: PolymorphicMaterialSymbolProps<C>,
|
||||
ref: Ref<C>
|
||||
): ReactElement => {
|
||||
const Component =
|
||||
onClick !== undefined ? "button" : ((as as ElementType) ?? "span")
|
||||
const style = { color, ...propStyle }
|
||||
|
||||
if (fill)
|
||||
style.fontVariationSettings = [style.fontVariationSettings, '"FILL" 1']
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
if (weight)
|
||||
style.fontVariationSettings = [
|
||||
style.fontVariationSettings,
|
||||
`"wght" ${weight}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
if (grade)
|
||||
style.fontVariationSettings = [
|
||||
style.fontVariationSettings,
|
||||
`"GRAD" ${grade}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
if (size) {
|
||||
style.fontVariationSettings = [
|
||||
style.fontVariationSettings,
|
||||
`"opsz" ${size}`,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(", ")
|
||||
style.fontSize = size
|
||||
}
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
ref={ref}
|
||||
style={style}
|
||||
onClick={onClick}
|
||||
className={cx("material-symbols", className)}
|
||||
>
|
||||
{icon}
|
||||
</Component>
|
||||
)
|
||||
}) as <C extends ElementType>(
|
||||
props: PolymorphicMaterialSymbolProps<C>
|
||||
) => ReactElement
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
export { MaterialSymbol, type MaterialSymbolProps } from "./MaterialSymbol"
|
||||
@@ -1,55 +0,0 @@
|
||||
import type {
|
||||
JSXElementConstructor,
|
||||
ComponentPropsWithoutRef,
|
||||
JSX,
|
||||
} from "react"
|
||||
import type { MaterialSymbolWeightArray, SymbolCodepointsArray } from "./consts"
|
||||
|
||||
export type SymbolCodepoints = (typeof SymbolCodepointsArray)[number]
|
||||
|
||||
export type MaterialSymbolWeight = (typeof MaterialSymbolWeightArray)[number]
|
||||
|
||||
export interface AsProperty<C extends React.ElementType> {
|
||||
/**
|
||||
* An override of the default HTML tag.
|
||||
* Can also be another React component.
|
||||
*/
|
||||
as?: C
|
||||
}
|
||||
|
||||
/**
|
||||
* A more sophisticated version of `InheritableElementProps` where
|
||||
* the passed in `as` prop will determine which props can be included
|
||||
*/
|
||||
export type PolymorphicComponentProps<
|
||||
C extends React.ElementType,
|
||||
Properties = Record<string, unknown>,
|
||||
> = InheritableElementProps<C, Properties & AsProperty<C>>
|
||||
|
||||
/**
|
||||
* Source: https://github.com/emotion-js/emotion/blob/master/packages/styled-base/types/helper.d.ts
|
||||
* A more precise version of just React.ComponentPropsWithoutRef on its own
|
||||
*/
|
||||
export type PropsOf<
|
||||
C extends keyof JSX.IntrinsicElements | JSXElementConstructor<unknown>,
|
||||
> = JSX.LibraryManagedAttributes<C, ComponentPropsWithoutRef<C>>
|
||||
|
||||
/**
|
||||
* Allows for extending a set of props (`ExtendedProps`) by an overriding set of props
|
||||
* (`OverrideProps`), ensuring that any duplicates are overridden by the overriding
|
||||
* set of props.
|
||||
*/
|
||||
export type ExtendableProps<
|
||||
ExtendedProperties = Record<string, unknown>,
|
||||
OverrideProperties = Record<string, unknown>,
|
||||
> = OverrideProperties & Omit<ExtendedProperties, keyof OverrideProperties>
|
||||
|
||||
/**
|
||||
* Allows for inheriting the props from the specified element type so that
|
||||
* props like children, className & style work, as well as element-specific
|
||||
* attributes like aria roles. The component (`C`) must be passed in.
|
||||
*/
|
||||
export type InheritableElementProps<
|
||||
C extends React.ElementType,
|
||||
Properties = Record<string, unknown>,
|
||||
> = ExtendableProps<PropsOf<C>, Properties>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
.iconWrapper {
|
||||
display: flex;
|
||||
}
|
||||
@@ -1,5 +1,65 @@
|
||||
export {
|
||||
MaterialIcon,
|
||||
type MaterialIconProps,
|
||||
type MaterialIconSetIconProps,
|
||||
} from "./MaterialIcon"
|
||||
import { HTMLAttributes } from "react"
|
||||
import { MaterialIconName, materialIcons } from "./generated"
|
||||
import { VariantProps } from "class-variance-authority"
|
||||
import { iconVariants } from "../variants"
|
||||
import styles from "./index.module.css"
|
||||
|
||||
export interface MaterialIconProps
|
||||
extends
|
||||
Omit<HTMLAttributes<HTMLOrSVGElement>, "color" | "id">,
|
||||
VariantProps<typeof iconVariants> {
|
||||
icon: MaterialIconName
|
||||
size?: number
|
||||
styleName?: "outlined" | "rounded" | "sharp"
|
||||
isFilled?: boolean
|
||||
}
|
||||
|
||||
export type MaterialIconSetIconProps = Omit<MaterialIconProps, "icon">
|
||||
|
||||
export function MaterialIcon({
|
||||
icon,
|
||||
size = 24,
|
||||
styleName = "outlined",
|
||||
color = "CurrentColor",
|
||||
isFilled,
|
||||
...props
|
||||
}: MaterialIconProps) {
|
||||
const iconStyles = materialIcons[icon]
|
||||
|
||||
if (!iconStyles) {
|
||||
console.warn(`Icon "${icon}" not found in registry`)
|
||||
return null
|
||||
}
|
||||
|
||||
const styleVariants = iconStyles[styleName]
|
||||
|
||||
if (!styleVariants) {
|
||||
console.warn(`Icon "${icon}" does not have style "${styleName}"`)
|
||||
return null
|
||||
}
|
||||
|
||||
const IconComponent = isFilled ? styleVariants.filled : styleVariants.outlined
|
||||
|
||||
if (!IconComponent) {
|
||||
console.warn(
|
||||
`Icon "${icon}" does not have ${
|
||||
isFilled ? "filled" : "outlined"
|
||||
} variant for style "${styleName}"`
|
||||
)
|
||||
return null
|
||||
}
|
||||
|
||||
const iconClassName = iconVariants({ color })
|
||||
|
||||
return (
|
||||
<span className={`${styles.iconWrapper}`} {...props}>
|
||||
<IconComponent
|
||||
width={size}
|
||||
height={size}
|
||||
className={iconClassName}
|
||||
aria-hidden
|
||||
focusable={false}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,11 +4,9 @@ import { memo, useState } from "react"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import Image from "../Image"
|
||||
import ImageFallback from "../ImageFallback"
|
||||
import Lightbox from "../Lightbox"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
import styles from "./imageGallery.module.css"
|
||||
import { ImageCounter } from "../ImageCounter"
|
||||
|
||||
@@ -5,7 +5,7 @@ import { expect } from "storybook/test"
|
||||
import { Input } from "./Input"
|
||||
import { TextField } from "react-aria-components"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import type { SymbolCodepoints } from "../Icons/MaterialIcon/MaterialSymbol/types"
|
||||
import { MaterialIconName } from "../Icons/MaterialIcon/generated"
|
||||
|
||||
const meta: Meta<typeof Input> = {
|
||||
title: "Core Components/Input",
|
||||
@@ -176,12 +176,12 @@ export const Default: Story = {
|
||||
data-validation-state={validationState}
|
||||
leftIcon={
|
||||
showLeftIcon && leftIconName ? (
|
||||
<MaterialIcon icon={leftIconName as SymbolCodepoints} />
|
||||
<MaterialIcon icon={leftIconName as MaterialIconName} />
|
||||
) : undefined
|
||||
}
|
||||
rightIcon={
|
||||
showRightIcon && rightIconName ? (
|
||||
<MaterialIcon icon={rightIconName as SymbolCodepoints} />
|
||||
<MaterialIcon icon={rightIconName as MaterialIconName} />
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -114,7 +114,7 @@ export function Gallery({
|
||||
})}
|
||||
role="button"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
onImageClick()
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { FullView } from "./FullView"
|
||||
import { Gallery } from "./Gallery"
|
||||
|
||||
import styles from "./lightbox.module.css"
|
||||
import { cx } from "class-variance-authority"
|
||||
|
||||
export type LightboxImage = {
|
||||
src: string
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useCallback, useEffect } from "react"
|
||||
|
||||
const ANIMATION_OFFSET = 300
|
||||
|
||||
@@ -17,14 +17,14 @@ export const animationVariants = {
|
||||
export function useKeyboardNavigation(onPrev: () => void, onNext: () => void) {
|
||||
const handleKeyDown = useCallback(
|
||||
(e: KeyboardEvent) => {
|
||||
if (e.key === 'ArrowLeft') onPrev()
|
||||
if (e.key === 'ArrowRight') onNext()
|
||||
if (e.key === "ArrowLeft") onPrev()
|
||||
if (e.key === "ArrowRight") onNext()
|
||||
},
|
||||
[onPrev, onNext]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('keydown', handleKeyDown)
|
||||
return () => window.removeEventListener('keydown', handleKeyDown)
|
||||
window.addEventListener("keydown", handleKeyDown)
|
||||
return () => window.removeEventListener("keydown", handleKeyDown)
|
||||
}, [handleKeyDown])
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import { RatePointsOption, RateTermDetails } from "../types"
|
||||
import { RadioGroup } from "react-aria-components"
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../../IconButton"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
|
||||
import { Radio } from "../../Radio"
|
||||
import Modal from "../Modal"
|
||||
import styles from "../rate-card.module.css"
|
||||
import { variants } from "../variants"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
|
||||
interface PointsRateCardProps {
|
||||
rateTitle: string
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
|
||||
import { MaterialIcon, MaterialIconSetIconProps } from "../Icons/MaterialIcon"
|
||||
import { toastVariants } from "./variants"
|
||||
|
||||
import { useIntl } from "react-intl"
|
||||
import { IconButton } from "../IconButton"
|
||||
import { Typography } from "../Typography"
|
||||
import styles from "./toasts.module.css"
|
||||
import { MaterialIcon, MaterialIconSetIconProps } from "../Icons/MaterialIcon"
|
||||
|
||||
export type ToastsProps = VariantProps<typeof toastVariants> & {
|
||||
variant: NonNullable<VariantProps<typeof toastVariants>["variant"]>
|
||||
|
||||
@@ -2,15 +2,15 @@ import type { VariantProps } from "class-variance-authority"
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
|
||||
import { ComponentProps } from "react"
|
||||
import type { SymbolCodepoints } from "../../Icons/MaterialIcon/MaterialSymbol/types"
|
||||
import type { variants } from "./variants"
|
||||
import { MaterialIconName } from "../../Icons/MaterialIcon/generated"
|
||||
|
||||
export const videoPlayerButtonIconNames = [
|
||||
"play_arrow",
|
||||
"pause",
|
||||
"volume_up",
|
||||
"volume_off",
|
||||
] satisfies SymbolCodepoints[]
|
||||
] satisfies MaterialIconName[]
|
||||
|
||||
type VideoPlayerButtonIconName = (typeof videoPlayerButtonIconNames)[number]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user