Merge branch 'develop' of bitbucket.org:scandic-swap/web into feature/tracking
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
.btn {
|
||||
background: none;
|
||||
/* No variable yet for radius 50px */
|
||||
border-radius: 50px;
|
||||
border-radius: var(--Corner-radius-Rounded);
|
||||
cursor: pointer;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@@ -10,12 +9,12 @@
|
||||
background-color 300ms ease,
|
||||
color 300ms ease;
|
||||
|
||||
/* TODO: Waiting for variables for buttons from Design team */
|
||||
font-family: var(--typography-Body-Bold-fontFamily);
|
||||
font-size: var(--typography-Body-Bold-fontSize);
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
line-height: var(--typography-Body-Bold-lineHeight);
|
||||
letter-spacing: 0.6%;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.wrapping {
|
||||
@@ -23,6 +22,10 @@
|
||||
padding-right: 0 !important;
|
||||
}
|
||||
|
||||
.fullWidth {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* INTENT */
|
||||
.primary,
|
||||
a.primary {
|
||||
@@ -69,21 +72,33 @@ a.default {
|
||||
}
|
||||
|
||||
/* SIZES */
|
||||
.small {
|
||||
.btn.small {
|
||||
font-size: var(--typography-Caption-Bold-fontSize);
|
||||
line-height: var(--typography-Caption-Bold-lineHeight);
|
||||
gap: var(--Spacing-x-quarter);
|
||||
height: 40px;
|
||||
padding: calc(var(--Spacing-x1) + 2px) var(--Spacing-x2); /* Special case padding to adjust the missing border */
|
||||
}
|
||||
|
||||
.btn.small.secondary {
|
||||
padding: var(--Spacing-x1) var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.medium {
|
||||
.btn.medium {
|
||||
gap: var(--Spacing-x-half);
|
||||
height: 48px;
|
||||
padding: calc(var(--Spacing-x-one-and-half) + 2px) var(--Spacing-x2); /* Special case padding to adjust the missing border */
|
||||
}
|
||||
|
||||
.medium.secondary {
|
||||
padding: var(--Spacing-x-one-and-half) var(--Spacing-x2);
|
||||
}
|
||||
|
||||
.large {
|
||||
.btn.large {
|
||||
gap: var(--Spacing-x-half);
|
||||
padding: calc(var(--Spacing-x2) + 2px) var(--Spacing-x3); /* Special case padding to adjust the missing border */
|
||||
}
|
||||
|
||||
.large.secondary {
|
||||
gap: var(--Spacing-x-half);
|
||||
height: 56px;
|
||||
padding: var(--Spacing-x2) var(--Spacing-x3);
|
||||
}
|
||||
|
||||
@@ -170,19 +185,19 @@ a.default {
|
||||
fill: var(--Base-Button-Secondary-On-Fill-Disabled);
|
||||
}
|
||||
|
||||
.baseTertiary {
|
||||
.btn.baseTertiary {
|
||||
background-color: var(--Base-Button-Tertiary-Fill-Normal);
|
||||
color: var(--Base-Button-Tertiary-On-Fill-Normal);
|
||||
}
|
||||
|
||||
.baseTertiary:active,
|
||||
.baseTertiary:focus,
|
||||
.baseTertiary:hover {
|
||||
.btn.baseTertiary:active,
|
||||
.btn.baseTertiary:focus,
|
||||
.btn.baseTertiary:hover {
|
||||
background-color: var(--Base-Button-Tertiary-Fill-Hover);
|
||||
color: var(--Base-Button-Tertiary-On-Fill-Hover);
|
||||
}
|
||||
|
||||
.baseTertiary:disabled {
|
||||
.btn.baseTertiary:disabled {
|
||||
background-color: var(--Base-Button-Tertiary-Fill-Disabled);
|
||||
color: var(--Base-Button-Tertiary-On-Fill-Disabled);
|
||||
}
|
||||
@@ -800,4 +815,4 @@ a.default {
|
||||
.icon.tertiaryLightSecondary:disabled svg,
|
||||
.icon.tertiaryLightSecondary:disabled svg * {
|
||||
fill: var(--Tertiary-Light-Button-Secondary-On-Fill-Disabled);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,23 @@ import { buttonVariants } from "./variants"
|
||||
import type { ButtonProps } from "./button"
|
||||
|
||||
export default function Button(props: ButtonProps) {
|
||||
const { className, intent, size, theme, wrapping, variant, ...restProps } =
|
||||
props
|
||||
const {
|
||||
className,
|
||||
intent,
|
||||
size,
|
||||
theme,
|
||||
fullWidth,
|
||||
wrapping,
|
||||
variant,
|
||||
...restProps
|
||||
} = props
|
||||
|
||||
const classNames = buttonVariants({
|
||||
className,
|
||||
intent,
|
||||
size,
|
||||
theme,
|
||||
fullWidth,
|
||||
wrapping,
|
||||
variant,
|
||||
})
|
||||
|
||||
@@ -33,6 +33,9 @@ export const buttonVariants = cva(styles.btn, {
|
||||
wrapping: {
|
||||
true: styles.wrapping,
|
||||
},
|
||||
fullWidth: {
|
||||
true: styles.fullWidth,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
intent: "primary",
|
||||
|
||||
@@ -23,6 +23,8 @@ export interface CardProps
|
||||
heading?: string | null
|
||||
bodyText?: string | null
|
||||
backgroundImage?: ImageVaultAsset
|
||||
imageHeight?: number
|
||||
imageWidth?: number
|
||||
onPrimaryButtonClick?: () => void
|
||||
onSecondaryButtonClick?: () => void
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Link from "next/link"
|
||||
|
||||
import Image from "@/components/Image"
|
||||
import Button from "@/components/TempDesignSystem/Button"
|
||||
import Link from "@/components/TempDesignSystem/Link"
|
||||
import BiroScript from "@/components/TempDesignSystem/Text/BiroScript"
|
||||
import Body from "@/components/TempDesignSystem/Text/Body"
|
||||
import Title from "@/components/TempDesignSystem/Text/Title"
|
||||
@@ -21,10 +22,19 @@ export default function Card({
|
||||
className,
|
||||
theme,
|
||||
backgroundImage,
|
||||
imageHeight,
|
||||
imageWidth,
|
||||
onPrimaryButtonClick,
|
||||
onSecondaryButtonClick,
|
||||
}: CardProps) {
|
||||
const { buttonTheme, primaryLinkColor, secondaryLinkColor } = getTheme(theme)
|
||||
const buttonTheme = getTheme(theme)
|
||||
|
||||
imageHeight = imageHeight || 320
|
||||
imageWidth =
|
||||
imageWidth ||
|
||||
(backgroundImage
|
||||
? backgroundImage.dimensions.aspectRatio * imageHeight
|
||||
: 420)
|
||||
|
||||
return (
|
||||
<article
|
||||
@@ -39,8 +49,8 @@ export default function Card({
|
||||
src={backgroundImage.url}
|
||||
className={styles.image}
|
||||
alt={backgroundImage.meta.alt || backgroundImage.title}
|
||||
width={backgroundImage.dimensions.width || 420}
|
||||
height={backgroundImage.dimensions.height || 320}
|
||||
width={imageWidth}
|
||||
height={imageHeight}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
@@ -76,7 +86,6 @@ export default function Card({
|
||||
<Link
|
||||
href={primaryButton.href}
|
||||
target={primaryButton.openInNewTab ? "_blank" : undefined}
|
||||
color={primaryLinkColor}
|
||||
onClick={onPrimaryButtonClick}
|
||||
>
|
||||
{primaryButton.title}
|
||||
@@ -94,7 +103,6 @@ export default function Card({
|
||||
<Link
|
||||
href={secondaryButton.href}
|
||||
target={secondaryButton.openInNewTab ? "_blank" : undefined}
|
||||
color={secondaryLinkColor}
|
||||
onClick={onSecondaryButtonClick}
|
||||
>
|
||||
{secondaryButton.title}
|
||||
|
||||
@@ -1,36 +1,47 @@
|
||||
.divider {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: 1px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.horizontal {
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.dotted {
|
||||
border-bottom-style: dotted;
|
||||
.vertical {
|
||||
height: 100%;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.burgundy {
|
||||
border-bottom-color: var(--Scandic-Brand-Burgundy);
|
||||
background-color: var(--Scandic-Brand-Burgundy);
|
||||
}
|
||||
|
||||
.pale {
|
||||
border-bottom-color: var(--Primary-Dark-On-Surface-Text);
|
||||
background-color: var(--Primary-Dark-On-Surface-Text);
|
||||
}
|
||||
|
||||
.peach {
|
||||
border-bottom-color: var(--Primary-Light-On-Surface-Divider);
|
||||
background-color: var(--Primary-Light-On-Surface-Divider);
|
||||
}
|
||||
|
||||
.beige {
|
||||
border-bottom-color: var(--Scandic-Beige-20);
|
||||
background-color: var(--Scandic-Beige-20);
|
||||
}
|
||||
|
||||
.white {
|
||||
border-bottom-color: var(--UI-Opacity-White-100);
|
||||
background-color: var(--UI-Opacity-White-100);
|
||||
}
|
||||
|
||||
.subtle {
|
||||
border-bottom-color: var(--Base-Border-Subtle);
|
||||
background-color: var(--Base-Border-Subtle);
|
||||
}
|
||||
|
||||
.primaryLightSubtle {
|
||||
background-color: var(--Primary-Light-On-Surface-Divider-subtle);
|
||||
}
|
||||
|
||||
.baseSurfaceSubtleNormal {
|
||||
background-color: var(--Base-Surface-Subtle-Normal);
|
||||
}
|
||||
|
||||
.opacity100 {
|
||||
|
||||
@@ -5,25 +5,27 @@ import styles from "./divider.module.css"
|
||||
export const dividerVariants = cva(styles.divider, {
|
||||
variants: {
|
||||
color: {
|
||||
burgundy: styles.burgundy,
|
||||
peach: styles.peach,
|
||||
baseSurfaceSubtleNormal: styles.baseSurfaceSubtleNormal,
|
||||
beige: styles.beige,
|
||||
white: styles.white,
|
||||
subtle: styles.subtle,
|
||||
burgundy: styles.burgundy,
|
||||
pale: styles.pale,
|
||||
peach: styles.peach,
|
||||
primaryLightSubtle: styles.primaryLightSubtle,
|
||||
subtle: styles.subtle,
|
||||
white: styles.white,
|
||||
},
|
||||
opacity: {
|
||||
100: styles.opacity100,
|
||||
8: styles.opacity8,
|
||||
},
|
||||
variant: {
|
||||
default: styles.default,
|
||||
dotted: styles.dotted,
|
||||
horizontal: styles.horizontal,
|
||||
vertical: styles.vertical,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
color: "burgundy",
|
||||
opacity: 100,
|
||||
variant: "default",
|
||||
variant: "horizontal",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
import NextLink from "next/link"
|
||||
import { usePathname, useRouter } from "next/navigation"
|
||||
import { startTransition, useCallback } from "react"
|
||||
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
||||
import { startTransition, useCallback, useMemo } from "react"
|
||||
|
||||
import { trackClick } from "@/utils/tracking"
|
||||
|
||||
@@ -22,9 +22,14 @@ export default function Link({
|
||||
variant,
|
||||
trackingId,
|
||||
onClick,
|
||||
/**
|
||||
* Decides if the link should include the current search params in the URL
|
||||
*/
|
||||
keepSearchParams,
|
||||
...props
|
||||
}: LinkProps) {
|
||||
const currentPageSlug = usePathname()
|
||||
const searchParams = useSearchParams()
|
||||
let isActive = active || currentPageSlug === href
|
||||
|
||||
if (partialMatch && !isActive) {
|
||||
@@ -42,6 +47,12 @@ export default function Link({
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
const fullUrl = useMemo(() => {
|
||||
const search =
|
||||
keepSearchParams && searchParams.size ? `?${searchParams}` : ""
|
||||
return `${href}${search}`
|
||||
}, [href, searchParams, keepSearchParams])
|
||||
|
||||
const trackClickById = useCallback(() => {
|
||||
if (trackingId) {
|
||||
trackClick(trackingId)
|
||||
@@ -65,12 +76,17 @@ export default function Link({
|
||||
// track navigation nor start a router transition.
|
||||
return
|
||||
}
|
||||
if (href.startsWith("tel:") || href.startsWith("mailto:")) {
|
||||
// If href contains tel or mailto protocols we don't want to
|
||||
// track navigation nor start a router transition.
|
||||
return
|
||||
}
|
||||
e.preventDefault()
|
||||
startTransition(() => {
|
||||
router.push(href, { scroll })
|
||||
router.push(fullUrl, { scroll })
|
||||
})
|
||||
}}
|
||||
href={href}
|
||||
href={fullUrl}
|
||||
id={trackingId}
|
||||
{...props}
|
||||
/>
|
||||
|
||||
@@ -10,4 +10,5 @@ export interface LinkProps
|
||||
partialMatch?: boolean
|
||||
prefetch?: boolean
|
||||
trackingId?: string
|
||||
keepSearchParams?: boolean
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { useIsSSR } from "@react-aria/ssr"
|
||||
import { useContext } from "react"
|
||||
import { useContext, useState } from "react"
|
||||
import {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
@@ -29,6 +29,15 @@ function SidePeek({
|
||||
}: React.PropsWithChildren<SidePeekProps>) {
|
||||
const isSSR = useIsSSR()
|
||||
const intl = useIntl()
|
||||
|
||||
const [rootDiv, setRootDiv] = useState<HTMLDivElement | undefined>(undefined)
|
||||
|
||||
function setRef(node: HTMLDivElement | null) {
|
||||
if (node) {
|
||||
setRootDiv(node)
|
||||
}
|
||||
}
|
||||
|
||||
const context = useContext(SidePeekContext)
|
||||
function onClose() {
|
||||
const closeHandler = handleClose || context?.handleClose
|
||||
@@ -44,42 +53,45 @@ function SidePeek({
|
||||
)
|
||||
}
|
||||
return (
|
||||
<DialogTrigger>
|
||||
<ModalOverlay
|
||||
className={styles.overlay}
|
||||
isOpen={isOpen || 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"
|
||||
<div ref={setRef}>
|
||||
<DialogTrigger>
|
||||
<ModalOverlay
|
||||
UNSTABLE_portalContainer={rootDiv}
|
||||
className={styles.overlay}
|
||||
isOpen={isOpen || 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}
|
||||
>
|
||||
{title}
|
||||
</Title>
|
||||
) : null}
|
||||
<Button
|
||||
aria-label={intl.formatMessage({ id: "Close" })}
|
||||
className={styles.closeButton}
|
||||
intent="text"
|
||||
onPress={onClose}
|
||||
>
|
||||
<CloseIcon color="burgundy" height={32} width={32} />
|
||||
</Button>
|
||||
</header>
|
||||
<div className={styles.sidePeekContent}>{children}</div>
|
||||
</aside>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</ModalOverlay>
|
||||
</DialogTrigger>
|
||||
<CloseIcon color="burgundy" height={32} width={32} />
|
||||
</Button>
|
||||
</header>
|
||||
<div className={styles.sidePeekContent}>{children}</div>
|
||||
</aside>
|
||||
</Dialog>
|
||||
</Modal>
|
||||
</ModalOverlay>
|
||||
</DialogTrigger>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@
|
||||
|
||||
.sidePeekContent {
|
||||
padding: var(--Spacing-x4);
|
||||
overflow-y: auto;
|
||||
}
|
||||
@media screen and (min-width: 1367px) {
|
||||
.modal {
|
||||
@@ -94,8 +95,4 @@
|
||||
.modal[data-exiting] {
|
||||
animation: slide-in 250ms reverse;
|
||||
}
|
||||
|
||||
.overlay {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@
|
||||
color: var(--UI-Text-Medium-contrast);
|
||||
}
|
||||
|
||||
.textHighContrast {
|
||||
color: var(--UI-Text-High-contrast);
|
||||
}
|
||||
|
||||
.white {
|
||||
color: var(--UI-Opacity-White-100);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ const config = {
|
||||
pale: styles.pale,
|
||||
red: styles.red,
|
||||
textMediumContrast: styles.textMediumContrast,
|
||||
textHighContrast: styles.textHighContrast,
|
||||
white: styles.white,
|
||||
peach50: styles.peach50,
|
||||
peach80: styles.peach80,
|
||||
|
||||
@@ -63,6 +63,10 @@ p.caption {
|
||||
color: var(--UI-Text-Active);
|
||||
}
|
||||
|
||||
.uiTextMediumContrast {
|
||||
color: var(--UI-Text-Medium-contrast);
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ const config = {
|
||||
red: styles.red,
|
||||
white: styles.white,
|
||||
uiTextActive: styles.uiTextActive,
|
||||
uiTextMediumContrast: styles.uiTextMediumContrast,
|
||||
},
|
||||
textTransform: {
|
||||
bold: styles.bold,
|
||||
|
||||
Reference in New Issue
Block a user