-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from jtiala/anchor
Add anchor
- Loading branch information
Showing
24 changed files
with
323 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
import { Anchor } from "@themeless-ui/react"; | ||
|
||
const meta = { | ||
title: "Navigation/Anchor", | ||
component: Anchor, | ||
tags: ["autodocs"], | ||
} satisfies Meta<typeof Anchor>; | ||
|
||
export default meta; | ||
type Story = StoryObj<typeof meta>; | ||
|
||
const href = "https://example.com"; | ||
const children = "Example.com"; | ||
|
||
export const Default: Story = { | ||
args: { | ||
href, | ||
children, | ||
}, | ||
}; | ||
|
||
export const ExternalLink: Story = { | ||
args: { | ||
href, | ||
target: "_blank", | ||
children, | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,7 @@ | |
], | ||
"packageManager": "[email protected]", | ||
"scripts": { | ||
"dev": "turbo run dev --no-cache --continue", | ||
"dev": "turbo run dev --no-cache --continue --concurrency=12", | ||
"build": "turbo run build", | ||
"preview": "turbo run preview", | ||
"test": "turbo run test", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { | ||
componentToJson, | ||
describe, | ||
expect, | ||
it, | ||
render, | ||
renderer, | ||
screen, | ||
} from "../../../test"; | ||
import { Anchor } from "./Anchor"; | ||
|
||
const href = "https://example.com"; | ||
const children = "Example.com"; | ||
|
||
const defaultAnchor = ( | ||
<Anchor testId="anchor" href={href}> | ||
{children} | ||
</Anchor> | ||
); | ||
|
||
const externalAnchor = ( | ||
<Anchor testId="anchor" href={href} target="_blank"> | ||
{children} | ||
</Anchor> | ||
); | ||
|
||
describe("Anchor", async () => { | ||
it("should render default anchor", () => { | ||
expect(componentToJson(renderer.create(defaultAnchor))).toMatchSnapshot(); | ||
|
||
render(defaultAnchor); | ||
|
||
const anchor = screen.getByTestId("anchor"); | ||
const linkRelationships = anchor.getAttribute("rel"); | ||
|
||
expect(anchor).toBeInTheDocument(); | ||
expect(anchor).toHaveTextContent(children); | ||
expect(linkRelationships).toBeFalsy(); | ||
}); | ||
|
||
it("should render external anchor", () => { | ||
expect(componentToJson(renderer.create(externalAnchor))).toMatchSnapshot(); | ||
|
||
render(externalAnchor); | ||
|
||
const anchor = screen.getByTestId("anchor"); | ||
const linkRelationships = (anchor.getAttribute("rel") || "").split(" "); | ||
|
||
expect(anchor).toBeInTheDocument(); | ||
expect(anchor).toHaveTextContent(children); | ||
expect(anchor).toHaveAttribute("target", "_blank"); | ||
expect(linkRelationships).toContain("noopener"); | ||
expect(linkRelationships).toContain("noreferrer"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { CommonComponentProps, cn } from "@themeless-ui/utils"; | ||
import { AnchorHTMLAttributes, ReactNode } from "react"; | ||
|
||
type HTMLAnchorProps = AnchorHTMLAttributes<HTMLAnchorElement>; | ||
|
||
export type AnchorProps = { | ||
/** | ||
* The URL that the hyperlink points to. | ||
*/ | ||
href?: HTMLAnchorProps["href"]; | ||
|
||
/** | ||
* The relationship of the linked URL. | ||
* | ||
* If `rel` is not defined and the anchor has `target` as `_blank`, the following relationships will be added automatically: | ||
* - `noopener` to prevent reverse tabnabbing | ||
* - `noreferrer` to prevent passing referrer information to the target | ||
*/ | ||
rel?: HTMLAnchorProps["rel"]; | ||
|
||
/** | ||
* Where to display the linked URL. | ||
*/ | ||
target?: AnchorHTMLAttributes<HTMLAnchorElement>["target"]; | ||
|
||
/** | ||
* Causes the browser to treat the linked URL as a download. | ||
*/ | ||
download?: AnchorHTMLAttributes<HTMLAnchorElement>["download"]; | ||
|
||
/** | ||
* A function that is called when the anchor is clicked. | ||
*/ | ||
onClick?: AnchorHTMLAttributes<HTMLAnchorElement>["onClick"]; | ||
|
||
/** | ||
* A function that is called when the anchor is focused. | ||
*/ | ||
onFocus?: AnchorHTMLAttributes<HTMLAnchorElement>["onFocus"]; | ||
|
||
/** | ||
* A function that is called when the anchor hast lost focus. | ||
*/ | ||
onBlur?: AnchorHTMLAttributes<HTMLAnchorElement>["onBlur"]; | ||
|
||
/** | ||
* A function that is called when mouse enters the anchor. | ||
*/ | ||
onMouseEnter?: AnchorHTMLAttributes<HTMLAnchorElement>["onMouseEnter"]; | ||
|
||
/** | ||
* A function that is called when mouse leaves the anchor. | ||
*/ | ||
onMouseLeave?: AnchorHTMLAttributes<HTMLAnchorElement>["onMouseLeave"]; | ||
|
||
/** | ||
* A function that is called when one or more touch points are placed on the touch surface. | ||
*/ | ||
onTouchStart?: AnchorHTMLAttributes<HTMLAnchorElement>["onTouchStart"]; | ||
|
||
/** | ||
* A function that is called when one or more touch points are removed from the touch surface. | ||
*/ | ||
onTouchEnd?: AnchorHTMLAttributes<HTMLAnchorElement>["onTouchEnd"]; | ||
|
||
/** | ||
* Anchor content. | ||
*/ | ||
children?: ReactNode; | ||
} & CommonComponentProps; | ||
|
||
const className = cn("anchor"); | ||
|
||
/** | ||
* Display a hyperlink. | ||
*/ | ||
export function Anchor({ | ||
href, | ||
rel, | ||
target, | ||
download, | ||
onClick, | ||
onFocus, | ||
onBlur, | ||
onMouseEnter, | ||
onMouseLeave, | ||
onTouchStart, | ||
onTouchEnd, | ||
children, | ||
testId, | ||
}: AnchorProps) { | ||
const openInNewTab = target === "_blank"; | ||
const linkRelationships = | ||
rel || openInNewTab ? "noopener noreferrer" : undefined; | ||
|
||
return ( | ||
<a | ||
href={href} | ||
rel={linkRelationships} | ||
target={target} | ||
download={download} | ||
onClick={onClick} | ||
onFocus={onFocus} | ||
onBlur={onBlur} | ||
onMouseEnter={onMouseEnter} | ||
onMouseLeave={onMouseLeave} | ||
onTouchStart={onTouchStart} | ||
onTouchEnd={onTouchEnd} | ||
className={className} | ||
data-testid={testId} | ||
> | ||
{children} | ||
</a> | ||
); | ||
} |
23 changes: 23 additions & 0 deletions
23
packages/react/src/components/Anchor/__snapshots__/Anchor.test.tsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html | ||
|
||
exports[`Anchor > should render default anchor 1`] = ` | ||
<a | ||
className="tui__anchor" | ||
data-testid="anchor" | ||
href="https://example.com" | ||
> | ||
Example.com | ||
</a> | ||
`; | ||
|
||
exports[`Anchor > should render external anchor 1`] = ` | ||
<a | ||
className="tui__anchor" | ||
data-testid="anchor" | ||
href="https://example.com" | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
Example.com | ||
</a> | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export { Anchor } from "./Anchor"; | ||
export type { AnchorProps } from "./Anchor"; |
Oops, something went wrong.