Merged in fix/BOOK-323-enter-details-scroll-error (pull request #2986)
Fix/BOOK-323 enter details scroll error * fix(BOOK-323): scroll to invalid element on submit on enter details * fix(BOOK-323): update error message design * fix(BOOK-323): clean up * fix(BOOK-323): scroll to fields in room in right order * fix(BOOK-323): add id to translations * fix(BOOK-323): remove undefined * fix(BOOK-323): fix submitting state * fix(BOOK-323): use ref in multiroom for scrolling to right element, add membershipNo * fix(BOOK-323): fix invalid border country * fix(BOOK-323): use error message component * fix(BOOK-323): fix invalid focused styling on mobile * fix(BOOK-323): remove redundant dependency in callback Approved-by: Erik Tiekstra
This commit is contained in:
@@ -38,11 +38,3 @@
|
||||
.topAlign {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.error {
|
||||
align-items: center;
|
||||
color: var(--Scandic-Red-60);
|
||||
display: flex;
|
||||
gap: var(--Spacing-x-half);
|
||||
margin: var(--Spacing-x1) 0 0;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
|
||||
import styles from './checkbox.module.css'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import Caption from '../../Caption'
|
||||
import { ErrorMessage } from '../ErrorMessage'
|
||||
|
||||
interface CheckboxProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
||||
name: string
|
||||
@@ -36,7 +36,7 @@ const Checkbox = forwardRef<
|
||||
ref
|
||||
) {
|
||||
const { control } = useFormContext()
|
||||
const { field, fieldState } = useController({
|
||||
const { field, fieldState, formState } = useController({
|
||||
control,
|
||||
name,
|
||||
rules: registerOptions,
|
||||
@@ -48,6 +48,7 @@ const Checkbox = forwardRef<
|
||||
isSelected={field.value}
|
||||
onChange={field.onChange}
|
||||
data-testid={name}
|
||||
name={name}
|
||||
isDisabled={registerOptions?.disabled}
|
||||
excludeFromTabOrder
|
||||
>
|
||||
@@ -68,12 +69,15 @@ const Checkbox = forwardRef<
|
||||
{children}
|
||||
</span>
|
||||
{fieldState.error && !hideError ? (
|
||||
<Caption className={styles.error} fontOnly>
|
||||
<MaterialIcon icon="info" color="Icon/Interactive/Accent" />
|
||||
{(fieldState.error.message &&
|
||||
errorCodeMessages?.[fieldState.error.message]) ||
|
||||
fieldState.error.message}
|
||||
</Caption>
|
||||
<ErrorMessage
|
||||
errors={formState.errors}
|
||||
name={name}
|
||||
messageLabel={
|
||||
(fieldState.error.message &&
|
||||
errorCodeMessages?.[fieldState.error.message]) ||
|
||||
fieldState.error.message
|
||||
}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -52,6 +52,10 @@
|
||||
&[data-invalid] {
|
||||
border-color: var(--Border-Interactive-Error);
|
||||
}
|
||||
|
||||
&[data-invalid][data-focused] {
|
||||
outline: 2px solid var(--Border-Interactive-Error);
|
||||
}
|
||||
}
|
||||
|
||||
.inner {
|
||||
|
||||
@@ -10,7 +10,12 @@ export function Error({ children }: React.PropsWithChildren) {
|
||||
variant="Body/Supporting text (caption)/smRegular"
|
||||
>
|
||||
<span>
|
||||
<MaterialIcon icon="info" color="Icon/Feedback/Error" />
|
||||
<MaterialIcon
|
||||
icon="error"
|
||||
color="Icon/Feedback/Error"
|
||||
isFilled
|
||||
size={20}
|
||||
/>
|
||||
{children}
|
||||
</span>
|
||||
</Typography>
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { MessageBanner } from './index'
|
||||
|
||||
type MessageBannerType = 'default' | 'error' | 'info'
|
||||
type TextColor = 'default' | 'error'
|
||||
|
||||
const meta: Meta<typeof MessageBanner> = {
|
||||
title: 'Components/MessageBanner',
|
||||
component: MessageBanner,
|
||||
argTypes: {
|
||||
type: {
|
||||
control: { type: 'select' },
|
||||
options: ['default', 'error', 'info'] as MessageBannerType[],
|
||||
},
|
||||
textColor: {
|
||||
control: { type: 'select' },
|
||||
options: ['default', 'error'] as TextColor[],
|
||||
},
|
||||
text: { control: 'text' },
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
type Story = StoryObj<typeof MessageBanner>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
type: 'default',
|
||||
textColor: 'default',
|
||||
text: 'This is a default message',
|
||||
},
|
||||
}
|
||||
|
||||
export const Warning: Story = {
|
||||
args: {
|
||||
type: 'error',
|
||||
textColor: 'default',
|
||||
text: 'This is a warning message',
|
||||
},
|
||||
}
|
||||
|
||||
export const WarningErrorText: Story = {
|
||||
args: {
|
||||
type: 'error',
|
||||
textColor: 'error',
|
||||
text: 'Warning with error text color',
|
||||
},
|
||||
}
|
||||
|
||||
export const Info: Story = {
|
||||
args: {
|
||||
type: 'info',
|
||||
textColor: 'default',
|
||||
text: 'This is an info message',
|
||||
},
|
||||
}
|
||||
|
||||
export const InfoErrorText: Story = {
|
||||
args: {
|
||||
type: 'info',
|
||||
textColor: 'error',
|
||||
text: 'Info with error text color',
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
import styles from './messageBanner.module.css'
|
||||
import { Typography } from '../Typography'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
|
||||
type MessageBannerType = 'default' | 'error' | 'info'
|
||||
type TextColor = 'default' | 'error'
|
||||
|
||||
const textVariants = cva('', {
|
||||
variants: {
|
||||
textColor: {
|
||||
default: styles.textDefault,
|
||||
error: styles.textError,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
textColor: 'default',
|
||||
},
|
||||
})
|
||||
|
||||
type MessageBannerProps = {
|
||||
type?: MessageBannerType
|
||||
textColor?: TextColor
|
||||
text: string
|
||||
}
|
||||
|
||||
export function MessageBanner({
|
||||
type = 'default',
|
||||
textColor = 'default',
|
||||
text,
|
||||
}: MessageBannerProps) {
|
||||
const textClass = textVariants({ textColor })
|
||||
|
||||
const iconName = type === 'error' ? 'error' : 'info'
|
||||
const iconColor =
|
||||
type === 'error'
|
||||
? 'Icon/Feedback/Error'
|
||||
: type === 'info'
|
||||
? 'Icon/Feedback/Information'
|
||||
: 'Icon/Default'
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Typography
|
||||
className={textClass}
|
||||
variant="Body/Supporting text (caption)/smRegular"
|
||||
>
|
||||
<span className={styles.content}>
|
||||
<MaterialIcon size={20} icon={iconName} color={iconColor} isFilled />
|
||||
{text}
|
||||
</span>
|
||||
</Typography>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
.container {
|
||||
display: flex;
|
||||
padding: var(--Space-x15);
|
||||
background-color: var(--Surface-Primary-Default);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
border: 1px solid var(--Border-Default);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--Space-x1);
|
||||
}
|
||||
|
||||
.textDefault {
|
||||
color: var(--Text-Default);
|
||||
}
|
||||
|
||||
.textError {
|
||||
color: var(--Text-Feedback-Error-Accent);
|
||||
}
|
||||
@@ -36,8 +36,8 @@ export const DinersClubIcon = (props: PaymentIconProps) => (
|
||||
y2="21.6"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#3479C0" />
|
||||
<stop offset="1" stop-color="#133362" />
|
||||
<stop stopColor="#3479C0" />
|
||||
<stop offset="1" stopColor="#133362" />
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_5382_46858">
|
||||
<rect width="48" height="32" fill="white" />
|
||||
|
||||
@@ -89,10 +89,10 @@ export const DiscoverIcon = (props: PaymentIconProps) => (
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(28.6 17.5998) rotate(-142.431) scale(6.56048 6.47264)"
|
||||
>
|
||||
<stop stop-color="#F59900" />
|
||||
<stop offset="0.210082" stop-color="#F39501" />
|
||||
<stop offset="0.908163" stop-color="#CE3C0B" />
|
||||
<stop offset="1" stop-color="#A4420A" />
|
||||
<stop stopColor="#F59900" />
|
||||
<stop offset="0.210082" stopColor="#F39501" />
|
||||
<stop offset="0.908163" stopColor="#CE3C0B" />
|
||||
<stop offset="1" stopColor="#A4420A" />
|
||||
</radialGradient>
|
||||
<clipPath id="clip0_5382_46865">
|
||||
<rect width="48" height="32" rx="3" fill="white" />
|
||||
|
||||
@@ -49,10 +49,10 @@ export const JcbIcon = (props: PaymentIconProps) => (
|
||||
y2="16.0328"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#007940" />
|
||||
<stop offset="0.2285" stop-color="#00873F" />
|
||||
<stop offset="0.7433" stop-color="#40A737" />
|
||||
<stop offset="1" stop-color="#5CB531" />
|
||||
<stop stopColor="#007940" />
|
||||
<stop offset="0.2285" stopColor="#00873F" />
|
||||
<stop offset="0.7433" stopColor="#40A737" />
|
||||
<stop offset="1" stopColor="#5CB531" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear_5382_46863"
|
||||
@@ -62,10 +62,10 @@ export const JcbIcon = (props: PaymentIconProps) => (
|
||||
y2="16.001"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#007940" />
|
||||
<stop offset="0.2285" stop-color="#00873F" />
|
||||
<stop offset="0.7433" stop-color="#40A737" />
|
||||
<stop offset="1" stop-color="#5CB531" />
|
||||
<stop stopColor="#007940" />
|
||||
<stop offset="0.2285" stopColor="#00873F" />
|
||||
<stop offset="0.7433" stopColor="#40A737" />
|
||||
<stop offset="1" stopColor="#5CB531" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint2_linear_5382_46863"
|
||||
@@ -75,10 +75,10 @@ export const JcbIcon = (props: PaymentIconProps) => (
|
||||
y2="14.4771"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#007940" />
|
||||
<stop offset="0.2285" stop-color="#00873F" />
|
||||
<stop offset="0.7433" stop-color="#40A737" />
|
||||
<stop offset="1" stop-color="#5CB531" />
|
||||
<stop stopColor="#007940" />
|
||||
<stop offset="0.2285" stopColor="#00873F" />
|
||||
<stop offset="0.7433" stopColor="#40A737" />
|
||||
<stop offset="1" stopColor="#5CB531" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint3_linear_5382_46863"
|
||||
@@ -88,11 +88,11 @@ export const JcbIcon = (props: PaymentIconProps) => (
|
||||
y2="16.001"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#6C2C2F" />
|
||||
<stop offset="0.1735" stop-color="#882730" />
|
||||
<stop offset="0.5731" stop-color="#BE1833" />
|
||||
<stop offset="0.8585" stop-color="#DC0436" />
|
||||
<stop offset="1" stop-color="#E60039" />
|
||||
<stop stopColor="#6C2C2F" />
|
||||
<stop offset="0.1735" stopColor="#882730" />
|
||||
<stop offset="0.5731" stopColor="#BE1833" />
|
||||
<stop offset="0.8585" stopColor="#DC0436" />
|
||||
<stop offset="1" stopColor="#E60039" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint4_linear_5382_46863"
|
||||
@@ -102,10 +102,10 @@ export const JcbIcon = (props: PaymentIconProps) => (
|
||||
y2="16.001"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#1F286F" />
|
||||
<stop offset="0.4751" stop-color="#004E94" />
|
||||
<stop offset="0.8261" stop-color="#0066B1" />
|
||||
<stop offset="1" stop-color="#006FBC" />
|
||||
<stop stopColor="#1F286F" />
|
||||
<stop offset="0.4751" stopColor="#004E94" />
|
||||
<stop offset="0.8261" stopColor="#0066B1" />
|
||||
<stop offset="1" stopColor="#006FBC" />
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_5382_46863">
|
||||
<rect width="48" height="32" rx="3" fill="white" />
|
||||
|
||||
@@ -61,8 +61,8 @@ export const SwishIcon = (props: PaymentIconProps) => {
|
||||
y2="13.9987"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#EF3220" />
|
||||
<stop offset="1" stop-color="#FCD205" />
|
||||
<stop stopColor="#EF3220" />
|
||||
<stop offset="1" stopColor="#FCD205" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear_5382_46851"
|
||||
@@ -72,10 +72,10 @@ export const SwishIcon = (props: PaymentIconProps) => {
|
||||
y2="21.8844"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#FCD205" />
|
||||
<stop offset="0.263921" stop-color="#F47216" />
|
||||
<stop offset="0.560797" stop-color="#B31A93" />
|
||||
<stop offset="1" stop-color="#2743A0" />
|
||||
<stop stopColor="#FCD205" />
|
||||
<stop offset="0.263921" stopColor="#F47216" />
|
||||
<stop offset="0.560797" stopColor="#B31A93" />
|
||||
<stop offset="1" stopColor="#2743A0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint2_linear_5382_46851"
|
||||
@@ -85,10 +85,10 @@ export const SwishIcon = (props: PaymentIconProps) => {
|
||||
y2="18.0191"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#7FD3B9" />
|
||||
<stop offset="0.265705" stop-color="#66CDE1" />
|
||||
<stop offset="0.554471" stop-color="#6D8ED1" />
|
||||
<stop offset="1" stop-color="#2743A0" />
|
||||
<stop stopColor="#7FD3B9" />
|
||||
<stop offset="0.265705" stopColor="#66CDE1" />
|
||||
<stop offset="0.554471" stopColor="#6D8ED1" />
|
||||
<stop offset="1" stopColor="#2743A0" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint3_linear_5382_46851"
|
||||
@@ -98,10 +98,10 @@ export const SwishIcon = (props: PaymentIconProps) => {
|
||||
y2="10.1074"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
>
|
||||
<stop stop-color="#1E5CB2" />
|
||||
<stop offset="0.246658" stop-color="#4DC4CE" />
|
||||
<stop offset="0.564821" stop-color="#66C657" />
|
||||
<stop offset="1" stop-color="#FCD205" />
|
||||
<stop stopColor="#1E5CB2" />
|
||||
<stop offset="0.246658" stopColor="#4DC4CE" />
|
||||
<stop offset="0.564821" stopColor="#66C657" />
|
||||
<stop offset="1" stopColor="#FCD205" />
|
||||
</linearGradient>
|
||||
<clipPath id="clip0_5382_46851">
|
||||
<rect width="48" height="32" fill="white" />
|
||||
|
||||
@@ -52,6 +52,9 @@
|
||||
&[data-invalid] {
|
||||
border-color: var(--Border-Interactive-Error);
|
||||
}
|
||||
&[data-invalid][data-focused] {
|
||||
outline: 2px solid var(--Border-Interactive-Error);
|
||||
}
|
||||
}
|
||||
|
||||
.chevron {
|
||||
|
||||
@@ -147,6 +147,7 @@
|
||||
"./Map/Markers/HotelMarkerByType": "./lib/components/Map/Markers/HotelMarkerByType.tsx",
|
||||
"./Map/Markers/PoiMarker": "./lib/components/Map/Markers/PoiMarker/index.tsx",
|
||||
"./Map/types": "./lib/components/Map/types.ts",
|
||||
"./MessageBanner": "./lib/components/MessageBanner/index.tsx",
|
||||
"./Modal": "./lib/components/Modal/index.tsx",
|
||||
"./Modal/ModalContentWithActions": "./lib/components/Modal/ModalContentWithActions/index.tsx",
|
||||
"./NoRateAvailableCard": "./lib/components/RateCard/NoRateAvailable/index.tsx",
|
||||
|
||||
Reference in New Issue
Block a user