Skip to content

Commit

Permalink
feat: badge asChild
Browse files Browse the repository at this point in the history
  • Loading branch information
seedy authored Apr 15, 2022
1 parent 27606f6 commit 7ae6a3e
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 10 deletions.
7 changes: 7 additions & 0 deletions components/Badge/Badge.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { VariantProps } from '../../stitches.config';
import { Badge, COLORS } from './Badge';
import { Flex } from '../Flex';
import { modifyVariantsForStory } from '../../utils/modifyVariantsForStory';
import { UnstyledLink } from '../Link';

type BadgeVariants = VariantProps<typeof Badge>;
type BadgeProps = BadgeVariants & {};
Expand Down Expand Up @@ -85,3 +86,9 @@ const Customize: ComponentStory<typeof BadgeForStory> = (args) => (
Customize
</Badge>
);

export const BadgeLink: ComponentStory<typeof BadgeForStory> = (args) => (
<Badge asChild interactive {...args}>
<UnstyledLink href="https://traefik.io">Link</UnstyledLink>
</Badge>
);
15 changes: 15 additions & 0 deletions components/Badge/Badge.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Badge } from './Badge';
import { UnstyledLink } from '../Link';
import { render } from '@testing-library/react';

describe('Badge', () => {
it('should render Badge as link', () => {
const { getByRole } = render(
<Badge asChild interactive>
<UnstyledLink href="https://traefik.io">Link</UnstyledLink>
</Badge>
);

expect(getByRole('link')).toBeInTheDocument();
});
});
28 changes: 18 additions & 10 deletions components/Badge/Badge.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { ComponentProps, createContext } from 'react';
import { styled, VariantProps, CSS } from '../../stitches.config';
import React, { ComponentProps, useMemo } from 'react';
import { styled, VariantProps } from '../../stitches.config';
import { Slot } from '@radix-ui/react-slot';

export const COLORS = ['gray', 'red', 'blue', 'green', 'neon', 'orange', 'purple'] as const;
type COLOR_VALUES = typeof COLORS[number];
Expand Down Expand Up @@ -85,7 +86,8 @@ const BADGE_BASE_STYLES = {
},
};

export const StyledSpanBadge = styled('span', BADGE_BASE_STYLES);
const StyledSpanBadge = styled('span', BADGE_BASE_STYLES);
const StyledSpanBadgeSlot = styled(Slot, StyledSpanBadge);

const StyledButtonBadge = styled('button', BADGE_BASE_STYLES, {
'&:focus-visible': {
Expand All @@ -106,17 +108,23 @@ const StyledButtonBadge = styled('button', BADGE_BASE_STYLES, {
},
},
});
const StyledButtonBadgeSlot = styled(Slot, StyledButtonBadge);

interface BadgeProps
extends ComponentProps<typeof StyledButtonBadge>,
VariantProps<typeof StyledButtonBadge> {}
VariantProps<typeof StyledButtonBadge> {
asChild?: boolean;
}

export const Badge = React.forwardRef<React.ElementRef<typeof StyledButtonBadge>, BadgeProps>(
({ interactive, ...props }, forwardedRef) => {
return interactive ? (
<StyledButtonBadge {...props} ref={forwardedRef} />
) : (
<StyledSpanBadge {...props} ref={forwardedRef} />
);
({ interactive, asChild, ...props }, forwardedRef) => {
const Component = useMemo(() => {
if (interactive) {
return asChild ? StyledButtonBadgeSlot : StyledButtonBadge;
}
return asChild ? StyledSpanBadgeSlot : StyledSpanBadge;
}, [asChild]);

return <Component {...props} ref={forwardedRef} />;
}
);

0 comments on commit 7ae6a3e

Please sign in to comment.