From 5a457af5c2a29238a5327932a3e8a3e3b732a136 Mon Sep 17 00:00:00 2001 From: Piotr Monwid-Olechnowicz Date: Fri, 1 Nov 2024 22:07:16 +0100 Subject: [PATCH] Add TextLink --- .../src/components/text-link.stories.tsx | 31 ++++++++++++++++ .../components/src/components/text-link.tsx | 35 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 packages/components/src/components/text-link.stories.tsx create mode 100644 packages/components/src/components/text-link.tsx diff --git a/packages/components/src/components/text-link.stories.tsx b/packages/components/src/components/text-link.stories.tsx new file mode 100644 index 000000000..ce0565f8e --- /dev/null +++ b/packages/components/src/components/text-link.stories.tsx @@ -0,0 +1,31 @@ +import Layout from 'nextra-theme-docs'; +import { Meta, StoryObj } from '@storybook/react'; +import { hiveThemeDecorator } from '../../../../.storybook/hive-theme-decorator'; +import { ArrowIcon } from './icons'; +import { TextLink, TextLinkProps } from './text-link'; + +export default { + title: 'Components/TextLink', + component: TextLink, + decorators: [hiveThemeDecorator], + args: { + href: '#', + }, +} satisfies Meta; + +export const WithUnderline: StoryObj = { + args: { + children: 'The Guild', + }, +}; + +export const WithArrow: StoryObj = { + args: { + children: ( + <> + Learn more + + + ), + }, +}; diff --git a/packages/components/src/components/text-link.tsx b/packages/components/src/components/text-link.tsx new file mode 100644 index 000000000..24f94676d --- /dev/null +++ b/packages/components/src/components/text-link.tsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { cn } from '../cn'; +import { Anchor, AnchorProps } from './anchor'; +import { ArrowIcon } from './icons'; + +export interface TextLinkProps extends AnchorProps {} + +export function TextLink({ className, children, ...rest }: TextLinkProps) { + const hasArrow = + children && + flattenFragments(children).some( + child => typeof child === 'object' && child && 'type' in child && child.type === ArrowIcon, + ); + + return ( + + {children} + + ); +} + +function flattenFragments(children: React.ReactNode): React.ReactNode[] { + return React.Children.toArray(children).flatMap(child => + typeof child === 'object' && 'type' in child && child.type === React.Fragment + ? (child.props.children as React.ReactNode[]) + : child, + ); +}