@sproutsocial/seeds-react-link 1.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.
- package/.eslintrc.js +4 -0
- package/.turbo/turbo-build.log +21 -0
- package/CHANGELOG.md +7 -0
- package/dist/esm/index.js +108 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +25 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +141 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +9 -0
- package/package.json +47 -0
- package/src/Link.tsx +45 -0
- package/src/LinkTypes.ts +28 -0
- package/src/__tests__/features.test.tsx +111 -0
- package/src/__tests__/types.test.tsx +47 -0
- package/src/constants.ts +14 -0
- package/src/index.stories.tsx +101 -0
- package/src/index.ts +6 -0
- package/src/styles.ts +56 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +12 -0
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
yarn run v1.22.22
|
|
2
|
+
$ tsup --dts
|
|
3
|
+
CLI Building entry: src/index.ts
|
|
4
|
+
CLI Using tsconfig: tsconfig.json
|
|
5
|
+
CLI tsup v8.0.2
|
|
6
|
+
CLI Using tsup config: /home/runner/work/seeds/seeds/seeds-react/seeds-react-link/tsup.config.ts
|
|
7
|
+
CLI Target: es2022
|
|
8
|
+
CLI Cleaning output folder
|
|
9
|
+
CJS Build start
|
|
10
|
+
ESM Build start
|
|
11
|
+
CJS dist/index.js 4.21 KB
|
|
12
|
+
CJS dist/index.js.map 5.41 KB
|
|
13
|
+
CJS ⚡️ Build success in 56ms
|
|
14
|
+
ESM dist/esm/index.js 2.27 KB
|
|
15
|
+
ESM dist/esm/index.js.map 5.38 KB
|
|
16
|
+
ESM ⚡️ Build success in 63ms
|
|
17
|
+
DTS Build start
|
|
18
|
+
DTS ⚡️ Build success in 18856ms
|
|
19
|
+
DTS dist/index.d.ts 1.25 KB
|
|
20
|
+
DTS dist/index.d.mts 1.25 KB
|
|
21
|
+
Done in 21.76s.
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// src/Link.tsx
|
|
2
|
+
import "react";
|
|
3
|
+
|
|
4
|
+
// src/styles.ts
|
|
5
|
+
import styled, { css } from "styled-components";
|
|
6
|
+
import {
|
|
7
|
+
TYPOGRAPHY,
|
|
8
|
+
COMMON,
|
|
9
|
+
FLEXBOX
|
|
10
|
+
} from "@sproutsocial/seeds-react-system-props";
|
|
11
|
+
import { focusRing, disabled } from "@sproutsocial/seeds-react-mixins";
|
|
12
|
+
import Text from "@sproutsocial/seeds-react-text";
|
|
13
|
+
var Container = styled(Text)`
|
|
14
|
+
border: 0;
|
|
15
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
16
|
+
text-decoration: ${(props) => props.underline ? "underline" : "none"};
|
|
17
|
+
appearance: none;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
${(props) => props.disabled && css`
|
|
20
|
+
opacity: 0.4;
|
|
21
|
+
cursor: not-allowed;
|
|
22
|
+
`}
|
|
23
|
+
font-weight: ${(props) => props.theme.fontWeights.semibold};
|
|
24
|
+
color: ${(props) => props.theme.colors.link.base};
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
28
|
+
text-decoration: underline;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&:active {
|
|
32
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:focus {
|
|
36
|
+
${focusRing}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&:focus:active {
|
|
40
|
+
box-shadow: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
${(props) => !props.href && css`
|
|
44
|
+
background: none;
|
|
45
|
+
`}
|
|
46
|
+
|
|
47
|
+
${(props) => props.disabled && disabled}
|
|
48
|
+
|
|
49
|
+
${COMMON}
|
|
50
|
+
${TYPOGRAPHY}
|
|
51
|
+
${FLEXBOX}
|
|
52
|
+
`;
|
|
53
|
+
var styles_default = Container;
|
|
54
|
+
|
|
55
|
+
// src/Link.tsx
|
|
56
|
+
import { jsx } from "react/jsx-runtime";
|
|
57
|
+
var Link = ({
|
|
58
|
+
href,
|
|
59
|
+
external,
|
|
60
|
+
children,
|
|
61
|
+
disabled: disabled2,
|
|
62
|
+
onClick,
|
|
63
|
+
as,
|
|
64
|
+
underline = true,
|
|
65
|
+
qa = {},
|
|
66
|
+
...rest
|
|
67
|
+
}) => {
|
|
68
|
+
if (!href && external) {
|
|
69
|
+
console.warn(
|
|
70
|
+
"Warning: external prop cannot be set without a href declaration"
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
const type = as || (href ? "a" : "button");
|
|
74
|
+
return /* @__PURE__ */ jsx(
|
|
75
|
+
styles_default,
|
|
76
|
+
{
|
|
77
|
+
href,
|
|
78
|
+
target: external ? "_blank" : void 0,
|
|
79
|
+
type: type === "button" ? "button" : void 0,
|
|
80
|
+
rel: external ? "noopener noreferrer" : void 0,
|
|
81
|
+
forwardedAs: type,
|
|
82
|
+
"aria-disabled": disabled2 ? disabled2 : void 0,
|
|
83
|
+
disabled: disabled2,
|
|
84
|
+
onClick,
|
|
85
|
+
underline,
|
|
86
|
+
"data-qa-link": "",
|
|
87
|
+
"data-qa-link-isdisabled": disabled2 === true,
|
|
88
|
+
...qa,
|
|
89
|
+
...rest,
|
|
90
|
+
children
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
var Link_default = Link;
|
|
95
|
+
|
|
96
|
+
// src/LinkTypes.ts
|
|
97
|
+
import "react";
|
|
98
|
+
|
|
99
|
+
// src/constants.ts
|
|
100
|
+
import { COLOR_BLUE_900 } from "@sproutsocial/seeds-color";
|
|
101
|
+
|
|
102
|
+
// src/index.ts
|
|
103
|
+
var src_default = Link_default;
|
|
104
|
+
export {
|
|
105
|
+
Link_default as Link,
|
|
106
|
+
src_default as default
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/Link.tsx","../../src/styles.ts","../../src/LinkTypes.ts","../../src/constants.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Container from \"./styles\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Link = ({\n href,\n external,\n children,\n disabled,\n onClick,\n as,\n underline = true,\n qa = {},\n ...rest\n}: TypeLinkProps) => {\n if (!href && external) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Warning: external prop cannot be set without a href declaration\"\n );\n }\n\n const type = as || (href ? \"a\" : \"button\");\n return (\n <Container\n href={href}\n target={external ? \"_blank\" : undefined}\n type={type === \"button\" ? \"button\" : undefined}\n rel={external ? \"noopener noreferrer\" : undefined}\n forwardedAs={type}\n aria-disabled={disabled ? disabled : undefined}\n disabled={disabled}\n onClick={onClick}\n underline={underline}\n data-qa-link=\"\"\n data-qa-link-isdisabled={disabled === true}\n {...qa}\n {...rest}\n >\n {children}\n </Container>\n );\n};\n\nexport default Link;\n","import styled, { css } from \"styled-components\";\nimport {\n TYPOGRAPHY,\n COMMON,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport { focusRing, disabled } from \"@sproutsocial/seeds-react-mixins\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Container = styled(Text)<TypeLinkProps>`\n border: 0;\n font-family: ${(props) => props.theme.fontFamily};\n text-decoration: ${(props) => (props.underline ? \"underline\" : \"none\")};\n appearance: none;\n cursor: pointer;\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n cursor: not-allowed;\n `}\n font-weight: ${(props) => props.theme.fontWeights.semibold};\n color: ${(props) => props.theme.colors.link.base};\n\n &:hover {\n color: ${(props) => props.theme.colors.link.hover};\n text-decoration: underline;\n }\n\n &:active {\n color: ${(props) => props.theme.colors.link.hover};\n }\n\n &:focus {\n ${focusRing}\n }\n\n &:focus:active {\n box-shadow: none;\n }\n\n ${(props) =>\n !props.href &&\n css`\n background: none;\n `}\n\n ${(props) => props.disabled && disabled}\n\n ${COMMON}\n ${TYPOGRAPHY}\n ${FLEXBOX}\n`;\n\nexport default Container;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeTextProps } from \"@sproutsocial/seeds-react-text\";\nimport type { TypeSystemFlexboxProps } from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeLinkProps\n extends Omit<\n TypeTextProps,\n keyof Omit<React.ComponentPropsWithoutRef<\"span\">, \"color\">\n >,\n Omit<React.ComponentPropsWithoutRef<\"button\">, \"color\">,\n TypeSystemFlexboxProps {\n /** Optional prop to make the URL open in a new tab */\n external?: boolean;\n children: React.ReactNode;\n\n /** Setting this prop will cause the component to be rendered as a link */\n href?: string;\n\n /** Disables user action and applies a disabled style to the component */\n disabled?: boolean;\n\n /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */\n onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;\n as?: TypeStyledComponentsCommonProps[\"as\"];\n underline?: boolean;\n qa?: { [key: string]: unknown }; // should this be string|number?\n}\n","import { COLOR_BLUE_900 } from \"@sproutsocial/seeds-color\";\n\nconst defaultLink = {\n color: \"link\",\n hoverColor: \"link.hover\",\n activeColor: COLOR_BLUE_900,\n fontWeight: \"semibold\",\n};\n\nconst linkTheme = {\n default: defaultLink,\n};\n\nexport default linkTheme;\n","import Link from \"./Link\";\n\nexport default Link;\nexport { Link };\nexport * from \"./LinkTypes\";\nexport * from \"./constants\";\n"],"mappings":";AAAA,OAAuB;;;ACAvB,OAAO,UAAU,WAAW;AAC5B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,WAAW,gBAAgB;AACpC,OAAO,UAAU;AAGjB,IAAM,YAAY,OAAO,IAAI;AAAA;AAAA,iBAEZ,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA,qBAC7B,CAAC,UAAW,MAAM,YAAY,cAAc,MAAO;AAAA;AAAA;AAAA,IAGpE,CAAC,UACD,MAAM,YACN;AAAA;AAAA;AAAA,KAGC;AAAA,iBACY,CAAC,UAAU,MAAM,MAAM,YAAY,QAAQ;AAAA,WACjD,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA,aAGrC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA,MAI/C,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOX,CAAC,UACD,CAAC,MAAM,QACP;AAAA;AAAA,KAEC;AAAA;AAAA,IAED,CAAC,UAAU,MAAM,YAAY,QAAQ;AAAA;AAAA,KAEpC,MAAM;AAAA,KACN,UAAU;AAAA,KACV,OAAO;AAAA;AAGZ,IAAO,iBAAQ;;;AD/BX;AApBJ,IAAM,OAAO,CAAC;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAA;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,KAAK,CAAC;AAAA,EACN,GAAG;AACL,MAAqB;AACnB,MAAI,CAAC,QAAQ,UAAU;AAErB,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,OAAO,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,WAAW,WAAW;AAAA,MAC9B,MAAM,SAAS,WAAW,WAAW;AAAA,MACrC,KAAK,WAAW,wBAAwB;AAAA,MACxC,aAAa;AAAA,MACb,iBAAeA,YAAWA,YAAW;AAAA,MACrC,UAAUA;AAAA,MACV;AAAA,MACA;AAAA,MACA,gBAAa;AAAA,MACb,2BAAyBA,cAAa;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE5Cf,OAAuB;;;ACAvB,SAAS,sBAAsB;;;ACE/B,IAAO,cAAQ;","names":["disabled"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { TypeSystemFlexboxProps, TypeStyledComponentsCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
|
+
import { TypeTextProps } from '@sproutsocial/seeds-react-text';
|
|
5
|
+
|
|
6
|
+
interface TypeLinkProps extends Omit<TypeTextProps, keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">>, Omit<React.ComponentPropsWithoutRef<"button">, "color">, TypeSystemFlexboxProps {
|
|
7
|
+
/** Optional prop to make the URL open in a new tab */
|
|
8
|
+
external?: boolean;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
/** Setting this prop will cause the component to be rendered as a link */
|
|
11
|
+
href?: string;
|
|
12
|
+
/** Disables user action and applies a disabled style to the component */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
|
|
15
|
+
onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
|
|
16
|
+
as?: TypeStyledComponentsCommonProps["as"];
|
|
17
|
+
underline?: boolean;
|
|
18
|
+
qa?: {
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare const Link: ({ href, external, children, disabled, onClick, as, underline, qa, ...rest }: TypeLinkProps) => react_jsx_runtime.JSX.Element;
|
|
24
|
+
|
|
25
|
+
export { Link, type TypeLinkProps, Link as default };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { TypeSystemFlexboxProps, TypeStyledComponentsCommonProps } from '@sproutsocial/seeds-react-system-props';
|
|
4
|
+
import { TypeTextProps } from '@sproutsocial/seeds-react-text';
|
|
5
|
+
|
|
6
|
+
interface TypeLinkProps extends Omit<TypeTextProps, keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">>, Omit<React.ComponentPropsWithoutRef<"button">, "color">, TypeSystemFlexboxProps {
|
|
7
|
+
/** Optional prop to make the URL open in a new tab */
|
|
8
|
+
external?: boolean;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
/** Setting this prop will cause the component to be rendered as a link */
|
|
11
|
+
href?: string;
|
|
12
|
+
/** Disables user action and applies a disabled style to the component */
|
|
13
|
+
disabled?: boolean;
|
|
14
|
+
/** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
|
|
15
|
+
onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
|
|
16
|
+
as?: TypeStyledComponentsCommonProps["as"];
|
|
17
|
+
underline?: boolean;
|
|
18
|
+
qa?: {
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
declare const Link: ({ href, external, children, disabled, onClick, as, underline, qa, ...rest }: TypeLinkProps) => react_jsx_runtime.JSX.Element;
|
|
24
|
+
|
|
25
|
+
export { Link, type TypeLinkProps, Link as default };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var src_exports = {};
|
|
32
|
+
__export(src_exports, {
|
|
33
|
+
Link: () => Link_default,
|
|
34
|
+
default: () => src_default
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(src_exports);
|
|
37
|
+
|
|
38
|
+
// src/Link.tsx
|
|
39
|
+
var React = require("react");
|
|
40
|
+
|
|
41
|
+
// src/styles.ts
|
|
42
|
+
var import_styled_components = __toESM(require("styled-components"));
|
|
43
|
+
var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
|
|
44
|
+
var import_seeds_react_mixins = require("@sproutsocial/seeds-react-mixins");
|
|
45
|
+
var import_seeds_react_text = __toESM(require("@sproutsocial/seeds-react-text"));
|
|
46
|
+
var Container = (0, import_styled_components.default)(import_seeds_react_text.default)`
|
|
47
|
+
border: 0;
|
|
48
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
49
|
+
text-decoration: ${(props) => props.underline ? "underline" : "none"};
|
|
50
|
+
appearance: none;
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
${(props) => props.disabled && import_styled_components.css`
|
|
53
|
+
opacity: 0.4;
|
|
54
|
+
cursor: not-allowed;
|
|
55
|
+
`}
|
|
56
|
+
font-weight: ${(props) => props.theme.fontWeights.semibold};
|
|
57
|
+
color: ${(props) => props.theme.colors.link.base};
|
|
58
|
+
|
|
59
|
+
&:hover {
|
|
60
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
61
|
+
text-decoration: underline;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&:active {
|
|
65
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
&:focus {
|
|
69
|
+
${import_seeds_react_mixins.focusRing}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
&:focus:active {
|
|
73
|
+
box-shadow: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
${(props) => !props.href && import_styled_components.css`
|
|
77
|
+
background: none;
|
|
78
|
+
`}
|
|
79
|
+
|
|
80
|
+
${(props) => props.disabled && import_seeds_react_mixins.disabled}
|
|
81
|
+
|
|
82
|
+
${import_seeds_react_system_props.COMMON}
|
|
83
|
+
${import_seeds_react_system_props.TYPOGRAPHY}
|
|
84
|
+
${import_seeds_react_system_props.FLEXBOX}
|
|
85
|
+
`;
|
|
86
|
+
var styles_default = Container;
|
|
87
|
+
|
|
88
|
+
// src/Link.tsx
|
|
89
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
90
|
+
var Link = ({
|
|
91
|
+
href,
|
|
92
|
+
external,
|
|
93
|
+
children,
|
|
94
|
+
disabled: disabled2,
|
|
95
|
+
onClick,
|
|
96
|
+
as,
|
|
97
|
+
underline = true,
|
|
98
|
+
qa = {},
|
|
99
|
+
...rest
|
|
100
|
+
}) => {
|
|
101
|
+
if (!href && external) {
|
|
102
|
+
console.warn(
|
|
103
|
+
"Warning: external prop cannot be set without a href declaration"
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const type = as || (href ? "a" : "button");
|
|
107
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
108
|
+
styles_default,
|
|
109
|
+
{
|
|
110
|
+
href,
|
|
111
|
+
target: external ? "_blank" : void 0,
|
|
112
|
+
type: type === "button" ? "button" : void 0,
|
|
113
|
+
rel: external ? "noopener noreferrer" : void 0,
|
|
114
|
+
forwardedAs: type,
|
|
115
|
+
"aria-disabled": disabled2 ? disabled2 : void 0,
|
|
116
|
+
disabled: disabled2,
|
|
117
|
+
onClick,
|
|
118
|
+
underline,
|
|
119
|
+
"data-qa-link": "",
|
|
120
|
+
"data-qa-link-isdisabled": disabled2 === true,
|
|
121
|
+
...qa,
|
|
122
|
+
...rest,
|
|
123
|
+
children
|
|
124
|
+
}
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
var Link_default = Link;
|
|
128
|
+
|
|
129
|
+
// src/LinkTypes.ts
|
|
130
|
+
var React2 = require("react");
|
|
131
|
+
|
|
132
|
+
// src/constants.ts
|
|
133
|
+
var import_seeds_color = require("@sproutsocial/seeds-color");
|
|
134
|
+
|
|
135
|
+
// src/index.ts
|
|
136
|
+
var src_default = Link_default;
|
|
137
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
138
|
+
0 && (module.exports = {
|
|
139
|
+
Link
|
|
140
|
+
});
|
|
141
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Link.tsx","../src/styles.ts","../src/LinkTypes.ts","../src/constants.ts"],"sourcesContent":["import Link from \"./Link\";\n\nexport default Link;\nexport { Link };\nexport * from \"./LinkTypes\";\nexport * from \"./constants\";\n","import * as React from \"react\";\nimport Container from \"./styles\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Link = ({\n href,\n external,\n children,\n disabled,\n onClick,\n as,\n underline = true,\n qa = {},\n ...rest\n}: TypeLinkProps) => {\n if (!href && external) {\n // eslint-disable-next-line no-console\n console.warn(\n \"Warning: external prop cannot be set without a href declaration\"\n );\n }\n\n const type = as || (href ? \"a\" : \"button\");\n return (\n <Container\n href={href}\n target={external ? \"_blank\" : undefined}\n type={type === \"button\" ? \"button\" : undefined}\n rel={external ? \"noopener noreferrer\" : undefined}\n forwardedAs={type}\n aria-disabled={disabled ? disabled : undefined}\n disabled={disabled}\n onClick={onClick}\n underline={underline}\n data-qa-link=\"\"\n data-qa-link-isdisabled={disabled === true}\n {...qa}\n {...rest}\n >\n {children}\n </Container>\n );\n};\n\nexport default Link;\n","import styled, { css } from \"styled-components\";\nimport {\n TYPOGRAPHY,\n COMMON,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport { focusRing, disabled } from \"@sproutsocial/seeds-react-mixins\";\nimport Text from \"@sproutsocial/seeds-react-text\";\nimport type { TypeLinkProps } from \"./LinkTypes\";\n\nconst Container = styled(Text)<TypeLinkProps>`\n border: 0;\n font-family: ${(props) => props.theme.fontFamily};\n text-decoration: ${(props) => (props.underline ? \"underline\" : \"none\")};\n appearance: none;\n cursor: pointer;\n ${(props) =>\n props.disabled &&\n css`\n opacity: 0.4;\n cursor: not-allowed;\n `}\n font-weight: ${(props) => props.theme.fontWeights.semibold};\n color: ${(props) => props.theme.colors.link.base};\n\n &:hover {\n color: ${(props) => props.theme.colors.link.hover};\n text-decoration: underline;\n }\n\n &:active {\n color: ${(props) => props.theme.colors.link.hover};\n }\n\n &:focus {\n ${focusRing}\n }\n\n &:focus:active {\n box-shadow: none;\n }\n\n ${(props) =>\n !props.href &&\n css`\n background: none;\n `}\n\n ${(props) => props.disabled && disabled}\n\n ${COMMON}\n ${TYPOGRAPHY}\n ${FLEXBOX}\n`;\n\nexport default Container;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeTextProps } from \"@sproutsocial/seeds-react-text\";\nimport type { TypeSystemFlexboxProps } from \"@sproutsocial/seeds-react-system-props\";\n\nexport interface TypeLinkProps\n extends Omit<\n TypeTextProps,\n keyof Omit<React.ComponentPropsWithoutRef<\"span\">, \"color\">\n >,\n Omit<React.ComponentPropsWithoutRef<\"button\">, \"color\">,\n TypeSystemFlexboxProps {\n /** Optional prop to make the URL open in a new tab */\n external?: boolean;\n children: React.ReactNode;\n\n /** Setting this prop will cause the component to be rendered as a link */\n href?: string;\n\n /** Disables user action and applies a disabled style to the component */\n disabled?: boolean;\n\n /** Can be used in addition to an href but still renders as a link. Omitting href will render as button */\n onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;\n as?: TypeStyledComponentsCommonProps[\"as\"];\n underline?: boolean;\n qa?: { [key: string]: unknown }; // should this be string|number?\n}\n","import { COLOR_BLUE_900 } from \"@sproutsocial/seeds-color\";\n\nconst defaultLink = {\n color: \"link\",\n hoverColor: \"link.hover\",\n activeColor: COLOR_BLUE_900,\n fontWeight: \"semibold\",\n};\n\nconst linkTheme = {\n default: defaultLink,\n};\n\nexport default linkTheme;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;;;ACAvB,+BAA4B;AAC5B,sCAIO;AACP,gCAAoC;AACpC,8BAAiB;AAGjB,IAAM,gBAAY,yBAAAA,SAAO,wBAAAC,OAAI;AAAA;AAAA,iBAEZ,CAAC,UAAU,MAAM,MAAM,UAAU;AAAA,qBAC7B,CAAC,UAAW,MAAM,YAAY,cAAc,MAAO;AAAA;AAAA;AAAA,IAGpE,CAAC,UACD,MAAM,YACN;AAAA;AAAA;AAAA,KAGC;AAAA,iBACY,CAAC,UAAU,MAAM,MAAM,YAAY,QAAQ;AAAA,WACjD,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,IAAI;AAAA;AAAA;AAAA,aAGrC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,aAKxC,CAAC,UAAU,MAAM,MAAM,OAAO,KAAK,KAAK;AAAA;AAAA;AAAA;AAAA,MAI/C,mCAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOX,CAAC,UACD,CAAC,MAAM,QACP;AAAA;AAAA,KAEC;AAAA;AAAA,IAED,CAAC,UAAU,MAAM,YAAY,kCAAQ;AAAA;AAAA,KAEpC,sCAAM;AAAA,KACN,0CAAU;AAAA,KACV,uCAAO;AAAA;AAGZ,IAAO,iBAAQ;;;AD/BX;AApBJ,IAAM,OAAO,CAAC;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAAC;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ,KAAK,CAAC;AAAA,EACN,GAAG;AACL,MAAqB;AACnB,MAAI,CAAC,QAAQ,UAAU;AAErB,YAAQ;AAAA,MACN;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,OAAO,OAAO,MAAM;AACjC,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,QAAQ,WAAW,WAAW;AAAA,MAC9B,MAAM,SAAS,WAAW,WAAW;AAAA,MACrC,KAAK,WAAW,wBAAwB;AAAA,MACxC,aAAa;AAAA,MACb,iBAAeA,YAAWA,YAAW;AAAA,MACrC,UAAUA;AAAA,MACV;AAAA,MACA;AAAA,MACA,gBAAa;AAAA,MACb,2BAAyBA,cAAa;AAAA,MACrC,GAAG;AAAA,MACH,GAAG;AAAA,MAEH;AAAA;AAAA,EACH;AAEJ;AAEA,IAAO,eAAQ;;;AE5Cf,IAAAC,SAAuB;;;ACAvB,yBAA+B;;;AJE/B,IAAO,cAAQ;","names":["styled","Text","disabled","React"]}
|
package/jest.config.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sproutsocial/seeds-react-link",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Seeds React Link",
|
|
5
|
+
"author": "Sprout Social, Inc.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/esm/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsup --dts",
|
|
12
|
+
"build:debug": "tsup --dts --metafile",
|
|
13
|
+
"dev": "tsup --watch --dts",
|
|
14
|
+
"clean": "rm -rf .turbo dist",
|
|
15
|
+
"clean:modules": "rm -rf node_modules",
|
|
16
|
+
"typecheck": "tsc --noEmit",
|
|
17
|
+
"test": "jest",
|
|
18
|
+
"test:watch": "jest --watch --coverage=false"
|
|
19
|
+
},
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@sproutsocial/seeds-react-theme": "^*",
|
|
22
|
+
"@sproutsocial/seeds-react-system-props": "^*",
|
|
23
|
+
"@sproutsocial/seeds-react-mixins": "*",
|
|
24
|
+
"@sproutsocial/seeds-react-text": "*",
|
|
25
|
+
"@sproutsocial/seeds-color": "*"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/react": "^18.0.0",
|
|
29
|
+
"@types/styled-components": "^5.1.26",
|
|
30
|
+
"@sproutsocial/eslint-config-seeds": "*",
|
|
31
|
+
"react": "^18.0.0",
|
|
32
|
+
"styled-components": "^5.2.3",
|
|
33
|
+
"tsup": "^8.0.2",
|
|
34
|
+
"typescript": "^5.6.2",
|
|
35
|
+
"@sproutsocial/seeds-tsconfig": "*",
|
|
36
|
+
"@sproutsocial/seeds-testing": "*",
|
|
37
|
+
"@sproutsocial/seeds-react-testing-library": "*",
|
|
38
|
+
"@sproutsocial/seeds-react-icon": "*",
|
|
39
|
+
"@sproutsocial/seeds-react-box": "*"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"styled-components": "^5.2.3"
|
|
43
|
+
},
|
|
44
|
+
"engines": {
|
|
45
|
+
"node": ">=18"
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/Link.tsx
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import Container from "./styles";
|
|
3
|
+
import type { TypeLinkProps } from "./LinkTypes";
|
|
4
|
+
|
|
5
|
+
const Link = ({
|
|
6
|
+
href,
|
|
7
|
+
external,
|
|
8
|
+
children,
|
|
9
|
+
disabled,
|
|
10
|
+
onClick,
|
|
11
|
+
as,
|
|
12
|
+
underline = true,
|
|
13
|
+
qa = {},
|
|
14
|
+
...rest
|
|
15
|
+
}: TypeLinkProps) => {
|
|
16
|
+
if (!href && external) {
|
|
17
|
+
// eslint-disable-next-line no-console
|
|
18
|
+
console.warn(
|
|
19
|
+
"Warning: external prop cannot be set without a href declaration"
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const type = as || (href ? "a" : "button");
|
|
24
|
+
return (
|
|
25
|
+
<Container
|
|
26
|
+
href={href}
|
|
27
|
+
target={external ? "_blank" : undefined}
|
|
28
|
+
type={type === "button" ? "button" : undefined}
|
|
29
|
+
rel={external ? "noopener noreferrer" : undefined}
|
|
30
|
+
forwardedAs={type}
|
|
31
|
+
aria-disabled={disabled ? disabled : undefined}
|
|
32
|
+
disabled={disabled}
|
|
33
|
+
onClick={onClick}
|
|
34
|
+
underline={underline}
|
|
35
|
+
data-qa-link=""
|
|
36
|
+
data-qa-link-isdisabled={disabled === true}
|
|
37
|
+
{...qa}
|
|
38
|
+
{...rest}
|
|
39
|
+
>
|
|
40
|
+
{children}
|
|
41
|
+
</Container>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default Link;
|
package/src/LinkTypes.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { TypeStyledComponentsCommonProps } from "@sproutsocial/seeds-react-system-props";
|
|
3
|
+
import type { TypeTextProps } from "@sproutsocial/seeds-react-text";
|
|
4
|
+
import type { TypeSystemFlexboxProps } from "@sproutsocial/seeds-react-system-props";
|
|
5
|
+
|
|
6
|
+
export interface TypeLinkProps
|
|
7
|
+
extends Omit<
|
|
8
|
+
TypeTextProps,
|
|
9
|
+
keyof Omit<React.ComponentPropsWithoutRef<"span">, "color">
|
|
10
|
+
>,
|
|
11
|
+
Omit<React.ComponentPropsWithoutRef<"button">, "color">,
|
|
12
|
+
TypeSystemFlexboxProps {
|
|
13
|
+
/** Optional prop to make the URL open in a new tab */
|
|
14
|
+
external?: boolean;
|
|
15
|
+
children: React.ReactNode;
|
|
16
|
+
|
|
17
|
+
/** Setting this prop will cause the component to be rendered as a link */
|
|
18
|
+
href?: string;
|
|
19
|
+
|
|
20
|
+
/** Disables user action and applies a disabled style to the component */
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
|
|
23
|
+
/** Can be used in addition to an href but still renders as a link. Omitting href will render as button */
|
|
24
|
+
onClick?: (e: React.SyntheticEvent<HTMLButtonElement>) => void;
|
|
25
|
+
as?: TypeStyledComponentsCommonProps["as"];
|
|
26
|
+
underline?: boolean;
|
|
27
|
+
qa?: { [key: string]: unknown }; // should this be string|number?
|
|
28
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { TYPOGRAPHY_SIZE_600 } from "@sproutsocial/seeds-typography";
|
|
3
|
+
import { render, screen } from "@sproutsocial/seeds-react-testing-library";
|
|
4
|
+
import Link from "../Link";
|
|
5
|
+
|
|
6
|
+
describe("Racine Link", () => {
|
|
7
|
+
it("should render in an anchor tag", () => {
|
|
8
|
+
render(
|
|
9
|
+
<Link href="http://sproutsocial.style" external>
|
|
10
|
+
Link
|
|
11
|
+
</Link>
|
|
12
|
+
);
|
|
13
|
+
expect(screen.getByText("Link")).toBeInTheDocument();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it("should render disabled", () => {
|
|
17
|
+
render(
|
|
18
|
+
<>
|
|
19
|
+
<Link>Regular Link</Link>
|
|
20
|
+
<Link disabled>Disabled Link</Link>
|
|
21
|
+
</>
|
|
22
|
+
);
|
|
23
|
+
expect(screen.getByText("Regular Link")).toBeEnabled();
|
|
24
|
+
expect(screen.getByText("Disabled Link")).toBeDisabled();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it("setting external to prop true should add target blank attribute to anchor", () => {
|
|
28
|
+
render(
|
|
29
|
+
<Link href="http://sproutsocial.com" external>
|
|
30
|
+
Link
|
|
31
|
+
</Link>
|
|
32
|
+
);
|
|
33
|
+
expect(screen.getByText("Link").closest("a")?.target).toEqual("_blank");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("setting external to prop true should add rel='noopener' attribute", () => {
|
|
37
|
+
render(
|
|
38
|
+
<Link href="http://sproutsocial.com" external>
|
|
39
|
+
Link
|
|
40
|
+
</Link>
|
|
41
|
+
);
|
|
42
|
+
expect(screen.getByText("Link").closest("a")?.rel).toEqual(
|
|
43
|
+
"noopener noreferrer"
|
|
44
|
+
);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it("setting a onClick instead of href renders component as a Button", () => {
|
|
48
|
+
render(
|
|
49
|
+
<Link
|
|
50
|
+
onClick={() => {
|
|
51
|
+
// eslint-disable-next-line no-console
|
|
52
|
+
console.log("Button");
|
|
53
|
+
}}
|
|
54
|
+
>
|
|
55
|
+
Am I a button?
|
|
56
|
+
</Link>
|
|
57
|
+
);
|
|
58
|
+
expect(screen.getByText("Am I a button?").tagName).toEqual("BUTTON");
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it("setting both href and onClick renders component as an Anchor", () => {
|
|
62
|
+
render(
|
|
63
|
+
<Link
|
|
64
|
+
href="http://sproutsocial.com"
|
|
65
|
+
onClick={() => {
|
|
66
|
+
// eslint-disable-next-line no-console
|
|
67
|
+
console.log("Button");
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
Am I a button?
|
|
71
|
+
</Link>
|
|
72
|
+
);
|
|
73
|
+
expect(screen.getByText("Am I a button?").tagName).toEqual("A");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("Using the 'as' prop works as expected and retains styles from Text and Link", () => {
|
|
77
|
+
render(
|
|
78
|
+
<Link
|
|
79
|
+
as="span"
|
|
80
|
+
fontSize={600}
|
|
81
|
+
href="//sproutsocial.com/seeds/components/link"
|
|
82
|
+
>
|
|
83
|
+
Link as span
|
|
84
|
+
</Link>
|
|
85
|
+
);
|
|
86
|
+
expect(screen.getByText("Link as span").tagName).toEqual("SPAN");
|
|
87
|
+
expect(screen.getByText("Link as span")).toHaveStyleRule(
|
|
88
|
+
"font-size",
|
|
89
|
+
TYPOGRAPHY_SIZE_600.fontSize
|
|
90
|
+
);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("Has type attribute as button when rendered as a button element", () => {
|
|
94
|
+
render(<Link>Link</Link>);
|
|
95
|
+
expect(screen.getByDataQaLabel({ link: "" }).tagName).toEqual("BUTTON");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("Does not have type attribute when rendered as an anchor element", () => {
|
|
99
|
+
render(<Link href="google.com">Link</Link>);
|
|
100
|
+
expect(screen.getByDataQaLabel({ link: "" })).not.toHaveAttribute("type");
|
|
101
|
+
expect(screen.getByDataQaLabel({ link: "" }).tagName).not.toEqual("BUTTON");
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it("Can render with an underline", () => {
|
|
105
|
+
render(<Link underline>Link</Link>);
|
|
106
|
+
expect(screen.getByText("Link")).toHaveStyleRule(
|
|
107
|
+
"text-decoration",
|
|
108
|
+
"underline"
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React, { Fragment } from "react";
|
|
2
|
+
import { render } from "@sproutsocial/seeds-react-testing-library";
|
|
3
|
+
import Link from "../Link";
|
|
4
|
+
|
|
5
|
+
describe("Link Types", () => {
|
|
6
|
+
it("should render valid props", () => {
|
|
7
|
+
render(
|
|
8
|
+
<Fragment>
|
|
9
|
+
<Link href="http://sproutsocial.style">Link</Link>
|
|
10
|
+
<Link href="http://sproutsocial.style" external={false}>
|
|
11
|
+
Link
|
|
12
|
+
</Link>
|
|
13
|
+
<Link href="http://sproutsocial.style" external>
|
|
14
|
+
Link
|
|
15
|
+
</Link>
|
|
16
|
+
<Link href="#anchor">Link</Link>
|
|
17
|
+
<Link onClick={jest.fn()}>Link</Link>
|
|
18
|
+
<Link
|
|
19
|
+
fontSize={200}
|
|
20
|
+
fontWeight="bold"
|
|
21
|
+
color="text.subtext"
|
|
22
|
+
href="#anchor"
|
|
23
|
+
>
|
|
24
|
+
Link
|
|
25
|
+
</Link>
|
|
26
|
+
<Link
|
|
27
|
+
title="title"
|
|
28
|
+
fontSize={200}
|
|
29
|
+
fontWeight="bold"
|
|
30
|
+
href="#anchor"
|
|
31
|
+
external
|
|
32
|
+
truncated
|
|
33
|
+
ml="300"
|
|
34
|
+
style={{ whiteSpace: "nowrap" }}
|
|
35
|
+
>
|
|
36
|
+
Link
|
|
37
|
+
</Link>
|
|
38
|
+
{/* @ts-expect-error -test that childess is rejected */}
|
|
39
|
+
<Link fontSize={200} fontWeight="bold" href="#anchor" />
|
|
40
|
+
{/* @ts-expect-error -test that improper front size is rejected */}
|
|
41
|
+
<Link fontSize="12" href="link.com">
|
|
42
|
+
Link
|
|
43
|
+
</Link>
|
|
44
|
+
</Fragment>
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
});
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { COLOR_BLUE_900 } from "@sproutsocial/seeds-color";
|
|
2
|
+
|
|
3
|
+
const defaultLink = {
|
|
4
|
+
color: "link",
|
|
5
|
+
hoverColor: "link.hover",
|
|
6
|
+
activeColor: COLOR_BLUE_900,
|
|
7
|
+
fontWeight: "semibold",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
const linkTheme = {
|
|
11
|
+
default: defaultLink,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default linkTheme;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
// @ts-ignore-next-line: TS hates that this isn't part of the package.json vite magic
|
|
3
|
+
import { Banner } from "@sproutsocial/seeds-react-banner";
|
|
4
|
+
import { Box } from "@sproutsocial/seeds-react-box";
|
|
5
|
+
import { Icon } from "@sproutsocial/seeds-react-icon";
|
|
6
|
+
import { Link } from "./";
|
|
7
|
+
import { Text } from "@sproutsocial/seeds-react-text";
|
|
8
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
9
|
+
|
|
10
|
+
const meta: Meta<typeof Link> = {
|
|
11
|
+
title: "Components/Link",
|
|
12
|
+
component: Link,
|
|
13
|
+
args: {
|
|
14
|
+
href: "?path=/story/components-button--primary",
|
|
15
|
+
children: "Normal link",
|
|
16
|
+
external: false,
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default meta;
|
|
21
|
+
|
|
22
|
+
type Story = StoryObj<typeof Link>;
|
|
23
|
+
|
|
24
|
+
export const NormalLink: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
href: "?path=/story/components-button--primary",
|
|
27
|
+
children: "Normal link",
|
|
28
|
+
external: false,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const ExternalLink: Story = {
|
|
33
|
+
render: (args) => (
|
|
34
|
+
<Link {...args}>
|
|
35
|
+
<Box display="flex" alignItems="center">
|
|
36
|
+
External link
|
|
37
|
+
<Icon
|
|
38
|
+
ml={200}
|
|
39
|
+
size="mini"
|
|
40
|
+
name="arrow-right-up-solid"
|
|
41
|
+
role={undefined}
|
|
42
|
+
svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
|
|
43
|
+
/>
|
|
44
|
+
</Box>
|
|
45
|
+
</Link>
|
|
46
|
+
),
|
|
47
|
+
args: {
|
|
48
|
+
href: "#YouClickedAnExternalLink",
|
|
49
|
+
external: true,
|
|
50
|
+
children: "Opens in a new tab",
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const LinkAsAButton: Story = {
|
|
55
|
+
render: (args) => (
|
|
56
|
+
<Link
|
|
57
|
+
onClick={() => {
|
|
58
|
+
alert("You clicked a Button that looks like a Link!");
|
|
59
|
+
}}
|
|
60
|
+
>
|
|
61
|
+
{args.children}
|
|
62
|
+
</Link>
|
|
63
|
+
),
|
|
64
|
+
args: {
|
|
65
|
+
children: "Primary Link",
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const UnderlinedLink: Story = {
|
|
70
|
+
render: (args) => <Link underline={false}>{args.children}</Link>,
|
|
71
|
+
args: {
|
|
72
|
+
children: "Link underline set to false",
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const DecorativeBackgrounds: Story = {
|
|
77
|
+
render: () => (
|
|
78
|
+
<Banner
|
|
79
|
+
text={
|
|
80
|
+
<Box
|
|
81
|
+
width={1}
|
|
82
|
+
display="flex"
|
|
83
|
+
alignItems="center"
|
|
84
|
+
justifyContent="space-between"
|
|
85
|
+
>
|
|
86
|
+
<Text>Banners use decorative backgrounds</Text>
|
|
87
|
+
<Link external href="https://seeds.sproutsocial.com/components/link">
|
|
88
|
+
Links use text.body
|
|
89
|
+
<Icon
|
|
90
|
+
ml={200}
|
|
91
|
+
size="mini"
|
|
92
|
+
name="arrow-right-up-solid"
|
|
93
|
+
role={undefined}
|
|
94
|
+
svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
|
|
95
|
+
/>
|
|
96
|
+
</Link>
|
|
97
|
+
</Box>
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
),
|
|
101
|
+
};
|
package/src/index.ts
ADDED
package/src/styles.ts
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import styled, { css } from "styled-components";
|
|
2
|
+
import {
|
|
3
|
+
TYPOGRAPHY,
|
|
4
|
+
COMMON,
|
|
5
|
+
FLEXBOX,
|
|
6
|
+
} from "@sproutsocial/seeds-react-system-props";
|
|
7
|
+
import { focusRing, disabled } from "@sproutsocial/seeds-react-mixins";
|
|
8
|
+
import Text from "@sproutsocial/seeds-react-text";
|
|
9
|
+
import type { TypeLinkProps } from "./LinkTypes";
|
|
10
|
+
|
|
11
|
+
const Container = styled(Text)<TypeLinkProps>`
|
|
12
|
+
border: 0;
|
|
13
|
+
font-family: ${(props) => props.theme.fontFamily};
|
|
14
|
+
text-decoration: ${(props) => (props.underline ? "underline" : "none")};
|
|
15
|
+
appearance: none;
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
${(props) =>
|
|
18
|
+
props.disabled &&
|
|
19
|
+
css`
|
|
20
|
+
opacity: 0.4;
|
|
21
|
+
cursor: not-allowed;
|
|
22
|
+
`}
|
|
23
|
+
font-weight: ${(props) => props.theme.fontWeights.semibold};
|
|
24
|
+
color: ${(props) => props.theme.colors.link.base};
|
|
25
|
+
|
|
26
|
+
&:hover {
|
|
27
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
28
|
+
text-decoration: underline;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&:active {
|
|
32
|
+
color: ${(props) => props.theme.colors.link.hover};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
&:focus {
|
|
36
|
+
${focusRing}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
&:focus:active {
|
|
40
|
+
box-shadow: none;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
${(props) =>
|
|
44
|
+
!props.href &&
|
|
45
|
+
css`
|
|
46
|
+
background: none;
|
|
47
|
+
`}
|
|
48
|
+
|
|
49
|
+
${(props) => props.disabled && disabled}
|
|
50
|
+
|
|
51
|
+
${COMMON}
|
|
52
|
+
${TYPOGRAPHY}
|
|
53
|
+
${FLEXBOX}
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
export default Container;
|
package/tsconfig.json
ADDED
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { defineConfig } from "tsup";
|
|
2
|
+
|
|
3
|
+
export default defineConfig((options) => ({
|
|
4
|
+
entry: ["src/index.ts"],
|
|
5
|
+
format: ["cjs", "esm"],
|
|
6
|
+
clean: true,
|
|
7
|
+
legacyOutput: true,
|
|
8
|
+
dts: options.dts,
|
|
9
|
+
external: ["react"],
|
|
10
|
+
sourcemap: true,
|
|
11
|
+
metafile: options.metafile,
|
|
12
|
+
}));
|