Skip to content

Commit

Permalink
19756: Updated Link's display styles (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
lancegliser authored Mar 27, 2024
1 parent 2a8259f commit 18c4818
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 21 deletions.
7 changes: 7 additions & 0 deletions src/components/Icons/DocumentationIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { FC } from "react";
import { IconBaseProps } from "react-icons";
import { HiOutlineBookOpen } from "react-icons/hi";

export const DocumentationIcon: FC<IconBaseProps> = (props) => {
return <HiOutlineBookOpen {...props} />;
};
7 changes: 7 additions & 0 deletions src/components/Icons/NewWindowIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { FC } from "react";
import { IconBaseProps } from "react-icons";
import { HiExternalLink } from "react-icons/hi";

export const NewWindowIcon: FC<IconBaseProps> = (props) => {
return <HiExternalLink {...props} />;
};
45 changes: 45 additions & 0 deletions src/components/Icons/icons.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Meta, StoryObj } from "@storybook/react";
import { FC, ReactNode } from "react";
import { IconBaseProps } from "react-icons";
import { NewWindowIcon } from ".";
import { DocumentationIcon } from "./DocumentationIcon";

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta: Meta<IconBaseProps> = {
title: "Components/Icons",
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/7.0/react/writing-docs/docs-page
tags: ["autodocs"],
parameters: {
// More on Story layout: https://storybook.js.org/docs/react/configure/story-layout
layout: "centered",
},
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
argTypes: {},
args: {},
render: (args) => (
<div className="flex gap-4">
<IconWithLabel
label="Documentation"
Icon={<DocumentationIcon {...args} />}
/>
<IconWithLabel label="NewWindowIcon" Icon={<NewWindowIcon {...args} />} />
</div>
),
};

export default meta;
type Story = StoryObj<IconBaseProps>;

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
export const Default: Story = {
// More on args: https://storybook.js.org/docs/react/writing-stories/args
args: {},
};

type IconWithLabelProps = { label: string; Icon: ReactNode };
const IconWithLabel: FC<IconWithLabelProps> = ({ label, Icon }) => (
<div className="flex flex-col items-center justify-center">
<div>{Icon}</div>
<div>{label}</div>
</div>
);
2 changes: 2 additions & 0 deletions src/components/Icons/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./DocumentationIcon";
export * from "./NewWindowIcon";
20 changes: 14 additions & 6 deletions src/components/Typography/Link/Link.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from "@storybook/react";
import { Link } from ".";
import { Paragraph } from "..";

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta: Meta<typeof Link> = {
Expand All @@ -14,13 +15,14 @@ const meta: Meta<typeof Link> = {
argTypes: {},
args: {
href: "https://www.howso.com/",
children: (
<>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua.
</>
),
children: "adipiscing elit",
},
render: ({ children, ...args }) => (
<Paragraph>
Lorem ipsum dolor sit amet, consectetur <Link {...args}>{children}</Link>,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
</Paragraph>
),
};

export default meta;
Expand All @@ -32,6 +34,12 @@ export const Default: Story = {
args: {},
};

export const External: Story = {
args: {
external: true,
},
};

export const CustomClasses: Story = {
args: {
className: "font-black",
Expand Down
48 changes: 33 additions & 15 deletions src/components/Typography/Link/Link.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
import { FC } from "react";
import { ComponentProps, FC } from "react";
import { twMerge } from "tailwind-merge";
import { NewWindowIcon } from "../../Icons";

export type LinkProps = React.DetailedHTMLProps<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
HTMLAnchorElement
>;
export const Link: FC<LinkProps> = function (props) {
return (
<a
{...props}
className={twMerge(
"cursor-pointer text-blue-600 hover:underline dark:text-blue-500",
props.className
)}
/>
);
export type LinkProps = ComponentProps<"a"> & {
/** Indicates a link that will take the off site. */
external?: boolean;
};
/**
* A generic <a> link for use in non-structural contexts.
* If you need to create your own links, most commonly for React Router
* use `getLinkProps()`.
**/
export const Link: FC<LinkProps> = (props) => {
const { children, ...mergedProps } = getLinkProps(props);
return <a {...mergedProps}>{children}</a>;
};

/**
* Returns link props augmented with display standards:
* - className
* - External icon in children
*/
export const getLinkProps = (props: LinkProps): LinkProps => ({
...props,
className: twMerge(linkClasses, props.className),
children: (
<>
{props.children}
{props.external && <NewWindowIcon className="inline-block ml-[.25ch]" />}
</>
),
});

const linkClasses =
"inline-flex items-center text-primary-600 underline dark:text-primary-400";
1 change: 1 addition & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./Buttons";
export * from "./Feedback";
export * from "./Icons";
export * from "./Typography";

0 comments on commit 18c4818

Please sign in to comment.