fix(LOY-128): add rounded filter chip variant

This commit is contained in:
Christian Andolf
2025-06-09 16:28:21 +02:00
parent d560ac0fca
commit f292cc7922
6 changed files with 200 additions and 48 deletions

View File

@@ -2,7 +2,7 @@
import { cx } from "class-variance-authority"
import { Typography } from "@scandic-hotels/design-system/Typography"
import { ChipButton } from "@scandic-hotels/design-system/ChipButton"
import useScrollShadows from "@/hooks/useScrollShadows"
@@ -32,29 +32,23 @@ export default function TabFilters({
return (
<div
className={cx(
styles.containerWrapper,
showLeftShadow && styles.showLeftShadow,
showRightShadow && styles.showRightShadow
)}
className={cx(styles.containerWrapper, {
[styles.showLeftShadow]: showLeftShadow,
[styles.showRightShadow]: showRightShadow,
})}
>
<div className={styles.container} ref={containerRef}>
{categories.map((category) => (
<Typography
<ChipButton
key={category.identifier}
variant="Body/Supporting text (caption)/smRegular"
onPress={() => onFilterSelect(category.identifier)}
variant="FilterRounded"
selected={selectedFilter === category.identifier}
className={styles.filter}
>
<button
onClick={() => onFilterSelect(category.identifier)}
className={cx(styles.filter, {
[styles.selected]: selectedFilter === category.identifier,
})}
type="button"
>
<IconByCSSelect identifier={category.iconIdentifier} />
{category.label}
</button>
</Typography>
<IconByCSSelect identifier={category.iconIdentifier} />
{category.label}
</ChipButton>
))}
</div>
</div>

View File

@@ -38,25 +38,10 @@
scrollbar-width: none;
position: relative;
width: 100%;
padding: var(--Space-x05);
}
.filter {
display: flex;
align-items: center;
gap: var(--Space-x1);
background-color: transparent;
border: 1px solid var(--Border-Interactive-Selected);
border-radius: var(--Corner-radius-rounded);
padding: var(--Space-x1) var(--Space-x2);
transition: all 0.2s ease-in-out;
scroll-snap-align: start;
scroll-snap-align: center;
flex-shrink: 0;
cursor: pointer;
color: var(--Text-Default);
}
.filter.selected {
border-color: transparent;
background-color: var(--Base-Button-Tertiary-Fill-Normal);
color: var(--Text-Inverted);
}

View File

@@ -51,3 +51,61 @@ export const Outlined: Story = {
),
},
}
export const FilterRoundedLarge: Story = {
args: {
variant: 'FilterRounded',
onPress: fn(),
size: 'Large',
children: (
<>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
Button Chip
</>
),
},
}
export const FilterRoundedLargeSelected: Story = {
args: {
variant: 'FilterRounded',
onPress: fn(),
size: 'Large',
selected: true,
children: (
<>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
Button Chip
</>
),
},
}
export const FilterRoundedMedium: Story = {
args: {
variant: 'FilterRounded',
onPress: fn(),
size: 'Medium',
children: (
<>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
Button Chip
</>
),
},
}
export const FilterRoundedMediumSelected: Story = {
args: {
variant: 'FilterRounded',
onPress: fn(),
size: 'Medium',
selected: true,
children: (
<>
<MaterialIcon icon="location_city" size={20} color="CurrentColor" />
Button Chip
</>
),
},
}

View File

@@ -1,24 +1,25 @@
import { Button as ButtonRAC } from 'react-aria-components'
import { Typography } from '../Typography'
import { ChipButtonProps } from './types'
import { variants } from './variants'
export function ChipButton({
children,
variant,
selected = false,
size = 'Large',
className,
...props
}: ChipButtonProps) {
const classNames = variants({
variant,
selected,
size,
})
return (
<Typography variant="Body/Supporting text (caption)/smBold">
<ButtonRAC {...props} className={[className, classNames].join(' ')}>
{children}
</ButtonRAC>
</Typography>
<ButtonRAC {...props} className={[className, classNames].join(' ')}>
{children}
</ButtonRAC>
)
}

View File

@@ -7,6 +7,7 @@
align-items: center;
justify-content: center;
cursor: pointer;
gap: var(--Space-x05);
}
.Default {
@@ -30,8 +31,31 @@
border-color: var(--Border-Interactive-Selected);
}
.FilterRounded {
background-color: transparent;
border: 1px solid var(--Border-Interactive-Selected);
border-radius: var(--Corner-radius-rounded);
padding: var(--Space-x025) var(--Space-x2);
color: var(--Text-Default);
}
.selected {
border-color: transparent;
background-color: var(--Surface-Brand-Primary-3-Default);
color: var(--Text-Inverted);
}
.large {
height: 40px;
}
.medium {
height: 32px;
}
.Default:focus,
.Outlined:focus {
.Outlined:focus,
.FilterRounded:focus {
outline-offset: 4px;
outline-color: var(--Border-Interactive-Focus);
}

View File

@@ -2,24 +2,114 @@ 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'
const variantKeys = {
variant: {
Default: 'Default',
Outlined: 'Outlined',
FilterRounded: 'FilterRounded',
},
style: {
Medium: 'Medium',
Large: 'Large',
},
typography: {
Bold: 'Body/Supporting text (caption)/smBold',
Regular: 'Body/Supporting text (caption)/smRegular',
},
} as const
export const config = {
variants: {
variant: {
Default: styles.Default,
Outlined: styles.Outlined,
[variantKeys.variant.Default]: styles.Default,
[variantKeys.variant.Outlined]: styles.Outlined,
[variantKeys.variant.FilterRounded]: styles.FilterRounded,
},
selected: {
true: '',
false: '',
},
size: {
[variantKeys.style.Medium]: '',
[variantKeys.style.Large]: '',
},
},
compoundVariants: [
{
variant: variantKeys.variant.Default,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smBold'
],
],
},
{
variant: variantKeys.variant.Outlined,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smBold'
],
],
},
{
variant: variantKeys.variant.FilterRounded,
size: variantKeys.style.Medium,
selected: true,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular'
],
styles.selected,
styles.medium,
],
},
{
variant: variantKeys.variant.FilterRounded,
size: variantKeys.style.Medium,
selected: false,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular'
],
styles.medium,
],
},
{
variant: variantKeys.variant.FilterRounded,
size: variantKeys.style.Large,
selected: true,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular'
],
styles.selected,
styles.large,
],
},
{
variant: variantKeys.variant.FilterRounded,
size: variantKeys.style.Large,
selected: false,
className: [
typographyConfig.variants.variant[
'Body/Supporting text (caption)/smRegular'
],
styles.large,
],
},
],
defaultVariants: {
variant: 'Default',
variant: variantKeys.variant.Default,
},
} as const
}
export const variants = cva(styles.chip, config)
const chipConfig = {
variants: {
typography: config.variants.variant,
...config.variants,
},
defaultVariants: config.defaultVariants,
} as const