Skip to content

Commit

Permalink
feat(SkipLink): migrate to tailwind
Browse files Browse the repository at this point in the history
  • Loading branch information
vbulant authored and DSil committed Mar 8, 2024
1 parent f10714a commit a2eb45f
Show file tree
Hide file tree
Showing 44 changed files with 78 additions and 48 deletions.
2 changes: 1 addition & 1 deletion docs/src/data/tailwind-migration-status.yaml
Expand Up @@ -76,7 +76,7 @@ Select: true
Separator: true
ServiceLogo: true
Skeleton: true
SkipLink: false
SkipLink: true
SkipNavigation: false
Slide: true
Slider: true
Expand Down
2 changes: 2 additions & 0 deletions packages/orbit-components/src/SkipLink/README.md
Expand Up @@ -37,6 +37,8 @@ The table below contains all types of props available in the SkipLink component.
| :---------- | :------------------ | :------------------------------------- |
| buttonLabel | `string` | Description for screen readers. |
| **links** | [`links[]`](#links) | An array specifying links to point to. |
| dataTest | `string` | Optional prop for testing. |
| id | `string` | Optional id attribute. |

## links

Expand Down
21 changes: 21 additions & 0 deletions packages/orbit-components/src/SkipLink/SkipLink.ct-story.tsx
@@ -0,0 +1,21 @@
import * as React from "react";

import SkipLink from ".";

export default function SkipLinkStory() {
return (
<div className="p-md bg-cloud-light">
<div className="h-xxxl">
<SkipLink
dataTest="SkipLink"
links={[
{
href: "",
name: "Go go go!",
},
]}
/>
</div>
</div>
);
}
36 changes: 36 additions & 0 deletions packages/orbit-components/src/SkipLink/SkipLink.ct.tsx
@@ -0,0 +1,36 @@
import * as React from "react";
import { test, expect } from "@playwright/experimental-ct-react";

import SkipLinkStory from "./SkipLink.ct-story";
import RenderInRtl from "../utils/rtl/RenderInRtl";

test.describe("visual SkipLink", () => {
const forceShow = () => {
const link = document.querySelector("[data-test=SkipLink]>a");
link?.classList.remove("[&:not(:focus)]:sr-only");
};

test("default", async ({ mount }) => {
const component = await mount(<SkipLinkStory />);

await expect(component).toHaveScreenshot();
});

test("focus", async ({ mount }) => {
const component = await mount(<SkipLinkStory />);
await component.evaluate(forceShow);

await expect(component).toHaveScreenshot();
});

test("rtl", async ({ mount }) => {
const component = await mount(
<RenderInRtl>
<SkipLinkStory />
</RenderInRtl>,
);
await component.evaluate(forceShow);

await expect(component).toHaveScreenshot();
});
});
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion packages/orbit-components/src/SkipLink/SkipLink.stories.tsx
Expand Up @@ -62,10 +62,12 @@ export const Playground = () => {
"buttonLabel",
"Description for screen readers about where the user currently is or describing a more complex component.",
);
const dataTest = text("dataTest", "test");
const id = text("id", "ID");

return (
<div>
<SkipLink links={links} buttonLabel={buttonLabel} />
<SkipLink links={links} buttonLabel={buttonLabel} dataTest={dataTest} id={id} />
{Content}
</div>
);
Expand Down
Expand Up @@ -19,15 +19,22 @@ describe("SkipLink", () => {
onClick,
},
];
const dataTest = "test";
const id = "ID";

render(<SkipLink links={links} buttonLabel="https://www.kiwi.com/en/" />);
render(
<SkipLink links={links} buttonLabel="https://www.kiwi.com/en/" dataTest={dataTest} id={id} />,
);
expect(screen.getByRole("link")).toHaveAttribute(
"href",
"https://www.kiwi.com/cz/pages/content/terms",
);
expect(screen.getByRole("button")).toHaveAttribute("tabindex", "0");
expect(screen.getByRole("navigation")).toBeInTheDocument();
expect(screen.getByLabelText("https://www.kiwi.com/en/"));
const el = screen.getByTestId(dataTest);
expect(el).toBeInTheDocument();
expect(el).toHaveAttribute("id", id);

await user.click(screen.getByRole("button"));
expect(onClick).toHaveBeenCalled();
Expand Down
50 changes: 6 additions & 44 deletions packages/orbit-components/src/SkipLink/index.tsx
@@ -1,56 +1,18 @@
"use client";

import * as React from "react";
import styled, { css } from "styled-components";

import KEY_CODE_MAP from "../common/keyMaps";
import defaultTheme from "../defaultTheme";
import type { Props } from "./types";

const StyledNavigation = styled.nav``;

const StyledLink = styled.a`
${({ theme }) => css`
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
font-family: ${theme.orbit.fontFamily};
text-decoration: ${theme.orbit.textDecorationTextLinkPrimary};
font-size: ${theme.orbit.fontSizeTextLarge};
border-radius: ${theme.orbit.borderRadiusNormal};
color: ${theme.orbit.paletteInkDark};
&:focus {
top: 1rem;
left: 1rem;
clip: auto;
height: auto;
width: auto;
margin: 0;
overflow: visible;
padding: ${theme.orbit.spaceMedium};
background-color: ${theme.orbit.paletteWhite};
z-index: ${theme.orbit.zIndexOnTheTop};
}
`}
`;

StyledLink.defaultProps = {
theme: defaultTheme,
};

const SkipLink = ({ links, buttonLabel }: Props) => {
const SkipLink = ({ links, buttonLabel, dataTest, id }: Props) => {
return (
<StyledNavigation aria-label={buttonLabel}>
<nav aria-label={buttonLabel} data-test={dataTest} id={id}>
{links &&
links.map(({ href, name, onClick }, index) => {
return (
<StyledLink
<a
className="orbit-skip-link ltr:left-md rtl:right-md top-md p-md bg-white-normal z-onTop font-base text-large rounded-normal text-ink-dark absolute underline [&:not(:focus)]:sr-only"
key={encodeURIComponent(name + index)}
href={href}
tabIndex={onClick && 0}
Expand All @@ -63,10 +25,10 @@ const SkipLink = ({ links, buttonLabel }: Props) => {
}}
>
{name}
</StyledLink>
</a>
);
})}
</StyledNavigation>
</nav>
);
};

Expand Down
2 changes: 1 addition & 1 deletion packages/orbit-components/src/SkipLink/types.d.ts
Expand Up @@ -11,7 +11,7 @@ export interface Action {
readonly onClick?: Common.Event<React.SyntheticEvent<HTMLAnchorElement>>;
}

export interface Props {
export interface Props extends Common.Globals {
readonly links: Action[];
readonly buttonLabel?: string;
}

0 comments on commit a2eb45f

Please sign in to comment.