Skip to content

Commit

Permalink
Address feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
Vrishabhsk committed Dec 5, 2024
1 parent 8a22bfd commit 2133d46
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 91 deletions.
27 changes: 13 additions & 14 deletions packages/components/src/badge/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,54 @@ import { info, caution, error, published } from '@wordpress/icons';
* Internal dependencies
*/
import type { BadgeProps } from './types';
import type { WordPressComponentProps } from '../context';
import Icon from '../icon';

function Badge( {
className,
as: Component = 'div',
context = 'neutral',
intent = 'default',
children,
...props
}: BadgeProps ) {
}: WordPressComponentProps< BadgeProps, 'span', false > ) {
/**
* Returns an icon based on the badge context.
*
* @return {JSX.Element | null} The corresponding icon for the provided context.
* @return The corresponding icon for the provided context.
*/
function contextBasedIcon(): JSX.Element | null {
switch ( context ) {
function contextBasedIcon() {
switch ( intent ) {
case 'info':
return info;
case 'success':
return published;
case 'warning':
return caution;
case 'error':
return error;
case 'success':
return published;
default:
return null;
}
}

return (
<Component
<span
className={ clsx(
'components-badge',
`components-badge--${ context }`,
context !== 'neutral' && 'components-badge--has-icon',
`is-${ intent }`,
intent !== 'default' && 'has-icon',
className
) }
aria-label={ `${ context }-badge` }
{ ...props }
>
{ context !== 'neutral' && (
{ intent !== 'default' && (
<Icon
icon={ contextBasedIcon() }
size={ 16 }
fill="currentColor"
/>
) }
{ children }
</Component>
</span>
);
}

Expand Down
44 changes: 24 additions & 20 deletions packages/components/src/badge/stories/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,6 @@ import Badge from '..';
const meta = {
component: Badge,
title: 'Components/Containers/Badge',
argTypes: {
className: {
control: { type: 'text' },
},
as: {
control: { type: 'select' },
options: [ 'div', 'span' ],
},
context: {
control: { type: 'select' },
options: [ 'neutral', 'info', 'warning', 'error', 'success' ],
},
children: {
control: { type: null },
},
},
tags: [ 'status-private' ],
} satisfies Meta< typeof Badge >;

Expand All @@ -37,13 +21,33 @@ type Story = StoryObj< typeof meta >;
export const Default: Story = {
args: {
children: 'Code is Poetry',
context: 'neutral',
},
};

export const WithContext: Story = {
export const Info: Story = {
args: {
children: 'Code is Poetry',
context: 'success',
...Default.args,
intent: 'info',
},
};

export const Success: Story = {
args: {
...Default.args,
intent: 'success',
},
};

export const Warning: Story = {
args: {
...Default.args,
intent: 'warning',
},
};

export const Error: Story = {
args: {
...Default.args,
intent: 'error',
},
};
22 changes: 11 additions & 11 deletions packages/components/src/badge/styles.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
@mixin badge-color-variant( $base-color ) {
background-color: mix($white, $base-color, 90%);
color: mix($black, $base-color, 50%);
}

$badge-colors: (
"info": #3858e9,
"warning": $alert-yellow,
Expand All @@ -11,8 +6,8 @@ $badge-colors: (
);

.components-badge {
background: $gray-100;
color: $gray-800;
background-color: color-mix(in srgb, $white 90%, var(--base-color));
color: color-mix(in srgb, $black 50%, var(--base-color));
padding: 0 $grid-unit-10;
min-height: $grid-unit-30;
border-radius: $radius-small;
Expand All @@ -25,14 +20,19 @@ $badge-colors: (
align-items: center;
gap: 2px;

&--has-icon {
padding-left: $grid-unit-05;
&:where(.is-default) {
background-color: $gray-100;
color: $gray-800;
}

&.has-icon {
padding-inline-start: $grid-unit-05;
}

// Generate color variants
@each $type, $color in $badge-colors {
&.components-badge--#{$type} {
@include badge-color-variant( $color );
&.is-#{$type} {
--base-color: #{$color};
}
}
}
34 changes: 4 additions & 30 deletions packages/components/src/badge/test/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,11 @@ describe( 'Badge', () => {
expect( badge ).toHaveClass( 'components-badge' );
} );

it( 'should render as a span when specified', () => {
render( <Badge as="span">Code is Poetry</Badge> );
it( 'should render as per its intent and contain an icon', () => {
render( <Badge intent="error">Code is Poetry</Badge> );
const badge = screen.getByText( 'Code is Poetry' );
expect( badge.tagName ).toBe( 'SPAN' );
expect( badge ).toHaveClass( 'components-badge' );
} );

it( 'should render as a custom element when specified', () => {
render( <Badge as="article">Code is Poetry</Badge> );
const badge = screen.getByText( 'Code is Poetry' );
expect( badge.tagName ).toBe( 'ARTICLE' );
expect( badge ).toHaveClass( 'components-badge' );
expect( badge ).toHaveClass( 'components-badge', 'is-error' );
expect( badge ).toHaveClass( 'has-icon' );
} );

it( 'should combine custom className with default class', () => {
Expand All @@ -38,25 +31,6 @@ describe( 'Badge', () => {
expect( badge ).toHaveClass( 'custom-class' );
} );

it( 'should render children correctly', () => {
render(
<Badge>
<span>Nested</span> Content
</Badge>
);

const badge = screen.getByText( ( content, element ) => {
return element?.classList?.contains( 'components-badge' ) ?? false;
} );

expect( badge ).toBeInTheDocument();
expect( badge ).toHaveClass( 'components-badge' );
expect( badge ).toHaveTextContent( 'Nested Content' );

const nestedSpan = screen.getByText( 'Nested' );
expect( nestedSpan.tagName ).toBe( 'SPAN' );
} );

it( 'should pass through additional props', () => {
render( <Badge data-testid="custom-badge">Code is Poetry</Badge> );
const badge = screen.getByTestId( 'custom-badge' );
Expand Down
19 changes: 4 additions & 15 deletions packages/components/src/badge/types.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,16 @@
/**
* External dependencies
*/
import type { ElementType, ReactNode } from 'react';

export type BadgeProps = {
/**
* Additional classes for the badge component.
*/
className?: string;
/**
* Component type that will be used to render the badge component.
*
* @default 'div'
*/
as?: ElementType;
/**
* Badge variant.
*
* @default 'generic'
* @default 'default'
*/
context?: 'neutral' | 'info' | 'success' | 'warning' | 'error';
intent?: 'default' | 'info' | 'success' | 'warning' | 'error';
/**
* Element to display inside the badge.
* Text to display inside the badge.
*/
children: ReactNode;
children: string;
};
1 change: 0 additions & 1 deletion packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,6 @@ export {
} from './higher-order/with-focus-return';
export { default as withNotices } from './higher-order/with-notices';
export { default as withSpokenMessages } from './higher-order/with-spoken-messages';
export { default as Badge } from './badge';

// Private APIs.
export { privateApis } from './private-apis';

0 comments on commit 2133d46

Please sign in to comment.