@sproutsocial/seeds-react-visually-hidden 1.0.32 → 1.0.33
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/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +8 -0
- package/dist/esm/index.js +42 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +42 -3
- package/dist/index.js.map +1 -1
- package/dist/visually-hidden.css +12 -0
- package/package.json +9 -5
- package/src/VisuallyHidden.stories.tsx +9 -0
- package/src/VisuallyHidden.tsx +7 -14
- package/src/VisuallyHiddenHybrid.tsx +14 -0
- package/src/VisuallyHiddenStyled.tsx +15 -0
- package/src/VisuallyHiddenTailwind.tsx +32 -0
- package/src/__tests__/VisuallyHidden.css.test.ts +22 -0
- package/src/__tests__/VisuallyHidden.test.tsx +143 -2
- package/src/__tests__/VisuallyHidden.typetest.tsx +3 -0
- package/src/visually-hidden.css +12 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
yarn run v1.22.22
|
|
2
|
-
$ tsup --dts
|
|
2
|
+
$ tsup --dts && cp src/visually-hidden.css dist/visually-hidden.css
|
|
3
3
|
[34mCLI[39m Building entry: src/index.ts
|
|
4
4
|
[34mCLI[39m Using tsconfig: tsconfig.json
|
|
5
5
|
[34mCLI[39m tsup v8.5.0
|
|
@@ -8,14 +8,14 @@ $ tsup --dts
|
|
|
8
8
|
[34mCLI[39m Cleaning output folder
|
|
9
9
|
[34mCJS[39m Build start
|
|
10
10
|
[34mESM[39m Build start
|
|
11
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
12
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
14
|
-
[32mESM[39m [1mdist/esm/index.js [22m[
|
|
15
|
-
[32mESM[39m [1mdist/esm/index.js.map [22m[
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m3.53 KB[39m
|
|
12
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m3.37 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 84ms
|
|
14
|
+
[32mESM[39m [1mdist/esm/index.js [22m[32m1.63 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/esm/index.js.map [22m[32m3.24 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 84ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
21
|
-
Done in 5.
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 3998ms
|
|
19
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m482.00 B[39m
|
|
20
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m482.00 B[39m
|
|
21
|
+
Done in 5.07s.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# @sproutsocial/seeds-react-visually-hidden
|
|
2
2
|
|
|
3
|
+
## 1.0.33
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a33ef79: Add a Tailwind/CSS-class rendering path to VisuallyHidden using the Seeds hybrid pattern. Plain usage now renders the semantic `seeds-visually-hidden` class, while styled-system props and styled-components extensions retain the existing styled-components fallback. The component's public API and loose prop type remain unchanged, and the new CSS ships through package dist and `@sproutsocial/racine/css/components`.
|
|
8
|
+
- @sproutsocial/seeds-react-theme@4.5.1
|
|
9
|
+
- @sproutsocial/seeds-react-mixins@4.3.16
|
|
10
|
+
|
|
3
11
|
## 1.0.32
|
|
4
12
|
|
|
5
13
|
### Patch Changes
|
package/dist/esm/index.js
CHANGED
|
@@ -1,13 +1,52 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/VisuallyHiddenHybrid.tsx
|
|
2
|
+
import { needsStyledComponents } from "@sproutsocial/seeds-react-system-props";
|
|
3
|
+
|
|
4
|
+
// src/VisuallyHiddenStyled.tsx
|
|
2
5
|
import styled from "styled-components";
|
|
3
6
|
import { visuallyHidden } from "@sproutsocial/seeds-react-mixins";
|
|
4
7
|
import { jsx } from "react/jsx-runtime";
|
|
5
8
|
var StyledVisuallyHidden = styled.span`
|
|
6
9
|
${visuallyHidden}
|
|
7
10
|
`;
|
|
8
|
-
var
|
|
9
|
-
|
|
11
|
+
var VisuallyHiddenStyled = (props) => /* @__PURE__ */ jsx(StyledVisuallyHidden, { ...props });
|
|
12
|
+
|
|
13
|
+
// src/VisuallyHiddenTailwind.tsx
|
|
14
|
+
import isPropValid from "@emotion/is-prop-valid";
|
|
15
|
+
import * as React from "react";
|
|
16
|
+
var mergeClassNames = (...classes) => classes.filter(Boolean).join(" ");
|
|
17
|
+
var VisuallyHiddenTailwind = ({
|
|
18
|
+
as,
|
|
19
|
+
children,
|
|
20
|
+
className,
|
|
21
|
+
...rest
|
|
22
|
+
}) => {
|
|
23
|
+
const Element = as ?? "span";
|
|
24
|
+
const forwardedProps = typeof Element === "string" ? Object.fromEntries(
|
|
25
|
+
Object.entries(rest).filter(([name]) => isPropValid(name))
|
|
26
|
+
) : rest;
|
|
27
|
+
return React.createElement(
|
|
28
|
+
Element,
|
|
29
|
+
{
|
|
30
|
+
...forwardedProps,
|
|
31
|
+
className: mergeClassNames("seeds-visually-hidden", className)
|
|
32
|
+
},
|
|
33
|
+
children
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
VisuallyHiddenTailwind.displayName = "VisuallyHiddenTailwind";
|
|
37
|
+
|
|
38
|
+
// src/VisuallyHiddenHybrid.tsx
|
|
39
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
40
|
+
var VisuallyHiddenHybrid = (props) => {
|
|
41
|
+
if (needsStyledComponents(props)) {
|
|
42
|
+
return /* @__PURE__ */ jsx2(VisuallyHiddenStyled, { ...props });
|
|
43
|
+
}
|
|
44
|
+
return /* @__PURE__ */ jsx2(VisuallyHiddenTailwind, { ...props });
|
|
10
45
|
};
|
|
46
|
+
|
|
47
|
+
// src/VisuallyHidden.tsx
|
|
48
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
49
|
+
var VisuallyHidden = (props) => /* @__PURE__ */ jsx3(VisuallyHiddenHybrid, { ...props });
|
|
11
50
|
export {
|
|
12
51
|
VisuallyHidden
|
|
13
52
|
};
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/VisuallyHidden.tsx"],"sourcesContent":["import styled from \"styled-components\";\nimport { visuallyHidden } from \"@sproutsocial/seeds-react-mixins\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst StyledVisuallyHidden = styled.span`\n ${visuallyHidden}\n`;\n\nexport type VisuallyHiddenProps = ComponentPropsWithRef<\n typeof StyledVisuallyHidden\n>;\n\n// This wrapper component is needed for react-docgen to work.\n// It has issues with generating docs for the
|
|
1
|
+
{"version":3,"sources":["../../src/VisuallyHiddenHybrid.tsx","../../src/VisuallyHiddenStyled.tsx","../../src/VisuallyHiddenTailwind.tsx","../../src/VisuallyHidden.tsx"],"sourcesContent":["import { needsStyledComponents } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n VisuallyHiddenStyled,\n type VisuallyHiddenProps,\n} from \"./VisuallyHiddenStyled\";\nimport { VisuallyHiddenTailwind } from \"./VisuallyHiddenTailwind\";\n\nexport const VisuallyHiddenHybrid = (props: VisuallyHiddenProps) => {\n if (needsStyledComponents(props)) {\n return <VisuallyHiddenStyled {...props} />;\n }\n\n return <VisuallyHiddenTailwind {...props} />;\n};\n","import styled from \"styled-components\";\nimport { visuallyHidden } from \"@sproutsocial/seeds-react-mixins\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst StyledVisuallyHidden = styled.span`\n ${visuallyHidden}\n`;\n\nexport type VisuallyHiddenProps = ComponentPropsWithRef<\n typeof StyledVisuallyHidden\n>;\n\nexport const VisuallyHiddenStyled = (props: VisuallyHiddenProps) => (\n <StyledVisuallyHidden {...props} />\n);\n","import isPropValid from \"@emotion/is-prop-valid\";\nimport * as React from \"react\";\nimport type { VisuallyHiddenProps } from \"./VisuallyHiddenStyled\";\n\nconst mergeClassNames = (...classes: Array<string | undefined>) =>\n classes.filter(Boolean).join(\" \");\n\nexport const VisuallyHiddenTailwind = ({\n as,\n children,\n className,\n ...rest\n}: VisuallyHiddenProps) => {\n const Element = (as ?? \"span\") as React.ElementType;\n const forwardedProps =\n typeof Element === \"string\"\n ? Object.fromEntries(\n Object.entries(rest).filter(([name]) => isPropValid(name))\n )\n : rest;\n\n return React.createElement(\n Element,\n {\n ...forwardedProps,\n className: mergeClassNames(\"seeds-visually-hidden\", className),\n },\n children\n );\n};\n\nVisuallyHiddenTailwind.displayName = \"VisuallyHiddenTailwind\";\n","import { VisuallyHiddenHybrid } from \"./VisuallyHiddenHybrid\";\nimport type { VisuallyHiddenProps } from \"./VisuallyHiddenStyled\";\n\nexport type { VisuallyHiddenProps };\n\n// This wrapper component is needed for react-docgen to work.\n// It has issues with generating docs for the implementation directly.\nexport const VisuallyHidden = (props: VisuallyHiddenProps) => (\n <VisuallyHiddenHybrid {...props} />\n);\n"],"mappings":";AAAA,SAAS,6BAA6B;;;ACAtC,OAAO,YAAY;AACnB,SAAS,sBAAsB;AAY7B;AATF,IAAM,uBAAuB,OAAO;AAAA,IAChC,cAAc;AAAA;AAOX,IAAM,uBAAuB,CAAC,UACnC,oBAAC,wBAAsB,GAAG,OAAO;;;ACbnC,OAAO,iBAAiB;AACxB,YAAY,WAAW;AAGvB,IAAM,kBAAkB,IAAI,YAC1B,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG;AAE3B,IAAM,yBAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,QAAM,UAAW,MAAM;AACvB,QAAM,iBACJ,OAAO,YAAY,WACf,OAAO;AAAA,IACL,OAAO,QAAQ,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,MAAM,YAAY,IAAI,CAAC;AAAA,EAC3D,IACA;AAEN,SAAa;AAAA,IACX;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,WAAW,gBAAgB,yBAAyB,SAAS;AAAA,IAC/D;AAAA,IACA;AAAA,EACF;AACF;AAEA,uBAAuB,cAAc;;;AFtB1B,gBAAAA,YAAA;AAFJ,IAAM,uBAAuB,CAAC,UAA+B;AAClE,MAAI,sBAAsB,KAAK,GAAG;AAChC,WAAO,gBAAAA,KAAC,wBAAsB,GAAG,OAAO;AAAA,EAC1C;AAEA,SAAO,gBAAAA,KAAC,0BAAwB,GAAG,OAAO;AAC5C;;;AGLE,gBAAAC,YAAA;AADK,IAAM,iBAAiB,CAAC,UAC7B,gBAAAA,KAAC,wBAAsB,GAAG,OAAO;","names":["jsx","jsx"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -4,6 +4,7 @@ import { ComponentPropsWithRef } from 'react';
|
|
|
4
4
|
|
|
5
5
|
declare const StyledVisuallyHidden: styled_components.StyledComponent<"span", any, {}, never>;
|
|
6
6
|
type VisuallyHiddenProps = ComponentPropsWithRef<typeof StyledVisuallyHidden>;
|
|
7
|
+
|
|
7
8
|
declare const VisuallyHidden: (props: VisuallyHiddenProps) => react_jsx_runtime.JSX.Element;
|
|
8
9
|
|
|
9
10
|
export { VisuallyHidden, type VisuallyHiddenProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { ComponentPropsWithRef } from 'react';
|
|
|
4
4
|
|
|
5
5
|
declare const StyledVisuallyHidden: styled_components.StyledComponent<"span", any, {}, never>;
|
|
6
6
|
type VisuallyHiddenProps = ComponentPropsWithRef<typeof StyledVisuallyHidden>;
|
|
7
|
+
|
|
7
8
|
declare const VisuallyHidden: (props: VisuallyHiddenProps) => react_jsx_runtime.JSX.Element;
|
|
8
9
|
|
|
9
10
|
export { VisuallyHidden, type VisuallyHiddenProps };
|
package/dist/index.js
CHANGED
|
@@ -34,16 +34,55 @@ __export(index_exports, {
|
|
|
34
34
|
});
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
|
-
// src/
|
|
37
|
+
// src/VisuallyHiddenHybrid.tsx
|
|
38
|
+
var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
|
|
39
|
+
|
|
40
|
+
// src/VisuallyHiddenStyled.tsx
|
|
38
41
|
var import_styled_components = __toESM(require("styled-components"));
|
|
39
42
|
var import_seeds_react_mixins = require("@sproutsocial/seeds-react-mixins");
|
|
40
43
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
41
44
|
var StyledVisuallyHidden = import_styled_components.default.span`
|
|
42
45
|
${import_seeds_react_mixins.visuallyHidden}
|
|
43
46
|
`;
|
|
44
|
-
var
|
|
45
|
-
|
|
47
|
+
var VisuallyHiddenStyled = (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StyledVisuallyHidden, { ...props });
|
|
48
|
+
|
|
49
|
+
// src/VisuallyHiddenTailwind.tsx
|
|
50
|
+
var import_is_prop_valid = __toESM(require("@emotion/is-prop-valid"));
|
|
51
|
+
var React = __toESM(require("react"));
|
|
52
|
+
var mergeClassNames = (...classes) => classes.filter(Boolean).join(" ");
|
|
53
|
+
var VisuallyHiddenTailwind = ({
|
|
54
|
+
as,
|
|
55
|
+
children,
|
|
56
|
+
className,
|
|
57
|
+
...rest
|
|
58
|
+
}) => {
|
|
59
|
+
const Element = as ?? "span";
|
|
60
|
+
const forwardedProps = typeof Element === "string" ? Object.fromEntries(
|
|
61
|
+
Object.entries(rest).filter(([name]) => (0, import_is_prop_valid.default)(name))
|
|
62
|
+
) : rest;
|
|
63
|
+
return React.createElement(
|
|
64
|
+
Element,
|
|
65
|
+
{
|
|
66
|
+
...forwardedProps,
|
|
67
|
+
className: mergeClassNames("seeds-visually-hidden", className)
|
|
68
|
+
},
|
|
69
|
+
children
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
VisuallyHiddenTailwind.displayName = "VisuallyHiddenTailwind";
|
|
73
|
+
|
|
74
|
+
// src/VisuallyHiddenHybrid.tsx
|
|
75
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
76
|
+
var VisuallyHiddenHybrid = (props) => {
|
|
77
|
+
if ((0, import_seeds_react_system_props.needsStyledComponents)(props)) {
|
|
78
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VisuallyHiddenStyled, { ...props });
|
|
79
|
+
}
|
|
80
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VisuallyHiddenTailwind, { ...props });
|
|
46
81
|
};
|
|
82
|
+
|
|
83
|
+
// src/VisuallyHidden.tsx
|
|
84
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
85
|
+
var VisuallyHidden = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(VisuallyHiddenHybrid, { ...props });
|
|
47
86
|
// Annotate the CommonJS export names for ESM import in node:
|
|
48
87
|
0 && (module.exports = {
|
|
49
88
|
VisuallyHidden
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/VisuallyHidden.tsx"],"sourcesContent":["export * from \"./VisuallyHidden\";\n","import styled from \"styled-components\";\nimport { visuallyHidden } from \"@sproutsocial/seeds-react-mixins\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst StyledVisuallyHidden = styled.span`\n ${visuallyHidden}\n`;\n\nexport type VisuallyHiddenProps = ComponentPropsWithRef<\n typeof StyledVisuallyHidden\n>;\n\n// This wrapper component is needed for react-docgen to work.\n// It has issues with generating docs for the
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/VisuallyHiddenHybrid.tsx","../src/VisuallyHiddenStyled.tsx","../src/VisuallyHiddenTailwind.tsx","../src/VisuallyHidden.tsx"],"sourcesContent":["export * from \"./VisuallyHidden\";\n","import { needsStyledComponents } from \"@sproutsocial/seeds-react-system-props\";\nimport {\n VisuallyHiddenStyled,\n type VisuallyHiddenProps,\n} from \"./VisuallyHiddenStyled\";\nimport { VisuallyHiddenTailwind } from \"./VisuallyHiddenTailwind\";\n\nexport const VisuallyHiddenHybrid = (props: VisuallyHiddenProps) => {\n if (needsStyledComponents(props)) {\n return <VisuallyHiddenStyled {...props} />;\n }\n\n return <VisuallyHiddenTailwind {...props} />;\n};\n","import styled from \"styled-components\";\nimport { visuallyHidden } from \"@sproutsocial/seeds-react-mixins\";\nimport type { ComponentPropsWithRef } from \"react\";\n\nconst StyledVisuallyHidden = styled.span`\n ${visuallyHidden}\n`;\n\nexport type VisuallyHiddenProps = ComponentPropsWithRef<\n typeof StyledVisuallyHidden\n>;\n\nexport const VisuallyHiddenStyled = (props: VisuallyHiddenProps) => (\n <StyledVisuallyHidden {...props} />\n);\n","import isPropValid from \"@emotion/is-prop-valid\";\nimport * as React from \"react\";\nimport type { VisuallyHiddenProps } from \"./VisuallyHiddenStyled\";\n\nconst mergeClassNames = (...classes: Array<string | undefined>) =>\n classes.filter(Boolean).join(\" \");\n\nexport const VisuallyHiddenTailwind = ({\n as,\n children,\n className,\n ...rest\n}: VisuallyHiddenProps) => {\n const Element = (as ?? \"span\") as React.ElementType;\n const forwardedProps =\n typeof Element === \"string\"\n ? Object.fromEntries(\n Object.entries(rest).filter(([name]) => isPropValid(name))\n )\n : rest;\n\n return React.createElement(\n Element,\n {\n ...forwardedProps,\n className: mergeClassNames(\"seeds-visually-hidden\", className),\n },\n children\n );\n};\n\nVisuallyHiddenTailwind.displayName = \"VisuallyHiddenTailwind\";\n","import { VisuallyHiddenHybrid } from \"./VisuallyHiddenHybrid\";\nimport type { VisuallyHiddenProps } from \"./VisuallyHiddenStyled\";\n\nexport type { VisuallyHiddenProps };\n\n// This wrapper component is needed for react-docgen to work.\n// It has issues with generating docs for the implementation directly.\nexport const VisuallyHidden = (props: VisuallyHiddenProps) => (\n <VisuallyHiddenHybrid {...props} />\n);\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sCAAsC;;;ACAtC,+BAAmB;AACnB,gCAA+B;AAY7B;AATF,IAAM,uBAAuB,yBAAAA,QAAO;AAAA,IAChC,wCAAc;AAAA;AAOX,IAAM,uBAAuB,CAAC,UACnC,4CAAC,wBAAsB,GAAG,OAAO;;;ACbnC,2BAAwB;AACxB,YAAuB;AAGvB,IAAM,kBAAkB,IAAI,YAC1B,QAAQ,OAAO,OAAO,EAAE,KAAK,GAAG;AAE3B,IAAM,yBAAyB,CAAC;AAAA,EACrC;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MAA2B;AACzB,QAAM,UAAW,MAAM;AACvB,QAAM,iBACJ,OAAO,YAAY,WACf,OAAO;AAAA,IACL,OAAO,QAAQ,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,UAAM,qBAAAC,SAAY,IAAI,CAAC;AAAA,EAC3D,IACA;AAEN,SAAa;AAAA,IACX;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,WAAW,gBAAgB,yBAAyB,SAAS;AAAA,IAC/D;AAAA,IACA;AAAA,EACF;AACF;AAEA,uBAAuB,cAAc;;;AFtB1B,IAAAC,sBAAA;AAFJ,IAAM,uBAAuB,CAAC,UAA+B;AAClE,UAAI,uDAAsB,KAAK,GAAG;AAChC,WAAO,6CAAC,wBAAsB,GAAG,OAAO;AAAA,EAC1C;AAEA,SAAO,6CAAC,0BAAwB,GAAG,OAAO;AAC5C;;;AGLE,IAAAC,sBAAA;AADK,IAAM,iBAAiB,CAAC,UAC7B,6CAAC,wBAAsB,GAAG,OAAO;","names":["styled","isPropValid","import_jsx_runtime","import_jsx_runtime"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-visually-hidden",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.33",
|
|
4
4
|
"description": "Seeds React VisuallyHidden",
|
|
5
5
|
"author": "Sprout Social, Inc.",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
"module": "dist/esm/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"build": "tsup --dts",
|
|
12
|
-
"build:debug": "tsup --dts --metafile",
|
|
11
|
+
"build": "tsup --dts && cp src/visually-hidden.css dist/visually-hidden.css",
|
|
12
|
+
"build:debug": "tsup --dts --metafile && cp src/visually-hidden.css dist/visually-hidden.css",
|
|
13
13
|
"dev": "tsup --watch --dts",
|
|
14
14
|
"clean": "rm -rf .turbo dist",
|
|
15
15
|
"clean:modules": "rm -rf node_modules",
|
|
@@ -17,10 +17,14 @@
|
|
|
17
17
|
"test": "jest",
|
|
18
18
|
"test:watch": "jest --watch --coverage=false"
|
|
19
19
|
},
|
|
20
|
+
"sideEffects": [
|
|
21
|
+
"**/*.css"
|
|
22
|
+
],
|
|
20
23
|
"dependencies": {
|
|
21
|
-
"@
|
|
24
|
+
"@emotion/is-prop-valid": "^1.1.0",
|
|
25
|
+
"@sproutsocial/seeds-react-theme": "^4.5.1",
|
|
22
26
|
"@sproutsocial/seeds-react-system-props": "^3.2.1",
|
|
23
|
-
"@sproutsocial/seeds-react-mixins": "^4.3.
|
|
27
|
+
"@sproutsocial/seeds-react-mixins": "^4.3.16"
|
|
24
28
|
},
|
|
25
29
|
"devDependencies": {
|
|
26
30
|
"@types/react": "^18.0.0",
|
|
@@ -26,3 +26,12 @@ export const Default: Story = {
|
|
|
26
26
|
</Text>
|
|
27
27
|
),
|
|
28
28
|
};
|
|
29
|
+
|
|
30
|
+
export const TailwindUtilityOverride: Story = {
|
|
31
|
+
render: () => (
|
|
32
|
+
<VisuallyHidden className="static m-0 h-auto w-auto overflow-visible">
|
|
33
|
+
This text is visible because consumer utilities override the layered
|
|
34
|
+
component styles.
|
|
35
|
+
</VisuallyHidden>
|
|
36
|
+
),
|
|
37
|
+
};
|
package/src/VisuallyHidden.tsx
CHANGED
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import type { ComponentPropsWithRef } from "react";
|
|
1
|
+
import { VisuallyHiddenHybrid } from "./VisuallyHiddenHybrid";
|
|
2
|
+
import type { VisuallyHiddenProps } from "./VisuallyHiddenStyled";
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
${visuallyHidden}
|
|
7
|
-
`;
|
|
8
|
-
|
|
9
|
-
export type VisuallyHiddenProps = ComponentPropsWithRef<
|
|
10
|
-
typeof StyledVisuallyHidden
|
|
11
|
-
>;
|
|
4
|
+
export type { VisuallyHiddenProps };
|
|
12
5
|
|
|
13
6
|
// This wrapper component is needed for react-docgen to work.
|
|
14
|
-
// It has issues with generating docs for the
|
|
15
|
-
export const VisuallyHidden = (props: VisuallyHiddenProps) =>
|
|
16
|
-
|
|
17
|
-
|
|
7
|
+
// It has issues with generating docs for the implementation directly.
|
|
8
|
+
export const VisuallyHidden = (props: VisuallyHiddenProps) => (
|
|
9
|
+
<VisuallyHiddenHybrid {...props} />
|
|
10
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { needsStyledComponents } from "@sproutsocial/seeds-react-system-props";
|
|
2
|
+
import {
|
|
3
|
+
VisuallyHiddenStyled,
|
|
4
|
+
type VisuallyHiddenProps,
|
|
5
|
+
} from "./VisuallyHiddenStyled";
|
|
6
|
+
import { VisuallyHiddenTailwind } from "./VisuallyHiddenTailwind";
|
|
7
|
+
|
|
8
|
+
export const VisuallyHiddenHybrid = (props: VisuallyHiddenProps) => {
|
|
9
|
+
if (needsStyledComponents(props)) {
|
|
10
|
+
return <VisuallyHiddenStyled {...props} />;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return <VisuallyHiddenTailwind {...props} />;
|
|
14
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import styled from "styled-components";
|
|
2
|
+
import { visuallyHidden } from "@sproutsocial/seeds-react-mixins";
|
|
3
|
+
import type { ComponentPropsWithRef } from "react";
|
|
4
|
+
|
|
5
|
+
const StyledVisuallyHidden = styled.span`
|
|
6
|
+
${visuallyHidden}
|
|
7
|
+
`;
|
|
8
|
+
|
|
9
|
+
export type VisuallyHiddenProps = ComponentPropsWithRef<
|
|
10
|
+
typeof StyledVisuallyHidden
|
|
11
|
+
>;
|
|
12
|
+
|
|
13
|
+
export const VisuallyHiddenStyled = (props: VisuallyHiddenProps) => (
|
|
14
|
+
<StyledVisuallyHidden {...props} />
|
|
15
|
+
);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import isPropValid from "@emotion/is-prop-valid";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import type { VisuallyHiddenProps } from "./VisuallyHiddenStyled";
|
|
4
|
+
|
|
5
|
+
const mergeClassNames = (...classes: Array<string | undefined>) =>
|
|
6
|
+
classes.filter(Boolean).join(" ");
|
|
7
|
+
|
|
8
|
+
export const VisuallyHiddenTailwind = ({
|
|
9
|
+
as,
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
...rest
|
|
13
|
+
}: VisuallyHiddenProps) => {
|
|
14
|
+
const Element = (as ?? "span") as React.ElementType;
|
|
15
|
+
const forwardedProps =
|
|
16
|
+
typeof Element === "string"
|
|
17
|
+
? Object.fromEntries(
|
|
18
|
+
Object.entries(rest).filter(([name]) => isPropValid(name))
|
|
19
|
+
)
|
|
20
|
+
: rest;
|
|
21
|
+
|
|
22
|
+
return React.createElement(
|
|
23
|
+
Element,
|
|
24
|
+
{
|
|
25
|
+
...forwardedProps,
|
|
26
|
+
className: mergeClassNames("seeds-visually-hidden", className),
|
|
27
|
+
},
|
|
28
|
+
children
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
VisuallyHiddenTailwind.displayName = "VisuallyHiddenTailwind";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* eslint-env jest, node */
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
const cssPath = path.resolve(__dirname, "../visually-hidden.css");
|
|
6
|
+
|
|
7
|
+
describe("VisuallyHidden CSS", () => {
|
|
8
|
+
it("defines the semantic class in the components layer with the legacy declarations", () => {
|
|
9
|
+
const css = fs.readFileSync(cssPath, "utf8");
|
|
10
|
+
|
|
11
|
+
expect(css).toContain("@layer components");
|
|
12
|
+
expect(css).toContain(".seeds-visually-hidden");
|
|
13
|
+
expect(css).toContain("position: absolute;");
|
|
14
|
+
expect(css).toContain("width: 1px;");
|
|
15
|
+
expect(css).toContain("height: 1px;");
|
|
16
|
+
expect(css).toContain("padding: 0;");
|
|
17
|
+
expect(css).toContain("margin: -1px;");
|
|
18
|
+
expect(css).toContain("overflow: hidden;");
|
|
19
|
+
expect(css).toContain("clip: rect(0 0 0 0);");
|
|
20
|
+
expect(css).toContain("border: 0;");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import * as React from "react";
|
|
1
2
|
import { render, screen } from "@sproutsocial/seeds-react-testing-library";
|
|
3
|
+
import styled from "styled-components";
|
|
2
4
|
import { VisuallyHidden } from "../VisuallyHidden";
|
|
3
5
|
|
|
4
6
|
describe("VisuallyHidden", () => {
|
|
@@ -6,10 +8,11 @@ describe("VisuallyHidden", () => {
|
|
|
6
8
|
render(<VisuallyHidden>Hidden Content</VisuallyHidden>);
|
|
7
9
|
const element = screen.getByText("Hidden Content");
|
|
8
10
|
expect(element).toBeInTheDocument();
|
|
11
|
+
expect(element.tagName).toBe("SPAN");
|
|
9
12
|
});
|
|
10
13
|
|
|
11
|
-
it("
|
|
12
|
-
render(<VisuallyHidden>Hidden Content</VisuallyHidden>);
|
|
14
|
+
it("retains visually hidden styles on the styled fallback", () => {
|
|
15
|
+
render(<VisuallyHidden mt={200}>Hidden Content</VisuallyHidden>);
|
|
13
16
|
const element = screen.getByText("Hidden Content");
|
|
14
17
|
expect(element).toHaveStyle(`
|
|
15
18
|
position: absolute;
|
|
@@ -27,4 +30,142 @@ describe("VisuallyHidden", () => {
|
|
|
27
30
|
const element = screen.getByText("Hidden Content");
|
|
28
31
|
expect(element).toHaveAttribute("aria-label", "hidden");
|
|
29
32
|
});
|
|
33
|
+
|
|
34
|
+
it("renders a div with role status through the as prop", () => {
|
|
35
|
+
render(
|
|
36
|
+
<VisuallyHidden as="div" role="status" data-state="ready">
|
|
37
|
+
Status
|
|
38
|
+
</VisuallyHidden>
|
|
39
|
+
);
|
|
40
|
+
const element = screen.getByRole("status");
|
|
41
|
+
expect(element.tagName).toBe("DIV");
|
|
42
|
+
expect(element).toHaveAttribute("data-state", "ready");
|
|
43
|
+
expect(element).not.toHaveAttribute("as");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("forwards className, id, aria, and events", () => {
|
|
47
|
+
const onClick = jest.fn();
|
|
48
|
+
render(
|
|
49
|
+
<VisuallyHidden
|
|
50
|
+
className="consumer-class"
|
|
51
|
+
id="hidden-id"
|
|
52
|
+
aria-label="hidden label"
|
|
53
|
+
onClick={onClick}
|
|
54
|
+
>
|
|
55
|
+
Hidden Content
|
|
56
|
+
</VisuallyHidden>
|
|
57
|
+
);
|
|
58
|
+
const element = screen.getByText("Hidden Content");
|
|
59
|
+
expect(element).toHaveClass("consumer-class");
|
|
60
|
+
expect(element).toHaveAttribute("id", "hidden-id");
|
|
61
|
+
expect(element).toHaveAttribute("aria-label", "hidden label");
|
|
62
|
+
element.click();
|
|
63
|
+
expect(onClick).toHaveBeenCalledTimes(1);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("accepts but does not leak the intentionally loose invalid prop", () => {
|
|
67
|
+
const error = jest.spyOn(console, "error").mockImplementation(() => {});
|
|
68
|
+
render(
|
|
69
|
+
<VisuallyHidden invalidProp="invalid">Hidden Content</VisuallyHidden>
|
|
70
|
+
);
|
|
71
|
+
expect(screen.getByText("Hidden Content")).not.toHaveAttribute(
|
|
72
|
+
"invalidProp"
|
|
73
|
+
);
|
|
74
|
+
expect(error).not.toHaveBeenCalled();
|
|
75
|
+
error.mockRestore();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("preserves the current non-forwarded ref behavior", () => {
|
|
79
|
+
const ref = React.createRef<HTMLSpanElement>();
|
|
80
|
+
const originalError = console.error;
|
|
81
|
+
const expectedWarning = "Function components cannot be given refs";
|
|
82
|
+
const error = jest
|
|
83
|
+
.spyOn(console, "error")
|
|
84
|
+
.mockImplementation((...args: Parameters<typeof console.error>) => {
|
|
85
|
+
if (typeof args[0] === "string" && args[0].includes(expectedWarning)) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
originalError(...args);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
render(<VisuallyHidden ref={ref}>Hidden Content</VisuallyHidden>);
|
|
93
|
+
|
|
94
|
+
expect(ref.current).toBeNull();
|
|
95
|
+
expect(
|
|
96
|
+
error.mock.calls.filter(
|
|
97
|
+
([message]) =>
|
|
98
|
+
typeof message === "string" && message.includes(expectedWarning)
|
|
99
|
+
)
|
|
100
|
+
).toHaveLength(1);
|
|
101
|
+
expect(
|
|
102
|
+
error.mock.calls.filter(
|
|
103
|
+
([message]) =>
|
|
104
|
+
typeof message !== "string" || !message.includes(expectedWarning)
|
|
105
|
+
)
|
|
106
|
+
).toHaveLength(0);
|
|
107
|
+
error.mockRestore();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("passes arbitrary props and className to a custom component through as", () => {
|
|
111
|
+
const CustomComponent = ({
|
|
112
|
+
arbitraryProp,
|
|
113
|
+
className,
|
|
114
|
+
children,
|
|
115
|
+
}: {
|
|
116
|
+
arbitraryProp?: string;
|
|
117
|
+
className?: string;
|
|
118
|
+
children?: React.ReactNode;
|
|
119
|
+
}) => (
|
|
120
|
+
<span data-arbitrary-prop={arbitraryProp} className={className}>
|
|
121
|
+
{children}
|
|
122
|
+
</span>
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
render(
|
|
126
|
+
<VisuallyHidden
|
|
127
|
+
as={CustomComponent}
|
|
128
|
+
arbitraryProp="preserved"
|
|
129
|
+
className="consumer-class"
|
|
130
|
+
>
|
|
131
|
+
Hidden Content
|
|
132
|
+
</VisuallyHidden>
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
const element = screen.getByText("Hidden Content");
|
|
136
|
+
expect(element).toHaveAttribute("data-arbitrary-prop", "preserved");
|
|
137
|
+
expect(element).toHaveClass("consumer-class");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("uses the Tailwind path by default", () => {
|
|
141
|
+
render(<VisuallyHidden>Hidden Content</VisuallyHidden>);
|
|
142
|
+
expect(screen.getByText("Hidden Content")).toHaveClass(
|
|
143
|
+
"seeds-visually-hidden"
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
it("merges a plain consumer className on the Tailwind path", () => {
|
|
148
|
+
render(<VisuallyHidden className="static">Hidden Content</VisuallyHidden>);
|
|
149
|
+
expect(screen.getByText("Hidden Content")).toHaveClass(
|
|
150
|
+
"seeds-visually-hidden",
|
|
151
|
+
"static"
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("routes styled-system props to the styled-components fallback", () => {
|
|
156
|
+
render(<VisuallyHidden mt={200}>Hidden Content</VisuallyHidden>);
|
|
157
|
+
expect(screen.getByText("Hidden Content")).not.toHaveClass(
|
|
158
|
+
"seeds-visually-hidden"
|
|
159
|
+
);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("routes a styled extension to the styled-components fallback", () => {
|
|
163
|
+
const Extended = styled(VisuallyHidden)`
|
|
164
|
+
opacity: 0.5;
|
|
165
|
+
`;
|
|
166
|
+
render(<Extended>Hidden Content</Extended>);
|
|
167
|
+
const element = screen.getByText("Hidden Content");
|
|
168
|
+
expect(element).not.toHaveClass("seeds-visually-hidden");
|
|
169
|
+
expect(element).toHaveStyleRule("opacity", "0.5");
|
|
170
|
+
});
|
|
30
171
|
});
|
|
@@ -9,6 +9,9 @@ function VisuallyHiddenTypes() {
|
|
|
9
9
|
{/* This is allowed _for now_ since style.span component can accept anything */}
|
|
10
10
|
{/* In a future major release, consider making VisuallyHidden's prop more restrictive */}
|
|
11
11
|
<VisuallyHidden invalidProp="invalid">Content</VisuallyHidden>
|
|
12
|
+
<VisuallyHidden as="div" role="status">
|
|
13
|
+
Status
|
|
14
|
+
</VisuallyHidden>
|
|
12
15
|
</>
|
|
13
16
|
);
|
|
14
17
|
}
|