diff options
| -rw-r--r-- | src/components/atoms/buttons/button-link.stories.tsx | 67 | ||||
| -rw-r--r-- | src/components/atoms/buttons/button-link.test.tsx | 9 | ||||
| -rw-r--r-- | src/components/atoms/buttons/button-link.tsx | 49 | ||||
| -rw-r--r-- | src/components/atoms/buttons/buttons.module.scss | 2 |
4 files changed, 127 insertions, 0 deletions
diff --git a/src/components/atoms/buttons/button-link.stories.tsx b/src/components/atoms/buttons/button-link.stories.tsx new file mode 100644 index 0000000..d4df676 --- /dev/null +++ b/src/components/atoms/buttons/button-link.stories.tsx @@ -0,0 +1,67 @@ +import { ComponentMeta, ComponentStory } from '@storybook/react'; +import ButtonLinkComponent from './button-link'; + +export default { + title: 'Atoms/Buttons', + component: ButtonLinkComponent, + argTypes: { + 'aria-label': { + control: { + type: 'text', + }, + description: 'An accessible label.', + table: { + category: 'Accessibility', + }, + type: { + name: 'string', + required: false, + }, + }, + children: { + control: { + type: 'text', + }, + description: 'The link body.', + type: { + name: 'string', + required: true, + }, + }, + kind: { + control: { + type: 'select', + }, + description: 'The link kind.', + options: ['primary', 'secondary'], + table: { + category: 'Options', + defaultValue: { summary: 'secondary' }, + }, + type: { + name: 'string', + required: false, + }, + }, + target: { + control: { + type: null, + }, + description: 'The link target.', + type: { + name: 'string', + required: true, + }, + }, + }, +} as ComponentMeta<typeof ButtonLinkComponent>; + +const Template: ComponentStory<typeof ButtonLinkComponent> = (args) => ( + <ButtonLinkComponent {...args} /> +); + +export const ButtonLink = Template.bind({}); +ButtonLink.args = { + children: 'Link', + target: '#', +}; diff --git a/src/components/atoms/buttons/button-link.test.tsx b/src/components/atoms/buttons/button-link.test.tsx new file mode 100644 index 0000000..52ccdc7 --- /dev/null +++ b/src/components/atoms/buttons/button-link.test.tsx @@ -0,0 +1,9 @@ +import { render, screen } from '@test-utils'; +import ButtonLink from './button-link'; + +describe('ButtonLink', () => { + it('renders a ButtonLink component', () => { + render(<ButtonLink target="#">Button Link</ButtonLink>); + expect(screen.getByRole('link')).toHaveTextContent('Button Link'); + }); +}); diff --git a/src/components/atoms/buttons/button-link.tsx b/src/components/atoms/buttons/button-link.tsx new file mode 100644 index 0000000..c33a4b7 --- /dev/null +++ b/src/components/atoms/buttons/button-link.tsx @@ -0,0 +1,49 @@ +import Link from 'next/link'; +import { FC } from 'react'; +import styles from './buttons.module.scss'; + +type ButtonLinkProps = { + /** + * ButtonLink accessible label. + */ + 'aria-label'?: string; + /** + * True if it is an external link. Default: false. + */ + external?: boolean; + /** + * ButtonLink kind. Default: secondary. + */ + kind?: 'primary' | 'secondary'; + /** + * Define an URL as target. + */ + target: string; +}; + +/** + * ButtonLink component + * + * Use a button-like link as call to action. + */ +const ButtonLink: FC<ButtonLinkProps> = ({ + children, + target, + kind = 'secondary', + external = false, + ...props +}) => { + const kindClass = styles[`btn--${kind}`]; + + return external ? ( + <a href={target} className={`${styles.btn} ${kindClass}`} {...props}> + {children} + </a> + ) : ( + <Link href={target} {...props}> + <a className={`${styles.btn} ${kindClass}`}>{children}</a> + </Link> + ); +}; + +export default ButtonLink; diff --git a/src/components/atoms/buttons/buttons.module.scss b/src/components/atoms/buttons/buttons.module.scss index d6a488d..9dddf48 100644 --- a/src/components/atoms/buttons/buttons.module.scss +++ b/src/components/atoms/buttons/buttons.module.scss @@ -22,6 +22,7 @@ fun.convert-px(2) fun.convert-px(2) 0 fun.convert-px(3) var(--color-primary-dark); color: var(--color-fg-inverted); + text-decoration: none; text-shadow: fun.convert-px(2) fun.convert-px(2) 0 var(--color-shadow); &:disabled { @@ -36,6 +37,7 @@ 0 0 0 fun.convert-px(3) var(--color-primary-darker), fun.convert-px(7) fun.convert-px(7) 0 fun.convert-px(2) var(--color-primary-dark); + color: var(--color-fg-inverted); transform: translateX(#{fun.convert-px(-4)}) translateY(#{fun.convert-px(-4)}); } |
