Skip to content

Commit 685a349

Browse files
committed
Merge branch 'main' of https://github.com/PhillipsAuctionHouse/seldon into L3-2561-seldon-accessibility-improve-header-accessibility
2 parents 53d8685 + c6e8070 commit 685a349

File tree

19 files changed

+417
-71
lines changed

19 files changed

+417
-71
lines changed

.storybook/main.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ const __filename = fileURLToPath(import.meta.url);
66
const __dirname = dirname(__filename);
77
const config: StorybookConfig = {
88
stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
9-
addons: ['@storybook/addon-links', '@chromatic-com/storybook', '@storybook/addon-a11y', '@storybook/addon-docs'],
9+
addons: [
10+
'@storybook/addon-links',
11+
'@chromatic-com/storybook',
12+
'@storybook/addon-a11y',
13+
'@storybook/addon-docs',
14+
'storybook-addon-pseudo-states',
15+
],
1016
framework: {
1117
name: '@storybook/react-vite',
1218
options: {},

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
# [1.240.0](https://github.com/PhillipsAuctionHouse/seldon/compare/v1.239.0...v1.240.0) (2026-02-24)
2+
3+
4+
### Features
5+
6+
* **Composed Modal:** L3-10837 add min-widths to ComposedModal ([#784](https://github.com/PhillipsAuctionHouse/seldon/issues/784)) ([e865527](https://github.com/PhillipsAuctionHouse/seldon/commit/e865527bc6eb071fe3838fb4d052a1866b8bf56e))
7+
8+
# [1.239.0](https://github.com/PhillipsAuctionHouse/seldon/compare/v1.238.0...v1.239.0) (2026-02-23)
9+
10+
11+
### Features
12+
13+
* **filter:** L3-7878 Update border to 2px ([#813](https://github.com/PhillipsAuctionHouse/seldon/issues/813)) ([2ad6ec2](https://github.com/PhillipsAuctionHouse/seldon/commit/2ad6ec29426a3ee635deba0d86b70fe288c9d80e))
14+
15+
# [1.238.0](https://github.com/PhillipsAuctionHouse/seldon/compare/v1.237.0...v1.238.0) (2026-02-19)
16+
17+
18+
### Features
19+
20+
* **buttons:** L3-11299 L3-11476 Design System [RW] - Introduce small button component to Seldon, Remove ghost button variant ([#792](https://github.com/PhillipsAuctionHouse/seldon/issues/792)) ([dda9c0d](https://github.com/PhillipsAuctionHouse/seldon/commit/dda9c0df2f8e442ec07bd271f2c58f120b5a4c87))
21+
* **text-symbol:** L3-11066 Text Symbol Emoji Fix ([#806](https://github.com/PhillipsAuctionHouse/seldon/issues/806)) ([4ed7d68](https://github.com/PhillipsAuctionHouse/seldon/commit/4ed7d68f2f5c68dfc6abfa850591b496169c91e2))
22+
123
# [1.237.0](https://github.com/PhillipsAuctionHouse/seldon/compare/v1.236.0...v1.237.0) (2026-02-12)
224

325

package-lock.json

Lines changed: 20 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@phillips/seldon",
3-
"version": "1.237.0",
3+
"version": "1.240.0",
44
"repository": {
55
"type": "git",
66
"url": "https://github.com/PhillipsAuctionHouse/seldon"
@@ -132,6 +132,7 @@
132132
"sass": "^1.83.4",
133133
"semantic-release": "^25.0.0",
134134
"storybook": "^10.2.8",
135+
"storybook-addon-pseudo-states": "^10.2.8",
135136
"stylelint": "^16.8.1",
136137
"stylelint-config-standard": "^36.0.1",
137138
"stylelint-config-standard-scss": "^13.1.0",

src/components/Button/Button.stories.tsx

Lines changed: 148 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import type { Meta } from '@storybook/react-vite';
2-
32
import Button, { ButtonProps } from './Button';
4-
import { ButtonVariants } from './types';
3+
import { ButtonVariants, ButtonSizes } from './types';
54
import { Icon } from '../Icon';
5+
import { Loader } from '../..';
6+
import './_button.stories.scss';
67

78
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
89
const meta = {
@@ -16,6 +17,12 @@ const meta = {
1617
type: 'select',
1718
},
1819
},
20+
size: {
21+
options: Object.values(ButtonSizes),
22+
control: {
23+
type: 'select',
24+
},
25+
},
1926
linkSize: {
2027
options: ['sm', 'md', 'lg'],
2128
control: {
@@ -70,7 +77,7 @@ export const ButtonAsLinkWithPrefetch = (props: ButtonProps) => (
7077

7178
ButtonAsLinkWithPrefetch.args = {
7279
variant: ButtonVariants.tertiary,
73-
size: 'md',
80+
linkSize: 'md',
7481
};
7582

7683
export const ButtonWithSkeleton = (props: ButtonProps) => (
@@ -82,9 +89,144 @@ export const ButtonWithSkeleton = (props: ButtonProps) => (
8289
</div>
8390
);
8491

85-
ButtonAsLinkWithPrefetch.args = {
86-
variant: ButtonVariants.tertiary,
87-
size: 'md',
92+
export const SmallButtonVariant = (props: ButtonProps) => (
93+
<Button {...props} size={ButtonSizes.small}>
94+
Small Variant
95+
</Button>
96+
);
97+
98+
SmallButtonVariant.argTypes = {
99+
size: {
100+
control: false,
101+
},
102+
};
103+
104+
export const SmallButtonWithIcons = () => (
105+
<div style={{ display: 'flex', gap: '1rem' }}>
106+
<Button size={ButtonSizes.small} variant={ButtonVariants.primary}>
107+
<Icon icon="Add" />
108+
With Icon
109+
</Button>
110+
<Button size={ButtonSizes.small} variant={ButtonVariants.secondary} isIconLast>
111+
Icon Last
112+
<Icon icon="ArrowRight" />
113+
</Button>
114+
</div>
115+
);
116+
117+
SmallButtonWithIcons.argTypes = {
118+
size: {
119+
control: false,
120+
},
121+
};
122+
export const AllVariantsGrid = () => {
123+
const variants = [
124+
{ variant: ButtonVariants.primary, name: 'Primary' },
125+
{ variant: ButtonVariants.secondary, name: 'Secondary' },
126+
{ variant: ButtonVariants.tertiary, name: 'Tertiary' },
127+
];
128+
129+
const sizes = [
130+
{ size: ButtonSizes.default, name: 'Default' },
131+
{ size: ButtonSizes.small, name: 'Small' },
132+
];
133+
134+
return (
135+
<div className="all-variants-grid">
136+
{/* Header row */}
137+
<div className="all-variants-grid__header">
138+
<div className="all-variants-grid__header-cell">Variant</div>
139+
<div className="all-variants-grid__header-cell">Static</div>
140+
<div className="all-variants-grid__header-cell">Hover</div>
141+
<div className="all-variants-grid__header-cell">Focus</div>
142+
<div className="all-variants-grid__header-cell">Loading (Disabled)</div>
143+
<div className="all-variants-grid__header-cell">Disabled</div>
144+
</div>
145+
146+
{/* Grid rows for each variant and size combination */}
147+
{variants.map(({ variant, name: variantName }) =>
148+
sizes.map(({ size, name: sizeName }) => {
149+
const buttonText = size === ButtonSizes.small ? 'Clear' : 'Register To Bid';
150+
151+
return (
152+
<div key={`${variant}-${size}`} className="all-variants-grid__row">
153+
<div className="all-variants-grid__label-cell">
154+
{variantName} {sizeName}
155+
</div>
156+
157+
{/* Static */}
158+
<div className="all-variants-grid__button-cell">
159+
<Button variant={variant} size={size}>
160+
{buttonText}
161+
</Button>
162+
</div>
163+
164+
{/* Hover */}
165+
<div className="all-variants-grid__button-cell">
166+
<Button className="pseudo-hover" variant={variant} size={size}>
167+
{buttonText}
168+
</Button>
169+
</div>
170+
171+
{/* Focus */}
172+
<div className="all-variants-grid__button-cell">
173+
<Button className="pseudo-focus" variant={variant} size={size}>
174+
{buttonText}
175+
</Button>
176+
</div>
177+
178+
{/* Loading (Disabled) */}
179+
<div className="all-variants-grid__button-cell">
180+
<Button
181+
variant={variant}
182+
size={size}
183+
isDisabled
184+
style={{
185+
position: 'relative',
186+
display: 'inline-flex',
187+
alignItems: 'center',
188+
justifyContent: 'center',
189+
}}
190+
>
191+
{/* Mimic the same button width while showing loader */}
192+
<span
193+
aria-hidden="true"
194+
style={{
195+
visibility: 'hidden',
196+
display: 'inline-block',
197+
height: 0,
198+
overflow: 'hidden',
199+
whiteSpace: 'nowrap',
200+
}}
201+
>
202+
{buttonText}
203+
</span>
204+
<span style={{ position: 'absolute', left: '50%', top: '50%', transform: 'translate(-50%, -50%)' }}>
205+
<Loader />
206+
</span>
207+
</Button>
208+
</div>
209+
210+
{/* Disabled */}
211+
<div className="all-variants-grid__button-cell">
212+
<Button variant={variant} size={size} isDisabled>
213+
{buttonText}
214+
</Button>
215+
</div>
216+
</div>
217+
);
218+
}),
219+
)}
220+
</div>
221+
);
222+
};
223+
224+
AllVariantsGrid.parameters = {
225+
pseudo: {
226+
hover: ['.pseudo-hover'],
227+
focus: ['.pseudo-focus'],
228+
focusVisible: ['.pseudo-focus'],
229+
},
88230
};
89231

90232
// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args

src/components/Button/Button.test.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { px } from '../../utils';
33

44
import Button from './Button';
55
import { runCommonTests } from '../../utils/testUtils';
6-
import { ButtonVariants } from './types';
6+
import { ButtonVariants, ButtonSizes } from './types';
77

88
describe('Button', () => {
99
runCommonTests(Button, 'Button');
@@ -31,6 +31,29 @@ describe('Button', () => {
3131
expect(buttonElement).toHaveClass(`${px}-button--secondary`);
3232
expect(buttonElement).toHaveClass(`${px}-button--icon-last`);
3333
});
34+
35+
it('renders with default default size (no size class)', () => {
36+
render(<Button>Default Size</Button>);
37+
const buttonElement = screen.getByText('Default Size');
38+
expect(buttonElement).toHaveClass(`${px}-button`);
39+
expect(buttonElement).not.toHaveClass(`${px}-button--small`);
40+
expect(buttonElement).not.toHaveClass(`${px}-button--medium`);
41+
});
42+
43+
it('renders with small size class', () => {
44+
render(<Button size={ButtonSizes.small}>Small Button</Button>);
45+
const buttonElement = screen.getByText('Small Button');
46+
expect(buttonElement).toHaveClass(`${px}-button`);
47+
expect(buttonElement).toHaveClass(`${px}-button--small`);
48+
});
49+
50+
it('renders with explicit default size (no size class)', () => {
51+
render(<Button size={ButtonSizes.default}>Medium Button</Button>);
52+
const buttonElement = screen.getByText('Medium Button');
53+
expect(buttonElement).toHaveClass(`${px}-button`);
54+
expect(buttonElement).not.toHaveClass(`${px}-button--small`);
55+
expect(buttonElement).not.toHaveClass(`${px}-button--medium`);
56+
});
3457
it('should render as an anchor tag if href is passed', () => {
3558
render(<Button href="https://example.com">Link</Button>);
3659
const anchorElement = screen.getByRole('link', { name: 'Link' });

src/components/Button/Button.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import classnames from 'classnames';
22
import { getCommonProps, px } from '../../utils';
3-
import { ButtonVariants } from './types';
3+
import { ButtonVariants, ButtonSizes } from './types';
44
import { forwardRef, useState } from 'react';
55
import { Link, LinkVariants } from '../Link';
66

@@ -21,6 +21,10 @@ export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement | HT
2121
* Is this the principal call to action on the page?
2222
*/
2323
variant?: ButtonVariants;
24+
/**
25+
* The size of the button
26+
*/
27+
size?: ButtonSizes;
2428
/**
2529
* The type of the button.
2630
*/
@@ -66,6 +70,7 @@ const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(
6670
(
6771
{
6872
variant = ButtonVariants.primary,
73+
size = ButtonSizes.default,
6974
children,
7075
className,
7176
isIconLast: iconLast = false,
@@ -148,6 +153,7 @@ const Button = forwardRef<HTMLButtonElement | HTMLAnchorElement, ButtonProps>(
148153
className={classnames(
149154
`${baseClassName}`,
150155
`${baseClassName}--${variant}`,
156+
{ [`${baseClassName}--${size}`]: size !== ButtonSizes.default },
151157
{
152158
[`${baseClassName}--icon-last`]: iconLast,
153159
[`${px}-skeleton`]: isSkeletonLoading,

0 commit comments

Comments
 (0)