diff --git a/src/tedi/components/buttons/closing-button/closing-button.module.scss b/src/tedi/components/buttons/closing-button/closing-button.module.scss index 3004c36a..628e9b58 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.module.scss +++ b/src/tedi/components/buttons/closing-button/closing-button.module.scss @@ -1,28 +1,12 @@ .tedi-closing-button { - --general-icon-primary: var(--button-close-text-default); - display: flex; align-items: center; justify-content: center; padding: 0; cursor: pointer; - background-color: var(--button-close-background-default); - border: 1px solid var(--button-close-background-default); + border: 0; border-radius: var(--button-radius-default); - transition: background 0.5s ease; - - @each $state in hover, active { - &:#{ $state } { - --general-icon-primary: var(--button-close-text-#{$state}); - - background-color: var(--button-close-background-#{$state}); - } - } - - &:focus-visible { - outline: 2px solid var(--button-main-primary-border-focus); - outline-offset: -2px; - } + transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease; &--default { width: var(--button-sm-icon-size); @@ -33,4 +17,62 @@ width: var(--button-xs-icon-size); height: var(--button-xs-icon-size); } + + &--color-primary { + color: var(--button-close-text-default); + background-color: var(--button-close-background-default); + + &:hover { + color: var(--button-close-text-hover); + background-color: var(--button-close-background-hover); + } + + &:active { + color: var(--button-close-text-active); + background-color: var(--button-close-background-active); + } + + &:focus-visible { + color: var(--button-close-text-focus); + outline: 2px solid var(--button-main-primary-border-focus); + } + } + + &--color-brand { + color: var(--button-main-neutral-text-default); + background-color: var(--button-main-neutral-icon-only-background-default); + + &:hover { + color: var(--button-main-neutral-text-hover); + background-color: var(--button-main-neutral-icon-only-background-hover); + } + + &:active { + color: var(--button-main-neutral-text-active); + background-color: var(--button-main-neutral-icon-only-background-active); + } + + &:focus-visible { + outline: 2px solid var(--button-main-primary-border-focus); + } + } + + &--color-white { + color: var(--button-neutral-inverted-text-default); + background-color: var(--button-neutral-inverted-icon-only-background-default); + + &:hover { + color: var(--button-neutral-inverted-text-hover); + background-color: var(--button-main-neutral-inverted-icon-only-background-hover); + } + + &:active { + color: var(--button-neutral-inverted-text-active); + background-color: var(--button-main-neutral-inverted-icon-only-background-hover); + } + + &:focus-visible { + outline: 2px solid var(--button-main-neutral-inverted-text-focus); + } + } } diff --git a/src/tedi/components/buttons/closing-button/closing-button.spec.tsx b/src/tedi/components/buttons/closing-button/closing-button.spec.tsx index ff51a20e..9e27d065 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.spec.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.spec.tsx @@ -10,33 +10,35 @@ jest.mock('../../../providers/label-provider', () => ({ describe('ClosingButton component', () => { it('renders the ClosingButton with default props', () => { - render( - { - console.log('Button pressed'); - }} - /> - ); + render(); const button = screen.getByRole('button', { name: /close/i }); expect(button).toBeInTheDocument(); - expect(button).toHaveClass('tedi-closing-button'); - expect(button).toHaveClass('tedi-closing-button--default'); + expect(button).toHaveClass('tedi-closing-button tedi-closing-button--default tedi-closing-button--color-primary'); const icon = button.querySelector('span[data-name="icon"]'); expect(icon).toBeInTheDocument(); expect(icon).toHaveClass('tedi-icon--size-24'); }); - it('renders with small size when size="small"', () => { + it('renders with the correct small size class and icon size', () => { render(); const button = screen.getByRole('button', { name: /close/i }); + expect(button).toHaveClass('tedi-closing-button tedi-closing-button--small tedi-closing-button--color-primary'); + render( + { + console.log('Button pressed'); + }} + /> + ); + + expect(button).toBeInTheDocument(); + expect(button).toHaveClass('tedi-closing-button'); expect(button).toHaveClass('tedi-closing-button--small'); const icon = button.querySelector('span[data-name="icon"]'); - expect(icon).toBeInTheDocument(); - // Small button still uses default icon size expect(icon).toHaveClass('tedi-icon--size-24'); }); @@ -54,17 +56,21 @@ describe('ClosingButton component', () => { it('applies custom class names', () => { render(); - const button = screen.getByRole('button', { name: /Close/i }); - expect(button).toHaveClass('tedi-closing-button'); - expect(button).toHaveClass('tedi-closing-button--default'); - expect(button).toHaveClass('custom-class'); + const button = screen.getByRole('button', { name: /close/i }); + expect(button).toHaveClass( + 'tedi-closing-button tedi-closing-button--default tedi-closing-button--color-primary custom-class' + ); + const customButton = screen.getByRole('button', { name: /Close/i }); + expect(customButton).toHaveClass('tedi-closing-button'); + expect(customButton).toHaveClass('tedi-closing-button--default'); + expect(customButton).toHaveClass('custom-class'); }); it('triggers onClick handler when clicked', () => { const onClickMock = jest.fn(); render(); - const button = screen.getByRole('button', { name: /Close/i }); + const button = screen.getByRole('button', { name: /close/i }); fireEvent.click(button); expect(onClickMock).toHaveBeenCalledTimes(1); }); @@ -72,7 +78,7 @@ describe('ClosingButton component', () => { it('uses fallback label from label provider when title is not provided', () => { render(); - const button = screen.getByRole('button', { name: /Close/i }); + const button = screen.getByRole('button', { name: /close/i }); expect(button).toHaveAttribute('title', 'Close'); expect(button).toHaveAttribute('aria-label', 'Close'); }); @@ -84,4 +90,14 @@ describe('ClosingButton component', () => { expect(button).toHaveAttribute('title', 'Custom Close'); expect(button).toHaveAttribute('aria-label', 'Custom Close'); }); + + it('applies the correct color classes', () => { + const colors: Array<'primary' | 'brand' | 'white'> = ['primary', 'brand', 'white']; + + colors.forEach((color) => { + const { container } = render(); + const button = container.querySelector('button[data-name="closing-button"]'); + expect(button).toHaveClass(`tedi-closing-button--color-${color}`); + }); + }); }); diff --git a/src/tedi/components/buttons/closing-button/closing-button.stories.tsx b/src/tedi/components/buttons/closing-button/closing-button.stories.tsx index 2055e2d0..d2e0a084 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.stories.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.stories.tsx @@ -1,5 +1,6 @@ import { Meta, StoryFn, StoryObj } from '@storybook/react'; +import { Text } from '../../base/typography/text/text'; import { Col, Row } from '../../layout/grid'; import ClosingButton, { ClosingButtonProps } from './closing-button'; @@ -42,16 +43,18 @@ const SizeTemplate: StoryFn = () => { const stateArray = ['Default', 'Hover', 'Active', 'Focus']; -const StatesTemplate: StoryFn = () => { +const StatesTemplate: StoryFn = (args) => { return (
{stateArray.map((state) => ( - {state} + + {state} + - + ))} @@ -116,3 +119,32 @@ export const States: Story = { }, }, }; + +export const ColorBrand: Story = { + render: StatesTemplate, + args: { + color: 'brand', + }, + parameters: { + pseudo: { + hover: '#Hover', + active: '#Active', + focusVisible: '#Focus', + }, + }, +}; + +export const ColorInverted: Story = { + render: StatesTemplate, + args: { + color: 'white', + }, + parameters: { + pseudo: { + hover: '#Hover', + active: '#Active', + focusVisible: '#Focus', + }, + backgrounds: { default: 'brand' }, + }, +}; diff --git a/src/tedi/components/buttons/closing-button/closing-button.tsx b/src/tedi/components/buttons/closing-button/closing-button.tsx index 4e9f60d8..0eb7c77a 100644 --- a/src/tedi/components/buttons/closing-button/closing-button.tsx +++ b/src/tedi/components/buttons/closing-button/closing-button.tsx @@ -6,6 +6,7 @@ import { useLabels } from '../../../providers/label-provider'; import { Icon } from '../../base/icon/icon'; import styles from './closing-button.module.scss'; +type ClosingButtonColor = 'primary' | 'brand' | 'white'; export type ClosingButtonSize = 'default' | 'small'; export type ClosingButtonIconSize = 18 | 24; @@ -16,7 +17,7 @@ export interface ClosingButtonProps extends ButtonHTMLAttributes { const { getLabel } = useLabels(); - const { title = getLabel('close'), onClick, size = 'default', iconSize = 24, className, ...rest } = props; + const { + title = getLabel('close'), + onClick, + size = 'default', + iconSize = 24, + color = 'primary', + className, + ...rest + } = props; const resolvedSize: ClosingButtonSize = iconSize === 18 ? 'small' : size; const buttonClass = cn( styles['tedi-closing-button'], { + [styles[`tedi-closing-button--${size}`]]: size, + [styles[`tedi-closing-button--color-${color}`]]: color, [styles[`tedi-closing-button--${resolvedSize}`]]: resolvedSize, }, className @@ -62,7 +77,7 @@ export const ClosingButton = (props: ClosingButtonProps): JSX.Element => { title={title} aria-label={title} > - + ); };