Merged in fix/3697-prettier-configs (pull request #3396)

fix(SW-3691): Setup one prettier config for whole repo

* Setup prettierrc in root and remove other configs


Approved-by: Joakim Jäderberg
Approved-by: Linus Flood
This commit is contained in:
Rasmus Langvad
2026-01-07 12:45:50 +00:00
parent 932413412b
commit d0546926a9
500 changed files with 18367 additions and 18419 deletions

View File

@@ -1,7 +1,7 @@
{ {
"semi": false, "semi": false,
"singleQuote": true,
"trailingComma": "es5", "trailingComma": "es5",
"singleQuote": false,
"printWidth": 80, "printWidth": 80,
"tabWidth": 2, "tabWidth": 2,
"endOfLine": "lf" "endOfLine": "lf"

View File

@@ -1,14 +0,0 @@
/**
* @see https://prettier.io/docs/configuration
* @type {import("prettier").Config}
*/
const config = {
semi: false,
trailingComma: "es5",
singleQuote: false,
printWidth: 80,
tabWidth: 2,
endOfLine: "lf",
}
export default config

View File

@@ -16,13 +16,5 @@
"convert-csv-to-json": "^3.4.0", "convert-csv-to-json": "^3.4.0",
"jiti": "^2.6.1", "jiti": "^2.6.1",
"vitest": "^4.0.0" "vitest": "^4.0.0"
},
"prettier": {
"semi": false,
"trailingComma": "es5",
"singleQuote": false,
"printWidth": 80,
"tabWidth": 2,
"endOfLine": "lf"
} }
} }

View File

@@ -1,14 +0,0 @@
/**
* @see https://prettier.io/docs/configuration
* @type {import("prettier").Config}
*/
const config = {
semi: false,
trailingComma: "es5",
singleQuote: false,
printWidth: 80,
tabWidth: 2,
endOfLine: "lf",
}
export default config

View File

@@ -1,14 +0,0 @@
/**
* @see https://prettier.io/docs/configuration
* @type {import("prettier").Config}
*/
const config = {
semi: false,
trailingComma: "es5",
singleQuote: false,
printWidth: 80,
tabWidth: 2,
endOfLine: "lf",
}
export default config

View File

@@ -1,10 +1,10 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */ /* eslint-disable formatjs/no-literal-string-in-jsx */
import { useState } from 'react' import { useState } from "react"
import copy from 'copy-to-clipboard' import copy from "copy-to-clipboard"
import { kebabify } from '../../generate/utils' import { kebabify } from "../../generate/utils"
export type ThemeValue = Record<'resolved' | 'alias', string | number> export type ThemeValue = Record<"resolved" | "alias", string | number>
export type Theme = Record<string, ThemeValue> export type Theme = Record<string, ThemeValue>
@@ -20,7 +20,7 @@ export type ColorsProps = {
defaultThemeName?: string defaultThemeName?: string
} }
import styles from './colors.module.css' import styles from "./colors.module.css"
function getContrastColor(bgColor: string) { function getContrastColor(bgColor: string) {
const r = parseInt(bgColor.substring(1, 3), 16) const r = parseInt(bgColor.substring(1, 3), 16)
@@ -34,12 +34,12 @@ function getContrastColor(bgColor: string) {
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255 const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
if (luminance > 0.5) { if (luminance > 0.5) {
return '#000' return "#000"
} else { } else {
if (a < 255 / 2) { if (a < 255 / 2) {
return '#000' return "#000"
} }
return '#fff' return "#fff"
} }
} }
@@ -62,7 +62,7 @@ export function Colors({
defaultThemeName, defaultThemeName,
}: ColorsProps) { }: ColorsProps) {
const [selectedThemeName, setSelectedThemeName] = useState<string>( const [selectedThemeName, setSelectedThemeName] = useState<string>(
defaultThemeName || themes?.[0]?.name || '' defaultThemeName || themes?.[0]?.name || ""
) )
const [, setCopiedKey] = useState<string | null>(null) const [, setCopiedKey] = useState<string | null>(null)
@@ -78,8 +78,8 @@ export function Colors({
const grouping: Record<string, Theme> = {} const grouping: Record<string, Theme> = {}
for (const [k, v] of Object.entries(currentTheme)) { for (const [k, v] of Object.entries(currentTheme)) {
if (typeof v.resolved === 'string' && v.resolved.startsWith('#')) { if (typeof v.resolved === "string" && v.resolved.startsWith("#")) {
const key = k.replace(/\/[^/]+$/, '') const key = k.replace(/\/[^/]+$/, "")
if (!grouping[key]) { if (!grouping[key]) {
grouping[key] = {} grouping[key] = {}
} }
@@ -120,8 +120,8 @@ export function Colors({
onChange={(e) => { onChange={(e) => {
const el = document.getElementById(e.target.value) const el = document.getElementById(e.target.value)
el?.scrollIntoView({ el?.scrollIntoView({
behavior: 'smooth', behavior: "smooth",
block: 'start', block: "start",
}) })
}} }}
> >

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { CornerRadius } from './CornerRadius' import { CornerRadius } from "./CornerRadius"
import { base } from '../../lib/tokens' import { base } from "../../lib/tokens"
<Meta title="Tokens/Corner Radius" /> <Meta title="Tokens/Corner Radius" />

View File

@@ -1,9 +1,9 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */ /* eslint-disable formatjs/no-literal-string-in-jsx */
import copy from 'copy-to-clipboard' import copy from "copy-to-clipboard"
import { kebabify } from '../../generate/utils' import { kebabify } from "../../generate/utils"
import tableStyles from './tokens.module.css' import tableStyles from "./tokens.module.css"
type ThemeValue = { type ThemeValue = {
resolved: string | number resolved: string | number
@@ -24,15 +24,15 @@ export function CornerRadius({ theme }: CornerRadiusProps) {
// Filter corner radius tokens // Filter corner radius tokens
const cornerRadiusTokens: Theme = {} const cornerRadiusTokens: Theme = {}
for (const [k, v] of Object.entries(theme)) { for (const [k, v] of Object.entries(theme)) {
if (k.startsWith('Corner radius/')) { if (k.startsWith("Corner radius/")) {
cornerRadiusTokens[k] = v as ThemeValue cornerRadiusTokens[k] = v as ThemeValue
} }
} }
// Sort by value // Sort by value
const sortedTokens = Object.entries(cornerRadiusTokens).sort((a, b) => { const sortedTokens = Object.entries(cornerRadiusTokens).sort((a, b) => {
const aValue = typeof a[1].resolved === 'number' ? a[1].resolved : 0 const aValue = typeof a[1].resolved === "number" ? a[1].resolved : 0
const bValue = typeof b[1].resolved === 'number' ? b[1].resolved : 0 const bValue = typeof b[1].resolved === "number" ? b[1].resolved : 0
return aValue - bValue return aValue - bValue
}) })
@@ -51,7 +51,7 @@ export function CornerRadius({ theme }: CornerRadiusProps) {
</thead> </thead>
<tbody> <tbody>
{sortedTokens.map(([k, v]) => { {sortedTokens.map(([k, v]) => {
const value = typeof v.resolved === 'number' ? v.resolved : 0 const value = typeof v.resolved === "number" ? v.resolved : 0
const valuePx = `${value}px` const valuePx = `${value}px`
return ( return (

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Shadow } from './Shadow' import { Shadow } from "./Shadow"
import { base } from '../../lib/tokens' import { base } from "../../lib/tokens"
<Meta title="Tokens/Shadow" /> <Meta title="Tokens/Shadow" />

View File

@@ -1,9 +1,9 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */ /* eslint-disable formatjs/no-literal-string-in-jsx */
import copy from 'copy-to-clipboard' import copy from "copy-to-clipboard"
import { kebabify } from '../../generate/utils' import { kebabify } from "../../generate/utils"
import tableStyles from './tokens.module.css' import tableStyles from "./tokens.module.css"
type ThemeValue = { type ThemeValue = {
resolved: string | number resolved: string | number
@@ -24,15 +24,15 @@ export function Shadow({ theme }: ShadowProps) {
// Filter shadow tokens // Filter shadow tokens
const shadowTokens: Theme = {} const shadowTokens: Theme = {}
for (const [k, v] of Object.entries(theme)) { for (const [k, v] of Object.entries(theme)) {
if (k.startsWith('BoxShadow-')) { if (k.startsWith("BoxShadow-")) {
shadowTokens[k] = v as ThemeValue shadowTokens[k] = v as ThemeValue
} }
} }
// Sort by level // Sort by level
const sortedTokens = Object.entries(shadowTokens).sort((a, b) => { const sortedTokens = Object.entries(shadowTokens).sort((a, b) => {
const aLevel = parseInt(a[0].match(/\d+/)?.[0] || '0') const aLevel = parseInt(a[0].match(/\d+/)?.[0] || "0")
const bLevel = parseInt(b[0].match(/\d+/)?.[0] || '0') const bLevel = parseInt(b[0].match(/\d+/)?.[0] || "0")
return aLevel - bLevel return aLevel - bLevel
}) })
@@ -53,8 +53,8 @@ export function Shadow({ theme }: ShadowProps) {
<tbody> <tbody>
{sortedTokens.map(([k, v]) => { {sortedTokens.map(([k, v]) => {
const shadowValue = const shadowValue =
typeof v.resolved === 'string' ? v.resolved : '' typeof v.resolved === "string" ? v.resolved : ""
const level = k.match(/\d+/)?.[0] || '0' const level = k.match(/\d+/)?.[0] || "0"
return ( return (
<tr key={k} className={tableStyles.tableRow}> <tr key={k} className={tableStyles.tableRow}>
@@ -80,8 +80,8 @@ export function Shadow({ theme }: ShadowProps) {
}} }}
title="Click to copy" title="Click to copy"
style={{ style={{
fontSize: '0.75rem', fontSize: "0.75rem",
wordBreak: 'break-all', wordBreak: "break-all",
}} }}
> >
{shadowValue} {shadowValue}

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Spacing } from './Spacing' import { Spacing } from "./Spacing"
import { base } from '../../lib/tokens' import { base } from "../../lib/tokens"
<Meta title="Tokens/Spacing" /> <Meta title="Tokens/Spacing" />

View File

@@ -1,9 +1,9 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */ /* eslint-disable formatjs/no-literal-string-in-jsx */
import copy from 'copy-to-clipboard' import copy from "copy-to-clipboard"
import { kebabify } from '../../generate/utils' import { kebabify } from "../../generate/utils"
import tableStyles from './tokens.module.css' import tableStyles from "./tokens.module.css"
type ThemeValue = { type ThemeValue = {
resolved: string | number resolved: string | number
@@ -24,15 +24,15 @@ function copyToClipboard(text: string) {
function getBaseUnitMultiplier(tokenName: string): string { function getBaseUnitMultiplier(tokenName: string): string {
// Token names are like "Space/x0", "Space/x025", "Space/x05", "Space/x1", "Space/x15", etc. // Token names are like "Space/x0", "Space/x025", "Space/x05", "Space/x1", "Space/x15", etc.
const match = tokenName.match(/Space\/x(\d+)/) const match = tokenName.match(/Space\/x(\d+)/)
if (!match) return '0x' if (!match) return "0x"
const num = match[1] const num = match[1]
// Handle special cases // Handle special cases
if (num === '0') return '0x' if (num === "0") return "0x"
if (num === '025') return '0.25x' if (num === "025") return "0.25x"
if (num === '05') return '0.5x' if (num === "05") return "0.5x"
if (num === '15') return '1.5x' if (num === "15") return "1.5x"
// For other numbers, they're already the multiplier (x1 = 1x, x2 = 2x, etc.) // For other numbers, they're already the multiplier (x1 = 1x, x2 = 2x, etc.)
return `${num}x` return `${num}x`
@@ -42,15 +42,15 @@ export function Spacing({ theme }: SpacingProps) {
// Filter spacing tokens // Filter spacing tokens
const spacingTokens: Theme = {} const spacingTokens: Theme = {}
for (const [k, v] of Object.entries(theme)) { for (const [k, v] of Object.entries(theme)) {
if (k.startsWith('Space/')) { if (k.startsWith("Space/")) {
spacingTokens[k] = v as ThemeValue spacingTokens[k] = v as ThemeValue
} }
} }
// Sort by value // Sort by value
const sortedTokens = Object.entries(spacingTokens).sort((a, b) => { const sortedTokens = Object.entries(spacingTokens).sort((a, b) => {
const aValue = typeof a[1].resolved === 'number' ? a[1].resolved : 0 const aValue = typeof a[1].resolved === "number" ? a[1].resolved : 0
const bValue = typeof b[1].resolved === 'number' ? b[1].resolved : 0 const bValue = typeof b[1].resolved === "number" ? b[1].resolved : 0
return aValue - bValue return aValue - bValue
}) })
@@ -72,7 +72,7 @@ export function Spacing({ theme }: SpacingProps) {
</thead> </thead>
<tbody> <tbody>
{sortedTokens.map(([k, v]) => { {sortedTokens.map(([k, v]) => {
const value = typeof v.resolved === 'number' ? v.resolved : 0 const value = typeof v.resolved === "number" ? v.resolved : 0
const valuePx = `${value}px` const valuePx = `${value}px`
const multiplier = getBaseUnitMultiplier(k) const multiplier = getBaseUnitMultiplier(k)
@@ -112,7 +112,7 @@ export function Spacing({ theme }: SpacingProps) {
className={tableStyles.visualBar} className={tableStyles.visualBar}
style={{ style={{
width: `${value}px`, width: `${value}px`,
minWidth: value > 0 ? '2px' : '0', minWidth: value > 0 ? "2px" : "0",
}} }}
/> />
</div> </div>

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from './Colors' import { Colors } from "./Colors"
import { base } from '../../lib/tokens' import { base } from "../../lib/tokens"
<Meta title="Tokens/Colors/Base" /> <Meta title="Tokens/Colors/Base" />

View File

@@ -170,7 +170,7 @@
} }
.colorValue { .colorValue {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
font-size: 0.875rem; font-size: 0.875rem;
font-weight: 600; font-weight: 600;
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
@@ -203,7 +203,7 @@
} }
.tokenCode { .tokenCode {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
font-size: 12px; font-size: 12px;
background: #f9fafb; background: #f9fafb;
padding: 0.375rem 0.625rem; padding: 0.375rem 0.625rem;

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { downtownCamper } from '../../../lib/tokens' import { downtownCamper } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Downtown Camper" /> <Meta title="Tokens/Colors/Downtown Camper" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { grandHotel } from '../../../lib/tokens' import { grandHotel } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Grand Hotel" /> <Meta title="Tokens/Colors/Grand Hotel" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { haymarket } from '../../../lib/tokens' import { haymarket } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Haymarket" /> <Meta title="Tokens/Colors/Haymarket" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { hotelNorge } from '../../../lib/tokens' import { hotelNorge } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Hotel Norge" /> <Meta title="Tokens/Colors/Hotel Norge" />

View File

@@ -1,6 +1,6 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { import {
base, base,
@@ -12,7 +12,7 @@ import {
hotelNorge, hotelNorge,
grandHotel, grandHotel,
theDock, theDock,
} from '../../../lib/tokens' } from "../../../lib/tokens"
<Meta title="Tokens/Colors" /> <Meta title="Tokens/Colors" />
@@ -22,19 +22,19 @@ Select a theme to view all available color tokens. Click on any value to copy it
<Colors <Colors
themes={[ themes={[
{ name: 'base', displayName: 'Base', theme: base }, { name: "base", displayName: "Base", theme: base },
{ name: 'scandic', displayName: 'Scandic', theme: scandic }, { name: "scandic", displayName: "Scandic", theme: scandic },
{ name: 'scandicGo', displayName: 'Scandic Go', theme: scandicGo }, { name: "scandicGo", displayName: "Scandic Go", theme: scandicGo },
{ {
name: 'downtownCamper', name: "downtownCamper",
displayName: 'Downtown Camper', displayName: "Downtown Camper",
theme: downtownCamper, theme: downtownCamper,
}, },
{ name: 'haymarket', displayName: 'Haymarket', theme: haymarket }, { name: "haymarket", displayName: "Haymarket", theme: haymarket },
{ name: 'marski', displayName: 'Marski', theme: marski }, { name: "marski", displayName: "Marski", theme: marski },
{ name: 'hotelNorge', displayName: 'Hotel Norge', theme: hotelNorge }, { name: "hotelNorge", displayName: "Hotel Norge", theme: hotelNorge },
{ name: 'grandHotel', displayName: 'Grand Hotel', theme: grandHotel }, { name: "grandHotel", displayName: "Grand Hotel", theme: grandHotel },
{ name: 'theDock', displayName: 'The Dock', theme: theDock }, { name: "theDock", displayName: "The Dock", theme: theDock },
]} ]}
defaultThemeName="scandic" defaultThemeName="scandic"
/> />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { marski } from '../../../lib/tokens' import { marski } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Marski" /> <Meta title="Tokens/Colors/Marski" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { scandic } from '../../../lib/tokens' import { scandic } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Scandic" /> <Meta title="Tokens/Colors/Scandic" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { scandicGo } from '../../../lib/tokens' import { scandicGo } from "../../../lib/tokens"
<Meta title="Tokens/Colors/Scandic Go" /> <Meta title="Tokens/Colors/Scandic Go" />

View File

@@ -1,8 +1,8 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
import { Colors } from '../Colors' import { Colors } from "../Colors"
import { theDock } from '../../../lib/tokens' import { theDock } from "../../../lib/tokens"
<Meta title="Tokens/Colors/The Dock" /> <Meta title="Tokens/Colors/The Dock" />

View File

@@ -1,4 +1,4 @@
import { Meta } from '@storybook/addon-docs/blocks' import { Meta } from "@storybook/addon-docs/blocks"
<Meta title="Introduction" /> <Meta title="Introduction" />

View File

@@ -57,7 +57,7 @@
} }
.tokenName { .tokenName {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
background: #f3f4f6; background: #f3f4f6;
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
border-radius: 4px; border-radius: 4px;
@@ -73,7 +73,7 @@
} }
.value { .value {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
color: #6b7280; color: #6b7280;
cursor: pointer; cursor: pointer;
transition: color 0.15s ease; transition: color 0.15s ease;
@@ -98,7 +98,7 @@
} }
.visualBarLabel { .visualBarLabel {
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
font-size: 0.75rem; font-size: 0.75rem;
color: #6b7280; color: #6b7280;
min-width: 40px; min-width: 40px;

View File

@@ -1,4 +1,4 @@
import { FormProvider, useForm } from 'react-hook-form' import { FormProvider, useForm } from "react-hook-form"
export const FormDecorator = (Story: React.FC) => { export const FormDecorator = (Story: React.FC) => {
const formMethods = useForm() const formMethods = useForm()

View File

@@ -1,20 +1,20 @@
import type { StorybookConfig } from '@storybook/nextjs-vite' import type { StorybookConfig } from "@storybook/nextjs-vite"
import { mergeConfig } from 'vite' import { mergeConfig } from "vite"
const config: StorybookConfig = { const config: StorybookConfig = {
framework: '@storybook/nextjs-vite', framework: "@storybook/nextjs-vite",
stories: [ stories: [
'../lib/**/*.mdx', "../lib/**/*.mdx",
'../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)', "../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)",
'./content/**/*.mdx', "./content/**/*.mdx",
], ],
addons: [ addons: [
'@storybook/addon-links', "@storybook/addon-links",
'@storybook/addon-themes', "@storybook/addon-themes",
'@storybook/addon-vitest', "@storybook/addon-vitest",
'@storybook/addon-docs', "@storybook/addon-docs",
'@storybook/addon-a11y', "@storybook/addon-a11y",
'storybook-react-intl', "storybook-react-intl",
], ],
core: { core: {
disableTelemetry: true, disableTelemetry: true,
@@ -24,18 +24,18 @@ const config: StorybookConfig = {
plugins: [ plugins: [
// Add babel plugin for react-intl transformation // Add babel plugin for react-intl transformation
{ {
name: 'formatjs-transform', name: "formatjs-transform",
async transform(code, id) { async transform(code, id) {
if (id.includes('node_modules')) return if (id.includes("node_modules")) return
if (!/\.(jsx?|tsx?)$/.test(id)) return if (!/\.(jsx?|tsx?)$/.test(id)) return
const babel = await import('@babel/core') const babel = await import("@babel/core")
const result = babel.transformSync(code, { const result = babel.transformSync(code, {
plugins: [ plugins: [
[ [
'formatjs', "formatjs",
{ {
idInterpolationPattern: '[sha512:contenthash:base64:6]', idInterpolationPattern: "[sha512:contenthash:base64:6]",
ast: true, ast: true,
}, },
], ],

View File

@@ -1,5 +1,5 @@
import { addons } from 'storybook/manager-api' import { addons } from "storybook/manager-api"
import scandicTheme from './scandic-theme' import scandicTheme from "./scandic-theme"
addons.setConfig({ addons.setConfig({
theme: scandicTheme, theme: scandicTheme,

View File

@@ -1,25 +1,25 @@
import { withThemeByClassName } from '@storybook/addon-themes' import { withThemeByClassName } from "@storybook/addon-themes"
import type { Preview, ReactRenderer } from '@storybook/nextjs-vite' import type { Preview, ReactRenderer } from "@storybook/nextjs-vite"
import { IntlProvider } from 'react-intl' import { IntlProvider } from "react-intl"
import { reactIntl } from './reactIntl' import { reactIntl } from "./reactIntl"
import '../lib/design-system-new-deprecated.css' import "../lib/design-system-new-deprecated.css"
import '../lib/fonts.css' import "../lib/fonts.css"
import '../lib/normalize.css' import "../lib/normalize.css"
import '../lib/style.css' import "../lib/style.css"
export const themes = { export const themes = {
themes: { themes: {
Scandic: 'scandic', Scandic: "scandic",
'Scandic Go': 'scandic-go', "Scandic Go": "scandic-go",
'Downtown Camper': 'downtown-camper', "Downtown Camper": "downtown-camper",
'Grand Hotel': 'grand-hotel', "Grand Hotel": "grand-hotel",
Haymarket: 'haymarket', Haymarket: "haymarket",
'Hotel Norge': 'hotel-norge', "Hotel Norge": "hotel-norge",
Marski: 'marski', Marski: "marski",
'The Dock': 'the-dock', "The Dock": "the-dock",
}, },
defaultTheme: 'Scandic', defaultTheme: "Scandic",
} }
const preview: Preview = { const preview: Preview = {
@@ -36,14 +36,14 @@ const preview: Preview = {
initialGlobals: { initialGlobals: {
locale: reactIntl.defaultLocale, locale: reactIntl.defaultLocale,
locales: { locales: {
en: { icon: '🇬🇧', title: 'English', right: 'EN' }, en: { icon: "🇬🇧", title: "English", right: "EN" },
sv: { icon: '🇸🇪', title: 'Svenska', right: 'SV' }, sv: { icon: "🇸🇪", title: "Svenska", right: "SV" },
da: { icon: '🇩🇰', title: 'Dansk', right: 'DA' }, da: { icon: "🇩🇰", title: "Dansk", right: "DA" },
no: { icon: '🇳🇴', title: 'Norsk', right: 'NO' }, no: { icon: "🇳🇴", title: "Norsk", right: "NO" },
fi: { icon: '🇫🇮', title: 'Suomi', right: 'FI' }, fi: { icon: "🇫🇮", title: "Suomi", right: "FI" },
de: { icon: '🇩🇪', title: 'Deutsch', right: 'DE' }, de: { icon: "🇩🇪", title: "Deutsch", right: "DE" },
}, },
backgrounds: { value: 'scandicSubtle' }, backgrounds: { value: "scandicSubtle" },
}, },
parameters: { parameters: {
reactIntl, reactIntl,
@@ -61,13 +61,13 @@ const preview: Preview = {
options: { options: {
storySort: { storySort: {
order: [ order: [
'Introduction', "Introduction",
'Tokens', "Tokens",
'Core Components', "Core Components",
'Product Components', "Product Components",
'Patterns', "Patterns",
'Compositions', "Compositions",
'*', "*",
], ],
}, },
}, },
@@ -75,12 +75,12 @@ const preview: Preview = {
backgrounds: { backgrounds: {
options: { options: {
// 👇 Scandic // 👇 Scandic
scandicPrimary: { name: 'Scandic Primary', value: '#FAF6F2' }, scandicPrimary: { name: "Scandic Primary", value: "#FAF6F2" },
scandicSubtle: { name: 'Scandic Subtle', value: '#F2ECE6' }, scandicSubtle: { name: "Scandic Subtle", value: "#F2ECE6" },
scandicPrimaryDark: { name: 'Scandic Primary Dark', value: '#4D001B' }, scandicPrimaryDark: { name: "Scandic Primary Dark", value: "#4D001B" },
// 👇 Default values // 👇 Default values
storybookDark: { name: 'Storybook Dark', value: '#333' }, storybookDark: { name: "Storybook Dark", value: "#333" },
storybookLight: { name: 'Storybook Light', value: '#F7F9F2' }, storybookLight: { name: "Storybook Light", value: "#F7F9F2" },
}, },
}, },
@@ -88,11 +88,11 @@ const preview: Preview = {
// 'todo' - show a11y violations in the test UI only // 'todo' - show a11y violations in the test UI only
// 'error' - fail CI on a11y violations // 'error' - fail CI on a11y violations
// 'off' - skip a11y checks entirely // 'off' - skip a11y checks entirely
test: 'todo', test: "todo",
}, },
}, },
tags: ['autodocs'], tags: ["autodocs"],
} }
export default preview export default preview

View File

@@ -1,12 +1,12 @@
/* eslint-disable import/no-relative-packages */ /* eslint-disable import/no-relative-packages */
import en from '../../../apps/scandic-web/i18n/dictionaries/en.json' import en from "../../../apps/scandic-web/i18n/dictionaries/en.json"
import sv from '../../../apps/scandic-web/i18n/dictionaries/sv.json' import sv from "../../../apps/scandic-web/i18n/dictionaries/sv.json"
import da from '../../../apps/scandic-web/i18n/dictionaries/da.json' import da from "../../../apps/scandic-web/i18n/dictionaries/da.json"
import fi from '../../../apps/scandic-web/i18n/dictionaries/fi.json' import fi from "../../../apps/scandic-web/i18n/dictionaries/fi.json"
import de from '../../../apps/scandic-web/i18n/dictionaries/de.json' import de from "../../../apps/scandic-web/i18n/dictionaries/de.json"
import no from '../../../apps/scandic-web/i18n/dictionaries/no.json' import no from "../../../apps/scandic-web/i18n/dictionaries/no.json"
const locales = ['en', 'sv', 'da', 'fi', 'no', 'de'] const locales = ["en", "sv", "da", "fi", "no", "de"]
const messages: Record<(typeof locales)[number], unknown> = { const messages: Record<(typeof locales)[number], unknown> = {
en, en,
@@ -20,7 +20,7 @@ const messages: Record<(typeof locales)[number], unknown> = {
const formats = {} // optional, if you have any formats const formats = {} // optional, if you have any formats
export const reactIntl = { export const reactIntl = {
defaultLocale: 'en', defaultLocale: "en",
locales, locales,
messages, messages,
formats, formats,

View File

@@ -1,8 +1,8 @@
import { create } from 'storybook/theming' import { create } from "storybook/theming"
export default create({ export default create({
base: 'dark', base: "dark",
brandTitle: 'Scandic Design System', brandTitle: "Scandic Design System",
brandUrl: 'https://www.scandichotels.com/', brandUrl: "https://www.scandichotels.com/",
brandImage: '/img/scandic-logotype.png', brandImage: "/img/scandic-logotype.png",
}) })

View File

@@ -1,5 +1,5 @@
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview' import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview"
import { setProjectAnnotations } from '@storybook/nextjs-vite' import { setProjectAnnotations } from "@storybook/nextjs-vite"
import * as previewAnnotations from './preview' import * as previewAnnotations from "./preview"
setProjectAnnotations([a11yAddonAnnotations, previewAnnotations]) setProjectAnnotations([a11yAddonAnnotations, previewAnnotations])

View File

@@ -1,15 +1,15 @@
import { defineConfig, globalIgnores } from 'eslint/config' import { defineConfig, globalIgnores } from "eslint/config"
import globals from 'globals' import globals from "globals"
import tsParser from '@typescript-eslint/parser' import tsParser from "@typescript-eslint/parser"
import reactRefresh from 'eslint-plugin-react-refresh' import reactRefresh from "eslint-plugin-react-refresh"
import react from 'eslint-plugin-react' import react from "eslint-plugin-react"
import { FlatCompat } from '@eslint/eslintrc' import { FlatCompat } from "@eslint/eslintrc"
import js from '@eslint/js' import js from "@eslint/js"
import importPlugin from 'eslint-plugin-import' import importPlugin from "eslint-plugin-import"
import formatjs from 'eslint-plugin-formatjs' import formatjs from "eslint-plugin-formatjs"
import { fileURLToPath } from 'node:url' import { fileURLToPath } from "node:url"
import path from 'node:path' import path from "node:path"
const compat = new FlatCompat({ const compat = new FlatCompat({
recommendedConfig: js.configs.recommended, recommendedConfig: js.configs.recommended,
@@ -27,72 +27,72 @@ export default defineConfig([
parser: tsParser, parser: tsParser,
}, },
extends: compat.extends( extends: compat.extends(
'eslint:recommended', "eslint:recommended",
'plugin:@typescript-eslint/recommended', "plugin:@typescript-eslint/recommended",
'plugin:react-hooks/recommended', "plugin:react-hooks/recommended",
'plugin:storybook/recommended' "plugin:storybook/recommended"
), ),
plugins: { plugins: {
'react-refresh': reactRefresh, "react-refresh": reactRefresh,
import: importPlugin, import: importPlugin,
formatjs, formatjs,
react, react,
}, },
settings: { settings: {
// Ensure the plugin can resolve workspace packages and TS path aliases // Ensure the plugin can resolve workspace packages and TS path aliases
'import/resolver': { "import/resolver": {
typescript: { typescript: {
project: [path.join(packageDir, 'tsconfig.json')], project: [path.join(packageDir, "tsconfig.json")],
alwaysTryTypes: true, alwaysTryTypes: true,
}, },
node: { node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'], extensions: [".js", ".jsx", ".ts", ".tsx"],
}, },
}, },
}, },
rules: { rules: {
'import/no-relative-packages': 'error', "import/no-relative-packages": "error",
'import/no-extraneous-dependencies': [ "import/no-extraneous-dependencies": [
'error', "error",
{ {
includeInternal: true, includeInternal: true,
includeTypes: true, includeTypes: true,
packageDir: [packageDir], packageDir: [packageDir],
}, },
], ],
'react-refresh/only-export-components': [ "react-refresh/only-export-components": [
'warn', "warn",
{ {
allowConstantExport: true, allowConstantExport: true,
}, },
], ],
'react/jsx-curly-brace-presence': [ "react/jsx-curly-brace-presence": [
'error', "error",
{ {
props: 'never', props: "never",
children: 'never', children: "never",
propElementValues: 'always', propElementValues: "always",
}, },
], ],
'formatjs/enforce-default-message': ['error', 'literal'], "formatjs/enforce-default-message": ["error", "literal"],
'formatjs/enforce-placeholders': ['error'], "formatjs/enforce-placeholders": ["error"],
'formatjs/enforce-plural-rules': ['error'], "formatjs/enforce-plural-rules": ["error"],
'formatjs/no-literal-string-in-jsx': ['error'], "formatjs/no-literal-string-in-jsx": ["error"],
'formatjs/no-multiple-whitespaces': ['error'], "formatjs/no-multiple-whitespaces": ["error"],
'formatjs/no-multiple-plurals': ['error'], "formatjs/no-multiple-plurals": ["error"],
'formatjs/no-invalid-icu': ['error'], "formatjs/no-invalid-icu": ["error"],
'formatjs/enforce-id': ['error'], "formatjs/enforce-id": ["error"],
'formatjs/no-complex-selectors': ['error'], "formatjs/no-complex-selectors": ["error"],
'formatjs/no-useless-message': ['error'], "formatjs/no-useless-message": ["error"],
'formatjs/prefer-pound-in-plural': ['error'], "formatjs/prefer-pound-in-plural": ["error"],
}, },
}, },
{ {
files: ['**/*.stories.tsx'], files: ["**/*.stories.tsx"],
rules: { rules: {
'formatjs/no-literal-string-in-jsx': 'off', "formatjs/no-literal-string-in-jsx": "off",
}, },
}, },
globalIgnores(['**/dist', '**/.eslintrc.cjs', '**/storybook-static']), globalIgnores(["**/dist", "**/.eslintrc.cjs", "**/storybook-static"]),
]) ])

View File

@@ -1,14 +1,14 @@
import { extend } from 'colord' import { extend } from "colord"
import mixPlugin from 'colord/plugins/mix' import mixPlugin from "colord/plugins/mix"
import fs from 'node:fs' import fs from "node:fs"
import { import {
FALLBACK_THEME, FALLBACK_THEME,
getThemeForToken, getThemeForToken,
ignoreStyles, ignoreStyles,
kebabify, kebabify,
} from './utils' } from "./utils"
import json from './variables.json' assert { type: 'json' } import json from "./variables.json" assert { type: "json" }
extend([mixPlugin]) extend([mixPlugin])
@@ -26,7 +26,7 @@ themes.set(FALLBACK_THEME, new Map())
// Collect all real themes // Collect all real themes
json.collections json.collections
.find((collection) => { .find((collection) => {
return collection.name === 'Color Theming' return collection.name === "Color Theming"
}) })
?.modes.forEach((mode) => { ?.modes.forEach((mode) => {
themes.set(mode.name, new Map()) themes.set(mode.name, new Map())
@@ -42,7 +42,7 @@ const responsiveTokens = new Set()
// Collect responsive tokens // Collect responsive tokens
json.collections json.collections
.find((collection) => collection.name === 'Responsive') .find((collection) => collection.name === "Responsive")
?.modes.forEach((mode) => { ?.modes.forEach((mode) => {
mode.variables.forEach((variable) => { mode.variables.forEach((variable) => {
responsiveTokens.add(variable.name) responsiveTokens.add(variable.name)
@@ -60,23 +60,23 @@ json.collections.forEach((collection) => {
const tokenTheme = getThemeForToken(token, mode, themes) const tokenTheme = getThemeForToken(token, mode, themes)
switch (variable.type) { switch (variable.type) {
case 'boolean': case "boolean":
if (typeof variable.value === 'boolean') { if (typeof variable.value === "boolean") {
// Handle text transform // Handle text transform
if (/text transform/i.test(variable.name)) { if (/text transform/i.test(variable.name)) {
token = variable.name.replace( token = variable.name.replace(
/text transform/i, /text transform/i,
'Text-Transform' "Text-Transform"
) )
value = variable.value ? 'uppercase' : 'none' value = variable.value ? "uppercase" : "none"
} }
// Handle text decoration // Handle text decoration
else if (/text decoration/i.test(variable.name)) { else if (/text decoration/i.test(variable.name)) {
token = variable.name.replace( token = variable.name.replace(
/text decoration/i, /text decoration/i,
'Text-Decoration' "Text-Decoration"
) )
value = variable.value ? 'underline' : 'none' value = variable.value ? "underline" : "none"
} }
} else { } else {
throw new Error( throw new Error(
@@ -84,8 +84,8 @@ json.collections.forEach((collection) => {
) )
} }
break break
case 'number': case "number":
if (typeof variable.value === 'number') { if (typeof variable.value === "number") {
// Only use two decimals for all numbers // Only use two decimals for all numbers
value = Number(variable.value.toFixed(2)) value = Number(variable.value.toFixed(2))
} else { } else {
@@ -96,7 +96,7 @@ json.collections.forEach((collection) => {
break break
} }
if (typeof value === 'string' || typeof value === 'number') { if (typeof value === "string" || typeof value === "number") {
const theme = themes.get(tokenTheme) const theme = themes.get(tokenTheme)
if (theme) { if (theme) {
theme.set(token, { theme.set(token, {
@@ -125,11 +125,11 @@ json.collections.forEach((collection) => {
const tokenTheme = getThemeForToken(token, mode, themes) const tokenTheme = getThemeForToken(token, mode, themes)
switch (variable.type) { switch (variable.type) {
case 'color': case "color":
case 'string': case "string":
case 'number': case "number":
// Some values are defined as objects, so we need to dig out the real value // Some values are defined as objects, so we need to dig out the real value
if (typeof value === 'object' && 'name' in value) { if (typeof value === "object" && "name" in value) {
value = value.name value = value.name
} }
@@ -139,13 +139,13 @@ json.collections.forEach((collection) => {
value = `Impl-${value}` value = `Impl-${value}`
} }
if (typeof value === 'string') { if (typeof value === "string") {
const theme = themes.get(tokenTheme) const theme = themes.get(tokenTheme)
if (theme) { if (theme) {
theme.set(token, { theme.set(token, {
// We can only resolve aliases after we have collected all // We can only resolve aliases after we have collected all
// primitives and aliases. // primitives and aliases.
resolved: '', resolved: "",
alias: value, alias: value,
}) })
} }
@@ -165,8 +165,8 @@ json.collections.forEach((collection) => {
json.collections.forEach((collection) => { json.collections.forEach((collection) => {
collection.modes.forEach((mode) => { collection.modes.forEach((mode) => {
mode.variables.forEach((variable) => { mode.variables.forEach((variable) => {
if (variable.type === 'effect') { if (variable.type === "effect") {
if (typeof variable.value === 'object' && 'effects' in variable.value) { if (typeof variable.value === "object" && "effects" in variable.value) {
if (variable.value.effects.length > 1) { if (variable.value.effects.length > 1) {
console.warn( console.warn(
`Unsupported effect declaration with multiple effects.`, `Unsupported effect declaration with multiple effects.`,
@@ -176,7 +176,7 @@ json.collections.forEach((collection) => {
// We only support one effect declaration per variable // We only support one effect declaration per variable
const effect = variable.value.effects[0] const effect = variable.value.effects[0]
switch (effect.type) { switch (effect.type) {
case 'DROP_SHADOW': { case "DROP_SHADOW": {
const { r, g, b, a } = effect.color const { r, g, b, a } = effect.color
const { x, y } = effect.offset const { x, y } = effect.offset
const value = `${x}px ${y}px ${effect.radius}px ${effect.spread}px rgba(${r}, ${g}, ${b}, ${a})` const value = `${x}px ${y}px ${effect.radius}px ${effect.spread}px rgba(${r}, ${g}, ${b}, ${a})`
@@ -240,7 +240,7 @@ themes.forEach((themeTokenValues) => {
// Prepare for output // Prepare for output
const variablesJsOutput = [ const variablesJsOutput = [
'/* This file is generated, do not edit manually! */', "/* This file is generated, do not edit manually! */",
] ]
themes.forEach((themeTokenValues, themeKey) => { themes.forEach((themeTokenValues, themeKey) => {
const cssContentPrimitives: string[] = [] const cssContentPrimitives: string[] = []
@@ -255,12 +255,12 @@ themes.forEach((themeTokenValues, themeKey) => {
` --${outputToken}: var(--${kebabify(outputValue.toString())});` ` --${outputToken}: var(--${kebabify(outputValue.toString())});`
) )
} else { } else {
if (typeof outputValue === 'string') { if (typeof outputValue === "string") {
// Check for properties that need quotes // Check for properties that need quotes
if (/font(-| )family/gi.test(token)) { if (/font(-| )family/gi.test(token)) {
outputValue = `"${outputValue}"` outputValue = `"${outputValue}"`
} }
} else if (typeof outputValue === 'number') { } else if (typeof outputValue === "number") {
// font-weight is unitless // font-weight is unitless
if (!/font(-| )weight/gi.test(token)) { if (!/font(-| )weight/gi.test(token)) {
outputValue = `${outputValue}px` outputValue = `${outputValue}px`
@@ -278,25 +278,25 @@ themes.forEach((themeTokenValues, themeKey) => {
const filename = kebabify(themeKey).toLowerCase() const filename = kebabify(themeKey).toLowerCase()
const cssOutput = [ const cssOutput = [
'/* This file is generated, do not edit manually! */', "/* This file is generated, do not edit manually! */",
// The base styles target the :root. // The base styles target the :root.
// All themes require the use of their scoping classname to be used. // All themes require the use of their scoping classname to be used.
themeKey === FALLBACK_THEME ? ':root {' : `.${filename} {`, themeKey === FALLBACK_THEME ? ":root {" : `.${filename} {`,
' /* Values */', " /* Values */",
...cssContentPrimitives.sort(), ...cssContentPrimitives.sort(),
'', "",
' /* Aliases */', " /* Aliases */",
...cssContentAliases.sort(), ...cssContentAliases.sort(),
'}', "}",
'', // New line at end of file "", // New line at end of file
] ]
fs.writeFileSync(`../lib/styles/${filename}.css`, cssOutput.join('\n'), { fs.writeFileSync(`../lib/styles/${filename}.css`, cssOutput.join("\n"), {
encoding: 'utf-8', encoding: "utf-8",
}) })
const resolvedJsOutput = [ const resolvedJsOutput = [
'/* This file is generated, do not edit manually! */', "/* This file is generated, do not edit manually! */",
`export const theme = ${JSON.stringify( `export const theme = ${JSON.stringify(
Array.from(themeTokenValues).reduce( Array.from(themeTokenValues).reduce(
(acc, [token, value]) => { (acc, [token, value]) => {
@@ -313,9 +313,9 @@ themes.forEach((themeTokenValues, themeKey) => {
] ]
fs.writeFileSync( fs.writeFileSync(
`../lib/styles/${filename}.js`, `../lib/styles/${filename}.js`,
resolvedJsOutput.join('\n'), resolvedJsOutput.join("\n"),
{ {
encoding: 'utf-8', encoding: "utf-8",
} }
) )
@@ -323,14 +323,14 @@ themes.forEach((themeTokenValues, themeKey) => {
// It is mainly used for the Storybook to show all the variables. // It is mainly used for the Storybook to show all the variables.
variablesJsOutput.push( variablesJsOutput.push(
`export const ${themeKey `export const ${themeKey
.split(' ') .split(" ")
.map((v, i) => (i === 0 ? v.toLowerCase() : v)) .map((v, i) => (i === 0 ? v.toLowerCase() : v))
.join( .join(
'' ""
)} = ${JSON.stringify(Object.fromEntries(themeTokenValues.entries()))} as const` )} = ${JSON.stringify(Object.fromEntries(themeTokenValues.entries()))} as const`
) )
}) })
fs.writeFileSync(`../lib/tokens/index.ts`, variablesJsOutput.join('\n'), { fs.writeFileSync(`../lib/tokens/index.ts`, variablesJsOutput.join("\n"), {
encoding: 'utf-8', encoding: "utf-8",
}) })

View File

@@ -1,9 +1,9 @@
export function kebabify(str: string) { export function kebabify(str: string) {
return str.replace(/\/|\s/g, '-').replace(/\(|\)|\[|\]/g, '') return str.replace(/\/|\s/g, "-").replace(/\(|\)|\[|\]/g, "")
} }
export function ignoreStyles(mode: { name: string }) { export function ignoreStyles(mode: { name: string }) {
if (mode.name === 'Style') { if (mode.name === "Style") {
// Ignore Figma Styles, we only want to process variables. // Ignore Figma Styles, we only want to process variables.
// But the exported variables.json includes Figma Styles too. // But the exported variables.json includes Figma Styles too.
return false return false
@@ -12,7 +12,7 @@ export function ignoreStyles(mode: { name: string }) {
} }
// Some tokens are the same for all themes. Group them into this theme. // Some tokens are the same for all themes. Group them into this theme.
export const FALLBACK_THEME = 'base' export const FALLBACK_THEME = "base"
// The variables exported from Figma are not grouped by theme. // The variables exported from Figma are not grouped by theme.
// We used this function to help us group by theme. // We used this function to help us group by theme.
@@ -24,10 +24,10 @@ export function getThemeForToken(
themes: Map<string, unknown> themes: Map<string, unknown>
) { ) {
// If the given value is an object and has a name property, use that as comparison value. // If the given value is an object and has a name property, use that as comparison value.
const compare = typeof token === 'string' ? token : token.name const compare = typeof token === "string" ? token : token.name
const theme = Array.from(themes.keys()).find((theme) => { const theme = Array.from(themes.keys()).find((theme) => {
// Match against "theme/", use that if it matches // Match against "theme/", use that if it matches
if (compare.indexOf(theme + '/') >= 0) { if (compare.indexOf(theme + "/") >= 0) {
return theme return theme
} }

View File

@@ -1,18 +1,18 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import Accordion from './index' import Accordion from "./index"
import AccordionItem from './AccordionItem/index' import AccordionItem from "./AccordionItem/index"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { IconName } from '../Icons/iconName' import { IconName } from "../Icons/iconName"
import { Typography } from '../Typography' import { Typography } from "../Typography"
const meta: Meta<typeof Accordion> = { const meta: Meta<typeof Accordion> = {
title: 'Core Components/Accordion', title: "Core Components/Accordion",
component: Accordion, component: Accordion,
argTypes: { argTypes: {
type: { type: {
control: 'select', control: "select",
options: ['card', 'sidepeek', 'inline'], options: ["card", "sidepeek", "inline"],
}, },
}, },
} }
@@ -23,7 +23,7 @@ type Story = StoryObj<typeof Accordion>
export const Default: Story = { export const Default: Story = {
args: { args: {
type: 'card', type: "card",
}, },
render: (args) => ( render: (args) => (
<Accordion {...args}> <Accordion {...args}>
@@ -60,7 +60,7 @@ export const Default: Story = {
export const WithIcons: Story = { export const WithIcons: Story = {
args: { args: {
type: 'card', type: "card",
}, },
render: (args) => ( render: (args) => (
<Accordion {...args}> <Accordion {...args}>
@@ -106,7 +106,7 @@ export const WithIcons: Story = {
export const WithSubtitle: Story = { export const WithSubtitle: Story = {
args: { args: {
type: 'card', type: "card",
}, },
render: (args) => ( render: (args) => (
<Accordion {...args}> <Accordion {...args}>
@@ -140,7 +140,7 @@ export const WithSubtitle: Story = {
export const Inline: Story = { export const Inline: Story = {
args: { args: {
type: 'inline', type: "inline",
}, },
render: () => ( render: () => (
<Accordion type="inline"> <Accordion type="inline">

View File

@@ -1,23 +1,24 @@
'use client' "use client"
import { type ReactNode, useEffect, useRef } from 'react' import { type ReactNode, useEffect, useRef } from "react"
import { IconByIconName } from '../../Icons/IconByIconName' import { IconByIconName } from "../../Icons/IconByIconName"
import { MaterialIcon } from '../../Icons/MaterialIcon' import { MaterialIcon } from "../../Icons/MaterialIcon"
import { accordionItemVariants } from './variants' import { accordionItemVariants } from "./variants"
import styles from './accordionItem.module.css' import styles from "./accordionItem.module.css"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { IconName } from '../../Icons/iconName' import type { IconName } from "../../Icons/iconName"
import { Typography } from '../../Typography' import { Typography } from "../../Typography"
export interface AccordionItemProps export interface AccordionItemProps
extends React.HtmlHTMLAttributes<HTMLDetailsElement>, extends
React.HtmlHTMLAttributes<HTMLDetailsElement>,
VariantProps<typeof accordionItemVariants> { VariantProps<typeof accordionItemVariants> {
title: string title: string
titleLevel?: 'span' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' titleLevel?: "span" | "p" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
iconName?: IconName iconName?: IconName
icon?: ReactNode icon?: ReactNode
subtitle?: string subtitle?: string
@@ -31,7 +32,7 @@ export default function AccordionItem({
icon, icon,
iconName, iconName,
title, title,
titleLevel = 'p', titleLevel = "p",
type, type,
className, className,
subtitle, subtitle,
@@ -59,17 +60,17 @@ export default function AccordionItem({
if (details.open) { if (details.open) {
content.style.maxHeight = `${content.scrollHeight}px` content.style.maxHeight = `${content.scrollHeight}px`
content.addEventListener( content.addEventListener(
'transitionend', "transitionend",
() => { () => {
// Remove maxHeight after transition to allow content to transition multiple times // Remove maxHeight after transition to allow content to transition multiple times
content.style.maxHeight = 'none' content.style.maxHeight = "none"
}, },
{ once: true } { once: true }
) )
onOpen?.() onOpen?.()
} else { } else {
content.style.maxHeight = '0' content.style.maxHeight = "0"
} }
} }
} }
@@ -89,11 +90,11 @@ export default function AccordionItem({
<details ref={detailsRef} onToggle={toggleAccordion}> <details ref={detailsRef} onToggle={toggleAccordion}>
<summary className={styles.summary}> <summary className={styles.summary}>
{IconComp} {IconComp}
{type === 'sidepeek' ? ( {type === "sidepeek" ? (
<Typography variant="Title/Subtitle/md"> <Typography variant="Title/Subtitle/md">
<p className={styles.title}>{title}</p> <p className={styles.title}>{title}</p>
</Typography> </Typography>
) : type === 'inline' ? ( ) : type === "inline" ? (
<Typography variant="Body/Supporting text (caption)/smBold"> <Typography variant="Body/Supporting text (caption)/smBold">
<p className={styles.title}>{title}</p> <p className={styles.title}>{title}</p>
</Typography> </Typography>

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './accordionItem.module.css' import styles from "./accordionItem.module.css"
export const accordionItemVariants = cva(styles.accordionItem, { export const accordionItemVariants = cva(styles.accordionItem, {
variants: { variants: {
@@ -11,6 +11,6 @@ export const accordionItemVariants = cva(styles.accordionItem, {
}, },
}, },
defaultVariants: { defaultVariants: {
type: 'card', type: "card",
}, },
}) })

View File

@@ -1,12 +1,13 @@
import { Children, cloneElement, isValidElement } from 'react' import { Children, cloneElement, isValidElement } from "react"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { AccordionItemProps } from './AccordionItem' import type { AccordionItemProps } from "./AccordionItem"
import { accordionVariants } from './variants' import { accordionVariants } from "./variants"
interface AccordionProps interface AccordionProps
extends React.HtmlHTMLAttributes<HTMLUListElement>, extends
React.HtmlHTMLAttributes<HTMLUListElement>,
VariantProps<typeof accordionVariants> {} VariantProps<typeof accordionVariants> {}
export default function Accordion({ export default function Accordion({

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './accordion.module.css' import styles from "./accordion.module.css"
export const accordionVariants = cva(styles.accordion, { export const accordionVariants = cva(styles.accordion, {
variants: { variants: {
@@ -11,6 +11,6 @@ export const accordionVariants = cva(styles.accordion, {
}, },
}, },
defaultVariants: { defaultVariants: {
type: 'card', type: "card",
}, },
}) })

View File

@@ -1,22 +1,22 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Alert } from './index' import { Alert } from "./index"
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert' import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
import { expect, fn } from 'storybook/test' import { expect, fn } from "storybook/test"
const meta: Meta<typeof Alert> = { const meta: Meta<typeof Alert> = {
title: 'Core Components/Alert', title: "Core Components/Alert",
component: Alert, component: Alert,
parameters: { parameters: {
layout: 'centered', layout: "centered",
}, },
tags: ['autodocs'], tags: ["autodocs"],
argTypes: { argTypes: {
variant: { variant: {
control: { type: 'select' }, control: { type: "select" },
options: ['banner', 'inline'], options: ["banner", "inline"],
}, },
type: { type: {
control: { type: 'select' }, control: { type: "select" },
options: Object.values(AlertTypeEnum), options: Object.values(AlertTypeEnum),
}, },
close: { close: {
@@ -32,43 +32,43 @@ type Story = StoryObj<typeof meta>
export const Default: Story = { export const Default: Story = {
args: { args: {
variant: 'inline', variant: "inline",
type: AlertTypeEnum.Info, type: AlertTypeEnum.Info,
heading: 'Heading', heading: "Heading",
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.', text: "Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.",
close: undefined, close: undefined,
ariaRole: 'alert', ariaRole: "alert",
}, },
play: async ({ canvas }) => { play: async ({ canvas }) => {
canvas.findByRole('alert') canvas.findByRole("alert")
}, },
} }
export const Closable: Story = { export const Closable: Story = {
args: { args: {
variant: 'inline', variant: "inline",
type: AlertTypeEnum.Info, type: AlertTypeEnum.Info,
heading: 'Heading', heading: "Heading",
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.', text: "Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.",
close: fn(), close: fn(),
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.close).toHaveBeenCalledTimes(1) expect(args.close).toHaveBeenCalledTimes(1)
}, },
} }
export const WithPhonenumber: Story = { export const WithPhonenumber: Story = {
args: { args: {
variant: 'inline', variant: "inline",
type: AlertTypeEnum.Info, type: AlertTypeEnum.Info,
heading: 'Heading', heading: "Heading",
text: 'Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.', text: "Caramels danish jelly-o pudding tart croissant. Pie cotton candy jujubes carrot cake gummies. Apple pie cake chocolate bar halvah tootsie roll bonbon cheesecake. Brownie dessert macaroon bear claw pastry.",
close: fn(), close: fn(),
phoneContact: { phoneContact: {
displayText: 'Call us:', displayText: "Call us:",
phoneNumber: '+4685551234', phoneNumber: "+4685551234",
footnote: 'Available 24/7', footnote: "Available 24/7",
}, },
}, },
} }

View File

@@ -1,16 +1,16 @@
'use client' "use client"
import { useState } from 'react' import { useState } from "react"
import { useIntl } from 'react-intl' import { useIntl } from "react-intl"
import { Button } from '../../Button' import { Button } from "../../Button"
import { MaterialIcon } from '../../Icons/MaterialIcon' import { MaterialIcon } from "../../Icons/MaterialIcon"
import { JsonToHtml } from '../../JsonToHtml/JsonToHtml' import { JsonToHtml } from "../../JsonToHtml/JsonToHtml"
import SidePeek from '../../SidePeek' import SidePeek from "../../SidePeek"
import styles from './sidepeek.module.css' import styles from "./sidepeek.module.css"
import type { AlertSidepeekProps } from './sidepeek' import type { AlertSidepeekProps } from "./sidepeek"
export default function AlertSidepeek({ export default function AlertSidepeek({
ctaText, ctaText,
@@ -37,8 +37,8 @@ export default function AlertSidepeek({
isOpen={sidePeekIsOpen} isOpen={sidePeekIsOpen}
handleClose={() => setSidePeekIsOpen(false)} handleClose={() => setSidePeekIsOpen(false)}
closeLabel={intl.formatMessage({ closeLabel={intl.formatMessage({
id: 'common.close', id: "common.close",
defaultMessage: 'Close', defaultMessage: "Close",
})} })}
> >
<JsonToHtml <JsonToHtml

View File

@@ -1,4 +1,4 @@
import type { SidepeekContent } from '@scandic-hotels/common/constants/alert' import type { SidepeekContent } from "@scandic-hotels/common/constants/alert"
export interface AlertSidepeekProps { export interface AlertSidepeekProps {
ctaText: string ctaText: string

View File

@@ -1,11 +1,11 @@
import type { import type {
AlertTypeEnum, AlertTypeEnum,
SidepeekContent, SidepeekContent,
} from '@scandic-hotels/common/constants/alert' } from "@scandic-hotels/common/constants/alert"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { AriaRole } from 'react' import type { AriaRole } from "react"
import type { alertVariants } from './variants' import type { alertVariants } from "./variants"
export interface AlertProps extends VariantProps<typeof alertVariants> { export interface AlertProps extends VariantProps<typeof alertVariants> {
className?: string className?: string
@@ -26,5 +26,5 @@ export interface AlertProps extends VariantProps<typeof alertVariants> {
} | null } | null
close?: () => void close?: () => void
ariaRole?: AriaRole ariaRole?: AriaRole
ariaLive?: 'off' | 'assertive' | 'polite' ariaLive?: "off" | "assertive" | "polite"
} }

View File

@@ -1,17 +1,17 @@
'use client' "use client"
import { Button } from '../Button' import { Button } from "../Button"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import Link from '../OldDSLink' import Link from "../OldDSLink"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import AlertSidepeek from './Sidepeek' import AlertSidepeek from "./Sidepeek"
import { IconByAlertType } from './utils' import { IconByAlertType } from "./utils"
import { alertVariants } from './variants' import { alertVariants } from "./variants"
import styles from './alert.module.css' import styles from "./alert.module.css"
import type { AlertProps } from './alert' import type { AlertProps } from "./alert"
export function Alert({ export function Alert({
className, className,
@@ -61,7 +61,7 @@ export function Alert({
<> <>
<span> {phoneContact.displayText} </span> <span> {phoneContact.displayText} </span>
<Link <Link
href={`tel:${phoneContact.phoneNumber.replace(/ /g, '')}`} href={`tel:${phoneContact.phoneNumber.replace(/ /g, "")}`}
> >
{phoneContact.phoneNumber} {phoneContact.phoneNumber}
</Link> </Link>

View File

@@ -1,28 +1,28 @@
import { import {
MaterialIcon, MaterialIcon,
type MaterialIconSetIconProps, type MaterialIconSetIconProps,
} from '../Icons/MaterialIcon' } from "../Icons/MaterialIcon"
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert' import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
import type { JSX } from 'react' import type { JSX } from "react"
import type { AlertProps } from './alert' import type { AlertProps } from "./alert"
interface IconByAlertProps { interface IconByAlertProps {
alertType: AlertTypeEnum alertType: AlertTypeEnum
variant?: AlertProps['variant'] variant?: AlertProps["variant"]
} }
export function IconByAlertType({ export function IconByAlertType({
alertType, alertType,
variant = 'inline', variant = "inline",
...props ...props
}: IconByAlertProps & MaterialIconSetIconProps): JSX.Element { }: IconByAlertProps & MaterialIconSetIconProps): JSX.Element {
switch (alertType) { switch (alertType) {
case AlertTypeEnum.Alarm: case AlertTypeEnum.Alarm:
return ( return (
<MaterialIcon <MaterialIcon
color={variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Error'} color={variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Error"}
isFilled isFilled
icon="error" icon="error"
{...props} {...props}
@@ -33,7 +33,7 @@ export function IconByAlertType({
<MaterialIcon <MaterialIcon
icon="warning" icon="warning"
color={ color={
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Warning' variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Warning"
} }
isFilled isFilled
{...props} {...props}
@@ -44,7 +44,7 @@ export function IconByAlertType({
<MaterialIcon <MaterialIcon
icon="check_circle" icon="check_circle"
color={ color={
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Success' variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Success"
} }
isFilled isFilled
{...props} {...props}
@@ -55,7 +55,7 @@ export function IconByAlertType({
return ( return (
<MaterialIcon <MaterialIcon
color={ color={
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Information' variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Information"
} }
isFilled isFilled
icon="info" icon="info"

View File

@@ -1,8 +1,8 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert' import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
import styles from './alert.module.css' import styles from "./alert.module.css"
export const alertVariants = cva(styles.alert, { export const alertVariants = cva(styles.alert, {
variants: { variants: {
@@ -18,7 +18,7 @@ export const alertVariants = cva(styles.alert, {
}, },
}, },
defaultVariants: { defaultVariants: {
variant: 'inline', variant: "inline",
type: AlertTypeEnum.Info, type: AlertTypeEnum.Info,
}, },
}) })

View File

@@ -1,17 +1,17 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Avatar } from '.' import { Avatar } from "."
import { config } from './variants' import { config } from "./variants"
const meta: Meta<typeof Avatar> = { const meta: Meta<typeof Avatar> = {
title: 'Core Components/Avatar', title: "Core Components/Avatar",
component: Avatar, component: Avatar,
parameters: { parameters: {
layout: 'centered', layout: "centered",
}, },
argTypes: { argTypes: {
size: { size: {
control: { type: 'select' }, control: { type: "select" },
options: Object.keys(config.variants.size), options: Object.keys(config.variants.size),
}, },
}, },
@@ -20,31 +20,31 @@ const meta: Meta<typeof Avatar> = {
export default meta export default meta
type Story = StoryObj<typeof Avatar> type Story = StoryObj<typeof Avatar>
const imageFile = './img/profile-picture.png' as const const imageFile = "./img/profile-picture.png" as const
export const WithImage: Story = { export const WithImage: Story = {
args: { args: {
src: imageFile, src: imageFile,
alt: 'Profile photo', alt: "Profile photo",
size: 'md', size: "md",
}, },
} }
export const WithInitials: Story = { export const WithInitials: Story = {
args: { args: {
initials: 'FR', initials: "FR",
size: 'md', size: "md",
}, },
} }
export const Fallback: Story = { export const Fallback: Story = {
args: { args: {
size: 'md', size: "md",
}, },
} }
export const SmallSize: Story = { export const SmallSize: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Avatar src={imageFile} alt="Profile photo" size="sm" /> <Avatar src={imageFile} alt="Profile photo" size="sm" />
<Avatar initials="FR" size="sm" /> <Avatar initials="FR" size="sm" />
<Avatar size="sm" /> <Avatar size="sm" />
@@ -54,7 +54,7 @@ export const SmallSize: Story = {
export const MediumSize: Story = { export const MediumSize: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Avatar src={imageFile} alt="Profile photo" size="md" /> <Avatar src={imageFile} alt="Profile photo" size="md" />
<Avatar initials="FR" size="md" /> <Avatar initials="FR" size="md" />
<Avatar size="md" /> <Avatar size="md" />
@@ -64,7 +64,7 @@ export const MediumSize: Story = {
export const LargeSize: Story = { export const LargeSize: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Avatar src={imageFile} alt="Profile photo" size="lg" /> <Avatar src={imageFile} alt="Profile photo" size="lg" />
<Avatar initials="FR" size="lg" /> <Avatar initials="FR" size="lg" />
<Avatar size="lg" /> <Avatar size="lg" />
@@ -74,39 +74,39 @@ export const LargeSize: Story = {
export const AllSizes: Story = { export const AllSizes: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '24px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "24px", alignItems: "center" }}>
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
gap: '8px', gap: "8px",
alignItems: 'center', alignItems: "center",
}} }}
> >
<Avatar initials="FR" size="sm" /> <Avatar initials="FR" size="sm" />
<span style={{ fontSize: '12px' }}>Small (20px)</span> <span style={{ fontSize: "12px" }}>Small (20px)</span>
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
gap: '8px', gap: "8px",
alignItems: 'center', alignItems: "center",
}} }}
> >
<Avatar initials="FR" size="md" /> <Avatar initials="FR" size="md" />
<span style={{ fontSize: '12px' }}>Medium (32px)</span> <span style={{ fontSize: "12px" }}>Medium (32px)</span>
</div> </div>
<div <div
style={{ style={{
display: 'flex', display: "flex",
flexDirection: 'column', flexDirection: "column",
gap: '8px', gap: "8px",
alignItems: 'center', alignItems: "center",
}} }}
> >
<Avatar initials="FR" size="lg" /> <Avatar initials="FR" size="lg" />
<span style={{ fontSize: '12px' }}>Large (55px)</span> <span style={{ fontSize: "12px" }}>Large (55px)</span>
</div> </div>
</div> </div>
), ),

View File

@@ -1,28 +1,28 @@
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import Image from '../Image' import Image from "../Image"
import { variants } from './variants' import { variants } from "./variants"
import type { AvatarProps } from './types' import type { AvatarProps } from "./types"
export function Avatar({ export function Avatar({
src, src,
alt, alt,
initials, initials,
size = 'md', size = "md",
className, className,
}: AvatarProps) { }: AvatarProps) {
const classNames = variants({ size, className }) const classNames = variants({ size, className })
const pixelSize = size === 'sm' ? 24 : size === 'md' ? 32 : 55 const pixelSize = size === "sm" ? 24 : size === "md" ? 32 : 55
const iconSize = size === 'sm' ? 16 : 24 const iconSize = size === "sm" ? 16 : 24
return ( return (
<div className={classNames}> <div className={classNames}>
{src ? ( {src ? (
<Image src={src} alt={alt || ''} width={pixelSize} height={pixelSize} /> <Image src={src} alt={alt || ""} width={pixelSize} height={pixelSize} />
) : initials ? ( ) : initials ? (
<Typography <Typography
variant={size === 'lg' ? 'Title/Overline/sm' : 'Tag/sm'} variant={size === "lg" ? "Title/Overline/sm" : "Tag/sm"}
className={variants.initials} className={variants.initials}
> >
<span data-hj-suppress>{initials}</span> <span data-hj-suppress>{initials}</span>

View File

@@ -15,7 +15,7 @@ export interface AvatarProps {
* Size of the avatar * Size of the avatar
* @default 'md' * @default 'md'
*/ */
size?: 'sm' | 'md' | 'lg' size?: "sm" | "md" | "lg"
/** /**
* Additional CSS class names * Additional CSS class names
*/ */

View File

@@ -1,17 +1,17 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './avatar.module.css' import styles from "./avatar.module.css"
export const config = { export const config = {
variants: { variants: {
size: { size: {
sm: styles['size-sm'], sm: styles["size-sm"],
md: styles['size-md'], md: styles["size-md"],
lg: styles['size-lg'], lg: styles["size-lg"],
}, },
}, },
defaultVariants: { defaultVariants: {
size: 'md', size: "md",
}, },
} as const } as const

View File

@@ -1,12 +1,12 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { expect, fn } from 'storybook/test' import { expect, fn } from "storybook/test"
import { BackToTopButton } from '.' import { BackToTopButton } from "."
import { config as backToTopButtonConfig } from './variants' import { config as backToTopButtonConfig } from "./variants"
const meta: Meta<typeof BackToTopButton> = { const meta: Meta<typeof BackToTopButton> = {
title: 'Patterns/BackToTopButton', title: "Patterns/BackToTopButton",
component: BackToTopButton, component: BackToTopButton,
argTypes: { argTypes: {
onPress: { onPress: {
@@ -15,13 +15,13 @@ const meta: Meta<typeof BackToTopButton> = {
}, },
}, },
position: { position: {
control: 'select', control: "select",
options: Object.keys(backToTopButtonConfig.variants.position), options: Object.keys(backToTopButtonConfig.variants.position),
table: { table: {
type: { type: {
summary: 'string', summary: "string",
detail: Object.keys(backToTopButtonConfig.variants.position).join( detail: Object.keys(backToTopButtonConfig.variants.position).join(
' | ' " | "
), ),
}, },
defaultValue: { defaultValue: {
@@ -30,7 +30,7 @@ const meta: Meta<typeof BackToTopButton> = {
}, },
}, },
label: { label: {
control: 'text', control: "text",
}, },
}, },
} }
@@ -40,16 +40,16 @@ export default meta
type Story = StoryObj<typeof BackToTopButton> type Story = StoryObj<typeof BackToTopButton>
const globalStoryPropsInverted = { const globalStoryPropsInverted = {
backgrounds: { value: 'scandicPrimaryDark' }, backgrounds: { value: "scandicPrimaryDark" },
} }
export const Default: Story = { export const Default: Story = {
args: { args: {
onPress: fn(), onPress: fn(),
label: 'Back to top', label: "Back to top",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -57,10 +57,10 @@ export const Default: Story = {
export const PositionLeft: Story = { export const PositionLeft: Story = {
args: { args: {
...Default.args, ...Default.args,
position: 'left', position: "left",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -68,10 +68,10 @@ export const PositionLeft: Story = {
export const PositionCenter: Story = { export const PositionCenter: Story = {
args: { args: {
...Default.args, ...Default.args,
position: 'center', position: "center",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -79,10 +79,10 @@ export const PositionCenter: Story = {
export const PositionRight: Story = { export const PositionRight: Story = {
args: { args: {
...Default.args, ...Default.args,
position: 'right', position: "right",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -91,10 +91,10 @@ export const OnDarkBackground: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
onPress: fn(), onPress: fn(),
label: 'Back to top', label: "Back to top",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }

View File

@@ -31,7 +31,7 @@
/* This button is able to be on top of dark background colors, /* This button is able to be on top of dark background colors,
so we need to create an illusion that it also has an inverted border on focus */ so we need to create an illusion that it also has an inverted border on focus */
&::before { &::before {
content: ''; content: "";
position: absolute; position: absolute;
inset: -4px; inset: -4px;
border: 2px solid var(--Border-Inverted); border: 2px solid var(--Border-Inverted);

View File

@@ -1,20 +1,19 @@
'use client' "use client"
import { Button as ButtonRAC } from 'react-aria-components' import { Button as ButtonRAC } from "react-aria-components"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import { variants } from './variants' import { variants } from "./variants"
import styles from './backToTopButton.module.css' import styles from "./backToTopButton.module.css"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { ComponentProps } from 'react' import type { ComponentProps } from "react"
interface BackToTopButtonProps interface BackToTopButtonProps
extends ComponentProps<typeof ButtonRAC>, extends ComponentProps<typeof ButtonRAC>, VariantProps<typeof variants> {
VariantProps<typeof variants> {
label: string label: string
} }

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './backToTopButton.module.css' import styles from "./backToTopButton.module.css"
export const config = { export const config = {
variants: { variants: {
@@ -11,7 +11,7 @@ export const config = {
}, },
}, },
defaultVariants: { defaultVariants: {
position: 'right', position: "right",
}, },
} as const } as const

View File

@@ -1,9 +1,9 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Badge } from './Badge.tsx' import { Badge } from "./Badge.tsx"
const meta: Meta<typeof Badge> = { const meta: Meta<typeof Badge> = {
title: 'Core Components/Badge', title: "Core Components/Badge",
component: Badge, component: Badge,
} }
@@ -15,7 +15,7 @@ export const Default: Story = {}
export const XS: Story = { export const XS: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Badge number={3} color="primary" size="20" /> <Badge number={3} color="primary" size="20" />
<Badge number={3} color="green" size="20" /> <Badge number={3} color="green" size="20" />
</div> </div>
@@ -24,7 +24,7 @@ export const XS: Story = {
export const Small: Story = { export const Small: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Badge number={3} color="primary" size="24" /> <Badge number={3} color="primary" size="24" />
<Badge number={3} color="green" size="24" /> <Badge number={3} color="green" size="24" />
</div> </div>
@@ -32,7 +32,7 @@ export const Small: Story = {
} }
export const Medium: Story = { export const Medium: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Badge number={3} color="primary" size="28" /> <Badge number={3} color="primary" size="28" />
<Badge number={3} color="green" size="28" /> <Badge number={3} color="green" size="28" />
</div> </div>
@@ -40,7 +40,7 @@ export const Medium: Story = {
} }
export const Large: Story = { export const Large: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Badge number={3} color="primary" size="32" /> <Badge number={3} color="primary" size="32" />
<Badge number={3} color="green" size="32" /> <Badge number={3} color="green" size="32" />
</div> </div>
@@ -49,7 +49,7 @@ export const Large: Story = {
export const XL: Story = { export const XL: Story = {
render: () => ( render: () => (
<div style={{ display: 'flex', gap: '16px', alignItems: 'center' }}> <div style={{ display: "flex", gap: "16px", alignItems: "center" }}>
<Badge number={3} color="primary" size="36" /> <Badge number={3} color="primary" size="36" />
<Badge number={3} color="green" size="36" /> <Badge number={3} color="green" size="36" />
</div> </div>

View File

@@ -1,8 +1,8 @@
import { config } from './variants' import { config } from "./variants"
import { VariantProps } from 'class-variance-authority' import { VariantProps } from "class-variance-authority"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import { TypographyProps } from '../Typography/types' import { TypographyProps } from "../Typography/types"
interface BadgeProps extends VariantProps<typeof config> { interface BadgeProps extends VariantProps<typeof config> {
number: string | number number: string | number
@@ -21,15 +21,15 @@ export function Badge({ number, color, size }: BadgeProps) {
) )
} }
function getTypography(size: BadgeProps['size']): TypographyProps['variant'] { function getTypography(size: BadgeProps["size"]): TypographyProps["variant"] {
switch (size) { switch (size) {
case '36': case "36":
case '32': case "32":
return 'Body/Paragraph/mdBold' return "Body/Paragraph/mdBold"
case '28': case "28":
case '24': case "24":
return 'Body/Supporting text (caption)/smBold' return "Body/Supporting text (caption)/smBold"
case '20': case "20":
return 'Label/xsRegular' return "Label/xsRegular"
} }
} }

View File

@@ -1 +1 @@
export { Badge } from './Badge' export { Badge } from "./Badge"

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './badge.module.css' import styles from "./badge.module.css"
export const config = cva(styles.badge, { export const config = cva(styles.badge, {
variants: { variants: {
@@ -9,15 +9,15 @@ export const config = cva(styles.badge, {
green: styles.green, green: styles.green,
}, },
size: { size: {
'36': styles._36, "36": styles._36,
'32': styles._32, "32": styles._32,
'28': styles._28, "28": styles._28,
'24': styles._24, "24": styles._24,
'20': styles._20, "20": styles._20,
}, },
}, },
defaultVariants: { defaultVariants: {
color: 'primary', color: "primary",
size: '28', size: "28",
}, },
}) })

View File

@@ -1,12 +1,12 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from 'storybook/test' import { fn } from "storybook/test"
import { BookingCodeChip } from './index' import { BookingCodeChip } from "./index"
const meta = { const meta = {
title: 'Product Components/BookingCodeChip', title: "Product Components/BookingCodeChip",
component: BookingCodeChip, component: BookingCodeChip,
parameters: { parameters: {
layout: 'centered', layout: "centered",
}, },
} satisfies Meta<typeof BookingCodeChip> } satisfies Meta<typeof BookingCodeChip>

View File

@@ -1,13 +1,13 @@
import { useIntl } from 'react-intl' import { useIntl } from "react-intl"
import IconChip from '../IconChip' import IconChip from "../IconChip"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import FilledDiscountIcon from '../Icons/Nucleo/Benefits/FilledDiscount' import FilledDiscountIcon from "../Icons/Nucleo/Benefits/FilledDiscount"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import { cx } from 'class-variance-authority' import { cx } from "class-variance-authority"
import { IconButton } from '../IconButton' import { IconButton } from "../IconButton"
import styles from './bookingCodeChip.module.css' import styles from "./bookingCodeChip.module.css"
type BaseBookingCodeChipProps = { type BaseBookingCodeChipProps = {
alignCenter?: boolean alignCenter?: boolean
@@ -47,11 +47,11 @@ export function BookingCodeChip({
return null return null
} }
const color = isCampaignRate ? 'green' : 'blue' const color = isCampaignRate ? "green" : "blue"
const iconColor = isCampaignRate const iconColor = isCampaignRate
? 'Icon/Feedback/Success' ? "Icon/Feedback/Success"
: 'Icon/Feedback/Information' : "Icon/Feedback/Information"
const isUnavailableRate = isCampaignRate const isUnavailableRate = isCampaignRate
? isCampaignUnavailable ? isCampaignUnavailable
@@ -59,12 +59,12 @@ export function BookingCodeChip({
const label = isCampaignRate const label = isCampaignRate
? intl.formatMessage({ ? intl.formatMessage({
id: 'booking.campaign', id: "booking.campaign",
defaultMessage: 'Campaign', defaultMessage: "Campaign",
}) })
: intl.formatMessage({ : intl.formatMessage({
id: 'booking.bookingCode', id: "booking.bookingCode",
defaultMessage: 'Booking code', defaultMessage: "Booking code",
}) })
const icon = isCampaignRate ? ( const icon = isCampaignRate ? (
@@ -107,8 +107,8 @@ export function BookingCodeChip({
className={styles.removeButton} className={styles.removeButton}
onPress={onClose} onPress={onClose}
aria-label={intl.formatMessage({ aria-label={intl.formatMessage({
id: 'booking.removeBookingCode', id: "booking.removeBookingCode",
defaultMessage: 'Remove booking code', defaultMessage: "Remove booking code",
})} })}
iconName="close" iconName="close"
/> />

View File

@@ -1,41 +1,41 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { expect, fn } from 'storybook/test' import { expect, fn } from "storybook/test"
import { Button } from './Button' import { Button } from "./Button"
import { buttonIconNames } from './types' import { buttonIconNames } from "./types"
import { config as buttonConfig } from './variants' import { config as buttonConfig } from "./variants"
const meta: Meta<typeof Button> = { const meta: Meta<typeof Button> = {
title: 'Core Components/Button', title: "Core Components/Button",
component: Button, component: Button,
argTypes: { argTypes: {
onPress: { onPress: {
table: { table: {
type: { summary: 'function' }, type: { summary: "function" },
defaultValue: { summary: 'undefined' }, defaultValue: { summary: "undefined" },
}, },
description: 'Callback function to handle button press events.', description: "Callback function to handle button press events.",
}, },
variant: { variant: {
control: 'select', control: "select",
options: Object.keys(buttonConfig.variants.variant), options: Object.keys(buttonConfig.variants.variant),
default: 'Primary', default: "Primary",
table: { table: {
defaultValue: { defaultValue: {
summary: buttonConfig.defaultVariants.variant, summary: buttonConfig.defaultVariants.variant,
}, },
type: { type: {
summary: Object.keys(buttonConfig.variants.variant).join(' | '), summary: Object.keys(buttonConfig.variants.variant).join(" | "),
}, },
}, },
}, },
color: { color: {
control: 'select', control: "select",
options: Object.keys(buttonConfig.variants.color), options: Object.keys(buttonConfig.variants.color),
table: { table: {
type: { type: {
summary: Object.keys(buttonConfig.variants.color).join(' | '), summary: Object.keys(buttonConfig.variants.color).join(" | "),
}, },
defaultValue: { defaultValue: {
summary: buttonConfig.defaultVariants.color, summary: buttonConfig.defaultVariants.color,
@@ -43,11 +43,11 @@ const meta: Meta<typeof Button> = {
}, },
}, },
size: { size: {
control: 'select', control: "select",
options: Object.keys(buttonConfig.variants.size), options: Object.keys(buttonConfig.variants.size),
table: { table: {
type: { type: {
summary: Object.keys(buttonConfig.variants.size).join(' | '), summary: Object.keys(buttonConfig.variants.size).join(" | "),
}, },
defaultValue: { defaultValue: {
summary: buttonConfig.defaultVariants.size, summary: buttonConfig.defaultVariants.size,
@@ -55,63 +55,63 @@ const meta: Meta<typeof Button> = {
}, },
}, },
wrapping: { wrapping: {
control: 'boolean', control: "boolean",
options: Object.keys(buttonConfig.variants.wrapping), options: Object.keys(buttonConfig.variants.wrapping),
type: 'boolean', type: "boolean",
table: { table: {
defaultValue: { defaultValue: {
summary: buttonConfig.defaultVariants.wrapping.toString(), summary: buttonConfig.defaultVariants.wrapping.toString(),
}, },
}, },
description: description:
'Only applies to variant `Text`. If `false`, the button will use smaller padding.', "Only applies to variant `Text`. If `false`, the button will use smaller padding.",
}, },
leadingIconName: { leadingIconName: {
control: 'select', control: "select",
options: buttonIconNames, options: buttonIconNames,
table: { table: {
type: { summary: buttonIconNames.join(' | ') }, type: { summary: buttonIconNames.join(" | ") },
defaultValue: { summary: 'undefined' }, defaultValue: { summary: "undefined" },
}, },
description: 'Name of the Material Icon to use as leading icon.', description: "Name of the Material Icon to use as leading icon.",
}, },
trailingIconName: { trailingIconName: {
control: 'select', control: "select",
options: buttonIconNames, options: buttonIconNames,
table: { table: {
type: { summary: buttonIconNames.join(' | ') }, type: { summary: buttonIconNames.join(" | ") },
defaultValue: { summary: 'undefined' }, defaultValue: { summary: "undefined" },
}, },
description: 'Name of the Material Icon to use as trailing icon.', description: "Name of the Material Icon to use as trailing icon.",
}, },
isDisabled: { isDisabled: {
control: 'boolean', control: "boolean",
table: { table: {
type: { summary: 'boolean' }, type: { summary: "boolean" },
defaultValue: { summary: 'false' }, defaultValue: { summary: "false" },
}, },
}, },
isPending: { isPending: {
control: 'boolean', control: "boolean",
table: { table: {
type: { summary: 'boolean' }, type: { summary: "boolean" },
defaultValue: { summary: 'false' }, defaultValue: { summary: "false" },
}, },
}, },
fullWidth: { fullWidth: {
control: 'boolean', control: "boolean",
table: { table: {
type: { summary: 'boolean' }, type: { summary: "boolean" },
defaultValue: { summary: 'false' }, defaultValue: { summary: "false" },
}, },
description: description:
'By default, the button width adjusts to its content. Set to true to make the button take the full width of its container.', "By default, the button width adjusts to its content. Set to true to make the button take the full width of its container.",
}, },
}, },
} }
const globalStoryPropsInverted = { const globalStoryPropsInverted = {
backgrounds: { value: 'scandicPrimaryDark' }, backgrounds: { value: "scandicPrimaryDark" },
} }
export default meta export default meta
@@ -120,10 +120,10 @@ type Story = StoryObj<typeof Button>
export const Default: Story = { export const Default: Story = {
args: { args: {
onPress: fn(), onPress: fn(),
children: 'Button', children: "Button",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -131,11 +131,11 @@ export const Default: Story = {
export const PrimaryLarge: Story = { export const PrimaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Primary', variant: "Primary",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -143,10 +143,10 @@ export const PrimaryLarge: Story = {
export const PrimaryMedium: Story = { export const PrimaryMedium: Story = {
args: { args: {
...PrimaryLarge.args, ...PrimaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -154,10 +154,10 @@ export const PrimaryMedium: Story = {
export const PrimarySmall: Story = { export const PrimarySmall: Story = {
args: { args: {
...PrimaryLarge.args, ...PrimaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -169,7 +169,7 @@ export const PrimaryDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -181,7 +181,7 @@ export const PrimaryLoading: Story = {
onPress: fn(), // Fresh spy instance for loading test onPress: fn(), // Fresh spy instance for loading test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -192,7 +192,7 @@ export const PrimaryOnDarkBackground: Story = {
...PrimaryLarge.args, ...PrimaryLarge.args,
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -201,11 +201,11 @@ export const PrimaryInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
size: 'lg', size: "lg",
color: 'Inverted', color: "Inverted",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -214,10 +214,10 @@ export const PrimaryInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...PrimaryInvertedLarge.args, ...PrimaryInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -226,10 +226,10 @@ export const PrimaryInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...PrimaryInvertedLarge.args, ...PrimaryInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -242,7 +242,7 @@ export const PrimaryInvertedDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -255,7 +255,7 @@ export const PrimaryInvertedLoading: Story = {
onPress: fn(), // Fresh spy instance for loading test onPress: fn(), // Fresh spy instance for loading test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -263,11 +263,11 @@ export const PrimaryInvertedLoading: Story = {
export const SecondaryLarge: Story = { export const SecondaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Secondary', variant: "Secondary",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -275,10 +275,10 @@ export const SecondaryLarge: Story = {
export const SecondaryMedium: Story = { export const SecondaryMedium: Story = {
args: { args: {
...SecondaryLarge.args, ...SecondaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -286,10 +286,10 @@ export const SecondaryMedium: Story = {
export const SecondarySmall: Story = { export const SecondarySmall: Story = {
args: { args: {
...SecondaryLarge.args, ...SecondaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -301,7 +301,7 @@ export const SecondaryDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -313,7 +313,7 @@ export const SecondaryLoading: Story = {
onPress: fn(), // Fresh spy instance for loading test onPress: fn(), // Fresh spy instance for loading test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -322,12 +322,12 @@ export const SecondaryInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Secondary', variant: "Secondary",
color: 'Inverted', color: "Inverted",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -336,10 +336,10 @@ export const SecondaryInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...SecondaryInvertedLarge.args, ...SecondaryInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -348,10 +348,10 @@ export const SecondaryInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...SecondaryInvertedLarge.args, ...SecondaryInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -364,7 +364,7 @@ export const SecondaryInvertedDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -377,7 +377,7 @@ export const SecondaryInvertedLoading: Story = {
onPress: fn(), // Fresh spy instance for loading test onPress: fn(), // Fresh spy instance for loading test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -385,11 +385,11 @@ export const SecondaryInvertedLoading: Story = {
export const TertiaryLarge: Story = { export const TertiaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Tertiary', variant: "Tertiary",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -397,10 +397,10 @@ export const TertiaryLarge: Story = {
export const TertiaryMedium: Story = { export const TertiaryMedium: Story = {
args: { args: {
...TertiaryLarge.args, ...TertiaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -408,10 +408,10 @@ export const TertiaryMedium: Story = {
export const TertiarySmall: Story = { export const TertiarySmall: Story = {
args: { args: {
...TertiaryLarge.args, ...TertiaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -423,7 +423,7 @@ export const TertiaryDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -435,7 +435,7 @@ export const TertiaryLoading: Story = {
onPress: fn(), // Fresh spy instance for loading test onPress: fn(), // Fresh spy instance for loading test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -443,11 +443,11 @@ export const TertiaryLoading: Story = {
export const TextLarge: Story = { export const TextLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Text', variant: "Text",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -455,11 +455,11 @@ export const TextLarge: Story = {
export const TextMedium: Story = { export const TextMedium: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -467,11 +467,11 @@ export const TextMedium: Story = {
export const TextSmall: Story = { export const TextSmall: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -483,7 +483,7 @@ export const TextDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -494,7 +494,7 @@ export const TextNoWrapping: Story = {
wrapping: false, wrapping: false,
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -503,12 +503,12 @@ export const TextInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Text', variant: "Text",
color: 'Inverted', color: "Inverted",
size: 'lg', size: "lg",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -517,10 +517,10 @@ export const TextInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextInvertedLarge.args, ...TextInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -529,10 +529,10 @@ export const TextInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextInvertedLarge.args, ...TextInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
}, },
} }
@@ -545,7 +545,7 @@ export const TextInvertedDisabled: Story = {
onPress: fn(), // Fresh spy instance for disabled test onPress: fn(), // Fresh spy instance for disabled test
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(0) expect(args.onPress).toHaveBeenCalledTimes(0)
}, },
} }
@@ -553,15 +553,15 @@ export const TextInvertedDisabled: Story = {
export const TextWithIcon: Story = { export const TextWithIcon: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
children: 'Text with icon', children: "Text with icon",
trailingIconName: 'chevron_right', trailingIconName: "chevron_right",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
expect(canvas.getByText('Text with icon')).toBeDefined() expect(canvas.getByText("Text with icon")).toBeDefined()
expect(canvas.getByTestId('MaterialIcon')).toBeDefined() expect(canvas.getByTestId("MaterialIcon")).toBeDefined()
}, },
} }
@@ -569,13 +569,13 @@ export const TextWithIconInverted: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextWithIcon.args, ...TextWithIcon.args,
color: 'Inverted', color: "Inverted",
}, },
play: async ({ canvas, userEvent, args }) => { play: async ({ canvas, userEvent, args }) => {
await userEvent.click(await canvas.findByRole('button')) await userEvent.click(await canvas.findByRole("button"))
expect(args.onPress).toHaveBeenCalledTimes(1) expect(args.onPress).toHaveBeenCalledTimes(1)
expect(canvas.getByText('Text with icon')).toBeDefined() expect(canvas.getByText("Text with icon")).toBeDefined()
expect(canvas.getByTestId('MaterialIcon')).toBeDefined() expect(canvas.getByTestId("MaterialIcon")).toBeDefined()
}, },
} }

View File

@@ -1,10 +1,10 @@
import { Button as ButtonRAC } from 'react-aria-components' import { Button as ButtonRAC } from "react-aria-components"
import { Loading } from '../Loading/Loading' import { Loading } from "../Loading/Loading"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import type { ButtonProps } from './types' import type { ButtonProps } from "./types"
import { variants } from './variants' import { variants } from "./variants"
export function Button({ export function Button({
variant, variant,
@@ -30,9 +30,9 @@ export function Button({
return ( return (
<Typography <Typography
variant={ variant={
size === 'sm' size === "sm"
? 'Body/Supporting text (caption)/smBold' ? "Body/Supporting text (caption)/smBold"
: 'Body/Paragraph/mdBold' : "Body/Paragraph/mdBold"
} }
> >
<ButtonRAC {...props} className={classNames}> <ButtonRAC {...props} className={classNames}>
@@ -43,7 +43,7 @@ export function Button({
<MaterialIcon <MaterialIcon
icon={leadingIconName} icon={leadingIconName}
color="CurrentColor" color="CurrentColor"
size={size === 'sm' ? 20 : 24} size={size === "sm" ? 20 : 24}
/> />
) : null} ) : null}
{children} {children}
@@ -51,11 +51,11 @@ export function Button({
<MaterialIcon <MaterialIcon
icon={trailingIconName} icon={trailingIconName}
color="CurrentColor" color="CurrentColor"
size={size === 'sm' ? 20 : 24} size={size === "sm" ? 20 : 24}
/> />
) : null} ) : null}
{isPending ? ( {isPending ? (
<Loading size={size === 'sm' ? 18 : 20} type="CurrentColor" /> <Loading size={size === "sm" ? 18 : 20} type="CurrentColor" />
) : null} ) : null}
</> </>
) )

View File

@@ -27,7 +27,7 @@
outline-offset: 2px; outline-offset: 2px;
&::before { &::before {
content: ''; content: "";
position: absolute; position: absolute;
inset: -4px; inset: -4px;
border: 2px solid var(--Border-Inverted); border: 2px solid var(--Border-Inverted);

View File

@@ -1,4 +1,4 @@
export { Button } from './Button' export { Button } from "./Button"
export { type ButtonProps } from './types' export { type ButtonProps } from "./types"
// eslint-disable-next-line react-refresh/only-export-components // eslint-disable-next-line react-refresh/only-export-components
export { variants as buttonVariants, withButton } from './variants' export { variants as buttonVariants, withButton } from "./variants"

View File

@@ -1,28 +1,28 @@
import { Button } from 'react-aria-components' import { Button } from "react-aria-components"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { ComponentProps } from 'react' import type { ComponentProps } from "react"
import type { SymbolCodepoints } from '../Icons/MaterialIcon/MaterialSymbol/types' import type { SymbolCodepoints } from "../Icons/MaterialIcon/MaterialSymbol/types"
import type { variants } from './variants' import type { variants } from "./variants"
export const buttonIconNames = [ export const buttonIconNames = [
'add_circle', "add_circle",
'open_in_new', "open_in_new",
'keyboard_arrow_down', "keyboard_arrow_down",
'keyboard_arrow_up', "keyboard_arrow_up",
'edit_square', "edit_square",
'location_on', "location_on",
'link', "link",
'mail', "mail",
'cancel', "cancel",
'calendar_month', "calendar_month",
'calendar_clock', "calendar_clock",
'edit_calendar', "edit_calendar",
'calendar_add_on', "calendar_add_on",
'delete', "delete",
'chevron_right', "chevron_right",
'chevron_left', "chevron_left",
] as const ] as const
export type ButtonIconName = Extract< export type ButtonIconName = Extract<

View File

@@ -1,38 +1,38 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import { deepmerge } from 'deepmerge-ts' import { deepmerge } from "deepmerge-ts"
import styles from './button.module.css' import styles from "./button.module.css"
export const config = { export const config = {
variants: { variants: {
variant: { variant: {
Primary: styles['variant-primary'], Primary: styles["variant-primary"],
Secondary: styles['variant-secondary'], Secondary: styles["variant-secondary"],
Tertiary: styles['variant-tertiary'], Tertiary: styles["variant-tertiary"],
Text: styles['variant-text'], Text: styles["variant-text"],
}, },
color: { color: {
Primary: styles['color-primary'], Primary: styles["color-primary"],
Inverted: styles['color-inverted'], Inverted: styles["color-inverted"],
}, },
size: { size: {
sm: styles['size-sm'], sm: styles["size-sm"],
md: styles['size-md'], md: styles["size-md"],
lg: styles['size-lg'], lg: styles["size-lg"],
}, },
wrapping: { wrapping: {
true: undefined, true: undefined,
false: styles['no-wrapping'], false: styles["no-wrapping"],
}, },
fullWidth: { fullWidth: {
true: styles['full-width'], true: styles["full-width"],
false: undefined, false: undefined,
}, },
}, },
defaultVariants: { defaultVariants: {
variant: 'Primary', variant: "Primary",
color: 'Primary', color: "Primary",
size: 'lg', size: "lg",
wrapping: true, wrapping: true,
}, },
} as const } as const

View File

@@ -1,20 +1,20 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { expect, fn } from 'storybook/test' import { expect, fn } from "storybook/test"
import ButtonLink from '.' import ButtonLink from "."
import buttonMeta from '../Button/Button.stories' import buttonMeta from "../Button/Button.stories"
const meta: Meta<typeof ButtonLink> = { const meta: Meta<typeof ButtonLink> = {
title: 'Core Components/ButtonLink', title: "Core Components/ButtonLink",
component: ButtonLink, component: ButtonLink,
argTypes: { argTypes: {
onClick: { onClick: {
table: { table: {
type: { summary: 'function' }, type: { summary: "function" },
defaultValue: { summary: 'undefined' }, defaultValue: { summary: "undefined" },
}, },
description: 'Callback function to handle link click events.', description: "Callback function to handle link click events.",
}, },
variant: buttonMeta.argTypes?.variant, variant: buttonMeta.argTypes?.variant,
color: buttonMeta.argTypes?.color, color: buttonMeta.argTypes?.color,
@@ -25,16 +25,16 @@ const meta: Meta<typeof ButtonLink> = {
fullWidth: buttonMeta.argTypes?.fullWidth, fullWidth: buttonMeta.argTypes?.fullWidth,
href: { href: {
table: { table: {
type: { summary: 'string' }, type: { summary: "string" },
defaultValue: { summary: 'undefined' }, defaultValue: { summary: "undefined" },
}, },
description: 'The URL that the link points to.', description: "The URL that the link points to.",
}, },
}, },
} }
const globalStoryPropsInverted = { const globalStoryPropsInverted = {
backgrounds: { value: 'scandicPrimaryDark' }, backgrounds: { value: "scandicPrimaryDark" },
} }
export default meta export default meta
@@ -43,12 +43,12 @@ type Story = StoryObj<typeof ButtonLink>
export const Default: Story = { export const Default: Story = {
args: { args: {
onClick: fn(), onClick: fn(),
href: '#', href: "#",
children: 'Button link', children: "Button link",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -56,12 +56,12 @@ export const Default: Story = {
export const PrimaryLarge: Story = { export const PrimaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Primary', variant: "Primary",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -69,11 +69,11 @@ export const PrimaryLarge: Story = {
export const PrimaryMedium: Story = { export const PrimaryMedium: Story = {
args: { args: {
...PrimaryLarge.args, ...PrimaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -81,11 +81,11 @@ export const PrimaryMedium: Story = {
export const PrimarySmall: Story = { export const PrimarySmall: Story = {
args: { args: {
...PrimaryLarge.args, ...PrimaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -94,12 +94,12 @@ export const PrimaryOnDarkBackground: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Primary', variant: "Primary",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -108,14 +108,14 @@ export const PrimaryInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Primary', variant: "Primary",
color: 'Inverted', color: "Inverted",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -124,11 +124,11 @@ export const PrimaryInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...PrimaryInvertedLarge.args, ...PrimaryInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -137,11 +137,11 @@ export const PrimaryInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...PrimaryInvertedLarge.args, ...PrimaryInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -149,12 +149,12 @@ export const PrimaryInvertedSmall: Story = {
export const SecondaryLarge: Story = { export const SecondaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Secondary', variant: "Secondary",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -162,11 +162,11 @@ export const SecondaryLarge: Story = {
export const SecondaryMedium: Story = { export const SecondaryMedium: Story = {
args: { args: {
...SecondaryLarge.args, ...SecondaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -174,11 +174,11 @@ export const SecondaryMedium: Story = {
export const SecondarySmall: Story = { export const SecondarySmall: Story = {
args: { args: {
...SecondaryLarge.args, ...SecondaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -187,13 +187,13 @@ export const SecondaryInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Secondary', variant: "Secondary",
color: 'Inverted', color: "Inverted",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -202,11 +202,11 @@ export const SecondaryInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...SecondaryInvertedLarge.args, ...SecondaryInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -215,11 +215,11 @@ export const SecondaryInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...SecondaryInvertedLarge.args, ...SecondaryInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -227,12 +227,12 @@ export const SecondaryInvertedSmall: Story = {
export const TertiaryLarge: Story = { export const TertiaryLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Tertiary', variant: "Tertiary",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -240,11 +240,11 @@ export const TertiaryLarge: Story = {
export const TertiaryMedium: Story = { export const TertiaryMedium: Story = {
args: { args: {
...TertiaryLarge.args, ...TertiaryLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -252,11 +252,11 @@ export const TertiaryMedium: Story = {
export const TertiarySmall: Story = { export const TertiarySmall: Story = {
args: { args: {
...TertiaryLarge.args, ...TertiaryLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -264,12 +264,12 @@ export const TertiarySmall: Story = {
export const TextLarge: Story = { export const TextLarge: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Text', variant: "Text",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -277,11 +277,11 @@ export const TextLarge: Story = {
export const TextMedium: Story = { export const TextMedium: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -289,11 +289,11 @@ export const TextMedium: Story = {
export const TextSmall: Story = { export const TextSmall: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -301,12 +301,12 @@ export const TextSmall: Story = {
export const TextNoWrapping: Story = { export const TextNoWrapping: Story = {
args: { args: {
...TextLarge.args, ...TextLarge.args,
children: 'Text button with wrapping false', children: "Text button with wrapping false",
wrapping: false, wrapping: false,
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -315,13 +315,13 @@ export const TextInvertedLarge: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...Default.args, ...Default.args,
variant: 'Text', variant: "Text",
color: 'Inverted', color: "Inverted",
size: 'lg', size: "lg",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -330,11 +330,11 @@ export const TextInvertedMedium: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextInvertedLarge.args, ...TextInvertedLarge.args,
size: 'md', size: "md",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -343,11 +343,11 @@ export const TextInvertedSmall: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextInvertedLarge.args, ...TextInvertedLarge.args,
size: 'sm', size: "sm",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -355,13 +355,13 @@ export const TextInvertedSmall: Story = {
export const TextWithIcon: Story = { export const TextWithIcon: Story = {
args: { args: {
...Default.args, ...Default.args,
variant: 'Text', variant: "Text",
children: 'Text with icon', children: "Text with icon",
trailingIconName: 'chevron_right', trailingIconName: "chevron_right",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }
@@ -370,11 +370,11 @@ export const TextWithIconInverted: Story = {
globals: globalStoryPropsInverted, globals: globalStoryPropsInverted,
args: { args: {
...TextWithIcon.args, ...TextWithIcon.args,
color: 'Inverted', color: "Inverted",
}, },
play: async ({ canvasElement }) => { play: async ({ canvasElement }) => {
const link = canvasElement.querySelector('a') const link = canvasElement.querySelector("a")
if (!link) throw new Error('Link not found') if (!link) throw new Error("Link not found")
expect(link).toBeInTheDocument() expect(link).toBeInTheDocument()
}, },
} }

View File

@@ -1,19 +1,19 @@
'use client' "use client"
import { type ComponentProps } from 'react' import { type ComponentProps } from "react"
import { variants } from './variants' import { variants } from "./variants"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import Link from 'next/link' import Link from "next/link"
import { useIntl } from 'react-intl' import { useIntl } from "react-intl"
import { ButtonIconName } from '../Button/types' import { ButtonIconName } from "../Button/types"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { Typography } from '../Typography' import { Typography } from "../Typography"
export interface ButtonLinkProps export interface ButtonLinkProps
extends extends
Omit<ComponentProps<typeof Link>, 'color'>, Omit<ComponentProps<typeof Link>, "color">,
VariantProps<typeof variants> { VariantProps<typeof variants> {
leadingIconName?: ButtonIconName | null leadingIconName?: ButtonIconName | null
trailingIconName?: ButtonIconName | null trailingIconName?: ButtonIconName | null
@@ -44,30 +44,30 @@ export default function ButtonLink({
const intl = useIntl() const intl = useIntl()
const newTabText = intl.formatMessage({ const newTabText = intl.formatMessage({
id: 'common.linkOpenInNewTab', id: "common.linkOpenInNewTab",
defaultMessage: 'Opens in a new tab/window', defaultMessage: "Opens in a new tab/window",
}) })
return ( return (
<Typography <Typography
variant={ variant={
size === 'sm' size === "sm"
? 'Body/Supporting text (caption)/smBold' ? "Body/Supporting text (caption)/smBold"
: 'Body/Paragraph/mdBold' : "Body/Paragraph/mdBold"
} }
> >
<Link <Link
className={classNames} className={classNames}
href={href} href={href}
target={target} target={target}
title={target === '_blank' ? newTabText : ''} title={target === "_blank" ? newTabText : ""}
{...props} {...props}
> >
{leadingIconName ? ( {leadingIconName ? (
<MaterialIcon <MaterialIcon
icon={leadingIconName} icon={leadingIconName}
color="CurrentColor" color="CurrentColor"
size={size === 'sm' ? 20 : 24} size={size === "sm" ? 20 : 24}
/> />
) : null} ) : null}
{children} {children}
@@ -75,7 +75,7 @@ export default function ButtonLink({
<MaterialIcon <MaterialIcon
icon={trailingIconName} icon={trailingIconName}
color="CurrentColor" color="CurrentColor"
size={size === 'sm' ? 20 : 24} size={size === "sm" ? 20 : 24}
/> />
) : null} ) : null}
</Link> </Link>

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import { withButton } from '../Button' import { withButton } from "../Button"
import buttonStyles from '../Button/button.module.css' import buttonStyles from "../Button/button.module.css"
export const variants = cva([buttonStyles.button], withButton({})) export const variants = cva([buttonStyles.button], withButton({}))

View File

@@ -1,10 +1,11 @@
import { Slot } from '@radix-ui/react-slot' import { Slot } from "@radix-ui/react-slot"
import { captionVariants, fontOnlycaptionVariants } from './variants' import { captionVariants, fontOnlycaptionVariants } from "./variants"
import { VariantProps } from 'class-variance-authority' import { VariantProps } from "class-variance-authority"
interface CaptionProps interface CaptionProps
extends Omit<React.HTMLAttributes<HTMLHeadingElement>, 'color'>, extends
Omit<React.HTMLAttributes<HTMLHeadingElement>, "color">,
VariantProps<typeof captionVariants> { VariantProps<typeof captionVariants> {
asChild?: boolean asChild?: boolean
fontOnly?: boolean fontOnly?: boolean
@@ -15,7 +16,7 @@ interface CaptionProps
*/ */
export default function Caption({ export default function Caption({
asChild = false, asChild = false,
className = '', className = "",
color, color,
fontOnly = false, fontOnly = false,
textAlign, textAlign,
@@ -25,7 +26,7 @@ export default function Caption({
type, type,
...props ...props
}: CaptionProps) { }: CaptionProps) {
const Comp = asChild ? Slot : 'p' const Comp = asChild ? Slot : "p"
const classNames = fontOnly const classNames = fontOnly
? fontOnlycaptionVariants({ ? fontOnlycaptionVariants({
className, className,

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './caption.module.css' import styles from "./caption.module.css"
const config = { const config = {
variants: { variants: {
@@ -44,8 +44,8 @@ const config = {
}, },
}, },
defaultVariants: { defaultVariants: {
color: 'black', color: "black",
type: 'regular', type: "regular",
}, },
} as const } as const
@@ -70,7 +70,7 @@ const fontOnlyConfig = {
}, },
}, },
defaultVariants: { defaultVariants: {
type: 'regular', type: "regular",
}, },
} as const } as const

View File

@@ -1,9 +1,9 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Card } from './Card.tsx' import { Card } from "./Card.tsx"
const meta: Meta<typeof Card> = { const meta: Meta<typeof Card> = {
title: 'Core Components/Card', title: "Core Components/Card",
component: Card, component: Card,
} }
@@ -13,13 +13,13 @@ type Story = StoryObj<typeof Card>
export const Default: Story = { export const Default: Story = {
args: { args: {
as: 'Default', as: "Default",
}, },
} }
export const Featured: Story = { export const Featured: Story = {
args: { args: {
...Default.args, ...Default.args,
as: 'Featured', as: "Featured",
}, },
} }

View File

@@ -1,6 +1,6 @@
import { variants } from './variants' import { variants } from "./variants"
import type { CardProps } from './types' import type { CardProps } from "./types"
export function Card({ as, className, children }: CardProps) { export function Card({ as, className, children }: CardProps) {
const classNames = variants({ const classNames = variants({

View File

@@ -1,11 +1,11 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from 'storybook/test' import { fn } from "storybook/test"
import { themes } from '../../../../.storybook/preview' import { themes } from "../../../../.storybook/preview"
import { Card } from '../' import { Card } from "../"
import { Button } from '../../Button' import { Button } from "../../Button"
import { Typography } from '../../Typography' import { Typography } from "../../Typography"
type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & { type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & {
_onPrimaryPress?: () => void _onPrimaryPress?: () => void
@@ -18,18 +18,18 @@ type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & {
} }
const meta: Meta<CompositionProps> = { const meta: Meta<CompositionProps> = {
title: 'Compositions/Card', title: "Compositions/Card",
component: Card, component: Card,
decorators: [ decorators: [
(Story, context) => { (Story, context) => {
if (context.name.toLowerCase().indexOf('all themes') >= 0) { if (context.name.toLowerCase().indexOf("all themes") >= 0) {
return ( return (
<> <>
<h1>{context.name}</h1> <h1>{context.name}</h1>
{Object.entries(themes.themes).map(([key, value], ix) => { {Object.entries(themes.themes).map(([key, value], ix) => {
return ( return (
<div key={ix} className={value} style={{ padding: '1em 0' }}> <div key={ix} className={value} style={{ padding: "1em 0" }}>
<h2 style={{ paddingBottom: '0.5em' }}>{key}</h2> <h2 style={{ paddingBottom: "0.5em" }}>{key}</h2>
<Story /> <Story />
</div> </div>
) )
@@ -39,7 +39,7 @@ const meta: Meta<CompositionProps> = {
} }
return ( return (
<div style={{ display: 'flex' }}> <div style={{ display: "flex" }}>
<Story /> <Story />
</div> </div>
) )
@@ -47,19 +47,19 @@ const meta: Meta<CompositionProps> = {
], ],
argTypes: { argTypes: {
inMainArea: { inMainArea: {
name: 'Is in main area', name: "Is in main area",
}, },
showTitle: { showTitle: {
name: 'Composition: Show title', name: "Composition: Show title",
}, },
showPreamble: { showPreamble: {
name: 'Composition: Show preamble', name: "Composition: Show preamble",
}, },
showPrimaryButton: { showPrimaryButton: {
name: 'Composition: Show primary button', name: "Composition: Show primary button",
}, },
showSecondaryButton: { showSecondaryButton: {
name: 'Composition: Show secondary button', name: "Composition: Show secondary button",
}, },
_onPrimaryPress: { _onPrimaryPress: {
table: { table: {
@@ -110,7 +110,7 @@ const meta: Meta<CompositionProps> = {
{showSecondaryButton && ( {showSecondaryButton && (
<Button <Button
size={inMainArea ? 'lg' : 'sm'} size={inMainArea ? "lg" : "sm"}
variant="Secondary" variant="Secondary"
onPress={args._onSecondaryPress} onPress={args._onSecondaryPress}
> >
@@ -127,7 +127,7 @@ type Story = StoryObj<CompositionProps>
export const ContentCardMainArea: Story = { export const ContentCardMainArea: Story = {
args: { args: {
as: 'Default', as: "Default",
inMainArea: true, inMainArea: true,
showTitle: true, showTitle: true,
showPreamble: true, showPreamble: true,
@@ -140,7 +140,7 @@ export const ContentCardMainArea: Story = {
export const ContentCardNonMainArea: Story = { export const ContentCardNonMainArea: Story = {
args: { args: {
as: 'Default', as: "Default",
inMainArea: false, inMainArea: false,
showTitle: true, showTitle: true,
showPreamble: true, showPreamble: true,

View File

@@ -1 +1 @@
export { Card } from './Card' export { Card } from "./Card"

View File

@@ -1,11 +1,10 @@
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { variants } from './variants' import type { variants } from "./variants"
type CardStyles = 'Default' | 'Featured' type CardStyles = "Default" | "Featured"
export interface CardProps export interface CardProps
extends React.HTMLAttributes<HTMLDivElement>, extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof variants> {
VariantProps<typeof variants> {
as: CardStyles as: CardStyles
} }

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './card.module.css' import styles from "./card.module.css"
const config = { const config = {
variants: { variants: {
@@ -10,7 +10,7 @@ const config = {
}, },
}, },
defaultVariants: { defaultVariants: {
as: 'Default', as: "Default",
}, },
} as const } as const

View File

@@ -1,9 +1,10 @@
import { VariantProps } from 'class-variance-authority' import { VariantProps } from "class-variance-authority"
import { chipVariants } from './variants' import { chipVariants } from "./variants"
import Footnote from '../Footnote' import Footnote from "../Footnote"
export interface ChipProps export interface ChipProps
extends React.HtmlHTMLAttributes<HTMLDivElement>, extends
React.HtmlHTMLAttributes<HTMLDivElement>,
VariantProps<typeof chipVariants> {} VariantProps<typeof chipVariants> {}
/** /**

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './chip.module.css' import styles from "./chip.module.css"
export const chipVariants = cva(styles.chip, { export const chipVariants = cva(styles.chip, {
variants: { variants: {
@@ -17,7 +17,7 @@ export const chipVariants = cva(styles.chip, {
}, },
}, },
defaultVariants: { defaultVariants: {
size: 'medium', size: "medium",
variant: 'default', variant: "default",
}, },
}) })

View File

@@ -1,18 +1,18 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from 'storybook/test' import { fn } from "storybook/test"
import { MaterialIcon } from '../Icons/MaterialIcon/MaterialIcon.tsx' import { MaterialIcon } from "../Icons/MaterialIcon/MaterialIcon.tsx"
import { ChipButton } from './ChipButton.tsx' import { ChipButton } from "./ChipButton.tsx"
import { config as chipButtonConfig } from './variants' import { config as chipButtonConfig } from "./variants"
const meta: Meta<typeof ChipButton> = { const meta: Meta<typeof ChipButton> = {
title: 'Core Components/ChipButton', title: "Core Components/ChipButton",
component: ChipButton, component: ChipButton,
argTypes: { argTypes: {
variant: { variant: {
control: 'select', control: "select",
type: 'string', type: "string",
options: Object.keys(chipButtonConfig.variants.variant), options: Object.keys(chipButtonConfig.variants.variant),
}, },
onPress: { onPress: {
@@ -41,7 +41,7 @@ export const Default: Story = {
export const Outlined: Story = { export const Outlined: Story = {
args: { args: {
variant: 'Outlined', variant: "Outlined",
onPress: fn(), onPress: fn(),
children: ( children: (
<> <>
@@ -54,9 +54,9 @@ export const Outlined: Story = {
export const FilterRoundedLarge: Story = { export const FilterRoundedLarge: Story = {
args: { args: {
variant: 'FilterRounded', variant: "FilterRounded",
onPress: fn(), onPress: fn(),
size: 'Large', size: "Large",
children: ( children: (
<> <>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" /> <MaterialIcon icon="location_city" size={20} color="CurrentColor" />
@@ -68,9 +68,9 @@ export const FilterRoundedLarge: Story = {
export const FilterRoundedLargeSelected: Story = { export const FilterRoundedLargeSelected: Story = {
args: { args: {
variant: 'FilterRounded', variant: "FilterRounded",
onPress: fn(), onPress: fn(),
size: 'Large', size: "Large",
selected: true, selected: true,
children: ( children: (
<> <>
@@ -83,9 +83,9 @@ export const FilterRoundedLargeSelected: Story = {
export const FilterRoundedMedium: Story = { export const FilterRoundedMedium: Story = {
args: { args: {
variant: 'FilterRounded', variant: "FilterRounded",
onPress: fn(), onPress: fn(),
size: 'Medium', size: "Medium",
children: ( children: (
<> <>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" /> <MaterialIcon icon="location_city" size={20} color="CurrentColor" />
@@ -97,9 +97,9 @@ export const FilterRoundedMedium: Story = {
export const FilterRoundedMediumSelected: Story = { export const FilterRoundedMediumSelected: Story = {
args: { args: {
variant: 'FilterRounded', variant: "FilterRounded",
onPress: fn(), onPress: fn(),
size: 'Medium', size: "Medium",
selected: true, selected: true,
children: ( children: (
<> <>

View File

@@ -1,13 +1,13 @@
import { Button as ButtonRAC } from 'react-aria-components' import { Button as ButtonRAC } from "react-aria-components"
import { ChipButtonProps } from './types' import { ChipButtonProps } from "./types"
import { variants } from './variants' import { variants } from "./variants"
export function ChipButton({ export function ChipButton({
children, children,
variant, variant,
selected = false, selected = false,
size = 'Large', size = "Large",
className, className,
...props ...props
}: ChipButtonProps) { }: ChipButtonProps) {
@@ -18,7 +18,7 @@ export function ChipButton({
}) })
return ( return (
<ButtonRAC {...props} className={[className, classNames].join(' ')}> <ButtonRAC {...props} className={[className, classNames].join(" ")}>
{children} {children}
</ButtonRAC> </ButtonRAC>
) )

View File

@@ -1 +1 @@
export { ChipButton } from './ChipButton' export { ChipButton } from "./ChipButton"

View File

@@ -1,10 +1,9 @@
import { Button } from 'react-aria-components' import { Button } from "react-aria-components"
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { ComponentProps } from 'react' import type { ComponentProps } from "react"
import type { variants } from './variants' import type { variants } from "./variants"
export interface ChipButtonProps export interface ChipButtonProps
extends ComponentProps<typeof Button>, extends ComponentProps<typeof Button>, VariantProps<typeof variants> {}
VariantProps<typeof variants> {}

View File

@@ -1,22 +1,22 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import { deepmerge } from 'deepmerge-ts' import { deepmerge } from "deepmerge-ts"
import styles from './chip-button.module.css' import styles from "./chip-button.module.css"
import { config as typographyConfig } from '../Typography/variants' import { config as typographyConfig } from "../Typography/variants"
const variantKeys = { const variantKeys = {
variant: { variant: {
Default: 'Default', Default: "Default",
Outlined: 'Outlined', Outlined: "Outlined",
FilterRounded: 'FilterRounded', FilterRounded: "FilterRounded",
}, },
style: { style: {
Medium: 'Medium', Medium: "Medium",
Large: 'Large', Large: "Large",
}, },
typography: { typography: {
Bold: 'Body/Supporting text (caption)/smBold', Bold: "Body/Supporting text (caption)/smBold",
Regular: 'Body/Supporting text (caption)/smRegular', Regular: "Body/Supporting text (caption)/smRegular",
}, },
} as const } as const
@@ -28,12 +28,12 @@ export const config = {
[variantKeys.variant.FilterRounded]: styles.FilterRounded, [variantKeys.variant.FilterRounded]: styles.FilterRounded,
}, },
selected: { selected: {
true: '', true: "",
false: '', false: "",
}, },
size: { size: {
[variantKeys.style.Medium]: '', [variantKeys.style.Medium]: "",
[variantKeys.style.Large]: '', [variantKeys.style.Large]: "",
}, },
}, },
compoundVariants: [ compoundVariants: [
@@ -41,7 +41,7 @@ export const config = {
variant: variantKeys.variant.Default, variant: variantKeys.variant.Default,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smBold' "Body/Supporting text (caption)/smBold"
], ],
], ],
}, },
@@ -49,7 +49,7 @@ export const config = {
variant: variantKeys.variant.Outlined, variant: variantKeys.variant.Outlined,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smBold' "Body/Supporting text (caption)/smBold"
], ],
], ],
}, },
@@ -59,7 +59,7 @@ export const config = {
selected: true, selected: true,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular' "Body/Supporting text (caption)/smRegular"
], ],
styles.selected, styles.selected,
styles.medium, styles.medium,
@@ -71,7 +71,7 @@ export const config = {
selected: false, selected: false,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular' "Body/Supporting text (caption)/smRegular"
], ],
styles.medium, styles.medium,
], ],
@@ -82,7 +82,7 @@ export const config = {
selected: true, selected: true,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular' "Body/Supporting text (caption)/smRegular"
], ],
styles.selected, styles.selected,
styles.large, styles.large,
@@ -94,7 +94,7 @@ export const config = {
selected: false, selected: false,
className: [ className: [
typographyConfig.variants.variant[ typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular' "Body/Supporting text (caption)/smRegular"
], ],
styles.large, styles.large,
], ],

View File

@@ -1,10 +1,10 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { MaterialIcon } from '../Icons/MaterialIcon' import { MaterialIcon } from "../Icons/MaterialIcon"
import { ChipLink } from './ChipLink.tsx' import { ChipLink } from "./ChipLink.tsx"
const meta: Meta<typeof ChipLink> = { const meta: Meta<typeof ChipLink> = {
title: 'Core Components/ChipLink', title: "Core Components/ChipLink",
component: ChipLink, component: ChipLink,
} }
@@ -14,7 +14,7 @@ type Story = StoryObj<typeof ChipLink>
export const Default: Story = { export const Default: Story = {
args: { args: {
href: '/', href: "/",
onPress: (e) => console.log(e), onPress: (e) => console.log(e),
children: ( children: (
<> <>

View File

@@ -1,13 +1,13 @@
import { cx } from 'class-variance-authority' import { cx } from "class-variance-authority"
import { Typography } from '../Typography' import { Typography } from "../Typography"
import styles from './chip-link.module.css' import styles from "./chip-link.module.css"
import type { PropsWithChildren } from 'react' import type { PropsWithChildren } from "react"
import { import {
Link as LinkRAC, Link as LinkRAC,
LinkProps as LinkRACProps, LinkProps as LinkRACProps,
} from 'react-aria-components' } from "react-aria-components"
export function ChipLink({ export function ChipLink({
children, children,

View File

@@ -1 +1 @@
export { ChipLink } from './ChipLink' export { ChipLink } from "./ChipLink"

View File

@@ -1,19 +1,19 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { fn } from 'storybook/test' import { fn } from "storybook/test"
import { Chips } from './Chips.tsx' import { Chips } from "./Chips.tsx"
import { ChipLink } from '../ChipLink/ChipLink.tsx' import { ChipLink } from "../ChipLink/ChipLink.tsx"
import { ChipButton } from '../ChipButton/ChipButton.tsx' import { ChipButton } from "../ChipButton/ChipButton.tsx"
import { Default as ChipLinkDefault } from '../ChipLink/ChipLink.stories.tsx' import { Default as ChipLinkDefault } from "../ChipLink/ChipLink.stories.tsx"
import { Default as ChipButtonDefault } from '../ChipButton/ChipButton.stories.tsx' import { Default as ChipButtonDefault } from "../ChipButton/ChipButton.stories.tsx"
type StoryProps = React.ComponentPropsWithoutRef<typeof Chips> & { type StoryProps = React.ComponentPropsWithoutRef<typeof Chips> & {
onPress: () => void onPress: () => void
} }
const meta: Meta<StoryProps> = { const meta: Meta<StoryProps> = {
title: 'Compositions/Chips', title: "Compositions/Chips",
component: Chips, component: Chips,
argTypes: { argTypes: {
onPress: { onPress: {

View File

@@ -1,6 +1,6 @@
import styles from './chips.module.css' import styles from "./chips.module.css"
import type { PropsWithChildren } from 'react' import type { PropsWithChildren } from "react"
export function Chips({ children }: PropsWithChildren) { export function Chips({ children }: PropsWithChildren) {
return <div className={styles.chips}>{children}</div> return <div className={styles.chips}>{children}</div>

View File

@@ -1 +1 @@
export { Chips } from './Chips' export { Chips } from "./Chips"

View File

@@ -2,6 +2,6 @@
display: flex; display: flex;
} }
div[data-rac][data-open='true'] .chevron { div[data-rac][data-open="true"] .chevron {
transform: rotate(180deg); transform: rotate(180deg);
} }

View File

@@ -1,13 +1,13 @@
import { IconProps } from '../../Icons' import { IconProps } from "../../Icons"
import { MaterialIcon } from '../../Icons/MaterialIcon' import { MaterialIcon } from "../../Icons/MaterialIcon"
import styles from './chevron.module.css' import styles from "./chevron.module.css"
export default function SelectChevron(props: IconProps) { export default function SelectChevron(props: IconProps) {
return ( return (
<span aria-hidden="true" className={styles.chevron}> <span aria-hidden="true" className={styles.chevron}>
<MaterialIcon <MaterialIcon
icon="keyboard_arrow_down" icon="keyboard_arrow_down"
color={props.color ?? 'Icon/Default'} color={props.color ?? "Icon/Default"}
size={20} size={20}
/> />
</span> </span>

View File

@@ -1,5 +1,5 @@
'use client' "use client"
import { ReactElement, useState } from 'react' import { ReactElement, useState } from "react"
import { import {
Button, Button,
type Key, type Key,
@@ -8,17 +8,17 @@ import {
Popover, Popover,
Select as ReactAriaSelect, Select as ReactAriaSelect,
SelectValue, SelectValue,
} from 'react-aria-components' } from "react-aria-components"
import SelectChevron from './SelectChevron' import SelectChevron from "./SelectChevron"
import styles from './select.module.css' import styles from "./select.module.css"
import { InputLabel } from '../InputLabel' import { InputLabel } from "../InputLabel"
import { Typography } from '../Typography' import { Typography } from "../Typography"
interface SelectProps extends Omit< interface SelectProps extends Omit<
React.SelectHTMLAttributes<HTMLSelectElement>, React.SelectHTMLAttributes<HTMLSelectElement>,
'onSelect' "onSelect"
> { > {
defaultSelectedKey?: Key defaultSelectedKey?: Key
items: { label: string; value: Key }[] items: { label: string; value: Key }[]
@@ -37,14 +37,14 @@ interface SelectProps extends Omit<
type SelectPortalContainer = HTMLDivElement | undefined type SelectPortalContainer = HTMLDivElement | undefined
type SelectPortalContainerArgs = HTMLDivElement | null type SelectPortalContainerArgs = HTMLDivElement | null
const DELIMITER = ':' const DELIMITER = ":"
/** /**
* @deprecated Do not use. * @deprecated Do not use.
*/ */
export default function Select({ export default function Select({
className = '', className = "",
'aria-label': ariaLabel, "aria-label": ariaLabel,
defaultSelectedKey, defaultSelectedKey,
items, items,
label, label,
@@ -78,16 +78,16 @@ export default function Select({
let chevronProps = {} let chevronProps = {}
if (discreet) { if (discreet) {
chevronProps = { color: 'baseButtonTextOnFillNormal' } chevronProps = { color: "baseButtonTextOnFillNormal" }
} else if (disabled) { } else if (disabled) {
chevronProps = { color: 'disabled' } chevronProps = { color: "disabled" }
} }
return ( return (
<div className={`${styles.container} ${className}`} ref={setRef}> <div className={`${styles.container} ${className}`} ref={setRef}>
<ReactAriaSelect <ReactAriaSelect
aria-label={ariaLabel} aria-label={ariaLabel}
className={`${styles.select} ${discreet ? styles.discreet : ''} select-container`} className={`${styles.select} ${discreet ? styles.discreet : ""} select-container`}
defaultSelectedKey={defaultSelectedKey} defaultSelectedKey={defaultSelectedKey}
name={name} name={name}
onSelectionChange={handleOnSelect} onSelectionChange={handleOnSelect}
@@ -105,7 +105,7 @@ export default function Select({
<> <>
<InputLabel <InputLabel
required={required} required={required}
size={discreet ? 'discreet' : 'regular'} size={discreet ? "discreet" : "regular"}
> >
{label} {label}
{discreet && DELIMITER} {discreet && DELIMITER}
@@ -113,7 +113,7 @@ export default function Select({
{selectedText && ( {selectedText && (
<Typography <Typography
variant="Body/Paragraph/mdRegular" variant="Body/Paragraph/mdRegular"
className={optionsIcon ? styles.iconLabel : ''} className={optionsIcon ? styles.iconLabel : ""}
> >
<p> <p>
{optionsIcon ? optionsIcon : null} {optionsIcon ? optionsIcon : null}
@@ -165,9 +165,9 @@ export default function Select({
function useSetOverflowVisibleOnRA(isNestedInModal?: boolean) { function useSetOverflowVisibleOnRA(isNestedInModal?: boolean) {
function setOverflowVisible(isOpen: boolean) { function setOverflowVisible(isOpen: boolean) {
if (isOpen) { if (isOpen) {
document.body.style.overflow = 'visible' document.body.style.overflow = "visible"
} else if (!isNestedInModal) { } else if (!isNestedInModal) {
document.body.style.overflow = '' document.body.style.overflow = ""
} }
} }

View File

@@ -10,16 +10,16 @@
gap: var(--Space-x05); gap: var(--Space-x05);
} }
.select[data-focused='true'] { .select[data-focused="true"] {
border: 2px solid var(--Border-Interactive-Focus); border: 2px solid var(--Border-Interactive-Focus);
outline: none; outline: none;
} }
.select[data-focused='true'].discreet { .select[data-focused="true"].discreet {
border: 1px solid transparent; border: 1px solid transparent;
outline: none; outline: none;
} }
.select[data-focus-visible='true'].discreet { .select[data-focus-visible="true"].discreet {
border: 2px solid var(--Border-Interactive-Focus); border: 2px solid var(--Border-Interactive-Focus);
} }
@@ -97,8 +97,8 @@
padding: var(--Space-x1); padding: var(--Space-x1);
} }
.listBoxItem[data-focused='true'], .listBoxItem[data-focused="true"],
.listBoxItem[data-selected='true'] { .listBoxItem[data-selected="true"] {
background: var(--UI-Input-Controls-Surface-Hover); background: var(--UI-Input-Controls-Surface-Hover);
border-radius: var(--Corner-radius-md); border-radius: var(--Corner-radius-md);
outline: none; outline: none;
@@ -111,7 +111,7 @@
.listBoxItem.showRadioButton:before { .listBoxItem.showRadioButton:before {
flex-shrink: 0; flex-shrink: 0;
content: ''; content: "";
margin-right: var(--Space-x15); margin-right: var(--Space-x15);
background-color: white; background-color: white;
width: 24px; width: 24px;
@@ -120,6 +120,6 @@
box-shadow: inset 0 0 0 2px var(--Base-Border-Normal); box-shadow: inset 0 0 0 2px var(--Base-Border-Normal);
} }
.listBoxItem[data-selected='true'].showRadioButton:before { .listBoxItem[data-selected="true"].showRadioButton:before {
box-shadow: inset 0 0 0 8px var(--Surface-UI-Fill-Active); box-shadow: inset 0 0 0 8px var(--Surface-UI-Fill-Active);
} }

View File

@@ -1,9 +1,9 @@
import type { Meta, StoryObj } from '@storybook/nextjs-vite' import type { Meta, StoryObj } from "@storybook/nextjs-vite"
import { Divider } from './Divider' import { Divider } from "./Divider"
const meta: Meta<typeof Divider> = { const meta: Meta<typeof Divider> = {
title: 'Core Components/Divider', title: "Core Components/Divider",
component: Divider, component: Divider,
argTypes: {}, argTypes: {},
} }

View File

@@ -1,6 +1,6 @@
import { dividerVariants } from './variants' import { dividerVariants } from "./variants"
import type { DividerProps } from './types' import type { DividerProps } from "./types"
export function Divider({ className, color, variant }: DividerProps) { export function Divider({ className, color, variant }: DividerProps) {
const classNames = dividerVariants({ className, color, variant }) const classNames = dividerVariants({ className, color, variant })

View File

@@ -1,4 +1,4 @@
export { Divider } from './Divider' export { Divider } from "./Divider"
// eslint-disable-next-line react-refresh/only-export-components // eslint-disable-next-line react-refresh/only-export-components
export { dividerVariants } from './variants' export { dividerVariants } from "./variants"

View File

@@ -1,7 +1,8 @@
import type { VariantProps } from 'class-variance-authority' import type { VariantProps } from "class-variance-authority"
import type { dividerVariants } from './variants' import type { dividerVariants } from "./variants"
export interface DividerProps export interface DividerProps
extends Omit<React.HTMLAttributes<HTMLHRElement>, 'color'>, extends
Omit<React.HTMLAttributes<HTMLHRElement>, "color">,
VariantProps<typeof dividerVariants> {} VariantProps<typeof dividerVariants> {}

View File

@@ -1,6 +1,6 @@
import { cva } from 'class-variance-authority' import { cva } from "class-variance-authority"
import styles from './divider.module.css' import styles from "./divider.module.css"
export const dividerVariants = cva(styles.divider, { export const dividerVariants = cva(styles.divider, {
variants: { variants: {
@@ -9,15 +9,15 @@ export const dividerVariants = cva(styles.divider, {
pale: styles.pale, pale: styles.pale,
peach: styles.peach, peach: styles.peach,
white: styles.white, white: styles.white,
'Border/Divider/Accent': styles['Border-Divider-Accent'], "Border/Divider/Accent": styles["Border-Divider-Accent"],
'Border/Divider/Default': styles['Border-Divider-Default'], "Border/Divider/Default": styles["Border-Divider-Default"],
'Border/Divider/Brand/OnPrimary 3/Default': "Border/Divider/Brand/OnPrimary 3/Default":
styles['Border-Divider-Brand-OnPrimary-3-Default'], styles["Border-Divider-Brand-OnPrimary-3-Default"],
'Border/Divider/Subtle': styles['Border-Divider-Subtle'], "Border/Divider/Subtle": styles["Border-Divider-Subtle"],
'Surface/Brand/Primary 1/OnSurface/Accent Secondary': "Surface/Brand/Primary 1/OnSurface/Accent Secondary":
styles['Surface-Brand-Primary-1-OnSurface-Accent-Secondary'], styles["Surface-Brand-Primary-1-OnSurface-Accent-Secondary"],
'Border/Divider/Brand/OnAccent/Default': "Border/Divider/Brand/OnAccent/Default":
styles['Border-Divider-Brand-OnAccent-Default'], styles["Border-Divider-Brand-OnAccent-Default"],
}, },
variant: { variant: {
horizontal: styles.horizontal, horizontal: styles.horizontal,
@@ -25,7 +25,7 @@ export const dividerVariants = cva(styles.divider, {
}, },
}, },
defaultVariants: { defaultVariants: {
color: 'Border/Divider/Default', color: "Border/Divider/Default",
variant: 'horizontal', variant: "horizontal",
}, },
}) })

Some files were not shown because too many files have changed in this diff Show More