@purpurds/cta-link 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ ._purpur-cta-link_e7abc_1{align-items:center;border-radius:var(--purpur-border-radius-full);border-width:0;cursor:pointer;display:inline-flex;font-size:var(--purpur-typography-scale-100);font-family:var(--purpur-typography-family-default),Helvetica,Arial,"Lucida Grande",sans-serif;font-weight:var(--purpur-typography-weight-medium);gap:var(--purpur-spacing-100);justify-content:center;line-height:var(--purpur-spacing-300);outline:0;position:relative;text-decoration:none;transition:all var(--purpur-motion-duration-100) ease;width:auto}._purpur-cta-link_e7abc_1:focus:before{border-radius:var(--purpur-border-radius-full);box-shadow:0 0 0 var(--purpur-border-width-sm) var(--purpur-color-border-interactive-focus);content:"";display:block;inset:calc(var(--purpur-spacing-25) * -1);position:absolute}._purpur-cta-link_e7abc_1:focus:not(:focus-visible):before{box-shadow:none}._purpur-cta-link_e7abc_1 svg{display:block}._purpur-cta-link--sm_e7abc_33{padding:var(--purpur-spacing-100) var(--purpur-spacing-250)}._purpur-cta-link--sm_e7abc_33._purpur-cta-link--icon-only_e7abc_36{padding:var(--purpur-spacing-100)}._purpur-cta-link--md_e7abc_39{padding:var(--purpur-spacing-150) var(--purpur-spacing-300)}._purpur-cta-link--md_e7abc_39._purpur-cta-link--icon-only_e7abc_36{padding:var(--purpur-spacing-150)}._purpur-cta-link--lg_e7abc_45{padding:var(--purpur-spacing-200) var(--purpur-spacing-400)}._purpur-cta-link--lg_e7abc_45._purpur-cta-link--icon-only_e7abc_36{padding:var(--purpur-spacing-200)}._purpur-cta-link--full-width_e7abc_51{width:100%}._purpur-cta-link--primary_e7abc_54{background-color:var(--purpur-color-background-interactive-primary);color:var(--purpur-color-text-interactive-on-primary)}._purpur-cta-link--primary_e7abc_54:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-primary-hover)}._purpur-cta-link--primary_e7abc_54:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-primary-active)}._purpur-cta-link--primary-negative_e7abc_64{background-color:var(--purpur-color-background-interactive-primary-negative);color:var(--purpur-color-text-interactive-on-primary-negative)}._purpur-cta-link--primary-negative_e7abc_64:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-primary-negative-hover);border-color:var(--purpur-color-background-interactive-primary-negative-hover)}._purpur-cta-link--primary-negative_e7abc_64:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-primary-negative-active);border-color:var(--purpur-color-background-interactive-primary-negative-active)}._purpur-cta-link--secondary_e7abc_76{background-color:var(--purpur-color-background-interactive-transparent);box-shadow:inset 0 0 0 var(--purpur-border-width-xs) var(--purpur-color-border-interactive-primary);color:var(--purpur-color-text-interactive-primary)}._purpur-cta-link--secondary_e7abc_76:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-transparent-hover)}._purpur-cta-link--secondary_e7abc_76:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-transparent-active)}._purpur-cta-link--secondary-negative_e7abc_87{background-color:var(--purpur-color-background-interactive-transparent);box-shadow:inset 0 0 0 var(--purpur-border-width-xs) var(--purpur-color-border-interactive-primary-negative);color:var(--purpur-color-text-interactive-primary-negative)}._purpur-cta-link--secondary-negative_e7abc_87:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-transparent-negative-hover)}._purpur-cta-link--secondary-negative_e7abc_87:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-transparent-negative-active)}._purpur-cta-link--expressive_e7abc_98{background-color:var(--purpur-color-background-interactive-expressive);color:var(--purpur-color-text-interactive-on-expressive)}._purpur-cta-link--expressive_e7abc_98:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-expressive-hover)}._purpur-cta-link--expressive_e7abc_98:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-expressive-active)}._purpur-cta-link--expressive-negative_e7abc_108{background-color:var(--purpur-color-background-interactive-expressive-negative);color:var(--purpur-color-text-interactive-on-expressive-negative)}._purpur-cta-link--expressive-negative_e7abc_108:hover:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-expressive-negative-hover);color:var(--purpur-color-text-interactive-on-expressive-negative-hover)}._purpur-cta-link--expressive-negative_e7abc_108:active:not(._purpur-cta-link--disabled_e7abc_58){background-color:var(--purpur-color-background-interactive-expressive-negative-active);color:var(--purpur-color-text-interactive-on-expressive-negative-active)}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@purpurds/cta-link",
3
+ "version": "3.0.0",
4
+ "license": "AGPL-3.0-only",
5
+ "main": "./dist/cta-link.cjs.js",
6
+ "types": "./dist/cta-link.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "require": "./dist/cta-link.cjs.js",
10
+ "systemjs": "./dist/cta-link.system.js",
11
+ "types": "./dist/cta-link.d.ts",
12
+ "default": "./dist/cta-link.es.js"
13
+ },
14
+ "./styles": "./dist/styles.css"
15
+ },
16
+ "source": "src/cta-link.tsx",
17
+ "dependencies": {
18
+ "classnames": "~2.5.0",
19
+ "@purpurds/action": "3.0.0",
20
+ "@purpurds/icon": "3.0.0",
21
+ "@purpurds/tokens": "3.0.0"
22
+ },
23
+ "devDependencies": {
24
+ "@rushstack/eslint-patch": "~1.7.0",
25
+ "@storybook/blocks": "~7.6.0",
26
+ "@storybook/react": "~7.6.0",
27
+ "@telia/base-rig": "~8.2.0",
28
+ "@telia/react-rig": "~3.2.0",
29
+ "@testing-library/dom": "~9.3.3",
30
+ "@testing-library/jest-dom": "~6.3.0",
31
+ "@testing-library/react": "~14.1.2",
32
+ "@types/node": "18",
33
+ "@types/react-dom": "~18.2.17",
34
+ "@types/react": "~18.2.42",
35
+ "eslint-plugin-testing-library": "~6.2.0",
36
+ "eslint": "~8.56.0",
37
+ "jsdom": "~22.1.0",
38
+ "lint-staged": "~10.5.3",
39
+ "prettier": "~2.8.8",
40
+ "react-dom": "~18.2.0",
41
+ "react": "~18.2.0",
42
+ "typescript": "~5.2.2",
43
+ "vite": "~5.0.6",
44
+ "vitest": "~1.2.0",
45
+ "@purpurds/component-rig": "1.0.0"
46
+ },
47
+ "scripts": {
48
+ "build:dev": "vite",
49
+ "build:watch": "vite build --watch",
50
+ "build": "rm -rf dist && vite build && vite build --mode systemjs",
51
+ "ci:build": "rushx build",
52
+ "coverage": "vitest run --coverage",
53
+ "lint:fix": "eslint . --fix",
54
+ "lint": "lint-staged --no-stash 2>&1",
55
+ "sbdev": "rush sbdev",
56
+ "test:unit": "vitest run --passWithNoTests",
57
+ "test:watch": "vitest --watch",
58
+ "test": "rushx test:unit",
59
+ "typecheck": "tsc -p ./tsconfig.json"
60
+ }
61
+ }
package/readme.mdx ADDED
@@ -0,0 +1,56 @@
1
+ import { Meta, Stories, ArgTypes, Primary, Subtitle } from "@storybook/blocks";
2
+
3
+ import * as CtaLinkStories from "./src/cta-link.stories";
4
+ import packageInfo from "./package.json";
5
+
6
+ <Meta name="Docs" title="Components/CtaLink" of={CtaLinkStories} />
7
+
8
+ # CtaLink
9
+
10
+ <Subtitle>Version {packageInfo.version}</Subtitle>
11
+
12
+ ### Showcase
13
+
14
+ <Primary />
15
+
16
+ ### Properties
17
+
18
+ <ArgTypes />
19
+
20
+ ### Installation
21
+
22
+ #### Via NPM
23
+
24
+ Add the dependency to your consumer app like `"@purpurds/cta-link": "x.y.z"`
25
+
26
+ #### From outside the monorepo (build-time)
27
+
28
+ To install this package, you need to setup access to the artifactory. [Click here to go to the guide on how to do that](https://github.com/telia-company/jfrog-documentation/blob/main/doc/JFrog/JFrog_Onboarding.md#getting-access-to-artifactory-and-other-jfrog-applications).
29
+
30
+ ---
31
+
32
+ In MyApp.tsx
33
+
34
+ ```tsx
35
+ import "@purpurds/tokens/index.css";
36
+ ```
37
+
38
+ and
39
+
40
+ ```tsx
41
+ import "@purpurds/cta-link/styles";
42
+ ```
43
+
44
+ In MyComponent.tsx
45
+
46
+ ```tsx
47
+ import { CtaLink } from "@purpurds/cta-link";
48
+
49
+ export const MyComponent = () => {
50
+ return (
51
+ <div>
52
+ <CtaLink {...someProps}>Some content</CtaLink>
53
+ </div>
54
+ );
55
+ };
56
+ ```
@@ -0,0 +1,5 @@
1
+ @import "@purpurds/action/src/action.scss";
2
+
3
+ .purpur-cta-link {
4
+ @include action();
5
+ }
@@ -0,0 +1,59 @@
1
+ import React from "react";
2
+ import { sizes, variants } from "@purpurds/action";
3
+ import type { Meta, StoryObj } from "@storybook/react";
4
+
5
+ import "@purpurds/icon/styles";
6
+ import { CtaLink } from "./cta-link";
7
+
8
+ const meta: Meta<typeof CtaLink> = {
9
+ title: "Components/CtaLink",
10
+ component: CtaLink,
11
+ parameters: {
12
+ design: [
13
+ {
14
+ name: "CtaLink",
15
+ type: "figma",
16
+ url: "https://www.figma.com/file/XEaIIFskrrxIBHMZDkIuIg/Purpur-DS---Component-library-%26-guidelines?type=design&node-id=34461%3A39919&mode=design",
17
+ },
18
+ ],
19
+ },
20
+ argTypes: {
21
+ fullWidth: { control: { type: "boolean" } },
22
+ size: {
23
+ options: sizes,
24
+ control: { type: "select" },
25
+ },
26
+ variant: {
27
+ options: variants,
28
+ control: { type: "select" },
29
+ },
30
+ ["data-testid"]: { control: { type: "text" } },
31
+ className: { control: { type: "text" } },
32
+ children: { control: { type: "text" } },
33
+ },
34
+ };
35
+ export default meta;
36
+
37
+ type Story = StoryObj<typeof CtaLink>;
38
+
39
+ export const Showcase: Story = {
40
+ args: {
41
+ children: "CTA Link label",
42
+ fullWidth: false,
43
+ variant: "primary",
44
+ href: "#telia",
45
+ },
46
+ };
47
+
48
+ export const CtaLinkWithOnlyIcon: Story = {
49
+ name: "CTA Link with only icon",
50
+ parameters: {
51
+ controls: { exclude: ["children"] },
52
+ },
53
+ args: {
54
+ variant: "primary",
55
+ iconOnly: true,
56
+ ["aria-label"]: "CTA Link label",
57
+ },
58
+ render: ({ ...args }) => <CtaLink {...args} />,
59
+ };
@@ -0,0 +1,63 @@
1
+ import React from "react";
2
+ import * as matchers from "@testing-library/jest-dom/matchers";
3
+ import { cleanup, render, screen } from "@testing-library/react";
4
+ import { afterEach, describe, expect, it, vi } from "vitest";
5
+
6
+ import { CtaLink } from "./cta-link";
7
+
8
+ expect.extend(matchers);
9
+
10
+ describe("CtaLink", () => {
11
+ afterEach(() => {
12
+ cleanup();
13
+ });
14
+
15
+ it("should render", () => {
16
+ render(
17
+ <CtaLink variant="primary" data-testid="cta-link">
18
+ Some text content
19
+ </CtaLink>
20
+ );
21
+
22
+ expect(screen.getByTestId("cta-link")).toHaveTextContent("Some text content");
23
+ });
24
+
25
+ it("should use correct class for primary variant", () => {
26
+ render(
27
+ <CtaLink variant="primary" data-testid="cta-link">
28
+ Some text content
29
+ </CtaLink>
30
+ );
31
+
32
+ expect(
33
+ screen.getByTestId("cta-link").classList.contains("purpur-cta-link--primary")
34
+ ).toBeTruthy();
35
+ });
36
+
37
+ it("should not render children if iconOnly", async () => {
38
+ render(
39
+ <CtaLink variant="secondary" iconOnly aria-label="CTA Link label">
40
+ Link Children
41
+ </CtaLink>
42
+ );
43
+ expect(await screen.queryByText("Link Children")).toBe(null);
44
+ });
45
+
46
+ it("renders href", async () => {
47
+ render(
48
+ <CtaLink variant="primary" href="#telia" data-testid="link">
49
+ Link
50
+ </CtaLink>
51
+ );
52
+ expect(screen.getByTestId("link").getAttribute("href")).toContain("#telia");
53
+ });
54
+
55
+ it("douesn't render href", async () => {
56
+ render(
57
+ <CtaLink variant="primary" data-testid="link">
58
+ Link
59
+ </CtaLink>
60
+ );
61
+ expect(screen.getByTestId("link").getAttribute("href")).toBe(null);
62
+ });
63
+ });
@@ -0,0 +1,42 @@
1
+ import React, { AnchorHTMLAttributes } from "react";
2
+ import { ActionProps, SIZE } from "@purpurds/action";
3
+ import { arrowRight, Icon } from "@purpurds/icon";
4
+ import c from "classnames";
5
+
6
+ import styles from "./cta-link.module.scss";
7
+
8
+ const rootClassName = "purpur-cta-link";
9
+
10
+ export const CtaLink = ({
11
+ children,
12
+ className,
13
+ ["data-testid"]: dataTestid,
14
+ fullWidth = false,
15
+ iconOnly,
16
+ size = SIZE.MD,
17
+ variant,
18
+ ...props
19
+ }: ActionProps & AnchorHTMLAttributes<HTMLAnchorElement>) => {
20
+ const classes = c(
21
+ [
22
+ className,
23
+ styles[rootClassName],
24
+ styles[`${rootClassName}--${variant}`],
25
+ styles[`${rootClassName}--${size}`],
26
+ ],
27
+ {
28
+ [styles[`${rootClassName}--icon-only`]]: iconOnly,
29
+ [styles[`${rootClassName}--negative`]]: variant.endsWith("negative"),
30
+ [styles[`${rootClassName}--full-width`]]: fullWidth,
31
+ }
32
+ );
33
+
34
+ const Tag = props.href ? "a" : "span";
35
+
36
+ return (
37
+ <Tag className={classes} data-testid={dataTestid} {...props}>
38
+ {children && !iconOnly && children}{" "}
39
+ <Icon svg={arrowRight} size={size === SIZE.LG ? "sm" : "xs"} />
40
+ </Tag>
41
+ );
42
+ };
@@ -0,0 +1,4 @@
1
+ declare module "*.scss" {
2
+ const styles: { [className: string]: string };
3
+ export default styles;
4
+ }