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:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": false,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"endOfLine": "lf"
|
||||
@@ -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
|
||||
@@ -16,13 +16,5 @@
|
||||
"convert-csv-to-json": "^3.4.0",
|
||||
"jiti": "^2.6.1",
|
||||
"vitest": "^4.0.0"
|
||||
},
|
||||
"prettier": {
|
||||
"semi": false,
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": false,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"endOfLine": "lf"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,10 +1,10 @@
|
||||
/* eslint-disable formatjs/no-literal-string-in-jsx */
|
||||
import { useState } from 'react'
|
||||
import copy from 'copy-to-clipboard'
|
||||
import { useState } from "react"
|
||||
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>
|
||||
|
||||
@@ -20,7 +20,7 @@ export type ColorsProps = {
|
||||
defaultThemeName?: string
|
||||
}
|
||||
|
||||
import styles from './colors.module.css'
|
||||
import styles from "./colors.module.css"
|
||||
|
||||
function getContrastColor(bgColor: string) {
|
||||
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
|
||||
if (luminance > 0.5) {
|
||||
return '#000'
|
||||
return "#000"
|
||||
} else {
|
||||
if (a < 255 / 2) {
|
||||
return '#000'
|
||||
return "#000"
|
||||
}
|
||||
return '#fff'
|
||||
return "#fff"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ export function Colors({
|
||||
defaultThemeName,
|
||||
}: ColorsProps) {
|
||||
const [selectedThemeName, setSelectedThemeName] = useState<string>(
|
||||
defaultThemeName || themes?.[0]?.name || ''
|
||||
defaultThemeName || themes?.[0]?.name || ""
|
||||
)
|
||||
const [, setCopiedKey] = useState<string | null>(null)
|
||||
|
||||
@@ -78,8 +78,8 @@ export function Colors({
|
||||
const grouping: Record<string, Theme> = {}
|
||||
|
||||
for (const [k, v] of Object.entries(currentTheme)) {
|
||||
if (typeof v.resolved === 'string' && v.resolved.startsWith('#')) {
|
||||
const key = k.replace(/\/[^/]+$/, '')
|
||||
if (typeof v.resolved === "string" && v.resolved.startsWith("#")) {
|
||||
const key = k.replace(/\/[^/]+$/, "")
|
||||
if (!grouping[key]) {
|
||||
grouping[key] = {}
|
||||
}
|
||||
@@ -120,8 +120,8 @@ export function Colors({
|
||||
onChange={(e) => {
|
||||
const el = document.getElementById(e.target.value)
|
||||
el?.scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'start',
|
||||
behavior: "smooth",
|
||||
block: "start",
|
||||
})
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* 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 = {
|
||||
resolved: string | number
|
||||
@@ -24,15 +24,15 @@ export function CornerRadius({ theme }: CornerRadiusProps) {
|
||||
// Filter corner radius tokens
|
||||
const cornerRadiusTokens: Theme = {}
|
||||
for (const [k, v] of Object.entries(theme)) {
|
||||
if (k.startsWith('Corner radius/')) {
|
||||
if (k.startsWith("Corner radius/")) {
|
||||
cornerRadiusTokens[k] = v as ThemeValue
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by value
|
||||
const sortedTokens = Object.entries(cornerRadiusTokens).sort((a, b) => {
|
||||
const aValue = typeof a[1].resolved === 'number' ? a[1].resolved : 0
|
||||
const bValue = typeof b[1].resolved === 'number' ? b[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
|
||||
return aValue - bValue
|
||||
})
|
||||
|
||||
@@ -51,7 +51,7 @@ export function CornerRadius({ theme }: CornerRadiusProps) {
|
||||
</thead>
|
||||
<tbody>
|
||||
{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`
|
||||
|
||||
return (
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* 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 = {
|
||||
resolved: string | number
|
||||
@@ -24,15 +24,15 @@ export function Shadow({ theme }: ShadowProps) {
|
||||
// Filter shadow tokens
|
||||
const shadowTokens: Theme = {}
|
||||
for (const [k, v] of Object.entries(theme)) {
|
||||
if (k.startsWith('BoxShadow-')) {
|
||||
if (k.startsWith("BoxShadow-")) {
|
||||
shadowTokens[k] = v as ThemeValue
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by level
|
||||
const sortedTokens = Object.entries(shadowTokens).sort((a, b) => {
|
||||
const aLevel = parseInt(a[0].match(/\d+/)?.[0] || '0')
|
||||
const bLevel = parseInt(b[0].match(/\d+/)?.[0] || '0')
|
||||
const aLevel = parseInt(a[0].match(/\d+/)?.[0] || "0")
|
||||
const bLevel = parseInt(b[0].match(/\d+/)?.[0] || "0")
|
||||
return aLevel - bLevel
|
||||
})
|
||||
|
||||
@@ -53,8 +53,8 @@ export function Shadow({ theme }: ShadowProps) {
|
||||
<tbody>
|
||||
{sortedTokens.map(([k, v]) => {
|
||||
const shadowValue =
|
||||
typeof v.resolved === 'string' ? v.resolved : ''
|
||||
const level = k.match(/\d+/)?.[0] || '0'
|
||||
typeof v.resolved === "string" ? v.resolved : ""
|
||||
const level = k.match(/\d+/)?.[0] || "0"
|
||||
|
||||
return (
|
||||
<tr key={k} className={tableStyles.tableRow}>
|
||||
@@ -80,8 +80,8 @@ export function Shadow({ theme }: ShadowProps) {
|
||||
}}
|
||||
title="Click to copy"
|
||||
style={{
|
||||
fontSize: '0.75rem',
|
||||
wordBreak: 'break-all',
|
||||
fontSize: "0.75rem",
|
||||
wordBreak: "break-all",
|
||||
}}
|
||||
>
|
||||
{shadowValue}
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* 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 = {
|
||||
resolved: string | number
|
||||
@@ -24,15 +24,15 @@ function copyToClipboard(text: string) {
|
||||
function getBaseUnitMultiplier(tokenName: string): string {
|
||||
// Token names are like "Space/x0", "Space/x025", "Space/x05", "Space/x1", "Space/x15", etc.
|
||||
const match = tokenName.match(/Space\/x(\d+)/)
|
||||
if (!match) return '0x'
|
||||
if (!match) return "0x"
|
||||
|
||||
const num = match[1]
|
||||
|
||||
// Handle special cases
|
||||
if (num === '0') return '0x'
|
||||
if (num === '025') return '0.25x'
|
||||
if (num === '05') return '0.5x'
|
||||
if (num === '15') return '1.5x'
|
||||
if (num === "0") return "0x"
|
||||
if (num === "025") return "0.25x"
|
||||
if (num === "05") return "0.5x"
|
||||
if (num === "15") return "1.5x"
|
||||
|
||||
// For other numbers, they're already the multiplier (x1 = 1x, x2 = 2x, etc.)
|
||||
return `${num}x`
|
||||
@@ -42,15 +42,15 @@ export function Spacing({ theme }: SpacingProps) {
|
||||
// Filter spacing tokens
|
||||
const spacingTokens: Theme = {}
|
||||
for (const [k, v] of Object.entries(theme)) {
|
||||
if (k.startsWith('Space/')) {
|
||||
if (k.startsWith("Space/")) {
|
||||
spacingTokens[k] = v as ThemeValue
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by value
|
||||
const sortedTokens = Object.entries(spacingTokens).sort((a, b) => {
|
||||
const aValue = typeof a[1].resolved === 'number' ? a[1].resolved : 0
|
||||
const bValue = typeof b[1].resolved === 'number' ? b[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
|
||||
return aValue - bValue
|
||||
})
|
||||
|
||||
@@ -72,7 +72,7 @@ export function Spacing({ theme }: SpacingProps) {
|
||||
</thead>
|
||||
<tbody>
|
||||
{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 multiplier = getBaseUnitMultiplier(k)
|
||||
|
||||
@@ -112,7 +112,7 @@ export function Spacing({ theme }: SpacingProps) {
|
||||
className={tableStyles.visualBar}
|
||||
style={{
|
||||
width: `${value}px`,
|
||||
minWidth: value > 0 ? '2px' : '0',
|
||||
minWidth: value > 0 ? "2px" : "0",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
}
|
||||
|
||||
.colorValue {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
padding: 0.5rem 1rem;
|
||||
@@ -203,7 +203,7 @@
|
||||
}
|
||||
|
||||
.tokenCode {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
font-size: 12px;
|
||||
background: #f9fafb;
|
||||
padding: 0.375rem 0.625rem;
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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 {
|
||||
base,
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
hotelNorge,
|
||||
grandHotel,
|
||||
theDock,
|
||||
} from '../../../lib/tokens'
|
||||
} from "../../../lib/tokens"
|
||||
|
||||
<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
|
||||
themes={[
|
||||
{ name: 'base', displayName: 'Base', theme: base },
|
||||
{ name: 'scandic', displayName: 'Scandic', theme: scandic },
|
||||
{ name: 'scandicGo', displayName: 'Scandic Go', theme: scandicGo },
|
||||
{ name: "base", displayName: "Base", theme: base },
|
||||
{ name: "scandic", displayName: "Scandic", theme: scandic },
|
||||
{ name: "scandicGo", displayName: "Scandic Go", theme: scandicGo },
|
||||
{
|
||||
name: 'downtownCamper',
|
||||
displayName: 'Downtown Camper',
|
||||
name: "downtownCamper",
|
||||
displayName: "Downtown Camper",
|
||||
theme: downtownCamper,
|
||||
},
|
||||
{ name: 'haymarket', displayName: 'Haymarket', theme: haymarket },
|
||||
{ name: 'marski', displayName: 'Marski', theme: marski },
|
||||
{ name: 'hotelNorge', displayName: 'Hotel Norge', theme: hotelNorge },
|
||||
{ name: 'grandHotel', displayName: 'Grand Hotel', theme: grandHotel },
|
||||
{ name: 'theDock', displayName: 'The Dock', theme: theDock },
|
||||
{ name: "haymarket", displayName: "Haymarket", theme: haymarket },
|
||||
{ name: "marski", displayName: "Marski", theme: marski },
|
||||
{ name: "hotelNorge", displayName: "Hotel Norge", theme: hotelNorge },
|
||||
{ name: "grandHotel", displayName: "Grand Hotel", theme: grandHotel },
|
||||
{ name: "theDock", displayName: "The Dock", theme: theDock },
|
||||
]}
|
||||
defaultThemeName="scandic"
|
||||
/>
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -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" />
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Meta } from '@storybook/addon-docs/blocks'
|
||||
import { Meta } from "@storybook/addon-docs/blocks"
|
||||
|
||||
<Meta title="Introduction" />
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
}
|
||||
|
||||
.tokenName {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
background: #f3f4f6;
|
||||
padding: 0.25rem 0.5rem;
|
||||
border-radius: 4px;
|
||||
@@ -73,7 +73,7 @@
|
||||
}
|
||||
|
||||
.value {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
color: #6b7280;
|
||||
cursor: pointer;
|
||||
transition: color 0.15s ease;
|
||||
@@ -98,7 +98,7 @@
|
||||
}
|
||||
|
||||
.visualBarLabel {
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
||||
font-size: 0.75rem;
|
||||
color: #6b7280;
|
||||
min-width: 40px;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FormProvider, useForm } from 'react-hook-form'
|
||||
import { FormProvider, useForm } from "react-hook-form"
|
||||
|
||||
export const FormDecorator = (Story: React.FC) => {
|
||||
const formMethods = useForm()
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
import type { StorybookConfig } from '@storybook/nextjs-vite'
|
||||
import { mergeConfig } from 'vite'
|
||||
import type { StorybookConfig } from "@storybook/nextjs-vite"
|
||||
import { mergeConfig } from "vite"
|
||||
|
||||
const config: StorybookConfig = {
|
||||
framework: '@storybook/nextjs-vite',
|
||||
framework: "@storybook/nextjs-vite",
|
||||
stories: [
|
||||
'../lib/**/*.mdx',
|
||||
'../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)',
|
||||
'./content/**/*.mdx',
|
||||
"../lib/**/*.mdx",
|
||||
"../lib/**/*.stories.@(js|jsx|mjs|ts|tsx)",
|
||||
"./content/**/*.mdx",
|
||||
],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-themes',
|
||||
'@storybook/addon-vitest',
|
||||
'@storybook/addon-docs',
|
||||
'@storybook/addon-a11y',
|
||||
'storybook-react-intl',
|
||||
"@storybook/addon-links",
|
||||
"@storybook/addon-themes",
|
||||
"@storybook/addon-vitest",
|
||||
"@storybook/addon-docs",
|
||||
"@storybook/addon-a11y",
|
||||
"storybook-react-intl",
|
||||
],
|
||||
core: {
|
||||
disableTelemetry: true,
|
||||
@@ -24,18 +24,18 @@ const config: StorybookConfig = {
|
||||
plugins: [
|
||||
// Add babel plugin for react-intl transformation
|
||||
{
|
||||
name: 'formatjs-transform',
|
||||
name: "formatjs-transform",
|
||||
async transform(code, id) {
|
||||
if (id.includes('node_modules')) return
|
||||
if (id.includes("node_modules")) return
|
||||
if (!/\.(jsx?|tsx?)$/.test(id)) return
|
||||
|
||||
const babel = await import('@babel/core')
|
||||
const babel = await import("@babel/core")
|
||||
const result = babel.transformSync(code, {
|
||||
plugins: [
|
||||
[
|
||||
'formatjs',
|
||||
"formatjs",
|
||||
{
|
||||
idInterpolationPattern: '[sha512:contenthash:base64:6]',
|
||||
idInterpolationPattern: "[sha512:contenthash:base64:6]",
|
||||
ast: true,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { addons } from 'storybook/manager-api'
|
||||
import scandicTheme from './scandic-theme'
|
||||
import { addons } from "storybook/manager-api"
|
||||
import scandicTheme from "./scandic-theme"
|
||||
|
||||
addons.setConfig({
|
||||
theme: scandicTheme,
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { withThemeByClassName } from '@storybook/addon-themes'
|
||||
import type { Preview, ReactRenderer } from '@storybook/nextjs-vite'
|
||||
import { IntlProvider } from 'react-intl'
|
||||
import { reactIntl } from './reactIntl'
|
||||
import { withThemeByClassName } from "@storybook/addon-themes"
|
||||
import type { Preview, ReactRenderer } from "@storybook/nextjs-vite"
|
||||
import { IntlProvider } from "react-intl"
|
||||
import { reactIntl } from "./reactIntl"
|
||||
|
||||
import '../lib/design-system-new-deprecated.css'
|
||||
import '../lib/fonts.css'
|
||||
import '../lib/normalize.css'
|
||||
import '../lib/style.css'
|
||||
import "../lib/design-system-new-deprecated.css"
|
||||
import "../lib/fonts.css"
|
||||
import "../lib/normalize.css"
|
||||
import "../lib/style.css"
|
||||
|
||||
export const themes = {
|
||||
themes: {
|
||||
Scandic: 'scandic',
|
||||
'Scandic Go': 'scandic-go',
|
||||
'Downtown Camper': 'downtown-camper',
|
||||
'Grand Hotel': 'grand-hotel',
|
||||
Haymarket: 'haymarket',
|
||||
'Hotel Norge': 'hotel-norge',
|
||||
Marski: 'marski',
|
||||
'The Dock': 'the-dock',
|
||||
Scandic: "scandic",
|
||||
"Scandic Go": "scandic-go",
|
||||
"Downtown Camper": "downtown-camper",
|
||||
"Grand Hotel": "grand-hotel",
|
||||
Haymarket: "haymarket",
|
||||
"Hotel Norge": "hotel-norge",
|
||||
Marski: "marski",
|
||||
"The Dock": "the-dock",
|
||||
},
|
||||
defaultTheme: 'Scandic',
|
||||
defaultTheme: "Scandic",
|
||||
}
|
||||
|
||||
const preview: Preview = {
|
||||
@@ -36,14 +36,14 @@ const preview: Preview = {
|
||||
initialGlobals: {
|
||||
locale: reactIntl.defaultLocale,
|
||||
locales: {
|
||||
en: { icon: '🇬🇧', title: 'English', right: 'EN' },
|
||||
sv: { icon: '🇸🇪', title: 'Svenska', right: 'SV' },
|
||||
da: { icon: '🇩🇰', title: 'Dansk', right: 'DA' },
|
||||
no: { icon: '🇳🇴', title: 'Norsk', right: 'NO' },
|
||||
fi: { icon: '🇫🇮', title: 'Suomi', right: 'FI' },
|
||||
de: { icon: '🇩🇪', title: 'Deutsch', right: 'DE' },
|
||||
en: { icon: "🇬🇧", title: "English", right: "EN" },
|
||||
sv: { icon: "🇸🇪", title: "Svenska", right: "SV" },
|
||||
da: { icon: "🇩🇰", title: "Dansk", right: "DA" },
|
||||
no: { icon: "🇳🇴", title: "Norsk", right: "NO" },
|
||||
fi: { icon: "🇫🇮", title: "Suomi", right: "FI" },
|
||||
de: { icon: "🇩🇪", title: "Deutsch", right: "DE" },
|
||||
},
|
||||
backgrounds: { value: 'scandicSubtle' },
|
||||
backgrounds: { value: "scandicSubtle" },
|
||||
},
|
||||
parameters: {
|
||||
reactIntl,
|
||||
@@ -61,13 +61,13 @@ const preview: Preview = {
|
||||
options: {
|
||||
storySort: {
|
||||
order: [
|
||||
'Introduction',
|
||||
'Tokens',
|
||||
'Core Components',
|
||||
'Product Components',
|
||||
'Patterns',
|
||||
'Compositions',
|
||||
'*',
|
||||
"Introduction",
|
||||
"Tokens",
|
||||
"Core Components",
|
||||
"Product Components",
|
||||
"Patterns",
|
||||
"Compositions",
|
||||
"*",
|
||||
],
|
||||
},
|
||||
},
|
||||
@@ -75,12 +75,12 @@ const preview: Preview = {
|
||||
backgrounds: {
|
||||
options: {
|
||||
// 👇 Scandic
|
||||
scandicPrimary: { name: 'Scandic Primary', value: '#FAF6F2' },
|
||||
scandicSubtle: { name: 'Scandic Subtle', value: '#F2ECE6' },
|
||||
scandicPrimaryDark: { name: 'Scandic Primary Dark', value: '#4D001B' },
|
||||
scandicPrimary: { name: "Scandic Primary", value: "#FAF6F2" },
|
||||
scandicSubtle: { name: "Scandic Subtle", value: "#F2ECE6" },
|
||||
scandicPrimaryDark: { name: "Scandic Primary Dark", value: "#4D001B" },
|
||||
// 👇 Default values
|
||||
storybookDark: { name: 'Storybook Dark', value: '#333' },
|
||||
storybookLight: { name: 'Storybook Light', value: '#F7F9F2' },
|
||||
storybookDark: { name: "Storybook Dark", value: "#333" },
|
||||
storybookLight: { name: "Storybook Light", value: "#F7F9F2" },
|
||||
},
|
||||
},
|
||||
|
||||
@@ -88,11 +88,11 @@ const preview: Preview = {
|
||||
// 'todo' - show a11y violations in the test UI only
|
||||
// 'error' - fail CI on a11y violations
|
||||
// 'off' - skip a11y checks entirely
|
||||
test: 'todo',
|
||||
test: "todo",
|
||||
},
|
||||
},
|
||||
|
||||
tags: ['autodocs'],
|
||||
tags: ["autodocs"],
|
||||
}
|
||||
|
||||
export default preview
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* eslint-disable import/no-relative-packages */
|
||||
import en from '../../../apps/scandic-web/i18n/dictionaries/en.json'
|
||||
import sv from '../../../apps/scandic-web/i18n/dictionaries/sv.json'
|
||||
import da from '../../../apps/scandic-web/i18n/dictionaries/da.json'
|
||||
import fi from '../../../apps/scandic-web/i18n/dictionaries/fi.json'
|
||||
import de from '../../../apps/scandic-web/i18n/dictionaries/de.json'
|
||||
import no from '../../../apps/scandic-web/i18n/dictionaries/no.json'
|
||||
import en from "../../../apps/scandic-web/i18n/dictionaries/en.json"
|
||||
import sv from "../../../apps/scandic-web/i18n/dictionaries/sv.json"
|
||||
import da from "../../../apps/scandic-web/i18n/dictionaries/da.json"
|
||||
import fi from "../../../apps/scandic-web/i18n/dictionaries/fi.json"
|
||||
import de from "../../../apps/scandic-web/i18n/dictionaries/de.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> = {
|
||||
en,
|
||||
@@ -20,7 +20,7 @@ const messages: Record<(typeof locales)[number], unknown> = {
|
||||
const formats = {} // optional, if you have any formats
|
||||
|
||||
export const reactIntl = {
|
||||
defaultLocale: 'en',
|
||||
defaultLocale: "en",
|
||||
locales,
|
||||
messages,
|
||||
formats,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { create } from 'storybook/theming'
|
||||
import { create } from "storybook/theming"
|
||||
|
||||
export default create({
|
||||
base: 'dark',
|
||||
brandTitle: 'Scandic Design System',
|
||||
brandUrl: 'https://www.scandichotels.com/',
|
||||
brandImage: '/img/scandic-logotype.png',
|
||||
base: "dark",
|
||||
brandTitle: "Scandic Design System",
|
||||
brandUrl: "https://www.scandichotels.com/",
|
||||
brandImage: "/img/scandic-logotype.png",
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import * as a11yAddonAnnotations from '@storybook/addon-a11y/preview'
|
||||
import { setProjectAnnotations } from '@storybook/nextjs-vite'
|
||||
import * as previewAnnotations from './preview'
|
||||
import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview"
|
||||
import { setProjectAnnotations } from "@storybook/nextjs-vite"
|
||||
import * as previewAnnotations from "./preview"
|
||||
|
||||
setProjectAnnotations([a11yAddonAnnotations, previewAnnotations])
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { defineConfig, globalIgnores } from 'eslint/config'
|
||||
import globals from 'globals'
|
||||
import tsParser from '@typescript-eslint/parser'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
import react from 'eslint-plugin-react'
|
||||
import { FlatCompat } from '@eslint/eslintrc'
|
||||
import js from '@eslint/js'
|
||||
import importPlugin from 'eslint-plugin-import'
|
||||
import formatjs from 'eslint-plugin-formatjs'
|
||||
import { defineConfig, globalIgnores } from "eslint/config"
|
||||
import globals from "globals"
|
||||
import tsParser from "@typescript-eslint/parser"
|
||||
import reactRefresh from "eslint-plugin-react-refresh"
|
||||
import react from "eslint-plugin-react"
|
||||
import { FlatCompat } from "@eslint/eslintrc"
|
||||
import js from "@eslint/js"
|
||||
import importPlugin from "eslint-plugin-import"
|
||||
import formatjs from "eslint-plugin-formatjs"
|
||||
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'node:path'
|
||||
import { fileURLToPath } from "node:url"
|
||||
import path from "node:path"
|
||||
|
||||
const compat = new FlatCompat({
|
||||
recommendedConfig: js.configs.recommended,
|
||||
@@ -27,72 +27,72 @@ export default defineConfig([
|
||||
parser: tsParser,
|
||||
},
|
||||
extends: compat.extends(
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:react-hooks/recommended',
|
||||
'plugin:storybook/recommended'
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"plugin:storybook/recommended"
|
||||
),
|
||||
plugins: {
|
||||
'react-refresh': reactRefresh,
|
||||
"react-refresh": reactRefresh,
|
||||
import: importPlugin,
|
||||
formatjs,
|
||||
react,
|
||||
},
|
||||
settings: {
|
||||
// Ensure the plugin can resolve workspace packages and TS path aliases
|
||||
'import/resolver': {
|
||||
"import/resolver": {
|
||||
typescript: {
|
||||
project: [path.join(packageDir, 'tsconfig.json')],
|
||||
project: [path.join(packageDir, "tsconfig.json")],
|
||||
alwaysTryTypes: true,
|
||||
},
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
extensions: [".js", ".jsx", ".ts", ".tsx"],
|
||||
},
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'import/no-relative-packages': 'error',
|
||||
'import/no-extraneous-dependencies': [
|
||||
'error',
|
||||
"import/no-relative-packages": "error",
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
includeInternal: true,
|
||||
includeTypes: true,
|
||||
packageDir: [packageDir],
|
||||
},
|
||||
],
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
"react-refresh/only-export-components": [
|
||||
"warn",
|
||||
{
|
||||
allowConstantExport: true,
|
||||
},
|
||||
],
|
||||
'react/jsx-curly-brace-presence': [
|
||||
'error',
|
||||
"react/jsx-curly-brace-presence": [
|
||||
"error",
|
||||
{
|
||||
props: 'never',
|
||||
children: 'never',
|
||||
propElementValues: 'always',
|
||||
props: "never",
|
||||
children: "never",
|
||||
propElementValues: "always",
|
||||
},
|
||||
],
|
||||
|
||||
'formatjs/enforce-default-message': ['error', 'literal'],
|
||||
'formatjs/enforce-placeholders': ['error'],
|
||||
'formatjs/enforce-plural-rules': ['error'],
|
||||
'formatjs/no-literal-string-in-jsx': ['error'],
|
||||
'formatjs/no-multiple-whitespaces': ['error'],
|
||||
'formatjs/no-multiple-plurals': ['error'],
|
||||
'formatjs/no-invalid-icu': ['error'],
|
||||
'formatjs/enforce-id': ['error'],
|
||||
'formatjs/no-complex-selectors': ['error'],
|
||||
'formatjs/no-useless-message': ['error'],
|
||||
'formatjs/prefer-pound-in-plural': ['error'],
|
||||
"formatjs/enforce-default-message": ["error", "literal"],
|
||||
"formatjs/enforce-placeholders": ["error"],
|
||||
"formatjs/enforce-plural-rules": ["error"],
|
||||
"formatjs/no-literal-string-in-jsx": ["error"],
|
||||
"formatjs/no-multiple-whitespaces": ["error"],
|
||||
"formatjs/no-multiple-plurals": ["error"],
|
||||
"formatjs/no-invalid-icu": ["error"],
|
||||
"formatjs/enforce-id": ["error"],
|
||||
"formatjs/no-complex-selectors": ["error"],
|
||||
"formatjs/no-useless-message": ["error"],
|
||||
"formatjs/prefer-pound-in-plural": ["error"],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['**/*.stories.tsx'],
|
||||
files: ["**/*.stories.tsx"],
|
||||
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"]),
|
||||
])
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { extend } from 'colord'
|
||||
import mixPlugin from 'colord/plugins/mix'
|
||||
import fs from 'node:fs'
|
||||
import { extend } from "colord"
|
||||
import mixPlugin from "colord/plugins/mix"
|
||||
import fs from "node:fs"
|
||||
|
||||
import {
|
||||
FALLBACK_THEME,
|
||||
getThemeForToken,
|
||||
ignoreStyles,
|
||||
kebabify,
|
||||
} from './utils'
|
||||
import json from './variables.json' assert { type: 'json' }
|
||||
} from "./utils"
|
||||
import json from "./variables.json" assert { type: "json" }
|
||||
|
||||
extend([mixPlugin])
|
||||
|
||||
@@ -26,7 +26,7 @@ themes.set(FALLBACK_THEME, new Map())
|
||||
// Collect all real themes
|
||||
json.collections
|
||||
.find((collection) => {
|
||||
return collection.name === 'Color Theming'
|
||||
return collection.name === "Color Theming"
|
||||
})
|
||||
?.modes.forEach((mode) => {
|
||||
themes.set(mode.name, new Map())
|
||||
@@ -42,7 +42,7 @@ const responsiveTokens = new Set()
|
||||
|
||||
// Collect responsive tokens
|
||||
json.collections
|
||||
.find((collection) => collection.name === 'Responsive')
|
||||
.find((collection) => collection.name === "Responsive")
|
||||
?.modes.forEach((mode) => {
|
||||
mode.variables.forEach((variable) => {
|
||||
responsiveTokens.add(variable.name)
|
||||
@@ -60,23 +60,23 @@ json.collections.forEach((collection) => {
|
||||
const tokenTheme = getThemeForToken(token, mode, themes)
|
||||
|
||||
switch (variable.type) {
|
||||
case 'boolean':
|
||||
if (typeof variable.value === 'boolean') {
|
||||
case "boolean":
|
||||
if (typeof variable.value === "boolean") {
|
||||
// Handle text transform
|
||||
if (/text transform/i.test(variable.name)) {
|
||||
token = variable.name.replace(
|
||||
/text transform/i,
|
||||
'Text-Transform'
|
||||
"Text-Transform"
|
||||
)
|
||||
value = variable.value ? 'uppercase' : 'none'
|
||||
value = variable.value ? "uppercase" : "none"
|
||||
}
|
||||
// Handle text decoration
|
||||
else if (/text decoration/i.test(variable.name)) {
|
||||
token = variable.name.replace(
|
||||
/text decoration/i,
|
||||
'Text-Decoration'
|
||||
"Text-Decoration"
|
||||
)
|
||||
value = variable.value ? 'underline' : 'none'
|
||||
value = variable.value ? "underline" : "none"
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
@@ -84,8 +84,8 @@ json.collections.forEach((collection) => {
|
||||
)
|
||||
}
|
||||
break
|
||||
case 'number':
|
||||
if (typeof variable.value === 'number') {
|
||||
case "number":
|
||||
if (typeof variable.value === "number") {
|
||||
// Only use two decimals for all numbers
|
||||
value = Number(variable.value.toFixed(2))
|
||||
} else {
|
||||
@@ -96,7 +96,7 @@ json.collections.forEach((collection) => {
|
||||
break
|
||||
}
|
||||
|
||||
if (typeof value === 'string' || typeof value === 'number') {
|
||||
if (typeof value === "string" || typeof value === "number") {
|
||||
const theme = themes.get(tokenTheme)
|
||||
if (theme) {
|
||||
theme.set(token, {
|
||||
@@ -125,11 +125,11 @@ json.collections.forEach((collection) => {
|
||||
const tokenTheme = getThemeForToken(token, mode, themes)
|
||||
|
||||
switch (variable.type) {
|
||||
case 'color':
|
||||
case 'string':
|
||||
case 'number':
|
||||
case "color":
|
||||
case "string":
|
||||
case "number":
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -139,13 +139,13 @@ json.collections.forEach((collection) => {
|
||||
value = `Impl-${value}`
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
if (typeof value === "string") {
|
||||
const theme = themes.get(tokenTheme)
|
||||
if (theme) {
|
||||
theme.set(token, {
|
||||
// We can only resolve aliases after we have collected all
|
||||
// primitives and aliases.
|
||||
resolved: '',
|
||||
resolved: "",
|
||||
alias: value,
|
||||
})
|
||||
}
|
||||
@@ -165,8 +165,8 @@ json.collections.forEach((collection) => {
|
||||
json.collections.forEach((collection) => {
|
||||
collection.modes.forEach((mode) => {
|
||||
mode.variables.forEach((variable) => {
|
||||
if (variable.type === 'effect') {
|
||||
if (typeof variable.value === 'object' && 'effects' in variable.value) {
|
||||
if (variable.type === "effect") {
|
||||
if (typeof variable.value === "object" && "effects" in variable.value) {
|
||||
if (variable.value.effects.length > 1) {
|
||||
console.warn(
|
||||
`Unsupported effect declaration with multiple effects.`,
|
||||
@@ -176,7 +176,7 @@ json.collections.forEach((collection) => {
|
||||
// We only support one effect declaration per variable
|
||||
const effect = variable.value.effects[0]
|
||||
switch (effect.type) {
|
||||
case 'DROP_SHADOW': {
|
||||
case "DROP_SHADOW": {
|
||||
const { r, g, b, a } = effect.color
|
||||
const { x, y } = effect.offset
|
||||
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
|
||||
const variablesJsOutput = [
|
||||
'/* This file is generated, do not edit manually! */',
|
||||
"/* This file is generated, do not edit manually! */",
|
||||
]
|
||||
themes.forEach((themeTokenValues, themeKey) => {
|
||||
const cssContentPrimitives: string[] = []
|
||||
@@ -255,12 +255,12 @@ themes.forEach((themeTokenValues, themeKey) => {
|
||||
` --${outputToken}: var(--${kebabify(outputValue.toString())});`
|
||||
)
|
||||
} else {
|
||||
if (typeof outputValue === 'string') {
|
||||
if (typeof outputValue === "string") {
|
||||
// Check for properties that need quotes
|
||||
if (/font(-| )family/gi.test(token)) {
|
||||
outputValue = `"${outputValue}"`
|
||||
}
|
||||
} else if (typeof outputValue === 'number') {
|
||||
} else if (typeof outputValue === "number") {
|
||||
// font-weight is unitless
|
||||
if (!/font(-| )weight/gi.test(token)) {
|
||||
outputValue = `${outputValue}px`
|
||||
@@ -278,25 +278,25 @@ themes.forEach((themeTokenValues, themeKey) => {
|
||||
const filename = kebabify(themeKey).toLowerCase()
|
||||
|
||||
const cssOutput = [
|
||||
'/* This file is generated, do not edit manually! */',
|
||||
"/* This file is generated, do not edit manually! */",
|
||||
// The base styles target the :root.
|
||||
// All themes require the use of their scoping classname to be used.
|
||||
themeKey === FALLBACK_THEME ? ':root {' : `.${filename} {`,
|
||||
' /* Values */',
|
||||
themeKey === FALLBACK_THEME ? ":root {" : `.${filename} {`,
|
||||
" /* Values */",
|
||||
...cssContentPrimitives.sort(),
|
||||
'',
|
||||
' /* Aliases */',
|
||||
"",
|
||||
" /* Aliases */",
|
||||
...cssContentAliases.sort(),
|
||||
'}',
|
||||
'', // New line at end of file
|
||||
"}",
|
||||
"", // New line at end of file
|
||||
]
|
||||
|
||||
fs.writeFileSync(`../lib/styles/${filename}.css`, cssOutput.join('\n'), {
|
||||
encoding: 'utf-8',
|
||||
fs.writeFileSync(`../lib/styles/${filename}.css`, cssOutput.join("\n"), {
|
||||
encoding: "utf-8",
|
||||
})
|
||||
|
||||
const resolvedJsOutput = [
|
||||
'/* This file is generated, do not edit manually! */',
|
||||
"/* This file is generated, do not edit manually! */",
|
||||
`export const theme = ${JSON.stringify(
|
||||
Array.from(themeTokenValues).reduce(
|
||||
(acc, [token, value]) => {
|
||||
@@ -313,9 +313,9 @@ themes.forEach((themeTokenValues, themeKey) => {
|
||||
]
|
||||
fs.writeFileSync(
|
||||
`../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.
|
||||
variablesJsOutput.push(
|
||||
`export const ${themeKey
|
||||
.split(' ')
|
||||
.split(" ")
|
||||
.map((v, i) => (i === 0 ? v.toLowerCase() : v))
|
||||
.join(
|
||||
''
|
||||
""
|
||||
)} = ${JSON.stringify(Object.fromEntries(themeTokenValues.entries()))} as const`
|
||||
)
|
||||
})
|
||||
|
||||
fs.writeFileSync(`../lib/tokens/index.ts`, variablesJsOutput.join('\n'), {
|
||||
encoding: 'utf-8',
|
||||
fs.writeFileSync(`../lib/tokens/index.ts`, variablesJsOutput.join("\n"), {
|
||||
encoding: "utf-8",
|
||||
})
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
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 }) {
|
||||
if (mode.name === 'Style') {
|
||||
if (mode.name === "Style") {
|
||||
// Ignore Figma Styles, we only want to process variables.
|
||||
// But the exported variables.json includes Figma Styles too.
|
||||
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.
|
||||
export const FALLBACK_THEME = 'base'
|
||||
export const FALLBACK_THEME = "base"
|
||||
|
||||
// The variables exported from Figma are not grouped by theme.
|
||||
// We used this function to help us group by theme.
|
||||
@@ -24,10 +24,10 @@ export function getThemeForToken(
|
||||
themes: Map<string, unknown>
|
||||
) {
|
||||
// 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) => {
|
||||
// Match against "theme/", use that if it matches
|
||||
if (compare.indexOf(theme + '/') >= 0) {
|
||||
if (compare.indexOf(theme + "/") >= 0) {
|
||||
return theme
|
||||
}
|
||||
|
||||
|
||||
@@ -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 AccordionItem from './AccordionItem/index'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { IconName } from '../Icons/iconName'
|
||||
import { Typography } from '../Typography'
|
||||
import Accordion from "./index"
|
||||
import AccordionItem from "./AccordionItem/index"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import { IconName } from "../Icons/iconName"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
const meta: Meta<typeof Accordion> = {
|
||||
title: 'Core Components/Accordion',
|
||||
title: "Core Components/Accordion",
|
||||
component: Accordion,
|
||||
argTypes: {
|
||||
type: {
|
||||
control: 'select',
|
||||
options: ['card', 'sidepeek', 'inline'],
|
||||
control: "select",
|
||||
options: ["card", "sidepeek", "inline"],
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -23,7 +23,7 @@ type Story = StoryObj<typeof Accordion>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
type: 'card',
|
||||
type: "card",
|
||||
},
|
||||
render: (args) => (
|
||||
<Accordion {...args}>
|
||||
@@ -60,7 +60,7 @@ export const Default: Story = {
|
||||
|
||||
export const WithIcons: Story = {
|
||||
args: {
|
||||
type: 'card',
|
||||
type: "card",
|
||||
},
|
||||
render: (args) => (
|
||||
<Accordion {...args}>
|
||||
@@ -106,7 +106,7 @@ export const WithIcons: Story = {
|
||||
|
||||
export const WithSubtitle: Story = {
|
||||
args: {
|
||||
type: 'card',
|
||||
type: "card",
|
||||
},
|
||||
render: (args) => (
|
||||
<Accordion {...args}>
|
||||
@@ -140,7 +140,7 @@ export const WithSubtitle: Story = {
|
||||
|
||||
export const Inline: Story = {
|
||||
args: {
|
||||
type: 'inline',
|
||||
type: "inline",
|
||||
},
|
||||
render: () => (
|
||||
<Accordion type="inline">
|
||||
|
||||
@@ -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 { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { IconByIconName } from "../../Icons/IconByIconName"
|
||||
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 { IconName } from '../../Icons/iconName'
|
||||
import { Typography } from '../../Typography'
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { IconName } from "../../Icons/iconName"
|
||||
import { Typography } from "../../Typography"
|
||||
|
||||
export interface AccordionItemProps
|
||||
extends React.HtmlHTMLAttributes<HTMLDetailsElement>,
|
||||
extends
|
||||
React.HtmlHTMLAttributes<HTMLDetailsElement>,
|
||||
VariantProps<typeof accordionItemVariants> {
|
||||
title: string
|
||||
titleLevel?: 'span' | 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
||||
titleLevel?: "span" | "p" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
|
||||
iconName?: IconName
|
||||
icon?: ReactNode
|
||||
subtitle?: string
|
||||
@@ -31,7 +32,7 @@ export default function AccordionItem({
|
||||
icon,
|
||||
iconName,
|
||||
title,
|
||||
titleLevel = 'p',
|
||||
titleLevel = "p",
|
||||
type,
|
||||
className,
|
||||
subtitle,
|
||||
@@ -59,17 +60,17 @@ export default function AccordionItem({
|
||||
if (details.open) {
|
||||
content.style.maxHeight = `${content.scrollHeight}px`
|
||||
content.addEventListener(
|
||||
'transitionend',
|
||||
"transitionend",
|
||||
() => {
|
||||
// Remove maxHeight after transition to allow content to transition multiple times
|
||||
content.style.maxHeight = 'none'
|
||||
content.style.maxHeight = "none"
|
||||
},
|
||||
{ once: true }
|
||||
)
|
||||
|
||||
onOpen?.()
|
||||
} else {
|
||||
content.style.maxHeight = '0'
|
||||
content.style.maxHeight = "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,11 +90,11 @@ export default function AccordionItem({
|
||||
<details ref={detailsRef} onToggle={toggleAccordion}>
|
||||
<summary className={styles.summary}>
|
||||
{IconComp}
|
||||
{type === 'sidepeek' ? (
|
||||
{type === "sidepeek" ? (
|
||||
<Typography variant="Title/Subtitle/md">
|
||||
<p className={styles.title}>{title}</p>
|
||||
</Typography>
|
||||
) : type === 'inline' ? (
|
||||
) : type === "inline" ? (
|
||||
<Typography variant="Body/Supporting text (caption)/smBold">
|
||||
<p className={styles.title}>{title}</p>
|
||||
</Typography>
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -11,6 +11,6 @@ export const accordionItemVariants = cva(styles.accordionItem, {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: 'card',
|
||||
type: "card",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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 { accordionVariants } from './variants'
|
||||
import type { AccordionItemProps } from "./AccordionItem"
|
||||
import { accordionVariants } from "./variants"
|
||||
|
||||
interface AccordionProps
|
||||
extends React.HtmlHTMLAttributes<HTMLUListElement>,
|
||||
extends
|
||||
React.HtmlHTMLAttributes<HTMLUListElement>,
|
||||
VariantProps<typeof accordionVariants> {}
|
||||
|
||||
export default function Accordion({
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -11,6 +11,6 @@ export const accordionVariants = cva(styles.accordion, {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: 'card',
|
||||
type: "card",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { Alert } from './index'
|
||||
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert'
|
||||
import { expect, fn } from 'storybook/test'
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
import { Alert } from "./index"
|
||||
import { AlertTypeEnum } from "@scandic-hotels/common/constants/alert"
|
||||
import { expect, fn } from "storybook/test"
|
||||
|
||||
const meta: Meta<typeof Alert> = {
|
||||
title: 'Core Components/Alert',
|
||||
title: "Core Components/Alert",
|
||||
component: Alert,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
layout: "centered",
|
||||
},
|
||||
tags: ['autodocs'],
|
||||
tags: ["autodocs"],
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: ['banner', 'inline'],
|
||||
control: { type: "select" },
|
||||
options: ["banner", "inline"],
|
||||
},
|
||||
type: {
|
||||
control: { type: 'select' },
|
||||
control: { type: "select" },
|
||||
options: Object.values(AlertTypeEnum),
|
||||
},
|
||||
close: {
|
||||
@@ -32,43 +32,43 @@ type Story = StoryObj<typeof meta>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
variant: "inline",
|
||||
type: AlertTypeEnum.Info,
|
||||
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.',
|
||||
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.",
|
||||
close: undefined,
|
||||
ariaRole: 'alert',
|
||||
ariaRole: "alert",
|
||||
},
|
||||
play: async ({ canvas }) => {
|
||||
canvas.findByRole('alert')
|
||||
canvas.findByRole("alert")
|
||||
},
|
||||
}
|
||||
|
||||
export const Closable: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
variant: "inline",
|
||||
type: AlertTypeEnum.Info,
|
||||
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.',
|
||||
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.",
|
||||
close: fn(),
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.close).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
|
||||
export const WithPhonenumber: Story = {
|
||||
args: {
|
||||
variant: 'inline',
|
||||
variant: "inline",
|
||||
type: AlertTypeEnum.Info,
|
||||
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.',
|
||||
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.",
|
||||
close: fn(),
|
||||
phoneContact: {
|
||||
displayText: 'Call us:',
|
||||
phoneNumber: '+4685551234',
|
||||
footnote: 'Available 24/7',
|
||||
displayText: "Call us:",
|
||||
phoneNumber: "+4685551234",
|
||||
footnote: "Available 24/7",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useState } from "react"
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import { Button } from '../../Button'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import { JsonToHtml } from '../../JsonToHtml/JsonToHtml'
|
||||
import SidePeek from '../../SidePeek'
|
||||
import { Button } from "../../Button"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import { JsonToHtml } from "../../JsonToHtml/JsonToHtml"
|
||||
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({
|
||||
ctaText,
|
||||
@@ -37,8 +37,8 @@ export default function AlertSidepeek({
|
||||
isOpen={sidePeekIsOpen}
|
||||
handleClose={() => setSidePeekIsOpen(false)}
|
||||
closeLabel={intl.formatMessage({
|
||||
id: 'common.close',
|
||||
defaultMessage: 'Close',
|
||||
id: "common.close",
|
||||
defaultMessage: "Close",
|
||||
})}
|
||||
>
|
||||
<JsonToHtml
|
||||
|
||||
@@ -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 {
|
||||
ctaText: string
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type {
|
||||
AlertTypeEnum,
|
||||
SidepeekContent,
|
||||
} from '@scandic-hotels/common/constants/alert'
|
||||
import type { VariantProps } from 'class-variance-authority'
|
||||
import type { AriaRole } from 'react'
|
||||
} from "@scandic-hotels/common/constants/alert"
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { AriaRole } from "react"
|
||||
|
||||
import type { alertVariants } from './variants'
|
||||
import type { alertVariants } from "./variants"
|
||||
|
||||
export interface AlertProps extends VariantProps<typeof alertVariants> {
|
||||
className?: string
|
||||
@@ -26,5 +26,5 @@ export interface AlertProps extends VariantProps<typeof alertVariants> {
|
||||
} | null
|
||||
close?: () => void
|
||||
ariaRole?: AriaRole
|
||||
ariaLive?: 'off' | 'assertive' | 'polite'
|
||||
ariaLive?: "off" | "assertive" | "polite"
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
'use client'
|
||||
"use client"
|
||||
|
||||
import { Button } from '../Button'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import Link from '../OldDSLink'
|
||||
import { Typography } from '../Typography'
|
||||
import { Button } from "../Button"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import Link from "../OldDSLink"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
import AlertSidepeek from './Sidepeek'
|
||||
import { IconByAlertType } from './utils'
|
||||
import { alertVariants } from './variants'
|
||||
import AlertSidepeek from "./Sidepeek"
|
||||
import { IconByAlertType } from "./utils"
|
||||
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({
|
||||
className,
|
||||
@@ -61,7 +61,7 @@ export function Alert({
|
||||
<>
|
||||
<span> {phoneContact.displayText} </span>
|
||||
<Link
|
||||
href={`tel:${phoneContact.phoneNumber.replace(/ /g, '')}`}
|
||||
href={`tel:${phoneContact.phoneNumber.replace(/ /g, "")}`}
|
||||
>
|
||||
{phoneContact.phoneNumber}
|
||||
</Link>
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import {
|
||||
MaterialIcon,
|
||||
type MaterialIconSetIconProps,
|
||||
} from '../Icons/MaterialIcon'
|
||||
import { AlertTypeEnum } from '@scandic-hotels/common/constants/alert'
|
||||
} from "../Icons/MaterialIcon"
|
||||
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 {
|
||||
alertType: AlertTypeEnum
|
||||
variant?: AlertProps['variant']
|
||||
variant?: AlertProps["variant"]
|
||||
}
|
||||
|
||||
export function IconByAlertType({
|
||||
alertType,
|
||||
variant = 'inline',
|
||||
variant = "inline",
|
||||
...props
|
||||
}: IconByAlertProps & MaterialIconSetIconProps): JSX.Element {
|
||||
switch (alertType) {
|
||||
case AlertTypeEnum.Alarm:
|
||||
return (
|
||||
<MaterialIcon
|
||||
color={variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Error'}
|
||||
color={variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Error"}
|
||||
isFilled
|
||||
icon="error"
|
||||
{...props}
|
||||
@@ -33,7 +33,7 @@ export function IconByAlertType({
|
||||
<MaterialIcon
|
||||
icon="warning"
|
||||
color={
|
||||
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Warning'
|
||||
variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Warning"
|
||||
}
|
||||
isFilled
|
||||
{...props}
|
||||
@@ -44,7 +44,7 @@ export function IconByAlertType({
|
||||
<MaterialIcon
|
||||
icon="check_circle"
|
||||
color={
|
||||
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Success'
|
||||
variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Success"
|
||||
}
|
||||
isFilled
|
||||
{...props}
|
||||
@@ -55,7 +55,7 @@ export function IconByAlertType({
|
||||
return (
|
||||
<MaterialIcon
|
||||
color={
|
||||
variant === 'inline' ? 'Icon/Inverted' : 'Icon/Feedback/Information'
|
||||
variant === "inline" ? "Icon/Inverted" : "Icon/Feedback/Information"
|
||||
}
|
||||
isFilled
|
||||
icon="info"
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -18,7 +18,7 @@ export const alertVariants = cva(styles.alert, {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'inline',
|
||||
variant: "inline",
|
||||
type: AlertTypeEnum.Info,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
|
||||
import { Avatar } from '.'
|
||||
import { config } from './variants'
|
||||
import { Avatar } from "."
|
||||
import { config } from "./variants"
|
||||
|
||||
const meta: Meta<typeof Avatar> = {
|
||||
title: 'Core Components/Avatar',
|
||||
title: "Core Components/Avatar",
|
||||
component: Avatar,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
layout: "centered",
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
control: { type: "select" },
|
||||
options: Object.keys(config.variants.size),
|
||||
},
|
||||
},
|
||||
@@ -20,31 +20,31 @@ const meta: Meta<typeof Avatar> = {
|
||||
export default meta
|
||||
|
||||
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 = {
|
||||
args: {
|
||||
src: imageFile,
|
||||
alt: 'Profile photo',
|
||||
size: 'md',
|
||||
alt: "Profile photo",
|
||||
size: "md",
|
||||
},
|
||||
}
|
||||
|
||||
export const WithInitials: Story = {
|
||||
args: {
|
||||
initials: 'FR',
|
||||
size: 'md',
|
||||
initials: "FR",
|
||||
size: "md",
|
||||
},
|
||||
}
|
||||
|
||||
export const Fallback: Story = {
|
||||
args: {
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
}
|
||||
|
||||
export const SmallSize: Story = {
|
||||
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 initials="FR" size="sm" />
|
||||
<Avatar size="sm" />
|
||||
@@ -54,7 +54,7 @@ export const SmallSize: Story = {
|
||||
|
||||
export const MediumSize: Story = {
|
||||
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 initials="FR" size="md" />
|
||||
<Avatar size="md" />
|
||||
@@ -64,7 +64,7 @@ export const MediumSize: Story = {
|
||||
|
||||
export const LargeSize: Story = {
|
||||
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 initials="FR" size="lg" />
|
||||
<Avatar size="lg" />
|
||||
@@ -74,39 +74,39 @@ export const LargeSize: Story = {
|
||||
|
||||
export const AllSizes: Story = {
|
||||
render: () => (
|
||||
<div style={{ display: 'flex', gap: '24px', alignItems: 'center' }}>
|
||||
<div style={{ display: "flex", gap: "24px", alignItems: "center" }}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '8px',
|
||||
alignItems: 'center',
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Avatar initials="FR" size="sm" />
|
||||
<span style={{ fontSize: '12px' }}>Small (20px)</span>
|
||||
<span style={{ fontSize: "12px" }}>Small (20px)</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '8px',
|
||||
alignItems: 'center',
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Avatar initials="FR" size="md" />
|
||||
<span style={{ fontSize: '12px' }}>Medium (32px)</span>
|
||||
<span style={{ fontSize: "12px" }}>Medium (32px)</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '8px',
|
||||
alignItems: 'center',
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Avatar initials="FR" size="lg" />
|
||||
<span style={{ fontSize: '12px' }}>Large (55px)</span>
|
||||
<span style={{ fontSize: "12px" }}>Large (55px)</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
import Image from '../Image'
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import { Typography } from "../Typography"
|
||||
import Image from "../Image"
|
||||
|
||||
import { variants } from './variants'
|
||||
import type { AvatarProps } from './types'
|
||||
import { variants } from "./variants"
|
||||
import type { AvatarProps } from "./types"
|
||||
|
||||
export function Avatar({
|
||||
src,
|
||||
alt,
|
||||
initials,
|
||||
size = 'md',
|
||||
size = "md",
|
||||
className,
|
||||
}: AvatarProps) {
|
||||
const classNames = variants({ size, className })
|
||||
const pixelSize = size === 'sm' ? 24 : size === 'md' ? 32 : 55
|
||||
const iconSize = size === 'sm' ? 16 : 24
|
||||
const pixelSize = size === "sm" ? 24 : size === "md" ? 32 : 55
|
||||
const iconSize = size === "sm" ? 16 : 24
|
||||
|
||||
return (
|
||||
<div className={classNames}>
|
||||
{src ? (
|
||||
<Image src={src} alt={alt || ''} width={pixelSize} height={pixelSize} />
|
||||
<Image src={src} alt={alt || ""} width={pixelSize} height={pixelSize} />
|
||||
) : initials ? (
|
||||
<Typography
|
||||
variant={size === 'lg' ? 'Title/Overline/sm' : 'Tag/sm'}
|
||||
variant={size === "lg" ? "Title/Overline/sm" : "Tag/sm"}
|
||||
className={variants.initials}
|
||||
>
|
||||
<span data-hj-suppress>{initials}</span>
|
||||
|
||||
@@ -15,7 +15,7 @@ export interface AvatarProps {
|
||||
* Size of the avatar
|
||||
* @default 'md'
|
||||
*/
|
||||
size?: 'sm' | 'md' | 'lg'
|
||||
size?: "sm" | "md" | "lg"
|
||||
/**
|
||||
* Additional CSS class names
|
||||
*/
|
||||
|
||||
@@ -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 = {
|
||||
variants: {
|
||||
size: {
|
||||
sm: styles['size-sm'],
|
||||
md: styles['size-md'],
|
||||
lg: styles['size-lg'],
|
||||
sm: styles["size-sm"],
|
||||
md: styles["size-md"],
|
||||
lg: styles["size-lg"],
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
} as const
|
||||
|
||||
|
||||
@@ -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 { config as backToTopButtonConfig } from './variants'
|
||||
import { BackToTopButton } from "."
|
||||
import { config as backToTopButtonConfig } from "./variants"
|
||||
|
||||
const meta: Meta<typeof BackToTopButton> = {
|
||||
title: 'Patterns/BackToTopButton',
|
||||
title: "Patterns/BackToTopButton",
|
||||
component: BackToTopButton,
|
||||
argTypes: {
|
||||
onPress: {
|
||||
@@ -15,13 +15,13 @@ const meta: Meta<typeof BackToTopButton> = {
|
||||
},
|
||||
},
|
||||
position: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: Object.keys(backToTopButtonConfig.variants.position),
|
||||
table: {
|
||||
type: {
|
||||
summary: 'string',
|
||||
summary: "string",
|
||||
detail: Object.keys(backToTopButtonConfig.variants.position).join(
|
||||
' | '
|
||||
" | "
|
||||
),
|
||||
},
|
||||
defaultValue: {
|
||||
@@ -30,7 +30,7 @@ const meta: Meta<typeof BackToTopButton> = {
|
||||
},
|
||||
},
|
||||
label: {
|
||||
control: 'text',
|
||||
control: "text",
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -40,16 +40,16 @@ export default meta
|
||||
type Story = StoryObj<typeof BackToTopButton>
|
||||
|
||||
const globalStoryPropsInverted = {
|
||||
backgrounds: { value: 'scandicPrimaryDark' },
|
||||
backgrounds: { value: "scandicPrimaryDark" },
|
||||
}
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onPress: fn(),
|
||||
label: 'Back to top',
|
||||
label: "Back to top",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -57,10 +57,10 @@ export const Default: Story = {
|
||||
export const PositionLeft: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
position: 'left',
|
||||
position: "left",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -68,10 +68,10 @@ export const PositionLeft: Story = {
|
||||
export const PositionCenter: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
position: 'center',
|
||||
position: "center",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -79,10 +79,10 @@ export const PositionCenter: Story = {
|
||||
export const PositionRight: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
position: 'right',
|
||||
position: "right",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -91,10 +91,10 @@ export const OnDarkBackground: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
onPress: fn(),
|
||||
label: 'Back to top',
|
||||
label: "Back to top",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
/* 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 */
|
||||
&::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -4px;
|
||||
border: 2px solid var(--Border-Inverted);
|
||||
|
||||
@@ -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 { Typography } from '../Typography'
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
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 { ComponentProps } from 'react'
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { ComponentProps } from "react"
|
||||
|
||||
interface BackToTopButtonProps
|
||||
extends ComponentProps<typeof ButtonRAC>,
|
||||
VariantProps<typeof variants> {
|
||||
extends ComponentProps<typeof ButtonRAC>, VariantProps<typeof variants> {
|
||||
label: string
|
||||
}
|
||||
|
||||
|
||||
@@ -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 = {
|
||||
variants: {
|
||||
@@ -11,7 +11,7 @@ export const config = {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
position: 'right',
|
||||
position: "right",
|
||||
},
|
||||
} as const
|
||||
|
||||
|
||||
@@ -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> = {
|
||||
title: 'Core Components/Badge',
|
||||
title: "Core Components/Badge",
|
||||
component: Badge,
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ export const Default: Story = {}
|
||||
|
||||
export const XS: Story = {
|
||||
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="green" size="20" />
|
||||
</div>
|
||||
@@ -24,7 +24,7 @@ export const XS: Story = {
|
||||
|
||||
export const Small: Story = {
|
||||
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="green" size="24" />
|
||||
</div>
|
||||
@@ -32,7 +32,7 @@ export const Small: Story = {
|
||||
}
|
||||
export const Medium: Story = {
|
||||
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="green" size="28" />
|
||||
</div>
|
||||
@@ -40,7 +40,7 @@ export const Medium: Story = {
|
||||
}
|
||||
export const Large: Story = {
|
||||
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="green" size="32" />
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@ export const Large: Story = {
|
||||
|
||||
export const XL: Story = {
|
||||
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="green" size="36" />
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { config } from './variants'
|
||||
import { config } from "./variants"
|
||||
|
||||
import { VariantProps } from 'class-variance-authority'
|
||||
import { Typography } from '../Typography'
|
||||
import { TypographyProps } from '../Typography/types'
|
||||
import { VariantProps } from "class-variance-authority"
|
||||
import { Typography } from "../Typography"
|
||||
import { TypographyProps } from "../Typography/types"
|
||||
|
||||
interface BadgeProps extends VariantProps<typeof config> {
|
||||
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) {
|
||||
case '36':
|
||||
case '32':
|
||||
return 'Body/Paragraph/mdBold'
|
||||
case '28':
|
||||
case '24':
|
||||
return 'Body/Supporting text (caption)/smBold'
|
||||
case '20':
|
||||
return 'Label/xsRegular'
|
||||
case "36":
|
||||
case "32":
|
||||
return "Body/Paragraph/mdBold"
|
||||
case "28":
|
||||
case "24":
|
||||
return "Body/Supporting text (caption)/smBold"
|
||||
case "20":
|
||||
return "Label/xsRegular"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { Badge } from './Badge'
|
||||
export { Badge } from "./Badge"
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -9,15 +9,15 @@ export const config = cva(styles.badge, {
|
||||
green: styles.green,
|
||||
},
|
||||
size: {
|
||||
'36': styles._36,
|
||||
'32': styles._32,
|
||||
'28': styles._28,
|
||||
'24': styles._24,
|
||||
'20': styles._20,
|
||||
"36": styles._36,
|
||||
"32": styles._32,
|
||||
"28": styles._28,
|
||||
"24": styles._24,
|
||||
"20": styles._20,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
color: 'primary',
|
||||
size: '28',
|
||||
color: "primary",
|
||||
size: "28",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { fn } from 'storybook/test'
|
||||
import { BookingCodeChip } from './index'
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
import { fn } from "storybook/test"
|
||||
import { BookingCodeChip } from "./index"
|
||||
|
||||
const meta = {
|
||||
title: 'Product Components/BookingCodeChip',
|
||||
title: "Product Components/BookingCodeChip",
|
||||
component: BookingCodeChip,
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
layout: "centered",
|
||||
},
|
||||
} satisfies Meta<typeof BookingCodeChip>
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { useIntl } from 'react-intl'
|
||||
import { useIntl } from "react-intl"
|
||||
|
||||
import IconChip from '../IconChip'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import FilledDiscountIcon from '../Icons/Nucleo/Benefits/FilledDiscount'
|
||||
import { Typography } from '../Typography'
|
||||
import IconChip from "../IconChip"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import FilledDiscountIcon from "../Icons/Nucleo/Benefits/FilledDiscount"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
import { cx } from 'class-variance-authority'
|
||||
import { IconButton } from '../IconButton'
|
||||
import styles from './bookingCodeChip.module.css'
|
||||
import { cx } from "class-variance-authority"
|
||||
import { IconButton } from "../IconButton"
|
||||
import styles from "./bookingCodeChip.module.css"
|
||||
|
||||
type BaseBookingCodeChipProps = {
|
||||
alignCenter?: boolean
|
||||
@@ -47,11 +47,11 @@ export function BookingCodeChip({
|
||||
return null
|
||||
}
|
||||
|
||||
const color = isCampaignRate ? 'green' : 'blue'
|
||||
const color = isCampaignRate ? "green" : "blue"
|
||||
|
||||
const iconColor = isCampaignRate
|
||||
? 'Icon/Feedback/Success'
|
||||
: 'Icon/Feedback/Information'
|
||||
? "Icon/Feedback/Success"
|
||||
: "Icon/Feedback/Information"
|
||||
|
||||
const isUnavailableRate = isCampaignRate
|
||||
? isCampaignUnavailable
|
||||
@@ -59,12 +59,12 @@ export function BookingCodeChip({
|
||||
|
||||
const label = isCampaignRate
|
||||
? intl.formatMessage({
|
||||
id: 'booking.campaign',
|
||||
defaultMessage: 'Campaign',
|
||||
id: "booking.campaign",
|
||||
defaultMessage: "Campaign",
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: 'booking.bookingCode',
|
||||
defaultMessage: 'Booking code',
|
||||
id: "booking.bookingCode",
|
||||
defaultMessage: "Booking code",
|
||||
})
|
||||
|
||||
const icon = isCampaignRate ? (
|
||||
@@ -107,8 +107,8 @@ export function BookingCodeChip({
|
||||
className={styles.removeButton}
|
||||
onPress={onClose}
|
||||
aria-label={intl.formatMessage({
|
||||
id: 'booking.removeBookingCode',
|
||||
defaultMessage: 'Remove booking code',
|
||||
id: "booking.removeBookingCode",
|
||||
defaultMessage: "Remove booking code",
|
||||
})}
|
||||
iconName="close"
|
||||
/>
|
||||
|
||||
@@ -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 { buttonIconNames } from './types'
|
||||
import { config as buttonConfig } from './variants'
|
||||
import { Button } from "./Button"
|
||||
import { buttonIconNames } from "./types"
|
||||
import { config as buttonConfig } from "./variants"
|
||||
|
||||
const meta: Meta<typeof Button> = {
|
||||
title: 'Core Components/Button',
|
||||
title: "Core Components/Button",
|
||||
component: Button,
|
||||
argTypes: {
|
||||
onPress: {
|
||||
table: {
|
||||
type: { summary: 'function' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
type: { summary: "function" },
|
||||
defaultValue: { summary: "undefined" },
|
||||
},
|
||||
description: 'Callback function to handle button press events.',
|
||||
description: "Callback function to handle button press events.",
|
||||
},
|
||||
variant: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: Object.keys(buttonConfig.variants.variant),
|
||||
default: 'Primary',
|
||||
default: "Primary",
|
||||
table: {
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.variant,
|
||||
},
|
||||
type: {
|
||||
summary: Object.keys(buttonConfig.variants.variant).join(' | '),
|
||||
summary: Object.keys(buttonConfig.variants.variant).join(" | "),
|
||||
},
|
||||
},
|
||||
},
|
||||
color: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: Object.keys(buttonConfig.variants.color),
|
||||
table: {
|
||||
type: {
|
||||
summary: Object.keys(buttonConfig.variants.color).join(' | '),
|
||||
summary: Object.keys(buttonConfig.variants.color).join(" | "),
|
||||
},
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.color,
|
||||
@@ -43,11 +43,11 @@ const meta: Meta<typeof Button> = {
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: Object.keys(buttonConfig.variants.size),
|
||||
table: {
|
||||
type: {
|
||||
summary: Object.keys(buttonConfig.variants.size).join(' | '),
|
||||
summary: Object.keys(buttonConfig.variants.size).join(" | "),
|
||||
},
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.size,
|
||||
@@ -55,63 +55,63 @@ const meta: Meta<typeof Button> = {
|
||||
},
|
||||
},
|
||||
wrapping: {
|
||||
control: 'boolean',
|
||||
control: "boolean",
|
||||
options: Object.keys(buttonConfig.variants.wrapping),
|
||||
type: 'boolean',
|
||||
type: "boolean",
|
||||
table: {
|
||||
defaultValue: {
|
||||
summary: buttonConfig.defaultVariants.wrapping.toString(),
|
||||
},
|
||||
},
|
||||
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: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: buttonIconNames,
|
||||
table: {
|
||||
type: { summary: buttonIconNames.join(' | ') },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
type: { summary: buttonIconNames.join(" | ") },
|
||||
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: {
|
||||
control: 'select',
|
||||
control: "select",
|
||||
options: buttonIconNames,
|
||||
table: {
|
||||
type: { summary: buttonIconNames.join(' | ') },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
type: { summary: buttonIconNames.join(" | ") },
|
||||
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: {
|
||||
control: 'boolean',
|
||||
control: "boolean",
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
type: { summary: "boolean" },
|
||||
defaultValue: { summary: "false" },
|
||||
},
|
||||
},
|
||||
isPending: {
|
||||
control: 'boolean',
|
||||
control: "boolean",
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
type: { summary: "boolean" },
|
||||
defaultValue: { summary: "false" },
|
||||
},
|
||||
},
|
||||
fullWidth: {
|
||||
control: 'boolean',
|
||||
control: "boolean",
|
||||
table: {
|
||||
type: { summary: 'boolean' },
|
||||
defaultValue: { summary: 'false' },
|
||||
type: { summary: "boolean" },
|
||||
defaultValue: { summary: "false" },
|
||||
},
|
||||
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 = {
|
||||
backgrounds: { value: 'scandicPrimaryDark' },
|
||||
backgrounds: { value: "scandicPrimaryDark" },
|
||||
}
|
||||
export default meta
|
||||
|
||||
@@ -120,10 +120,10 @@ type Story = StoryObj<typeof Button>
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onPress: fn(),
|
||||
children: 'Button',
|
||||
children: "Button",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -131,11 +131,11 @@ export const Default: Story = {
|
||||
export const PrimaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'lg',
|
||||
variant: "Primary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -143,10 +143,10 @@ export const PrimaryLarge: Story = {
|
||||
export const PrimaryMedium: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -154,10 +154,10 @@ export const PrimaryMedium: Story = {
|
||||
export const PrimarySmall: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -169,7 +169,7 @@ export const PrimaryDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -181,7 +181,7 @@ export const PrimaryLoading: Story = {
|
||||
onPress: fn(), // Fresh spy instance for loading test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -192,7 +192,7 @@ export const PrimaryOnDarkBackground: Story = {
|
||||
...PrimaryLarge.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)
|
||||
},
|
||||
}
|
||||
@@ -201,11 +201,11 @@ export const PrimaryInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
size: 'lg',
|
||||
color: 'Inverted',
|
||||
size: "lg",
|
||||
color: "Inverted",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -214,10 +214,10 @@ export const PrimaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -226,10 +226,10 @@ export const PrimaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -242,7 +242,7 @@ export const PrimaryInvertedDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -255,7 +255,7 @@ export const PrimaryInvertedLoading: Story = {
|
||||
onPress: fn(), // Fresh spy instance for loading test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -263,11 +263,11 @@ export const PrimaryInvertedLoading: Story = {
|
||||
export const SecondaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
size: 'lg',
|
||||
variant: "Secondary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -275,10 +275,10 @@ export const SecondaryLarge: Story = {
|
||||
export const SecondaryMedium: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -286,10 +286,10 @@ export const SecondaryMedium: Story = {
|
||||
export const SecondarySmall: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -301,7 +301,7 @@ export const SecondaryDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -313,7 +313,7 @@ export const SecondaryLoading: Story = {
|
||||
onPress: fn(), // Fresh spy instance for loading test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -322,12 +322,12 @@ export const SecondaryInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
color: 'Inverted',
|
||||
size: 'lg',
|
||||
variant: "Secondary",
|
||||
color: "Inverted",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -336,10 +336,10 @@ export const SecondaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -348,10 +348,10 @@ export const SecondaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -364,7 +364,7 @@ export const SecondaryInvertedDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -377,7 +377,7 @@ export const SecondaryInvertedLoading: Story = {
|
||||
onPress: fn(), // Fresh spy instance for loading test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -385,11 +385,11 @@ export const SecondaryInvertedLoading: Story = {
|
||||
export const TertiaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Tertiary',
|
||||
size: 'lg',
|
||||
variant: "Tertiary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -397,10 +397,10 @@ export const TertiaryLarge: Story = {
|
||||
export const TertiaryMedium: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -408,10 +408,10 @@ export const TertiaryMedium: Story = {
|
||||
export const TertiarySmall: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -423,7 +423,7 @@ export const TertiaryDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -435,7 +435,7 @@ export const TertiaryLoading: Story = {
|
||||
onPress: fn(), // Fresh spy instance for loading test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -443,11 +443,11 @@ export const TertiaryLoading: Story = {
|
||||
export const TextLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
size: 'lg',
|
||||
variant: "Text",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -455,11 +455,11 @@ export const TextLarge: Story = {
|
||||
export const TextMedium: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -467,11 +467,11 @@ export const TextMedium: Story = {
|
||||
export const TextSmall: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -483,7 +483,7 @@ export const TextDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -494,7 +494,7 @@ export const TextNoWrapping: Story = {
|
||||
wrapping: false,
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -503,12 +503,12 @@ export const TextInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
color: 'Inverted',
|
||||
size: 'lg',
|
||||
variant: "Text",
|
||||
color: "Inverted",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -517,10 +517,10 @@ export const TextInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -529,10 +529,10 @@ export const TextInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(1)
|
||||
},
|
||||
}
|
||||
@@ -545,7 +545,7 @@ export const TextInvertedDisabled: Story = {
|
||||
onPress: fn(), // Fresh spy instance for disabled test
|
||||
},
|
||||
play: async ({ canvas, userEvent, args }) => {
|
||||
await userEvent.click(await canvas.findByRole('button'))
|
||||
await userEvent.click(await canvas.findByRole("button"))
|
||||
expect(args.onPress).toHaveBeenCalledTimes(0)
|
||||
},
|
||||
}
|
||||
@@ -553,15 +553,15 @@ export const TextInvertedDisabled: Story = {
|
||||
export const TextWithIcon: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
children: 'Text with icon',
|
||||
trailingIconName: 'chevron_right',
|
||||
children: "Text with icon",
|
||||
trailingIconName: "chevron_right",
|
||||
},
|
||||
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(canvas.getByText('Text with icon')).toBeDefined()
|
||||
expect(canvas.getByTestId('MaterialIcon')).toBeDefined()
|
||||
expect(canvas.getByText("Text with icon")).toBeDefined()
|
||||
expect(canvas.getByTestId("MaterialIcon")).toBeDefined()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -569,13 +569,13 @@ export const TextWithIconInverted: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextWithIcon.args,
|
||||
color: 'Inverted',
|
||||
color: "Inverted",
|
||||
},
|
||||
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(canvas.getByText('Text with icon')).toBeDefined()
|
||||
expect(canvas.getByTestId('MaterialIcon')).toBeDefined()
|
||||
expect(canvas.getByText("Text with icon")).toBeDefined()
|
||||
expect(canvas.getByTestId("MaterialIcon")).toBeDefined()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Button as ButtonRAC } from 'react-aria-components'
|
||||
import { Loading } from '../Loading/Loading'
|
||||
import { Button as ButtonRAC } from "react-aria-components"
|
||||
import { Loading } from "../Loading/Loading"
|
||||
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
import type { ButtonProps } from './types'
|
||||
import { variants } from './variants'
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import { Typography } from "../Typography"
|
||||
import type { ButtonProps } from "./types"
|
||||
import { variants } from "./variants"
|
||||
|
||||
export function Button({
|
||||
variant,
|
||||
@@ -30,9 +30,9 @@ export function Button({
|
||||
return (
|
||||
<Typography
|
||||
variant={
|
||||
size === 'sm'
|
||||
? 'Body/Supporting text (caption)/smBold'
|
||||
: 'Body/Paragraph/mdBold'
|
||||
size === "sm"
|
||||
? "Body/Supporting text (caption)/smBold"
|
||||
: "Body/Paragraph/mdBold"
|
||||
}
|
||||
>
|
||||
<ButtonRAC {...props} className={classNames}>
|
||||
@@ -43,7 +43,7 @@ export function Button({
|
||||
<MaterialIcon
|
||||
icon={leadingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
size={size === "sm" ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{children}
|
||||
@@ -51,11 +51,11 @@ export function Button({
|
||||
<MaterialIcon
|
||||
icon={trailingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
size={size === "sm" ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{isPending ? (
|
||||
<Loading size={size === 'sm' ? 18 : 20} type="CurrentColor" />
|
||||
<Loading size={size === "sm" ? 18 : 20} type="CurrentColor" />
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
outline-offset: 2px;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -4px;
|
||||
border: 2px solid var(--Border-Inverted);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export { Button } from './Button'
|
||||
export { type ButtonProps } from './types'
|
||||
export { Button } from "./Button"
|
||||
export { type ButtonProps } from "./types"
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export { variants as buttonVariants, withButton } from './variants'
|
||||
export { variants as buttonVariants, withButton } from "./variants"
|
||||
|
||||
@@ -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 { ComponentProps } from 'react'
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { ComponentProps } from "react"
|
||||
|
||||
import type { SymbolCodepoints } from '../Icons/MaterialIcon/MaterialSymbol/types'
|
||||
import type { variants } from './variants'
|
||||
import type { SymbolCodepoints } from "../Icons/MaterialIcon/MaterialSymbol/types"
|
||||
import type { variants } from "./variants"
|
||||
|
||||
export const buttonIconNames = [
|
||||
'add_circle',
|
||||
'open_in_new',
|
||||
'keyboard_arrow_down',
|
||||
'keyboard_arrow_up',
|
||||
'edit_square',
|
||||
'location_on',
|
||||
'link',
|
||||
'mail',
|
||||
'cancel',
|
||||
'calendar_month',
|
||||
'calendar_clock',
|
||||
'edit_calendar',
|
||||
'calendar_add_on',
|
||||
'delete',
|
||||
'chevron_right',
|
||||
'chevron_left',
|
||||
"add_circle",
|
||||
"open_in_new",
|
||||
"keyboard_arrow_down",
|
||||
"keyboard_arrow_up",
|
||||
"edit_square",
|
||||
"location_on",
|
||||
"link",
|
||||
"mail",
|
||||
"cancel",
|
||||
"calendar_month",
|
||||
"calendar_clock",
|
||||
"edit_calendar",
|
||||
"calendar_add_on",
|
||||
"delete",
|
||||
"chevron_right",
|
||||
"chevron_left",
|
||||
] as const
|
||||
|
||||
export type ButtonIconName = Extract<
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import { deepmerge } from 'deepmerge-ts'
|
||||
import styles from './button.module.css'
|
||||
import { deepmerge } from "deepmerge-ts"
|
||||
import styles from "./button.module.css"
|
||||
|
||||
export const config = {
|
||||
variants: {
|
||||
variant: {
|
||||
Primary: styles['variant-primary'],
|
||||
Secondary: styles['variant-secondary'],
|
||||
Tertiary: styles['variant-tertiary'],
|
||||
Text: styles['variant-text'],
|
||||
Primary: styles["variant-primary"],
|
||||
Secondary: styles["variant-secondary"],
|
||||
Tertiary: styles["variant-tertiary"],
|
||||
Text: styles["variant-text"],
|
||||
},
|
||||
color: {
|
||||
Primary: styles['color-primary'],
|
||||
Inverted: styles['color-inverted'],
|
||||
Primary: styles["color-primary"],
|
||||
Inverted: styles["color-inverted"],
|
||||
},
|
||||
size: {
|
||||
sm: styles['size-sm'],
|
||||
md: styles['size-md'],
|
||||
lg: styles['size-lg'],
|
||||
sm: styles["size-sm"],
|
||||
md: styles["size-md"],
|
||||
lg: styles["size-lg"],
|
||||
},
|
||||
wrapping: {
|
||||
true: undefined,
|
||||
false: styles['no-wrapping'],
|
||||
false: styles["no-wrapping"],
|
||||
},
|
||||
fullWidth: {
|
||||
true: styles['full-width'],
|
||||
true: styles["full-width"],
|
||||
false: undefined,
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'Primary',
|
||||
color: 'Primary',
|
||||
size: 'lg',
|
||||
variant: "Primary",
|
||||
color: "Primary",
|
||||
size: "lg",
|
||||
wrapping: true,
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -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 buttonMeta from '../Button/Button.stories'
|
||||
import ButtonLink from "."
|
||||
import buttonMeta from "../Button/Button.stories"
|
||||
|
||||
const meta: Meta<typeof ButtonLink> = {
|
||||
title: 'Core Components/ButtonLink',
|
||||
title: "Core Components/ButtonLink",
|
||||
component: ButtonLink,
|
||||
argTypes: {
|
||||
onClick: {
|
||||
table: {
|
||||
type: { summary: 'function' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
type: { summary: "function" },
|
||||
defaultValue: { summary: "undefined" },
|
||||
},
|
||||
description: 'Callback function to handle link click events.',
|
||||
description: "Callback function to handle link click events.",
|
||||
},
|
||||
variant: buttonMeta.argTypes?.variant,
|
||||
color: buttonMeta.argTypes?.color,
|
||||
@@ -25,16 +25,16 @@ const meta: Meta<typeof ButtonLink> = {
|
||||
fullWidth: buttonMeta.argTypes?.fullWidth,
|
||||
href: {
|
||||
table: {
|
||||
type: { summary: 'string' },
|
||||
defaultValue: { summary: 'undefined' },
|
||||
type: { summary: "string" },
|
||||
defaultValue: { summary: "undefined" },
|
||||
},
|
||||
description: 'The URL that the link points to.',
|
||||
description: "The URL that the link points to.",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const globalStoryPropsInverted = {
|
||||
backgrounds: { value: 'scandicPrimaryDark' },
|
||||
backgrounds: { value: "scandicPrimaryDark" },
|
||||
}
|
||||
export default meta
|
||||
|
||||
@@ -43,12 +43,12 @@ type Story = StoryObj<typeof ButtonLink>
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
onClick: fn(),
|
||||
href: '#',
|
||||
children: 'Button link',
|
||||
href: "#",
|
||||
children: "Button link",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -56,12 +56,12 @@ export const Default: Story = {
|
||||
export const PrimaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'lg',
|
||||
variant: "Primary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -69,11 +69,11 @@ export const PrimaryLarge: Story = {
|
||||
export const PrimaryMedium: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -81,11 +81,11 @@ export const PrimaryMedium: Story = {
|
||||
export const PrimarySmall: Story = {
|
||||
args: {
|
||||
...PrimaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -94,12 +94,12 @@ export const PrimaryOnDarkBackground: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
size: 'lg',
|
||||
variant: "Primary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -108,14 +108,14 @@ export const PrimaryInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Primary',
|
||||
color: 'Inverted',
|
||||
size: 'lg',
|
||||
variant: "Primary",
|
||||
color: "Inverted",
|
||||
size: "lg",
|
||||
},
|
||||
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -124,11 +124,11 @@ export const PrimaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -137,11 +137,11 @@ export const PrimaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...PrimaryInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -149,12 +149,12 @@ export const PrimaryInvertedSmall: Story = {
|
||||
export const SecondaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
size: 'lg',
|
||||
variant: "Secondary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -162,11 +162,11 @@ export const SecondaryLarge: Story = {
|
||||
export const SecondaryMedium: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -174,11 +174,11 @@ export const SecondaryMedium: Story = {
|
||||
export const SecondarySmall: Story = {
|
||||
args: {
|
||||
...SecondaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -187,13 +187,13 @@ export const SecondaryInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Secondary',
|
||||
color: 'Inverted',
|
||||
size: 'lg',
|
||||
variant: "Secondary",
|
||||
color: "Inverted",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -202,11 +202,11 @@ export const SecondaryInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -215,11 +215,11 @@ export const SecondaryInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...SecondaryInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -227,12 +227,12 @@ export const SecondaryInvertedSmall: Story = {
|
||||
export const TertiaryLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Tertiary',
|
||||
size: 'lg',
|
||||
variant: "Tertiary",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -240,11 +240,11 @@ export const TertiaryLarge: Story = {
|
||||
export const TertiaryMedium: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -252,11 +252,11 @@ export const TertiaryMedium: Story = {
|
||||
export const TertiarySmall: Story = {
|
||||
args: {
|
||||
...TertiaryLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -264,12 +264,12 @@ export const TertiarySmall: Story = {
|
||||
export const TextLarge: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
size: 'lg',
|
||||
variant: "Text",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -277,11 +277,11 @@ export const TextLarge: Story = {
|
||||
export const TextMedium: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -289,11 +289,11 @@ export const TextMedium: Story = {
|
||||
export const TextSmall: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -301,12 +301,12 @@ export const TextSmall: Story = {
|
||||
export const TextNoWrapping: Story = {
|
||||
args: {
|
||||
...TextLarge.args,
|
||||
children: 'Text button with wrapping false',
|
||||
children: "Text button with wrapping false",
|
||||
wrapping: false,
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -315,13 +315,13 @@ export const TextInvertedLarge: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
color: 'Inverted',
|
||||
size: 'lg',
|
||||
variant: "Text",
|
||||
color: "Inverted",
|
||||
size: "lg",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -330,11 +330,11 @@ export const TextInvertedMedium: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'md',
|
||||
size: "md",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -343,11 +343,11 @@ export const TextInvertedSmall: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextInvertedLarge.args,
|
||||
size: 'sm',
|
||||
size: "sm",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -355,13 +355,13 @@ export const TextInvertedSmall: Story = {
|
||||
export const TextWithIcon: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
variant: 'Text',
|
||||
children: 'Text with icon',
|
||||
trailingIconName: 'chevron_right',
|
||||
variant: "Text",
|
||||
children: "Text with icon",
|
||||
trailingIconName: "chevron_right",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
@@ -370,11 +370,11 @@ export const TextWithIconInverted: Story = {
|
||||
globals: globalStoryPropsInverted,
|
||||
args: {
|
||||
...TextWithIcon.args,
|
||||
color: 'Inverted',
|
||||
color: "Inverted",
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const link = canvasElement.querySelector('a')
|
||||
if (!link) throw new Error('Link not found')
|
||||
const link = canvasElement.querySelector("a")
|
||||
if (!link) throw new Error("Link not found")
|
||||
expect(link).toBeInTheDocument()
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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 Link from 'next/link'
|
||||
import { useIntl } from 'react-intl'
|
||||
import { ButtonIconName } from '../Button/types'
|
||||
import { MaterialIcon } from '../Icons/MaterialIcon'
|
||||
import { Typography } from '../Typography'
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import Link from "next/link"
|
||||
import { useIntl } from "react-intl"
|
||||
import { ButtonIconName } from "../Button/types"
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
export interface ButtonLinkProps
|
||||
extends
|
||||
Omit<ComponentProps<typeof Link>, 'color'>,
|
||||
Omit<ComponentProps<typeof Link>, "color">,
|
||||
VariantProps<typeof variants> {
|
||||
leadingIconName?: ButtonIconName | null
|
||||
trailingIconName?: ButtonIconName | null
|
||||
@@ -44,30 +44,30 @@ export default function ButtonLink({
|
||||
|
||||
const intl = useIntl()
|
||||
const newTabText = intl.formatMessage({
|
||||
id: 'common.linkOpenInNewTab',
|
||||
defaultMessage: 'Opens in a new tab/window',
|
||||
id: "common.linkOpenInNewTab",
|
||||
defaultMessage: "Opens in a new tab/window",
|
||||
})
|
||||
|
||||
return (
|
||||
<Typography
|
||||
variant={
|
||||
size === 'sm'
|
||||
? 'Body/Supporting text (caption)/smBold'
|
||||
: 'Body/Paragraph/mdBold'
|
||||
size === "sm"
|
||||
? "Body/Supporting text (caption)/smBold"
|
||||
: "Body/Paragraph/mdBold"
|
||||
}
|
||||
>
|
||||
<Link
|
||||
className={classNames}
|
||||
href={href}
|
||||
target={target}
|
||||
title={target === '_blank' ? newTabText : ''}
|
||||
title={target === "_blank" ? newTabText : ""}
|
||||
{...props}
|
||||
>
|
||||
{leadingIconName ? (
|
||||
<MaterialIcon
|
||||
icon={leadingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
size={size === "sm" ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
{children}
|
||||
@@ -75,7 +75,7 @@ export default function ButtonLink({
|
||||
<MaterialIcon
|
||||
icon={trailingIconName}
|
||||
color="CurrentColor"
|
||||
size={size === 'sm' ? 20 : 24}
|
||||
size={size === "sm" ? 20 : 24}
|
||||
/>
|
||||
) : null}
|
||||
</Link>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import { withButton } from '../Button'
|
||||
import buttonStyles from '../Button/button.module.css'
|
||||
import { withButton } from "../Button"
|
||||
import buttonStyles from "../Button/button.module.css"
|
||||
|
||||
export const variants = cva([buttonStyles.button], withButton({}))
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
|
||||
import { captionVariants, fontOnlycaptionVariants } from './variants'
|
||||
import { VariantProps } from 'class-variance-authority'
|
||||
import { captionVariants, fontOnlycaptionVariants } from "./variants"
|
||||
import { VariantProps } from "class-variance-authority"
|
||||
|
||||
interface CaptionProps
|
||||
extends Omit<React.HTMLAttributes<HTMLHeadingElement>, 'color'>,
|
||||
extends
|
||||
Omit<React.HTMLAttributes<HTMLHeadingElement>, "color">,
|
||||
VariantProps<typeof captionVariants> {
|
||||
asChild?: boolean
|
||||
fontOnly?: boolean
|
||||
@@ -15,7 +16,7 @@ interface CaptionProps
|
||||
*/
|
||||
export default function Caption({
|
||||
asChild = false,
|
||||
className = '',
|
||||
className = "",
|
||||
color,
|
||||
fontOnly = false,
|
||||
textAlign,
|
||||
@@ -25,7 +26,7 @@ export default function Caption({
|
||||
type,
|
||||
...props
|
||||
}: CaptionProps) {
|
||||
const Comp = asChild ? Slot : 'p'
|
||||
const Comp = asChild ? Slot : "p"
|
||||
const classNames = fontOnly
|
||||
? fontOnlycaptionVariants({
|
||||
className,
|
||||
|
||||
@@ -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 = {
|
||||
variants: {
|
||||
@@ -44,8 +44,8 @@ const config = {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
color: 'black',
|
||||
type: 'regular',
|
||||
color: "black",
|
||||
type: "regular",
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -70,7 +70,7 @@ const fontOnlyConfig = {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
type: 'regular',
|
||||
type: "regular",
|
||||
},
|
||||
} as const
|
||||
|
||||
|
||||
@@ -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> = {
|
||||
title: 'Core Components/Card',
|
||||
title: "Core Components/Card",
|
||||
component: Card,
|
||||
}
|
||||
|
||||
@@ -13,13 +13,13 @@ type Story = StoryObj<typeof Card>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
as: 'Default',
|
||||
as: "Default",
|
||||
},
|
||||
}
|
||||
|
||||
export const Featured: Story = {
|
||||
args: {
|
||||
...Default.args,
|
||||
as: 'Featured',
|
||||
as: "Featured",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
const classNames = variants({
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { fn } from 'storybook/test'
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
import { fn } from "storybook/test"
|
||||
|
||||
import { themes } from '../../../../.storybook/preview'
|
||||
import { themes } from "../../../../.storybook/preview"
|
||||
|
||||
import { Card } from '../'
|
||||
import { Button } from '../../Button'
|
||||
import { Typography } from '../../Typography'
|
||||
import { Card } from "../"
|
||||
import { Button } from "../../Button"
|
||||
import { Typography } from "../../Typography"
|
||||
|
||||
type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & {
|
||||
_onPrimaryPress?: () => void
|
||||
@@ -18,18 +18,18 @@ type CompositionProps = React.ComponentPropsWithoutRef<typeof Card> & {
|
||||
}
|
||||
|
||||
const meta: Meta<CompositionProps> = {
|
||||
title: 'Compositions/Card',
|
||||
title: "Compositions/Card",
|
||||
component: Card,
|
||||
decorators: [
|
||||
(Story, context) => {
|
||||
if (context.name.toLowerCase().indexOf('all themes') >= 0) {
|
||||
if (context.name.toLowerCase().indexOf("all themes") >= 0) {
|
||||
return (
|
||||
<>
|
||||
<h1>{context.name}</h1>
|
||||
{Object.entries(themes.themes).map(([key, value], ix) => {
|
||||
return (
|
||||
<div key={ix} className={value} style={{ padding: '1em 0' }}>
|
||||
<h2 style={{ paddingBottom: '0.5em' }}>{key}</h2>
|
||||
<div key={ix} className={value} style={{ padding: "1em 0" }}>
|
||||
<h2 style={{ paddingBottom: "0.5em" }}>{key}</h2>
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
@@ -39,7 +39,7 @@ const meta: Meta<CompositionProps> = {
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex' }}>
|
||||
<div style={{ display: "flex" }}>
|
||||
<Story />
|
||||
</div>
|
||||
)
|
||||
@@ -47,19 +47,19 @@ const meta: Meta<CompositionProps> = {
|
||||
],
|
||||
argTypes: {
|
||||
inMainArea: {
|
||||
name: 'Is in main area',
|
||||
name: "Is in main area",
|
||||
},
|
||||
showTitle: {
|
||||
name: 'Composition: Show title',
|
||||
name: "Composition: Show title",
|
||||
},
|
||||
showPreamble: {
|
||||
name: 'Composition: Show preamble',
|
||||
name: "Composition: Show preamble",
|
||||
},
|
||||
showPrimaryButton: {
|
||||
name: 'Composition: Show primary button',
|
||||
name: "Composition: Show primary button",
|
||||
},
|
||||
showSecondaryButton: {
|
||||
name: 'Composition: Show secondary button',
|
||||
name: "Composition: Show secondary button",
|
||||
},
|
||||
_onPrimaryPress: {
|
||||
table: {
|
||||
@@ -110,7 +110,7 @@ const meta: Meta<CompositionProps> = {
|
||||
|
||||
{showSecondaryButton && (
|
||||
<Button
|
||||
size={inMainArea ? 'lg' : 'sm'}
|
||||
size={inMainArea ? "lg" : "sm"}
|
||||
variant="Secondary"
|
||||
onPress={args._onSecondaryPress}
|
||||
>
|
||||
@@ -127,7 +127,7 @@ type Story = StoryObj<CompositionProps>
|
||||
|
||||
export const ContentCardMainArea: Story = {
|
||||
args: {
|
||||
as: 'Default',
|
||||
as: "Default",
|
||||
inMainArea: true,
|
||||
showTitle: true,
|
||||
showPreamble: true,
|
||||
@@ -140,7 +140,7 @@ export const ContentCardMainArea: Story = {
|
||||
|
||||
export const ContentCardNonMainArea: Story = {
|
||||
args: {
|
||||
as: 'Default',
|
||||
as: "Default",
|
||||
inMainArea: false,
|
||||
showTitle: true,
|
||||
showPreamble: true,
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { Card } from './Card'
|
||||
export { Card } from "./Card"
|
||||
|
||||
@@ -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
|
||||
extends React.HTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof variants> {
|
||||
extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof variants> {
|
||||
as: CardStyles
|
||||
}
|
||||
|
||||
@@ -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 = {
|
||||
variants: {
|
||||
@@ -10,7 +10,7 @@ const config = {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
as: 'Default',
|
||||
as: "Default",
|
||||
},
|
||||
} as const
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { VariantProps } from 'class-variance-authority'
|
||||
import { chipVariants } from './variants'
|
||||
import Footnote from '../Footnote'
|
||||
import { VariantProps } from "class-variance-authority"
|
||||
import { chipVariants } from "./variants"
|
||||
import Footnote from "../Footnote"
|
||||
|
||||
export interface ChipProps
|
||||
extends React.HtmlHTMLAttributes<HTMLDivElement>,
|
||||
extends
|
||||
React.HtmlHTMLAttributes<HTMLDivElement>,
|
||||
VariantProps<typeof chipVariants> {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -17,7 +17,7 @@ export const chipVariants = cva(styles.chip, {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: 'medium',
|
||||
variant: 'default',
|
||||
size: "medium",
|
||||
variant: "default",
|
||||
},
|
||||
})
|
||||
|
||||
@@ -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 { ChipButton } from './ChipButton.tsx'
|
||||
import { config as chipButtonConfig } from './variants'
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon/MaterialIcon.tsx"
|
||||
import { ChipButton } from "./ChipButton.tsx"
|
||||
import { config as chipButtonConfig } from "./variants"
|
||||
|
||||
const meta: Meta<typeof ChipButton> = {
|
||||
title: 'Core Components/ChipButton',
|
||||
title: "Core Components/ChipButton",
|
||||
component: ChipButton,
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: 'select',
|
||||
type: 'string',
|
||||
control: "select",
|
||||
type: "string",
|
||||
options: Object.keys(chipButtonConfig.variants.variant),
|
||||
},
|
||||
onPress: {
|
||||
@@ -41,7 +41,7 @@ export const Default: Story = {
|
||||
|
||||
export const Outlined: Story = {
|
||||
args: {
|
||||
variant: 'Outlined',
|
||||
variant: "Outlined",
|
||||
onPress: fn(),
|
||||
children: (
|
||||
<>
|
||||
@@ -54,9 +54,9 @@ export const Outlined: Story = {
|
||||
|
||||
export const FilterRoundedLarge: Story = {
|
||||
args: {
|
||||
variant: 'FilterRounded',
|
||||
variant: "FilterRounded",
|
||||
onPress: fn(),
|
||||
size: 'Large',
|
||||
size: "Large",
|
||||
children: (
|
||||
<>
|
||||
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
|
||||
@@ -68,9 +68,9 @@ export const FilterRoundedLarge: Story = {
|
||||
|
||||
export const FilterRoundedLargeSelected: Story = {
|
||||
args: {
|
||||
variant: 'FilterRounded',
|
||||
variant: "FilterRounded",
|
||||
onPress: fn(),
|
||||
size: 'Large',
|
||||
size: "Large",
|
||||
selected: true,
|
||||
children: (
|
||||
<>
|
||||
@@ -83,9 +83,9 @@ export const FilterRoundedLargeSelected: Story = {
|
||||
|
||||
export const FilterRoundedMedium: Story = {
|
||||
args: {
|
||||
variant: 'FilterRounded',
|
||||
variant: "FilterRounded",
|
||||
onPress: fn(),
|
||||
size: 'Medium',
|
||||
size: "Medium",
|
||||
children: (
|
||||
<>
|
||||
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
|
||||
@@ -97,9 +97,9 @@ export const FilterRoundedMedium: Story = {
|
||||
|
||||
export const FilterRoundedMediumSelected: Story = {
|
||||
args: {
|
||||
variant: 'FilterRounded',
|
||||
variant: "FilterRounded",
|
||||
onPress: fn(),
|
||||
size: 'Medium',
|
||||
size: "Medium",
|
||||
selected: true,
|
||||
children: (
|
||||
<>
|
||||
|
||||
@@ -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 { variants } from './variants'
|
||||
import { ChipButtonProps } from "./types"
|
||||
import { variants } from "./variants"
|
||||
|
||||
export function ChipButton({
|
||||
children,
|
||||
variant,
|
||||
selected = false,
|
||||
size = 'Large',
|
||||
size = "Large",
|
||||
className,
|
||||
...props
|
||||
}: ChipButtonProps) {
|
||||
@@ -18,7 +18,7 @@ export function ChipButton({
|
||||
})
|
||||
|
||||
return (
|
||||
<ButtonRAC {...props} className={[className, classNames].join(' ')}>
|
||||
<ButtonRAC {...props} className={[className, classNames].join(" ")}>
|
||||
{children}
|
||||
</ButtonRAC>
|
||||
)
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { ChipButton } from './ChipButton'
|
||||
export { ChipButton } from "./ChipButton"
|
||||
|
||||
@@ -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 { ComponentProps } from 'react'
|
||||
import type { VariantProps } from "class-variance-authority"
|
||||
import type { ComponentProps } from "react"
|
||||
|
||||
import type { variants } from './variants'
|
||||
import type { variants } from "./variants"
|
||||
|
||||
export interface ChipButtonProps
|
||||
extends ComponentProps<typeof Button>,
|
||||
VariantProps<typeof variants> {}
|
||||
extends ComponentProps<typeof Button>, VariantProps<typeof variants> {}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
import { cva } from 'class-variance-authority'
|
||||
import { cva } from "class-variance-authority"
|
||||
|
||||
import { deepmerge } from 'deepmerge-ts'
|
||||
import styles from './chip-button.module.css'
|
||||
import { config as typographyConfig } from '../Typography/variants'
|
||||
import { deepmerge } from "deepmerge-ts"
|
||||
import styles from "./chip-button.module.css"
|
||||
import { config as typographyConfig } from "../Typography/variants"
|
||||
|
||||
const variantKeys = {
|
||||
variant: {
|
||||
Default: 'Default',
|
||||
Outlined: 'Outlined',
|
||||
FilterRounded: 'FilterRounded',
|
||||
Default: "Default",
|
||||
Outlined: "Outlined",
|
||||
FilterRounded: "FilterRounded",
|
||||
},
|
||||
style: {
|
||||
Medium: 'Medium',
|
||||
Large: 'Large',
|
||||
Medium: "Medium",
|
||||
Large: "Large",
|
||||
},
|
||||
typography: {
|
||||
Bold: 'Body/Supporting text (caption)/smBold',
|
||||
Regular: 'Body/Supporting text (caption)/smRegular',
|
||||
Bold: "Body/Supporting text (caption)/smBold",
|
||||
Regular: "Body/Supporting text (caption)/smRegular",
|
||||
},
|
||||
} as const
|
||||
|
||||
@@ -28,12 +28,12 @@ export const config = {
|
||||
[variantKeys.variant.FilterRounded]: styles.FilterRounded,
|
||||
},
|
||||
selected: {
|
||||
true: '',
|
||||
false: '',
|
||||
true: "",
|
||||
false: "",
|
||||
},
|
||||
size: {
|
||||
[variantKeys.style.Medium]: '',
|
||||
[variantKeys.style.Large]: '',
|
||||
[variantKeys.style.Medium]: "",
|
||||
[variantKeys.style.Large]: "",
|
||||
},
|
||||
},
|
||||
compoundVariants: [
|
||||
@@ -41,7 +41,7 @@ export const config = {
|
||||
variant: variantKeys.variant.Default,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smBold'
|
||||
"Body/Supporting text (caption)/smBold"
|
||||
],
|
||||
],
|
||||
},
|
||||
@@ -49,7 +49,7 @@ export const config = {
|
||||
variant: variantKeys.variant.Outlined,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smBold'
|
||||
"Body/Supporting text (caption)/smBold"
|
||||
],
|
||||
],
|
||||
},
|
||||
@@ -59,7 +59,7 @@ export const config = {
|
||||
selected: true,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smRegular'
|
||||
"Body/Supporting text (caption)/smRegular"
|
||||
],
|
||||
styles.selected,
|
||||
styles.medium,
|
||||
@@ -71,7 +71,7 @@ export const config = {
|
||||
selected: false,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smRegular'
|
||||
"Body/Supporting text (caption)/smRegular"
|
||||
],
|
||||
styles.medium,
|
||||
],
|
||||
@@ -82,7 +82,7 @@ export const config = {
|
||||
selected: true,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smRegular'
|
||||
"Body/Supporting text (caption)/smRegular"
|
||||
],
|
||||
styles.selected,
|
||||
styles.large,
|
||||
@@ -94,7 +94,7 @@ export const config = {
|
||||
selected: false,
|
||||
className: [
|
||||
typographyConfig.variants.variant[
|
||||
'Body/Supporting text (caption)/smRegular'
|
||||
"Body/Supporting text (caption)/smRegular"
|
||||
],
|
||||
styles.large,
|
||||
],
|
||||
|
||||
@@ -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 { ChipLink } from './ChipLink.tsx'
|
||||
import { MaterialIcon } from "../Icons/MaterialIcon"
|
||||
import { ChipLink } from "./ChipLink.tsx"
|
||||
|
||||
const meta: Meta<typeof ChipLink> = {
|
||||
title: 'Core Components/ChipLink',
|
||||
title: "Core Components/ChipLink",
|
||||
component: ChipLink,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ type Story = StoryObj<typeof ChipLink>
|
||||
|
||||
export const Default: Story = {
|
||||
args: {
|
||||
href: '/',
|
||||
href: "/",
|
||||
onPress: (e) => console.log(e),
|
||||
children: (
|
||||
<>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { cx } from 'class-variance-authority'
|
||||
import { Typography } from '../Typography'
|
||||
import { cx } from "class-variance-authority"
|
||||
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 {
|
||||
Link as LinkRAC,
|
||||
LinkProps as LinkRACProps,
|
||||
} from 'react-aria-components'
|
||||
} from "react-aria-components"
|
||||
|
||||
export function ChipLink({
|
||||
children,
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { ChipLink } from './ChipLink'
|
||||
export { ChipLink } from "./ChipLink"
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import type { Meta, StoryObj } from '@storybook/nextjs-vite'
|
||||
import { fn } from 'storybook/test'
|
||||
import type { Meta, StoryObj } from "@storybook/nextjs-vite"
|
||||
import { fn } from "storybook/test"
|
||||
|
||||
import { Chips } from './Chips.tsx'
|
||||
import { ChipLink } from '../ChipLink/ChipLink.tsx'
|
||||
import { ChipButton } from '../ChipButton/ChipButton.tsx'
|
||||
import { Chips } from "./Chips.tsx"
|
||||
import { ChipLink } from "../ChipLink/ChipLink.tsx"
|
||||
import { ChipButton } from "../ChipButton/ChipButton.tsx"
|
||||
|
||||
import { Default as ChipLinkDefault } from '../ChipLink/ChipLink.stories.tsx'
|
||||
import { Default as ChipButtonDefault } from '../ChipButton/ChipButton.stories.tsx'
|
||||
import { Default as ChipLinkDefault } from "../ChipLink/ChipLink.stories.tsx"
|
||||
import { Default as ChipButtonDefault } from "../ChipButton/ChipButton.stories.tsx"
|
||||
|
||||
type StoryProps = React.ComponentPropsWithoutRef<typeof Chips> & {
|
||||
onPress: () => void
|
||||
}
|
||||
|
||||
const meta: Meta<StoryProps> = {
|
||||
title: 'Compositions/Chips',
|
||||
title: "Compositions/Chips",
|
||||
component: Chips,
|
||||
argTypes: {
|
||||
onPress: {
|
||||
|
||||
@@ -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) {
|
||||
return <div className={styles.chips}>{children}</div>
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { Chips } from './Chips'
|
||||
export { Chips } from "./Chips"
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
display: flex;
|
||||
}
|
||||
|
||||
div[data-rac][data-open='true'] .chevron {
|
||||
div[data-rac][data-open="true"] .chevron {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { IconProps } from '../../Icons'
|
||||
import { MaterialIcon } from '../../Icons/MaterialIcon'
|
||||
import styles from './chevron.module.css'
|
||||
import { IconProps } from "../../Icons"
|
||||
import { MaterialIcon } from "../../Icons/MaterialIcon"
|
||||
import styles from "./chevron.module.css"
|
||||
|
||||
export default function SelectChevron(props: IconProps) {
|
||||
return (
|
||||
<span aria-hidden="true" className={styles.chevron}>
|
||||
<MaterialIcon
|
||||
icon="keyboard_arrow_down"
|
||||
color={props.color ?? 'Icon/Default'}
|
||||
color={props.color ?? "Icon/Default"}
|
||||
size={20}
|
||||
/>
|
||||
</span>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import { ReactElement, useState } from 'react'
|
||||
"use client"
|
||||
import { ReactElement, useState } from "react"
|
||||
import {
|
||||
Button,
|
||||
type Key,
|
||||
@@ -8,17 +8,17 @@ import {
|
||||
Popover,
|
||||
Select as ReactAriaSelect,
|
||||
SelectValue,
|
||||
} from 'react-aria-components'
|
||||
} from "react-aria-components"
|
||||
|
||||
import SelectChevron from './SelectChevron'
|
||||
import SelectChevron from "./SelectChevron"
|
||||
|
||||
import styles from './select.module.css'
|
||||
import { InputLabel } from '../InputLabel'
|
||||
import { Typography } from '../Typography'
|
||||
import styles from "./select.module.css"
|
||||
import { InputLabel } from "../InputLabel"
|
||||
import { Typography } from "../Typography"
|
||||
|
||||
interface SelectProps extends Omit<
|
||||
React.SelectHTMLAttributes<HTMLSelectElement>,
|
||||
'onSelect'
|
||||
"onSelect"
|
||||
> {
|
||||
defaultSelectedKey?: Key
|
||||
items: { label: string; value: Key }[]
|
||||
@@ -37,14 +37,14 @@ interface SelectProps extends Omit<
|
||||
type SelectPortalContainer = HTMLDivElement | undefined
|
||||
type SelectPortalContainerArgs = HTMLDivElement | null
|
||||
|
||||
const DELIMITER = ':'
|
||||
const DELIMITER = ":"
|
||||
|
||||
/**
|
||||
* @deprecated Do not use.
|
||||
*/
|
||||
export default function Select({
|
||||
className = '',
|
||||
'aria-label': ariaLabel,
|
||||
className = "",
|
||||
"aria-label": ariaLabel,
|
||||
defaultSelectedKey,
|
||||
items,
|
||||
label,
|
||||
@@ -78,16 +78,16 @@ export default function Select({
|
||||
let chevronProps = {}
|
||||
|
||||
if (discreet) {
|
||||
chevronProps = { color: 'baseButtonTextOnFillNormal' }
|
||||
chevronProps = { color: "baseButtonTextOnFillNormal" }
|
||||
} else if (disabled) {
|
||||
chevronProps = { color: 'disabled' }
|
||||
chevronProps = { color: "disabled" }
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`${styles.container} ${className}`} ref={setRef}>
|
||||
<ReactAriaSelect
|
||||
aria-label={ariaLabel}
|
||||
className={`${styles.select} ${discreet ? styles.discreet : ''} select-container`}
|
||||
className={`${styles.select} ${discreet ? styles.discreet : ""} select-container`}
|
||||
defaultSelectedKey={defaultSelectedKey}
|
||||
name={name}
|
||||
onSelectionChange={handleOnSelect}
|
||||
@@ -105,7 +105,7 @@ export default function Select({
|
||||
<>
|
||||
<InputLabel
|
||||
required={required}
|
||||
size={discreet ? 'discreet' : 'regular'}
|
||||
size={discreet ? "discreet" : "regular"}
|
||||
>
|
||||
{label}
|
||||
{discreet && DELIMITER}
|
||||
@@ -113,7 +113,7 @@ export default function Select({
|
||||
{selectedText && (
|
||||
<Typography
|
||||
variant="Body/Paragraph/mdRegular"
|
||||
className={optionsIcon ? styles.iconLabel : ''}
|
||||
className={optionsIcon ? styles.iconLabel : ""}
|
||||
>
|
||||
<p>
|
||||
{optionsIcon ? optionsIcon : null}
|
||||
@@ -165,9 +165,9 @@ export default function Select({
|
||||
function useSetOverflowVisibleOnRA(isNestedInModal?: boolean) {
|
||||
function setOverflowVisible(isOpen: boolean) {
|
||||
if (isOpen) {
|
||||
document.body.style.overflow = 'visible'
|
||||
document.body.style.overflow = "visible"
|
||||
} else if (!isNestedInModal) {
|
||||
document.body.style.overflow = ''
|
||||
document.body.style.overflow = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
gap: var(--Space-x05);
|
||||
}
|
||||
|
||||
.select[data-focused='true'] {
|
||||
.select[data-focused="true"] {
|
||||
border: 2px solid var(--Border-Interactive-Focus);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.select[data-focused='true'].discreet {
|
||||
.select[data-focused="true"].discreet {
|
||||
border: 1px solid transparent;
|
||||
outline: none;
|
||||
}
|
||||
.select[data-focus-visible='true'].discreet {
|
||||
.select[data-focus-visible="true"].discreet {
|
||||
border: 2px solid var(--Border-Interactive-Focus);
|
||||
}
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
padding: var(--Space-x1);
|
||||
}
|
||||
|
||||
.listBoxItem[data-focused='true'],
|
||||
.listBoxItem[data-selected='true'] {
|
||||
.listBoxItem[data-focused="true"],
|
||||
.listBoxItem[data-selected="true"] {
|
||||
background: var(--UI-Input-Controls-Surface-Hover);
|
||||
border-radius: var(--Corner-radius-md);
|
||||
outline: none;
|
||||
@@ -111,7 +111,7 @@
|
||||
|
||||
.listBoxItem.showRadioButton:before {
|
||||
flex-shrink: 0;
|
||||
content: '';
|
||||
content: "";
|
||||
margin-right: var(--Space-x15);
|
||||
background-color: white;
|
||||
width: 24px;
|
||||
@@ -120,6 +120,6 @@
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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> = {
|
||||
title: 'Core Components/Divider',
|
||||
title: "Core Components/Divider",
|
||||
component: Divider,
|
||||
argTypes: {},
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
const classNames = dividerVariants({ className, color, variant })
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export { Divider } from './Divider'
|
||||
export { Divider } from "./Divider"
|
||||
|
||||
// eslint-disable-next-line react-refresh/only-export-components
|
||||
export { dividerVariants } from './variants'
|
||||
export { dividerVariants } from "./variants"
|
||||
|
||||
@@ -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
|
||||
extends Omit<React.HTMLAttributes<HTMLHRElement>, 'color'>,
|
||||
extends
|
||||
Omit<React.HTMLAttributes<HTMLHRElement>, "color">,
|
||||
VariantProps<typeof dividerVariants> {}
|
||||
|
||||
@@ -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, {
|
||||
variants: {
|
||||
@@ -9,15 +9,15 @@ export const dividerVariants = cva(styles.divider, {
|
||||
pale: styles.pale,
|
||||
peach: styles.peach,
|
||||
white: styles.white,
|
||||
'Border/Divider/Accent': styles['Border-Divider-Accent'],
|
||||
'Border/Divider/Default': styles['Border-Divider-Default'],
|
||||
'Border/Divider/Brand/OnPrimary 3/Default':
|
||||
styles['Border-Divider-Brand-OnPrimary-3-Default'],
|
||||
'Border/Divider/Subtle': styles['Border-Divider-Subtle'],
|
||||
'Surface/Brand/Primary 1/OnSurface/Accent Secondary':
|
||||
styles['Surface-Brand-Primary-1-OnSurface-Accent-Secondary'],
|
||||
'Border/Divider/Brand/OnAccent/Default':
|
||||
styles['Border-Divider-Brand-OnAccent-Default'],
|
||||
"Border/Divider/Accent": styles["Border-Divider-Accent"],
|
||||
"Border/Divider/Default": styles["Border-Divider-Default"],
|
||||
"Border/Divider/Brand/OnPrimary 3/Default":
|
||||
styles["Border-Divider-Brand-OnPrimary-3-Default"],
|
||||
"Border/Divider/Subtle": styles["Border-Divider-Subtle"],
|
||||
"Surface/Brand/Primary 1/OnSurface/Accent Secondary":
|
||||
styles["Surface-Brand-Primary-1-OnSurface-Accent-Secondary"],
|
||||
"Border/Divider/Brand/OnAccent/Default":
|
||||
styles["Border-Divider-Brand-OnAccent-Default"],
|
||||
},
|
||||
variant: {
|
||||
horizontal: styles.horizontal,
|
||||
@@ -25,7 +25,7 @@ export const dividerVariants = cva(styles.divider, {
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
color: 'Border/Divider/Default',
|
||||
variant: 'horizontal',
|
||||
color: "Border/Divider/Default",
|
||||
variant: "horizontal",
|
||||
},
|
||||
})
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user