Add large size to Badge
- Add lg tokens: height 32px, paddingX 16px, fontSize 14px, iconSize 16px - Refactor component to use size map instead of ternary - Update stories: Sizes now shows all three, CompleteMatrix includes large Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,7 @@ const meta: Meta<typeof Badge> = {
|
|||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
control: 'select',
|
control: 'select',
|
||||||
options: ['small', 'medium'],
|
options: ['small', 'medium', 'large'],
|
||||||
description: 'Size preset',
|
description: 'Size preset',
|
||||||
table: { defaultValue: { summary: 'medium' } },
|
table: { defaultValue: { summary: 'medium' } },
|
||||||
},
|
},
|
||||||
@@ -120,27 +120,13 @@ export const WithIconsFilled: Story = {
|
|||||||
|
|
||||||
// ─── Sizes ──────────────────────────────────────────────────────────────────
|
// ─── Sizes ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/** Both sizes side by side */
|
/** All three sizes side by side */
|
||||||
export const Sizes: Story = {
|
export const Sizes: Story = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
|
<div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
|
||||||
<Badge size="small" color="brand" icon={<StarIcon />}>Small</Badge>
|
<Badge size="small" color="brand" icon={<StarIcon />}>Small</Badge>
|
||||||
<Badge size="medium" color="brand" icon={<StarIcon />}>Medium</Badge>
|
<Badge size="medium" color="brand" icon={<StarIcon />}>Medium</Badge>
|
||||||
</div>
|
<Badge size="large" color="brand" icon={<StarIcon />}>Large</Badge>
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
/** All colours in small size */
|
|
||||||
export const SmallSizes: Story = {
|
|
||||||
name: 'Small — All Colours',
|
|
||||||
render: () => (
|
|
||||||
<div style={{ display: 'flex', gap: 8, flexWrap: 'wrap', alignItems: 'center' }}>
|
|
||||||
<Badge size="small" color="default">Default</Badge>
|
|
||||||
<Badge size="small" color="brand" icon={<StarIcon />}>Brand</Badge>
|
|
||||||
<Badge size="small" color="success" icon={<CheckCircleIcon />}>Success</Badge>
|
|
||||||
<Badge size="small" color="warning">Warning</Badge>
|
|
||||||
<Badge size="small" color="error">Error</Badge>
|
|
||||||
<Badge size="small" color="info">Info</Badge>
|
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@@ -249,7 +235,7 @@ export const CompleteMatrix: Story = {
|
|||||||
{variant}
|
{variant}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
|
||||||
{(['medium', 'small'] as const).map((size) => (
|
{(['large', 'medium', 'small'] as const).map((size) => (
|
||||||
<div key={size} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
<div key={size} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
|
||||||
<span style={{ width: 60, fontSize: 12, color: '#737373' }}>{size}</span>
|
<span style={{ width: 60, fontSize: 12, color: '#737373' }}>{size}</span>
|
||||||
{colors.map((color) => (
|
{colors.map((color) => (
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export interface BadgeProps extends Omit<BoxProps, 'color'> {
|
|||||||
/** Visual style: "filled" (solid background) or "soft" (tonal/subtle background) */
|
/** Visual style: "filled" (solid background) or "soft" (tonal/subtle background) */
|
||||||
variant?: 'filled' | 'soft';
|
variant?: 'filled' | 'soft';
|
||||||
/** Size preset */
|
/** Size preset */
|
||||||
size?: 'small' | 'medium';
|
size?: 'small' | 'medium' | 'large';
|
||||||
/** Optional leading icon */
|
/** Optional leading icon */
|
||||||
icon?: React.ReactNode;
|
icon?: React.ReactNode;
|
||||||
/** Label text */
|
/** Label text */
|
||||||
@@ -91,7 +91,28 @@ export const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|||||||
},
|
},
|
||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const isSmall = size === 'small';
|
const sizeMap = {
|
||||||
|
small: {
|
||||||
|
height: 'var(--fa-badge-height-sm)',
|
||||||
|
px: 'var(--fa-badge-padding-x-sm)',
|
||||||
|
fontSize: 'var(--fa-badge-font-size-sm)',
|
||||||
|
iconSize: 'var(--fa-badge-icon-size-sm)',
|
||||||
|
},
|
||||||
|
medium: {
|
||||||
|
height: 'var(--fa-badge-height-md)',
|
||||||
|
px: 'var(--fa-badge-padding-x-md)',
|
||||||
|
fontSize: 'var(--fa-badge-font-size-md)',
|
||||||
|
iconSize: 'var(--fa-badge-icon-size-md)',
|
||||||
|
},
|
||||||
|
large: {
|
||||||
|
height: 'var(--fa-badge-height-lg)',
|
||||||
|
px: 'var(--fa-badge-padding-x-lg)',
|
||||||
|
fontSize: 'var(--fa-badge-font-size-lg)',
|
||||||
|
iconSize: 'var(--fa-badge-icon-size-lg)',
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
const s = sizeMap[size];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
@@ -107,12 +128,12 @@ export const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|||||||
display: 'inline-flex',
|
display: 'inline-flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
gap: 'var(--fa-badge-icon-gap-default)',
|
gap: 'var(--fa-badge-icon-gap-default)',
|
||||||
minHeight: isSmall ? 'var(--fa-badge-height-sm)' : 'var(--fa-badge-height-md)',
|
minHeight: s.height,
|
||||||
px: isSmall ? 'var(--fa-badge-padding-x-sm)' : 'var(--fa-badge-padding-x-md)',
|
px: s.px,
|
||||||
borderRadius: 'var(--fa-badge-border-radius-default)',
|
borderRadius: 'var(--fa-badge-border-radius-default)',
|
||||||
backgroundColor: colors.bg,
|
backgroundColor: colors.bg,
|
||||||
color: colors.text,
|
color: colors.text,
|
||||||
fontSize: isSmall ? 'var(--fa-badge-font-size-sm)' : 'var(--fa-badge-font-size-md)',
|
fontSize: s.fontSize,
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
fontFamily: theme.typography.fontFamily,
|
fontFamily: theme.typography.fontFamily,
|
||||||
lineHeight: 1,
|
lineHeight: 1,
|
||||||
@@ -121,7 +142,7 @@ export const Badge = React.forwardRef<HTMLDivElement, BadgeProps>(
|
|||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
// Icon sizing
|
// Icon sizing
|
||||||
'& > .MuiSvgIcon-root, & > svg': {
|
'& > .MuiSvgIcon-root, & > svg': {
|
||||||
fontSize: isSmall ? 'var(--fa-badge-icon-size-sm)' : 'var(--fa-badge-icon-size-md)',
|
fontSize: s.iconSize,
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,8 +5,10 @@
|
|||||||
:root {
|
:root {
|
||||||
--fa-badge-height-sm: 22px; /** Small — compact inline status indicators */
|
--fa-badge-height-sm: 22px; /** Small — compact inline status indicators */
|
||||||
--fa-badge-height-md: 26px; /** Medium — default status badges, card labels */
|
--fa-badge-height-md: 26px; /** Medium — default status badges, card labels */
|
||||||
|
--fa-badge-height-lg: 32px; /** Large — prominent labels, hero badges, marketing callouts */
|
||||||
--fa-badge-icon-size-sm: 12px; /** 12px icons in small badges */
|
--fa-badge-icon-size-sm: 12px; /** 12px icons in small badges */
|
||||||
--fa-badge-icon-size-md: 14px; /** 14px icons in medium badges */
|
--fa-badge-icon-size-md: 14px; /** 14px icons in medium badges */
|
||||||
|
--fa-badge-icon-size-lg: 16px; /** 16px icons in large badges */
|
||||||
--fa-button-height-xs: 28px; /** Extra-small — compact text buttons, inline actions */
|
--fa-button-height-xs: 28px; /** Extra-small — compact text buttons, inline actions */
|
||||||
--fa-button-height-sm: 32px; /** Small — secondary actions, toolbar buttons */
|
--fa-button-height-sm: 32px; /** Small — secondary actions, toolbar buttons */
|
||||||
--fa-button-height-md: 40px; /** Medium — default size, form submissions */
|
--fa-button-height-md: 40px; /** Medium — default size, form submissions */
|
||||||
@@ -212,8 +214,10 @@
|
|||||||
--fa-typography-overline-sm-letter-spacing: 1.5px;
|
--fa-typography-overline-sm-letter-spacing: 1.5px;
|
||||||
--fa-badge-padding-x-sm: var(--fa-spacing-2); /** 8px — compact horizontal padding */
|
--fa-badge-padding-x-sm: var(--fa-spacing-2); /** 8px — compact horizontal padding */
|
||||||
--fa-badge-padding-x-md: var(--fa-spacing-3); /** 12px — default horizontal padding */
|
--fa-badge-padding-x-md: var(--fa-spacing-3); /** 12px — default horizontal padding */
|
||||||
|
--fa-badge-padding-x-lg: var(--fa-spacing-4); /** 16px — generous horizontal padding */
|
||||||
--fa-badge-font-size-sm: var(--fa-font-size-2xs); /** 11px — small badge text */
|
--fa-badge-font-size-sm: var(--fa-font-size-2xs); /** 11px — small badge text */
|
||||||
--fa-badge-font-size-md: var(--fa-font-size-xs); /** 12px — default badge text */
|
--fa-badge-font-size-md: var(--fa-font-size-xs); /** 12px — default badge text */
|
||||||
|
--fa-badge-font-size-lg: var(--fa-font-size-sm); /** 14px — large badge text */
|
||||||
--fa-badge-icon-gap-default: var(--fa-spacing-1); /** 4px icon-text gap */
|
--fa-badge-icon-gap-default: var(--fa-spacing-1); /** 4px icon-text gap */
|
||||||
--fa-badge-border-radius-default: var(--fa-border-radius-full); /** Pill shape — fully rounded */
|
--fa-badge-border-radius-default: var(--fa-border-radius-full); /** Pill shape — fully rounded */
|
||||||
--fa-button-padding-x-xs: var(--fa-spacing-2); /** 8px — compact horizontal padding */
|
--fa-button-padding-x-xs: var(--fa-spacing-2); /** 8px — compact horizontal padding */
|
||||||
|
|||||||
@@ -4,12 +4,16 @@
|
|||||||
|
|
||||||
export const BadgeHeightSm = "22px"; // Small — compact inline status indicators
|
export const BadgeHeightSm = "22px"; // Small — compact inline status indicators
|
||||||
export const BadgeHeightMd = "26px"; // Medium — default status badges, card labels
|
export const BadgeHeightMd = "26px"; // Medium — default status badges, card labels
|
||||||
|
export const BadgeHeightLg = "32px"; // Large — prominent labels, hero badges, marketing callouts
|
||||||
export const BadgePaddingXSm = "8px"; // 8px — compact horizontal padding
|
export const BadgePaddingXSm = "8px"; // 8px — compact horizontal padding
|
||||||
export const BadgePaddingXMd = "12px"; // 12px — default horizontal padding
|
export const BadgePaddingXMd = "12px"; // 12px — default horizontal padding
|
||||||
|
export const BadgePaddingXLg = "16px"; // 16px — generous horizontal padding
|
||||||
export const BadgeFontSizeSm = "0.6875rem"; // 11px — small badge text
|
export const BadgeFontSizeSm = "0.6875rem"; // 11px — small badge text
|
||||||
export const BadgeFontSizeMd = "0.75rem"; // 12px — default badge text
|
export const BadgeFontSizeMd = "0.75rem"; // 12px — default badge text
|
||||||
|
export const BadgeFontSizeLg = "0.875rem"; // 14px — large badge text
|
||||||
export const BadgeIconSizeSm = "12px"; // 12px icons in small badges
|
export const BadgeIconSizeSm = "12px"; // 12px icons in small badges
|
||||||
export const BadgeIconSizeMd = "14px"; // 14px icons in medium badges
|
export const BadgeIconSizeMd = "14px"; // 14px icons in medium badges
|
||||||
|
export const BadgeIconSizeLg = "16px"; // 16px icons in large badges
|
||||||
export const BadgeIconGapDefault = "4px"; // 4px icon-text gap
|
export const BadgeIconGapDefault = "4px"; // 4px icon-text gap
|
||||||
export const BadgeBorderRadiusDefault = "9999px"; // Pill shape — fully rounded
|
export const BadgeBorderRadiusDefault = "9999px"; // Pill shape — fully rounded
|
||||||
export const ButtonHeightXs = "28px"; // Extra-small — compact text buttons, inline actions
|
export const ButtonHeightXs = "28px"; // Extra-small — compact text buttons, inline actions
|
||||||
|
|||||||
@@ -5,25 +5,29 @@
|
|||||||
"$type": "dimension",
|
"$type": "dimension",
|
||||||
"$description": "Badge heights per size.",
|
"$description": "Badge heights per size.",
|
||||||
"sm": { "$value": "22px", "$description": "Small — compact inline status indicators" },
|
"sm": { "$value": "22px", "$description": "Small — compact inline status indicators" },
|
||||||
"md": { "$value": "26px", "$description": "Medium — default status badges, card labels" }
|
"md": { "$value": "26px", "$description": "Medium — default status badges, card labels" },
|
||||||
|
"lg": { "$value": "32px", "$description": "Large — prominent labels, hero badges, marketing callouts" }
|
||||||
},
|
},
|
||||||
"paddingX": {
|
"paddingX": {
|
||||||
"$type": "dimension",
|
"$type": "dimension",
|
||||||
"$description": "Horizontal padding per size.",
|
"$description": "Horizontal padding per size.",
|
||||||
"sm": { "$value": "{spacing.2}", "$description": "8px — compact horizontal padding" },
|
"sm": { "$value": "{spacing.2}", "$description": "8px — compact horizontal padding" },
|
||||||
"md": { "$value": "{spacing.3}", "$description": "12px — default horizontal padding" }
|
"md": { "$value": "{spacing.3}", "$description": "12px — default horizontal padding" },
|
||||||
|
"lg": { "$value": "{spacing.4}", "$description": "16px — generous horizontal padding" }
|
||||||
},
|
},
|
||||||
"fontSize": {
|
"fontSize": {
|
||||||
"$type": "dimension",
|
"$type": "dimension",
|
||||||
"$description": "Font size per badge size.",
|
"$description": "Font size per badge size.",
|
||||||
"sm": { "$value": "{fontSize.2xs}", "$description": "11px — small badge text" },
|
"sm": { "$value": "{fontSize.2xs}", "$description": "11px — small badge text" },
|
||||||
"md": { "$value": "{fontSize.xs}", "$description": "12px — default badge text" }
|
"md": { "$value": "{fontSize.xs}", "$description": "12px — default badge text" },
|
||||||
|
"lg": { "$value": "{fontSize.sm}", "$description": "14px — large badge text" }
|
||||||
},
|
},
|
||||||
"iconSize": {
|
"iconSize": {
|
||||||
"$type": "dimension",
|
"$type": "dimension",
|
||||||
"$description": "Icon dimensions per badge size.",
|
"$description": "Icon dimensions per badge size.",
|
||||||
"sm": { "$value": "12px", "$description": "12px icons in small badges" },
|
"sm": { "$value": "12px", "$description": "12px icons in small badges" },
|
||||||
"md": { "$value": "14px", "$description": "14px icons in medium badges" }
|
"md": { "$value": "14px", "$description": "14px icons in medium badges" },
|
||||||
|
"lg": { "$value": "16px", "$description": "16px icons in large badges" }
|
||||||
},
|
},
|
||||||
"iconGap": {
|
"iconGap": {
|
||||||
"$type": "dimension",
|
"$type": "dimension",
|
||||||
|
|||||||
Reference in New Issue
Block a user