Merge branch 'develop' into feature/tracking

This commit is contained in:
Linus Flood
2024-10-17 11:09:33 +02:00
175 changed files with 4058 additions and 1119 deletions

View File

@@ -6,13 +6,6 @@
padding: var(--Spacing-x1);
}
.accordionItem.light {
background-color: var(--Base-Surface-Primary-light-Normal);
}
.accordionItem.subtle {
background-color: var(--Base-Background-Primary-Normal);
}
.summary {
position: relative;
display: flex;
@@ -48,7 +41,7 @@
}
.content {
padding: 0 var(--Spacing-x-one-and-half);
padding: var(--Spacing-x1) var(--Spacing-x-one-and-half) var(--Spacing-x1);
overflow: hidden;
max-height: 0;
transition: max-height 0.3s;

View File

@@ -2,7 +2,7 @@ import { VariantProps } from "class-variance-authority"
import { accordionItemVariants } from "./variants"
import { IconName } from "@/types/components/icon"
import type { IconName } from "@/types/components/icon"
export interface AccordionItemProps
extends React.HtmlHTMLAttributes<HTMLDetailsElement>,

View File

@@ -5,17 +5,19 @@ import { useRef } from "react"
import { ChevronDownIcon } from "@/components/Icons"
import { getIconByIconName } from "@/components/Icons/get-icon-by-icon-name"
import { AccordionItemProps } from "./accordionItem"
import { accordionItemVariants } from "./variants"
import styles from "./accordionItem.module.css"
import type { AccordionItemProps } from "./accordionItem"
export default function AccordionItem({
children,
icon,
title,
theme,
variant,
className,
}: AccordionItemProps) {
const contentRef = useRef<HTMLDivElement>(null)
const detailsRef = useRef<HTMLDetailsElement>(null)
@@ -43,7 +45,7 @@ export default function AccordionItem({
}
return (
<li className={accordionItemVariants({ variant, theme })}>
<li className={accordionItemVariants({ className, variant, theme })}>
<details ref={detailsRef} onToggle={toggleAccordion}>
<summary className={styles.summary}>
{IconComp && <IconComp className={styles.icon} color="burgundy" />}

View File

@@ -12,3 +12,7 @@
.accordion.subtle {
background-color: var(--Base-Background-Primary-Normal);
}
.accordion li:last-child {
border: none;
}

View File

@@ -1,9 +1,10 @@
import { Children, cloneElement, isValidElement } from "react"
import { AccordionItemProps } from "./AccordionItem/accordionItem"
import { AccordionProps } from "./accordion"
import { accordionVariants } from "./variants"
import type { AccordionProps } from "./accordion"
export default function Accordion({
children,
className,

View File

@@ -60,7 +60,7 @@
}
.themeThree {
--font-color: var(--Tertiary-Light-Surface-Text);
--font-color: var(--Tertiary-Light-On-Surface-Text);
--script-color: var(--Tertiary-Light-On-Surface-Accent);
background: var(--Tertiary-Light-Surface-Normal);
@@ -74,7 +74,7 @@
}
.themePrimaryDim {
--font-color: var(--Primary-Light-On-Surface-Text);
--font-color: var(--Primary-Dim-On-Surface-Text);
--script-color: var(--Primary-Dim-On-Surface-Accent);
background: var(--Primary-Dim-Surface-Normal);

View File

@@ -9,6 +9,11 @@
background: var(--UI-Input-Controls-Fill-Selected);
}
.container[data-disabled] .checkbox {
border: 1px solid var(--UI-Input-Controls-Border-Disabled);
background: var(--UI-Input-Controls-Surface-Disabled);
}
.checkboxContainer {
display: flex;
align-items: flex-start;
@@ -20,13 +25,12 @@
width: 24px;
height: 24px;
min-width: 24px;
border: 2px solid var(--UI-Input-Controls-Border-Normal);
border: 1px solid var(--UI-Input-Controls-Border-Normal);
border-radius: 4px;
transition: all 200ms;
display: flex;
align-items: center;
justify-content: center;
transition: all 200ms;
forced-color-adjust: none;
}

View File

@@ -1,7 +0,0 @@
import { RegisterOptions } from "react-hook-form"
export interface CheckboxProps
extends React.InputHTMLAttributes<HTMLInputElement> {
name: string
registerOptions?: RegisterOptions
}

View File

@@ -7,10 +7,10 @@ import { InfoCircleIcon } from "@/components/Icons"
import CheckIcon from "@/components/Icons/Check"
import Caption from "@/components/TempDesignSystem/Text/Caption"
import { CheckboxProps } from "./checkbox"
import styles from "./checkbox.module.css"
import { CheckboxProps } from "@/types/components/checkbox"
export default function Checkbox({
name,
children,
@@ -29,6 +29,7 @@ export default function Checkbox({
isSelected={field.value}
onChange={field.onChange}
data-testid={name}
isDisabled={registerOptions?.disabled}
>
{({ isSelected }) => (
<>

View File

@@ -29,14 +29,14 @@ export default function Card({
return (
<label className={styles.label} data-declined={declined}>
<Caption className={styles.title} textTransform="bold" uppercase>
<Caption className={styles.title} type="label" uppercase>
{title}
</Caption>
{subtitle ? (
<Caption
className={styles.subtitle}
color={highlightSubtitle ? "baseTextAccent" : "uiTextHighContrast"}
textTransform="bold"
type="regular"
>
{subtitle}
</Caption>

View File

@@ -20,8 +20,8 @@ import type { DateProps } from "./date"
export default function DateSelect({ name, registerOptions = {} }: DateProps) {
const intl = useIntl()
const d = useWatch({ name })
const { control, setValue } = useFormContext()
const currentValue = useWatch({ name })
const { control, setValue, trigger } = useFormContext()
const { field } = useController({
control,
name,
@@ -47,7 +47,7 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
}))
const years = rangeArray(1900, currentYear - 18)
.reverse()
.map((year) => ({ value: year, label: `${year}` }))
.map((year) => ({ value: year, label: year.toString() }))
function createOnSelect(selector: DateName) {
/**
@@ -68,6 +68,8 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
const month = selector === DateName.month ? value : newSegments.month
if (year !== null && month !== null) {
newSegments.daysInMonth = dt().year(year).month(month).daysInMonth()
} else if (month !== null) {
newSegments.daysInMonth = dt().month(month).daysInMonth()
}
}
@@ -79,6 +81,7 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
.set("date", Math.min(newSegments.date!, newSegments.daysInMonth))
setValue(name, newDate.format("YYYY-MM-DD"))
trigger(name)
}
setDateSegment(newSegments)
}
@@ -95,9 +98,9 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
* date, but we can't check isNan since
* we recieve the date as "1999-01-01"
*/
dateValue = dt(d).isValid() ? parseDate(d) : null
dateValue = dt(currentValue).isValid() ? parseDate(currentValue) : null
} catch (error) {
console.error(error)
console.warn("Known error for parse date in DateSelect: ", error)
}
return (
@@ -130,9 +133,10 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
placeholder="DD"
required
tabIndex={3}
defaultValue={
defaultSelectedKey={
segment.isPlaceholder ? undefined : segment.value
}
value={segment.isPlaceholder ? undefined : segment.value}
/>
</div>
)
@@ -148,9 +152,10 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
placeholder="MM"
required
tabIndex={2}
defaultValue={
defaultSelectedKey={
segment.isPlaceholder ? undefined : segment.value
}
value={segment.isPlaceholder ? undefined : segment.value}
/>
</div>
)
@@ -166,9 +171,10 @@ export default function DateSelect({ name, registerOptions = {} }: DateProps) {
placeholder="YYYY"
required
tabIndex={1}
defaultValue={
defaultSelectedKey={
segment.isPlaceholder ? undefined : segment.value
}
value={segment.isPlaceholder ? undefined : segment.value}
/>
</div>
)

View File

@@ -30,10 +30,11 @@ export default function NewPassword({
placeholder = "",
registerOptions = {},
label,
visibilityToggleable = true,
}: NewPasswordProps) {
const { control } = useFormContext()
const intl = useIntl()
const [isPasswordVisible, setPasswordVisible] = useState(false)
const [isPasswordVisible, setIsPasswordVisible] = useState(false)
function getErrorMessage(key: PasswordValidatorKey) {
switch (key) {
@@ -69,7 +70,9 @@ export default function NewPassword({
onChange={field.onChange}
validationBehavior="aria"
value={field.value}
type={isPasswordVisible ? "text" : "password"}
type={
visibilityToggleable && isPasswordVisible ? "text" : "password"
}
>
<div className={styles.inputWrapper}>
<AriaInputWithLabel
@@ -78,18 +81,24 @@ export default function NewPassword({
id={field.name}
label={intl.formatMessage({ id: "New password" })}
placeholder={placeholder}
type={isPasswordVisible ? "text" : "password"}
type={
visibilityToggleable && isPasswordVisible
? "text"
: "password"
}
/>
<Button
className={styles.eyeIcon}
type="button"
variant="icon"
size="small"
intent="tertiary"
onClick={() => setPasswordVisible(!isPasswordVisible)}
>
{isPasswordVisible ? <EyeHideIcon /> : <EyeShowIcon />}
</Button>
{visibilityToggleable ? (
<Button
className={styles.eyeIcon}
type="button"
variant="icon"
size="small"
intent="tertiary"
onClick={() => setIsPasswordVisible((value) => !value)}
>
{isPasswordVisible ? <EyeHideIcon /> : <EyeShowIcon />}
</Button>
) : null}
</div>
{field.value ? (
<div className={styles.errors}>

View File

@@ -4,6 +4,7 @@ export interface NewPasswordProps
extends React.InputHTMLAttributes<HTMLInputElement> {
label?: string
registerOptions?: RegisterOptions
visibilityToggleable?: boolean
}
export interface IconProps {

View File

@@ -16,4 +16,8 @@
.twoColumns {
grid-template-columns: repeat(2, 1fr);
}
.oneColumn {
grid-template-columns: 1fr;
}
}

View File

@@ -4,6 +4,4 @@ import type { VariantProps } from "class-variance-authority"
export interface StackableGridProps
extends React.HTMLAttributes<HTMLDivElement>,
VariantProps<typeof stackableGridVariants> {
columns?: 2 | 3
}
VariantProps<typeof stackableGridVariants> {}

View File

@@ -5,6 +5,7 @@ import styles from "./stackable.module.css"
export const stackableGridVariants = cva(styles.container, {
variants: {
columns: {
1: styles.oneColumn,
2: styles.twoColumns,
3: styles.threeColumns,
},

View File

@@ -9,7 +9,7 @@ import type { LinkChipProps } from "./chip"
export default function LinkChip({ url, title }: LinkChipProps) {
return (
<Caption textTransform="bold" color="burgundy" asChild>
<Caption type="bold" color="burgundy" asChild>
<Link href={url} className={styles.linkChip}>
{title}
<ChevronRightSmallIcon color="burgundy" width={20} height={20} />

View File

@@ -16,6 +16,8 @@ export default function ShowMoreButton({
intent,
disabled,
showLess,
textShowMore = "Show less",
textShowLess = "Show more",
loadMoreData,
}: ShowMoreButtonProps) {
const intl = useIntl()
@@ -36,7 +38,7 @@ export default function ShowMoreButton({
intent="text"
>
<ChevronDownIcon className={styles.icon} />
{intl.formatMessage({ id: showLess ? "Show less" : "Show more" })}
{intl.formatMessage({ id: showLess ? textShowLess : textShowMore })}
</Button>
</div>
)

View File

@@ -7,5 +7,7 @@ export interface ShowMoreButtonProps
VariantProps<typeof showMoreButtonVariants> {
disabled?: boolean
showLess?: boolean
textShowMore?: string
textShowLess?: string
loadMoreData: () => void
}

View File

@@ -2,12 +2,7 @@
import { useIsSSR } from "@react-aria/ssr"
import { useContext, useState } from "react"
import {
Dialog,
DialogTrigger,
Modal,
ModalOverlay,
} from "react-aria-components"
import { Dialog, Modal, ModalOverlay } from "react-aria-components"
import { useIntl } from "react-intl"
import { CloseLargeIcon } from "@/components/Icons"
@@ -52,48 +47,45 @@ function SidePeek({
</div>
)
}
return (
<div ref={setRef}>
<DialogTrigger>
<ModalOverlay
UNSTABLE_portalContainer={rootDiv}
className={styles.overlay}
isOpen={
isOpen || (!!contentKey && contentKey === context?.activeSidePeek)
}
onOpenChange={onClose}
isDismissable
>
<Modal className={styles.modal}>
<Dialog className={styles.dialog}>
<aside className={styles.sidePeek}>
<header className={styles.header}>
{title ? (
<Title
color="burgundy"
textTransform="uppercase"
level="h2"
as="h3"
>
{title}
</Title>
) : null}
<Button
aria-label={intl.formatMessage({ id: "Close" })}
className={styles.closeButton}
intent="text"
onPress={onClose}
<ModalOverlay
UNSTABLE_portalContainer={rootDiv}
className={styles.overlay}
isOpen={
isOpen || (!!contentKey && contentKey === context?.activeSidePeek)
}
onOpenChange={onClose}
isDismissable
>
<Modal className={styles.modal}>
<Dialog className={styles.dialog} aria-label={title}>
<aside className={styles.sidePeek}>
<header className={styles.header}>
{title ? (
<Title
color="burgundy"
textTransform="uppercase"
level="h2"
as="h3"
>
<CloseLargeIcon color="burgundy" />
</Button>
</header>
<div className={styles.sidePeekContent}>{children}</div>
</aside>
</Dialog>
</Modal>
</ModalOverlay>
</DialogTrigger>
{title}
</Title>
) : null}
<Button
aria-label={intl.formatMessage({ id: "Close" })}
className={styles.closeButton}
intent="text"
onPress={onClose}
>
<CloseLargeIcon color="burgundy" />
</Button>
</header>
<div className={styles.sidePeekContent}>{children}</div>
</aside>
</Dialog>
</Modal>
</ModalOverlay>
</div>
)
}

View File

@@ -96,6 +96,10 @@
color: var(--UI-Text-High-contrast);
}
.uiTextMediumContrast {
color: var(--UI-Text-Medium-contrast);
}
.uiTextPlaceholder {
color: var(--UI-Text-Placeholder);
}

View File

@@ -17,6 +17,7 @@ const config = {
peach50: styles.peach50,
peach80: styles.peach80,
uiTextHighContrast: styles.uiTextHighContrast,
uiTextMediumContrast: styles.uiTextMediumContrast,
uiTextPlaceholder: styles.uiTextPlaceholder,
},
textAlign: {

View File

@@ -10,20 +10,19 @@ p.caption {
.bold {
font-family: var(--typography-Caption-Bold-fontFamily);
font-size: var(--typography-Caption-Bold-fontSize);
font-weight: var(--typography-Caption-Bold-fontWeight);
font-weight: 500; /* var(--typography-Caption-Bold-fontWeight); /* Commented till figma values are fixed to 500 instead of medium */
letter-spacing: var(--typography-Caption-Bold-letterSpacing);
line-height: var(--typography-Caption-Bold-lineHeight);
text-decoration: var(--typography-Caption-Bold-textDecoration);
}
.uppercase {
font-family: var(--typography-Caption-Bold-fontFamily);
font-size: var(--typography-Caption-Bold-fontSize);
font-weight: var(--typography-Caption-Bold-fontWeight);
letter-spacing: var(--typography-Caption-Bold-letterSpacing);
line-height: var(--typography-Caption-Bold-lineHeight);
text-decoration: var(--typography-Caption-Bold-textDecoration);
text-transform: uppercase;
.labels {
font-family: var(--typography-Caption-Labels-fontFamily);
font-size: var(--typography-Caption-Labels-fontSize);
font-weight: var(--typography-Caption-Labels-fontWeight);
letter-spacing: var(--typography-Caption-Labels-letterSpacing);
line-height: var(--typography-Caption-Labels-lineHeight);
text-decoration: var(--typography-Caption-Labels-textDecoration);
}
.regular {
@@ -35,6 +34,10 @@ p.caption {
text-decoration: var(--typography-Caption-Regular-textDecoration);
}
.uppercase {
text-transform: uppercase;
}
.baseTextAccent {
color: var(--Base-Text-Accent);
}

View File

@@ -12,6 +12,7 @@ export default function Caption({
textAlign,
textTransform,
uppercase,
type,
...props
}: CaptionProps) {
const Comp = asChild ? Slot : "p"
@@ -20,6 +21,7 @@ export default function Caption({
className,
textTransform,
uppercase,
type,
})
: captionVariants({
className,
@@ -27,6 +29,7 @@ export default function Caption({
textTransform,
textAlign,
uppercase,
type,
})
return <Comp className={classNames} {...props} />
}

View File

@@ -4,6 +4,11 @@ import styles from "./caption.module.css"
const config = {
variants: {
type: {
regular: styles.regular,
bold: styles.bold,
label: styles.labels,
},
color: {
baseTextAccent: styles.baseTextAccent,
black: styles.black,
@@ -19,8 +24,6 @@ const config = {
disabled: styles.disabled,
},
textTransform: {
bold: styles.bold,
regular: styles.regular,
uppercase: styles.uppercase,
},
textAlign: {
@@ -33,7 +36,7 @@ const config = {
},
defaultVariants: {
color: "black",
textTransform: "regular",
type: "regular",
},
} as const
@@ -41,9 +44,12 @@ export const captionVariants = cva(styles.caption, config)
const fontOnlyConfig = {
variants: {
textTransform: {
bold: styles.bold,
type: {
regular: styles.regular,
bold: styles.bold,
label: styles.labels,
},
textTransform: {
uppercase: styles.uppercase,
},
uppercase: {
@@ -51,7 +57,7 @@ const fontOnlyConfig = {
},
},
defaultVariants: {
textTransform: "regular",
type: "regular",
},
} as const

View File

@@ -25,13 +25,16 @@
text-decoration: var(--typography-Footnote-Regular-textDecoration);
}
.labels {
font-family: var(--typography-Footnote-Labels-fontFamily);
font-size: var(--typography-Footnote-Labels-fontSize);
font-weight: var(--typography-Footnote-Labels-fontWeight);
letter-spacing: var(--typography-Footnote-Labels-letterSpacing);
line-height: var(--typography-Footnote-Labels-lineHeight);
text-decoration: var(--typography-Footnote-Labels-textDecoration);
}
.uppercase {
font-family: var(--typography-Footnote-Regular-fontFamily);
font-size: var(--typography-Footnote-Regular-fontSize);
font-weight: var(--typography-Footnote-Bold-fontWeight);
letter-spacing: var(--typography-Footnote-Regular-letterSpacing);
line-height: var(--typography-Footnote-Regular-lineHeight);
text-decoration: var(--typography-Footnote-Regular-textDecoration);
text-transform: uppercase;
}

View File

@@ -11,20 +11,23 @@ export default function Footnote({
fontOnly = false,
textAlign,
textTransform,
type,
...props
}: FootnoteProps) {
const Comp = asChild ? Slot : "p"
const classNames = fontOnly
? footnoteFontOnlyVariants({
className,
textAlign,
textTransform,
})
className,
textAlign,
textTransform,
type,
})
: footnoteVariants({
className,
color,
textAlign,
textTransform,
})
className,
color,
textAlign,
textTransform,
type,
})
return <Comp className={classNames} {...props} />
}

View File

@@ -4,6 +4,11 @@ import styles from "./footnote.module.css"
const config = {
variants: {
type: {
regular: styles.regular,
bold: styles.bold,
label: styles.labels,
},
color: {
black: styles.black,
burgundy: styles.burgundy,
@@ -18,13 +23,11 @@ const config = {
left: styles.left,
},
textTransform: {
bold: styles.bold,
regular: styles.regular,
uppercase: styles.uppercase,
},
},
defaultVariants: {
textTransform: "regular",
type: "regular",
},
} as const
@@ -32,18 +35,21 @@ export const footnoteVariants = cva(styles.footnote, config)
const fontOnlyConfig = {
variants: {
type: {
regular: styles.regular,
bold: styles.bold,
label: styles.labels,
},
textAlign: {
center: styles.center,
left: styles.left,
},
textTransform: {
bold: styles.bold,
regular: styles.regular,
uppercase: styles.uppercase,
},
},
defaultVariants: {
textTransform: "regular",
type: "regular",
},
} as const

View File

@@ -20,7 +20,7 @@ export function Tooltip<P extends TooltipPosition>({
<div className={styles.tooltipContainer} role="tooltip" aria-label={text}>
<div className={className}>
{heading && (
<Caption textTransform="bold" color="white">
<Caption type="bold" color="white">
{heading}
</Caption>
)}