@sproutsocial/seeds-react-loader-button 1.0.33 → 1.0.45

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.
@@ -8,14 +8,14 @@ $ tsup --dts
8
8
  CLI Cleaning output folder
9
9
  CJS Build start
10
10
  ESM Build start
11
- CJS dist/index.js 3.62 KB
12
- CJS dist/index.js.map 3.09 KB
13
- CJS ⚡️ Build success in 77ms
14
- ESM dist/esm/index.js 1.62 KB
15
- ESM dist/esm/index.js.map 2.96 KB
16
- ESM ⚡️ Build success in 77ms
11
+ CJS dist/index.js 6.19 KB
12
+ CJS dist/index.js.map 7.61 KB
13
+ CJS ⚡️ Build success in 18ms
14
+ ESM dist/esm/index.js 3.72 KB
15
+ ESM dist/esm/index.js.map 7.41 KB
16
+ ESM ⚡️ Build success in 18ms
17
17
  DTS Build start
18
- DTS ⚡️ Build success in 4681ms
19
- DTS dist/index.d.ts 470.00 B
20
- DTS dist/index.d.mts 470.00 B
21
- Done in 6.02s.
18
+ DTS ⚡️ Build success in 4778ms
19
+ DTS dist/index.d.ts 619.00 B
20
+ DTS dist/index.d.mts 619.00 B
21
+ Done in 6.46s.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,105 @@
1
1
  # @sproutsocial/seeds-react-loader-button
2
2
 
3
+ ## 1.0.45
4
+
5
+ ### Patch Changes
6
+
7
+ - @sproutsocial/seeds-react-button@2.2.1
8
+
9
+ ## 1.0.44
10
+
11
+ ### Patch Changes
12
+
13
+ - Updated dependencies [8945c86]
14
+ - @sproutsocial/seeds-react-loader@1.0.22
15
+
16
+ ## 1.0.43
17
+
18
+ ### Patch Changes
19
+
20
+ - edc1819: Migrate link, text, banner, loader-button, and content-header to the Tailwind hybrid pattern (mirroring seeds-react-button). Each component gains a pure CSS-class `*Tailwind` implementation, a `*Hybrid` router that falls back to styled-components when system/styled props are present, and a component-scoped CSS file of `seeds-*` classes built on `var(--…)` tokens. Component CSS is wrapped in `@layer components` so consumer Tailwind utility overrides win the cascade, and the per-component CSS import is dropped from the `*Tailwind` files since the CSS is aggregated into `@sproutsocial/racine/css/components` at build time. Legacy `styles.ts` paths are unchanged.
21
+
22
+ ## 1.0.42
23
+
24
+ ### Patch Changes
25
+
26
+ - Updated dependencies [456a20f]
27
+ - Updated dependencies [5892f44]
28
+ - @sproutsocial/seeds-react-button@2.2.0
29
+ - @sproutsocial/seeds-react-system-props@3.1.1
30
+ - @sproutsocial/seeds-react-box@1.1.21
31
+ - @sproutsocial/seeds-react-loader@1.0.21
32
+
33
+ ## 1.0.41
34
+
35
+ ### Patch Changes
36
+
37
+ - Updated dependencies [5114a32]
38
+ - Updated dependencies [a0fe3d3]
39
+ - @sproutsocial/seeds-react-theme@4.1.0
40
+ - @sproutsocial/seeds-react-button@2.1.3
41
+ - @sproutsocial/seeds-react-box@1.1.20
42
+ - @sproutsocial/seeds-react-loader@1.0.20
43
+
44
+ ## 1.0.40
45
+
46
+ ### Patch Changes
47
+
48
+ - Updated dependencies [cb27f07]
49
+ - @sproutsocial/seeds-react-button@2.1.2
50
+
51
+ ## 1.0.39
52
+
53
+ ### Patch Changes
54
+
55
+ - Updated dependencies [40d2dfe]
56
+ - @sproutsocial/seeds-react-button@2.1.1
57
+
58
+ ## 1.0.38
59
+
60
+ ### Patch Changes
61
+
62
+ - Updated dependencies [132ef9d]
63
+ - Updated dependencies [132ef9d]
64
+ - Updated dependencies [132ef9d]
65
+ - @sproutsocial/seeds-react-button@2.1.0
66
+ - @sproutsocial/seeds-react-theme@4.0.0
67
+ - @sproutsocial/seeds-react-system-props@3.1.0
68
+ - @sproutsocial/seeds-react-box@1.1.19
69
+ - @sproutsocial/seeds-react-loader@1.0.19
70
+
71
+ ## 1.0.37
72
+
73
+ ### Patch Changes
74
+
75
+ - @sproutsocial/seeds-react-button@2.0.8
76
+
77
+ ## 1.0.36
78
+
79
+ ### Patch Changes
80
+
81
+ - Updated dependencies [47c62b3]
82
+ - @sproutsocial/seeds-react-theme@3.7.1
83
+ - @sproutsocial/seeds-react-box@1.1.18
84
+ - @sproutsocial/seeds-react-loader@1.0.18
85
+ - @sproutsocial/seeds-react-button@2.0.7
86
+
87
+ ## 1.0.35
88
+
89
+ ### Patch Changes
90
+
91
+ - Updated dependencies [06da9c2]
92
+ - @sproutsocial/seeds-react-theme@3.7.0
93
+ - @sproutsocial/seeds-react-box@1.1.17
94
+ - @sproutsocial/seeds-react-loader@1.0.17
95
+ - @sproutsocial/seeds-react-button@2.0.6
96
+
97
+ ## 1.0.34
98
+
99
+ ### Patch Changes
100
+
101
+ - @sproutsocial/seeds-react-button@2.0.5
102
+
3
103
  ## 1.0.33
4
104
 
5
105
  ### Patch Changes
package/dist/esm/index.js CHANGED
@@ -1,11 +1,66 @@
1
1
  // src/LoaderButton.tsx
2
2
  import "react";
3
+
4
+ // src/LoaderButtonHybrid.tsx
5
+ import "react";
3
6
  import styled from "styled-components";
7
+ import Box2 from "@sproutsocial/seeds-react-box";
8
+ import Button2 from "@sproutsocial/seeds-react-button";
9
+ import Loader2 from "@sproutsocial/seeds-react-loader";
10
+
11
+ // src/LoaderButtonTailwind.tsx
12
+ import "react";
4
13
  import Box from "@sproutsocial/seeds-react-box";
5
14
  import Button from "@sproutsocial/seeds-react-button";
6
15
  import Loader from "@sproutsocial/seeds-react-loader";
7
16
  import { jsx, jsxs } from "react/jsx-runtime";
8
- var StyledLoaderButton = styled(Button)`
17
+ function cn(...inputs) {
18
+ const classes = [];
19
+ for (const input of inputs) {
20
+ if (!input) continue;
21
+ if (typeof input === "string") {
22
+ classes.push(input);
23
+ } else if (typeof input === "object") {
24
+ for (const [key, value] of Object.entries(input)) {
25
+ if (value) {
26
+ classes.push(key);
27
+ }
28
+ }
29
+ }
30
+ }
31
+ return classes.join(" ");
32
+ }
33
+ var LoaderButtonTailwind = ({
34
+ isLoading = false,
35
+ disabled,
36
+ loaderLabel,
37
+ children,
38
+ appearance = "unstyled",
39
+ className,
40
+ ...rest
41
+ }) => {
42
+ const isDisabled = disabled || isLoading;
43
+ const classes = cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || void 0;
44
+ return /* @__PURE__ */ jsx(
45
+ Button,
46
+ {
47
+ disabled: isDisabled,
48
+ appearance,
49
+ "data-qa-button-isloading": isLoading === true,
50
+ className: classes,
51
+ ...rest,
52
+ children: /* @__PURE__ */ jsxs(Box, { position: "relative", children: [
53
+ /* @__PURE__ */ jsx(Box, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
54
+ isLoading && /* @__PURE__ */ jsx(Box, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx(Loader, { text: loaderLabel, size: "small", delay: false }) })
55
+ ] })
56
+ }
57
+ );
58
+ };
59
+
60
+ // src/LoaderButtonHybrid.tsx
61
+ import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
62
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
63
+ var StyledLoaderButton = styled(Button2)`
9
64
  background-color: ${({ theme, appearance, disabled }) => {
10
65
  const buttonBackgroundColor = theme.colors.button[appearance]?.background?.base;
11
66
  const isBackgroundColorTransparent = buttonBackgroundColor === "transparent";
@@ -13,7 +68,7 @@ var StyledLoaderButton = styled(Button)`
13
68
  }};
14
69
  ${({ disabled }) => disabled && "opacity: 1;"}
15
70
  `;
16
- var LoaderButton = ({
71
+ var LoaderButtonHybrid = ({
17
72
  isLoading = false,
18
73
  disabled,
19
74
  loaderLabel,
@@ -21,20 +76,38 @@ var LoaderButton = ({
21
76
  appearance = "unstyled",
22
77
  ...rest
23
78
  }) => {
24
- return /* @__PURE__ */ jsx(
25
- StyledLoaderButton,
79
+ if (hasStyledProps(rest)) {
80
+ return /* @__PURE__ */ jsx2(
81
+ StyledLoaderButton,
82
+ {
83
+ disabled: disabled || isLoading,
84
+ appearance,
85
+ "data-qa-button-isloading": isLoading === true,
86
+ ...rest,
87
+ children: /* @__PURE__ */ jsxs2(Box2, { position: "relative", children: [
88
+ /* @__PURE__ */ jsx2(Box2, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
89
+ isLoading && /* @__PURE__ */ jsx2(Box2, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx2(Loader2, { text: loaderLabel, size: "small", delay: false }) })
90
+ ] })
91
+ }
92
+ );
93
+ }
94
+ return /* @__PURE__ */ jsx2(
95
+ LoaderButtonTailwind,
26
96
  {
27
- disabled: disabled || isLoading,
97
+ isLoading,
98
+ disabled,
99
+ loaderLabel,
28
100
  appearance,
29
- "data-qa-button-isloading": isLoading === true,
30
101
  ...rest,
31
- children: /* @__PURE__ */ jsxs(Box, { position: "relative", children: [
32
- /* @__PURE__ */ jsx(Box, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
33
- isLoading && /* @__PURE__ */ jsx(Box, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ jsx(Loader, { text: loaderLabel, size: "small", delay: false }) })
34
- ] })
102
+ children
35
103
  }
36
104
  );
37
105
  };
106
+ var LoaderButtonHybrid_default = LoaderButtonHybrid;
107
+
108
+ // src/LoaderButton.tsx
109
+ import { jsx as jsx3 } from "react/jsx-runtime";
110
+ var LoaderButton = (props) => /* @__PURE__ */ jsx3(LoaderButtonHybrid_default, { ...props });
38
111
  var LoaderButton_default = LoaderButton;
39
112
 
40
113
  // src/index.ts
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/LoaderButton.tsx","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButton = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n};\n\nexport default LoaderButton;\n","import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n"],"mappings":";AAAA,OAAuB;AACvB,OAAO,YAAY;AACnB,OAAO,SAAS;AAChB,OAAO,YAAY;AACnB,OAAO,YAAY;AAqCb,SACE,KADF;AAlCN,IAAM,qBAAqB,OAAO,MAAM;AAAA,sBAClB,CAAC,EAAE,OAAO,YAAY,SAAS,MAAM;AACvD,QAAM,wBACJ,MAAM,OAAO,OAAO,UAA8C,GAC9D,YAAY;AAElB,QAAM,+BACJ,0BAA0B;AAG5B,SAAO,WACH,+BACE,gBACA,GAAG,qBAAqB,OAC1B;AACN,CAAC;AAAA,IACC,CAAC,EAAE,SAAS,MAAM,YAAY,aAAa;AAAA;AAGxC,IAAM,eAAe,CAAC;AAAA,EAC3B,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,GAAG;AACL,MAA6B;AAC3B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB;AAAA,MACA,4BAA0B,cAAc;AAAA,MACvC,GAAG;AAAA,MAEJ,+BAAC,OAAI,UAAS,YACZ;AAAA,4BAAC,OAAI,SAAS,YAAY,IAAI,GAAG,eAAa,WAC3C,UACH;AAAA,QACC,aACC,oBAAC,OAAI,UAAS,YAAW,KAAK,IAAI,MAAM,GAAG,OAAO,GAAG,QAAQ,GAC3D,8BAAC,UAAO,MAAM,aAAa,MAAK,SAAQ,OAAO,OAAO,GACxD;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,uBAAQ;;;ACrDf,IAAO,gBAAQ;","names":[]}
1
+ {"version":3,"sources":["../../src/LoaderButton.tsx","../../src/LoaderButtonHybrid.tsx","../../src/LoaderButtonTailwind.tsx","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport LoaderButtonHybrid from \"./LoaderButtonHybrid\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n/**\n * LoaderButton component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (for\n * consumers using system props or a styled() extension).\n */\nexport const LoaderButton = (props: TypeLoaderButtonProps) => (\n <LoaderButtonHybrid {...props} />\n);\n\nexport default LoaderButton;\n","/**\n * Hybrid LoaderButton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport { LoaderButtonTailwind } from \"./LoaderButtonTailwind\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButtonHybrid = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n if (hasStyledProps(rest)) {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <LoaderButtonTailwind\n isLoading={isLoading}\n disabled={disabled}\n loaderLabel={loaderLabel}\n appearance={appearance}\n {...rest}\n >\n {children}\n </LoaderButtonTailwind>\n );\n};\n\nexport default LoaderButtonHybrid;\n","/**\n * Tailwind CSS implementation of LoaderButton component\n * Renders Button with its appearance classes plus a disabled-dimming layer\n * from loader-button.css.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nexport const LoaderButtonTailwind = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n className,\n ...rest\n}: TypeLoaderButtonProps) => {\n const isDisabled = disabled || isLoading;\n const classes =\n cn({ \"seeds-loader-btn-disabled\": !!isDisabled }, className) || undefined;\n\n return (\n <Button\n disabled={isDisabled}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n className={classes}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </Button>\n );\n};\n\nexport default LoaderButtonTailwind;\n","import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n"],"mappings":"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","names":["Box","Button","Loader","jsx","jsxs","Button","Box","Loader","jsx"]}
package/dist/index.d.mts CHANGED
@@ -6,6 +6,11 @@ interface TypeLoaderButtonProps extends TypeButtonProps {
6
6
  loaderLabel: string;
7
7
  }
8
8
 
9
- declare const LoaderButton: ({ isLoading, disabled, loaderLabel, children, appearance, ...rest }: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
9
+ /**
10
+ * LoaderButton component. Automatically routes between the Tailwind
11
+ * implementation (preferred) and the styled-components implementation (for
12
+ * consumers using system props or a styled() extension).
13
+ */
14
+ declare const LoaderButton: (props: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
10
15
 
11
16
  export { LoaderButton, type TypeLoaderButtonProps, LoaderButton as default };
package/dist/index.d.ts CHANGED
@@ -6,6 +6,11 @@ interface TypeLoaderButtonProps extends TypeButtonProps {
6
6
  loaderLabel: string;
7
7
  }
8
8
 
9
- declare const LoaderButton: ({ isLoading, disabled, loaderLabel, children, appearance, ...rest }: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
9
+ /**
10
+ * LoaderButton component. Automatically routes between the Tailwind
11
+ * implementation (preferred) and the styled-components implementation (for
12
+ * consumers using system props or a styled() extension).
13
+ */
14
+ declare const LoaderButton: (props: TypeLoaderButtonProps) => react_jsx_runtime.JSX.Element;
10
15
 
11
16
  export { LoaderButton, type TypeLoaderButtonProps, LoaderButton as default };
package/dist/index.js CHANGED
@@ -36,13 +36,68 @@ __export(index_exports, {
36
36
  module.exports = __toCommonJS(index_exports);
37
37
 
38
38
  // src/LoaderButton.tsx
39
- var React = require("react");
39
+ var React3 = require("react");
40
+
41
+ // src/LoaderButtonHybrid.tsx
42
+ var React2 = require("react");
40
43
  var import_styled_components = __toESM(require("styled-components"));
44
+ var import_seeds_react_box2 = __toESM(require("@sproutsocial/seeds-react-box"));
45
+ var import_seeds_react_button2 = __toESM(require("@sproutsocial/seeds-react-button"));
46
+ var import_seeds_react_loader2 = __toESM(require("@sproutsocial/seeds-react-loader"));
47
+
48
+ // src/LoaderButtonTailwind.tsx
49
+ var React = require("react");
41
50
  var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
42
51
  var import_seeds_react_button = __toESM(require("@sproutsocial/seeds-react-button"));
43
52
  var import_seeds_react_loader = __toESM(require("@sproutsocial/seeds-react-loader"));
44
53
  var import_jsx_runtime = require("react/jsx-runtime");
45
- var StyledLoaderButton = (0, import_styled_components.default)(import_seeds_react_button.default)`
54
+ function cn(...inputs) {
55
+ const classes = [];
56
+ for (const input of inputs) {
57
+ if (!input) continue;
58
+ if (typeof input === "string") {
59
+ classes.push(input);
60
+ } else if (typeof input === "object") {
61
+ for (const [key, value] of Object.entries(input)) {
62
+ if (value) {
63
+ classes.push(key);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return classes.join(" ");
69
+ }
70
+ var LoaderButtonTailwind = ({
71
+ isLoading = false,
72
+ disabled,
73
+ loaderLabel,
74
+ children,
75
+ appearance = "unstyled",
76
+ className,
77
+ ...rest
78
+ }) => {
79
+ const isDisabled = disabled || isLoading;
80
+ const classes = cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || void 0;
81
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
82
+ import_seeds_react_button.default,
83
+ {
84
+ disabled: isDisabled,
85
+ appearance,
86
+ "data-qa-button-isloading": isLoading === true,
87
+ className: classes,
88
+ ...rest,
89
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { position: "relative", children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
91
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_loader.default, { text: loaderLabel, size: "small", delay: false }) })
92
+ ] })
93
+ }
94
+ );
95
+ };
96
+
97
+ // src/LoaderButtonHybrid.tsx
98
+ var import_seeds_react_system_props = require("@sproutsocial/seeds-react-system-props");
99
+ var import_jsx_runtime2 = require("react/jsx-runtime");
100
+ var StyledLoaderButton = (0, import_styled_components.default)(import_seeds_react_button2.default)`
46
101
  background-color: ${({ theme, appearance, disabled }) => {
47
102
  const buttonBackgroundColor = theme.colors.button[appearance]?.background?.base;
48
103
  const isBackgroundColorTransparent = buttonBackgroundColor === "transparent";
@@ -50,7 +105,7 @@ var StyledLoaderButton = (0, import_styled_components.default)(import_seeds_reac
50
105
  }};
51
106
  ${({ disabled }) => disabled && "opacity: 1;"}
52
107
  `;
53
- var LoaderButton = ({
108
+ var LoaderButtonHybrid = ({
54
109
  isLoading = false,
55
110
  disabled,
56
111
  loaderLabel,
@@ -58,20 +113,38 @@ var LoaderButton = ({
58
113
  appearance = "unstyled",
59
114
  ...rest
60
115
  }) => {
61
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
62
- StyledLoaderButton,
116
+ if ((0, import_seeds_react_system_props.hasStyledProps)(rest)) {
117
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
118
+ StyledLoaderButton,
119
+ {
120
+ disabled: disabled || isLoading,
121
+ appearance,
122
+ "data-qa-button-isloading": isLoading === true,
123
+ ...rest,
124
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_seeds_react_box2.default, { position: "relative", children: [
125
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_box2.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
126
+ isLoading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_box2.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_loader2.default, { text: loaderLabel, size: "small", delay: false }) })
127
+ ] })
128
+ }
129
+ );
130
+ }
131
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
132
+ LoaderButtonTailwind,
63
133
  {
64
- disabled: disabled || isLoading,
134
+ isLoading,
135
+ disabled,
136
+ loaderLabel,
65
137
  appearance,
66
- "data-qa-button-isloading": isLoading === true,
67
138
  ...rest,
68
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { position: "relative", children: [
69
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { opacity: isLoading ? 0 : 1, "aria-hidden": isLoading, children }),
70
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_box.default, { position: "absolute", top: -2, left: 0, right: 0, bottom: 0, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_seeds_react_loader.default, { text: loaderLabel, size: "small", delay: false }) })
71
- ] })
139
+ children
72
140
  }
73
141
  );
74
142
  };
143
+ var LoaderButtonHybrid_default = LoaderButtonHybrid;
144
+
145
+ // src/LoaderButton.tsx
146
+ var import_jsx_runtime3 = require("react/jsx-runtime");
147
+ var LoaderButton = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(LoaderButtonHybrid_default, { ...props });
75
148
  var LoaderButton_default = LoaderButton;
76
149
 
77
150
  // src/index.ts
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/LoaderButton.tsx"],"sourcesContent":["import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n","import * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButton = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n};\n\nexport default LoaderButton;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,YAAuB;AACvB,+BAAmB;AACnB,6BAAgB;AAChB,gCAAmB;AACnB,gCAAmB;AAqCb;AAlCN,IAAM,yBAAqB,yBAAAA,SAAO,0BAAAC,OAAM;AAAA,sBAClB,CAAC,EAAE,OAAO,YAAY,SAAS,MAAM;AACvD,QAAM,wBACJ,MAAM,OAAO,OAAO,UAA8C,GAC9D,YAAY;AAElB,QAAM,+BACJ,0BAA0B;AAG5B,SAAO,WACH,+BACE,gBACA,GAAG,qBAAqB,OAC1B;AACN,CAAC;AAAA,IACC,CAAC,EAAE,SAAS,MAAM,YAAY,aAAa;AAAA;AAGxC,IAAM,eAAe,CAAC;AAAA,EAC3B,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb,GAAG;AACL,MAA6B;AAC3B,SACE;AAAA,IAAC;AAAA;AAAA,MACC,UAAU,YAAY;AAAA,MACtB;AAAA,MACA,4BAA0B,cAAc;AAAA,MACvC,GAAG;AAAA,MAEJ,uDAAC,uBAAAC,SAAA,EAAI,UAAS,YACZ;AAAA,oDAAC,uBAAAA,SAAA,EAAI,SAAS,YAAY,IAAI,GAAG,eAAa,WAC3C,UACH;AAAA,QACC,aACC,4CAAC,uBAAAA,SAAA,EAAI,UAAS,YAAW,KAAK,IAAI,MAAM,GAAG,OAAO,GAAG,QAAQ,GAC3D,sDAAC,0BAAAC,SAAA,EAAO,MAAM,aAAa,MAAK,SAAQ,OAAO,OAAO,GACxD;AAAA,SAEJ;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,uBAAQ;;;ADrDf,IAAO,gBAAQ;","names":["styled","Button","Box","Loader"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/LoaderButton.tsx","../src/LoaderButtonHybrid.tsx","../src/LoaderButtonTailwind.tsx"],"sourcesContent":["import LoaderButton from \"./LoaderButton\";\n\nexport default LoaderButton;\nexport { LoaderButton };\nexport * from \"./LoaderButtonTypes\";\n","import * as React from \"react\";\nimport LoaderButtonHybrid from \"./LoaderButtonHybrid\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n/**\n * LoaderButton component. Automatically routes between the Tailwind\n * implementation (preferred) and the styled-components implementation (for\n * consumers using system props or a styled() extension).\n */\nexport const LoaderButton = (props: TypeLoaderButtonProps) => (\n <LoaderButtonHybrid {...props} />\n);\n\nexport default LoaderButton;\n","/**\n * Hybrid LoaderButton Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport styled from \"styled-components\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport { LoaderButtonTailwind } from \"./LoaderButtonTailwind\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\nconst StyledLoaderButton = styled(Button)`\n background-color: ${({ theme, appearance, disabled }) => {\n const buttonBackgroundColor =\n theme.colors.button[appearance as keyof typeof theme.colors.button]\n ?.background?.base;\n\n const isBackgroundColorTransparent =\n buttonBackgroundColor === \"transparent\";\n\n // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.\n return disabled\n ? isBackgroundColorTransparent\n ? \"transparent\"\n : `${buttonBackgroundColor}66`\n : buttonBackgroundColor;\n }};\n ${({ disabled }) => disabled && \"opacity: 1;\"}\n`;\n\nexport const LoaderButtonHybrid = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n ...rest\n}: TypeLoaderButtonProps) => {\n if (hasStyledProps(rest)) {\n return (\n <StyledLoaderButton\n disabled={disabled || isLoading}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </StyledLoaderButton>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <LoaderButtonTailwind\n isLoading={isLoading}\n disabled={disabled}\n loaderLabel={loaderLabel}\n appearance={appearance}\n {...rest}\n >\n {children}\n </LoaderButtonTailwind>\n );\n};\n\nexport default LoaderButtonHybrid;\n","/**\n * Tailwind CSS implementation of LoaderButton component\n * Renders Button with its appearance classes plus a disabled-dimming layer\n * from loader-button.css.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Loader from \"@sproutsocial/seeds-react-loader\";\nimport type { TypeLoaderButtonProps } from \"./LoaderButtonTypes\";\n\n// Utility for merging class names properly\nfunction cn(\n ...inputs: (string | undefined | null | false | Record<string, boolean>)[]\n): string {\n const classes: string[] = [];\n\n for (const input of inputs) {\n if (!input) continue;\n\n if (typeof input === \"string\") {\n classes.push(input);\n } else if (typeof input === \"object\") {\n for (const [key, value] of Object.entries(input)) {\n if (value) {\n classes.push(key);\n }\n }\n }\n }\n\n return classes.join(\" \");\n}\n\nexport const LoaderButtonTailwind = ({\n isLoading = false,\n disabled,\n loaderLabel,\n children,\n appearance = \"unstyled\",\n className,\n ...rest\n}: TypeLoaderButtonProps) => {\n const isDisabled = disabled || isLoading;\n const classes =\n cn({ \"seeds-loader-btn-disabled\": !!isDisabled }, className) || undefined;\n\n return (\n <Button\n disabled={isDisabled}\n appearance={appearance}\n data-qa-button-isloading={isLoading === true}\n className={classes}\n {...rest}\n >\n <Box position=\"relative\">\n <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>\n {children}\n </Box>\n {isLoading && (\n <Box position=\"absolute\" top={-2} left={0} right={0} bottom={0}>\n <Loader text={loaderLabel} size=\"small\" delay={false} />\n </Box>\n )}\n </Box>\n </Button>\n );\n};\n\nexport default LoaderButtonTailwind;\n"],"mappings":"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","names":["React","React","import_seeds_react_box","import_seeds_react_button","import_seeds_react_loader","Button","Box","Loader","import_jsx_runtime","styled","Button","Box","Loader","import_jsx_runtime"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutsocial/seeds-react-loader-button",
3
- "version": "1.0.33",
3
+ "version": "1.0.45",
4
4
  "description": "Seeds React LoaderButton",
5
5
  "author": "Sprout Social, Inc.",
6
6
  "license": "MIT",
@@ -18,11 +18,11 @@
18
18
  "test:watch": "jest --watch --coverage=false"
19
19
  },
20
20
  "dependencies": {
21
- "@sproutsocial/seeds-react-theme": "^3.6.2",
22
- "@sproutsocial/seeds-react-system-props": "^3.0.1",
23
- "@sproutsocial/seeds-react-box": "^1.1.16",
24
- "@sproutsocial/seeds-react-button": "^2.0.4",
25
- "@sproutsocial/seeds-react-loader": "^1.0.16"
21
+ "@sproutsocial/seeds-react-theme": "^4.1.0",
22
+ "@sproutsocial/seeds-react-system-props": "^3.1.1",
23
+ "@sproutsocial/seeds-react-box": "^1.1.21",
24
+ "@sproutsocial/seeds-react-button": "^2.2.1",
25
+ "@sproutsocial/seeds-react-loader": "^1.0.22"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/react": "^18.0.0",
@@ -77,3 +77,35 @@ export const AllLoaderButtons: Story = {
77
77
  </Box>
78
78
  ),
79
79
  };
80
+
81
+ /**
82
+ * Demonstrates that Tailwind utility classes passed via `className` override the
83
+ * component's own CSS. Because `loader-button.css` lives in `@layer components`,
84
+ * the utilities below win the cascade: `bg-[#FF6B00]` paints a loud orange
85
+ * background over the button's own fill, `text-[#FFFFFF]` flips the label white
86
+ * for contrast, and `p-300` adds padding so the orange box is obvious. If the
87
+ * `@layer components` wrapper were missing, the unlayered component rules would
88
+ * beat these utilities and the orange background would never show.
89
+ *
90
+ * The story is interactive: clicking the button flips it into the loading state
91
+ * so the loader appears, then clears after a short timeout.
92
+ */
93
+ export const TailwindOverrides: Story = {
94
+ render: () => {
95
+ const [isLoading, setIsLoading] = React.useState(false);
96
+ return (
97
+ <LoaderButton
98
+ loaderLabel="Loading..."
99
+ isLoading={isLoading}
100
+ className="bg-[#FF6B00] text-[#FFFFFF] p-300"
101
+ onClick={() => {
102
+ setIsLoading(true);
103
+ setTimeout(() => setIsLoading(false), 2000);
104
+ }}
105
+ >
106
+ Click to load
107
+ </LoaderButton>
108
+ );
109
+ },
110
+ name: "🚀 Tailwind class overrides",
111
+ };
@@ -1,56 +1,14 @@
1
1
  import * as React from "react";
2
- import styled from "styled-components";
3
- import Box from "@sproutsocial/seeds-react-box";
4
- import Button from "@sproutsocial/seeds-react-button";
5
- import Loader from "@sproutsocial/seeds-react-loader";
2
+ import LoaderButtonHybrid from "./LoaderButtonHybrid";
6
3
  import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
7
4
 
8
- const StyledLoaderButton = styled(Button)`
9
- background-color: ${({ theme, appearance, disabled }) => {
10
- const buttonBackgroundColor =
11
- theme.colors.button[appearance as keyof typeof theme.colors.button]
12
- ?.background?.base;
13
-
14
- const isBackgroundColorTransparent =
15
- buttonBackgroundColor === "transparent";
16
-
17
- // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.
18
- return disabled
19
- ? isBackgroundColorTransparent
20
- ? "transparent"
21
- : `${buttonBackgroundColor}66`
22
- : buttonBackgroundColor;
23
- }};
24
- ${({ disabled }) => disabled && "opacity: 1;"}
25
- `;
26
-
27
- export const LoaderButton = ({
28
- isLoading = false,
29
- disabled,
30
- loaderLabel,
31
- children,
32
- appearance = "unstyled",
33
- ...rest
34
- }: TypeLoaderButtonProps) => {
35
- return (
36
- <StyledLoaderButton
37
- disabled={disabled || isLoading}
38
- appearance={appearance}
39
- data-qa-button-isloading={isLoading === true}
40
- {...rest}
41
- >
42
- <Box position="relative">
43
- <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
44
- {children}
45
- </Box>
46
- {isLoading && (
47
- <Box position="absolute" top={-2} left={0} right={0} bottom={0}>
48
- <Loader text={loaderLabel} size="small" delay={false} />
49
- </Box>
50
- )}
51
- </Box>
52
- </StyledLoaderButton>
53
- );
54
- };
5
+ /**
6
+ * LoaderButton component. Automatically routes between the Tailwind
7
+ * implementation (preferred) and the styled-components implementation (for
8
+ * consumers using system props or a styled() extension).
9
+ */
10
+ export const LoaderButton = (props: TypeLoaderButtonProps) => (
11
+ <LoaderButtonHybrid {...props} />
12
+ );
55
13
 
56
14
  export default LoaderButton;
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Hybrid LoaderButton Component
3
+ * Automatically chooses between Tailwind and styled-components based on props.
4
+ */
5
+
6
+ import * as React from "react";
7
+ import styled from "styled-components";
8
+ import Box from "@sproutsocial/seeds-react-box";
9
+ import Button from "@sproutsocial/seeds-react-button";
10
+ import Loader from "@sproutsocial/seeds-react-loader";
11
+ import { LoaderButtonTailwind } from "./LoaderButtonTailwind";
12
+ import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
13
+ import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
14
+
15
+ const StyledLoaderButton = styled(Button)`
16
+ background-color: ${({ theme, appearance, disabled }) => {
17
+ const buttonBackgroundColor =
18
+ theme.colors.button[appearance as keyof typeof theme.colors.button]
19
+ ?.background?.base;
20
+
21
+ const isBackgroundColorTransparent =
22
+ buttonBackgroundColor === "transparent";
23
+
24
+ // If the button is disabled we want to check what the buttonBackgroundColor is, if it is transparent we want to return transparent, otherwise we want to return the buttonBackgroundColor with an opacity of 0.4. If the button is not disabled we want to return the buttonBackgroundColor.
25
+ return disabled
26
+ ? isBackgroundColorTransparent
27
+ ? "transparent"
28
+ : `${buttonBackgroundColor}66`
29
+ : buttonBackgroundColor;
30
+ }};
31
+ ${({ disabled }) => disabled && "opacity: 1;"}
32
+ `;
33
+
34
+ export const LoaderButtonHybrid = ({
35
+ isLoading = false,
36
+ disabled,
37
+ loaderLabel,
38
+ children,
39
+ appearance = "unstyled",
40
+ ...rest
41
+ }: TypeLoaderButtonProps) => {
42
+ if (hasStyledProps(rest)) {
43
+ return (
44
+ <StyledLoaderButton
45
+ disabled={disabled || isLoading}
46
+ appearance={appearance}
47
+ data-qa-button-isloading={isLoading === true}
48
+ {...rest}
49
+ >
50
+ <Box position="relative">
51
+ <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
52
+ {children}
53
+ </Box>
54
+ {isLoading && (
55
+ <Box position="absolute" top={-2} left={0} right={0} bottom={0}>
56
+ <Loader text={loaderLabel} size="small" delay={false} />
57
+ </Box>
58
+ )}
59
+ </Box>
60
+ </StyledLoaderButton>
61
+ );
62
+ }
63
+
64
+ // Use Tailwind version (preferred - better performance)
65
+ return (
66
+ <LoaderButtonTailwind
67
+ isLoading={isLoading}
68
+ disabled={disabled}
69
+ loaderLabel={loaderLabel}
70
+ appearance={appearance}
71
+ {...rest}
72
+ >
73
+ {children}
74
+ </LoaderButtonTailwind>
75
+ );
76
+ };
77
+
78
+ export default LoaderButtonHybrid;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Tailwind CSS implementation of LoaderButton component
3
+ * Renders Button with its appearance classes plus a disabled-dimming layer
4
+ * from loader-button.css.
5
+ */
6
+
7
+ import * as React from "react";
8
+ import Box from "@sproutsocial/seeds-react-box";
9
+ import Button from "@sproutsocial/seeds-react-button";
10
+ import Loader from "@sproutsocial/seeds-react-loader";
11
+ import type { TypeLoaderButtonProps } from "./LoaderButtonTypes";
12
+
13
+ // Utility for merging class names properly
14
+ function cn(
15
+ ...inputs: (string | undefined | null | false | Record<string, boolean>)[]
16
+ ): string {
17
+ const classes: string[] = [];
18
+
19
+ for (const input of inputs) {
20
+ if (!input) continue;
21
+
22
+ if (typeof input === "string") {
23
+ classes.push(input);
24
+ } else if (typeof input === "object") {
25
+ for (const [key, value] of Object.entries(input)) {
26
+ if (value) {
27
+ classes.push(key);
28
+ }
29
+ }
30
+ }
31
+ }
32
+
33
+ return classes.join(" ");
34
+ }
35
+
36
+ export const LoaderButtonTailwind = ({
37
+ isLoading = false,
38
+ disabled,
39
+ loaderLabel,
40
+ children,
41
+ appearance = "unstyled",
42
+ className,
43
+ ...rest
44
+ }: TypeLoaderButtonProps) => {
45
+ const isDisabled = disabled || isLoading;
46
+ const classes =
47
+ cn({ "seeds-loader-btn-disabled": !!isDisabled }, className) || undefined;
48
+
49
+ return (
50
+ <Button
51
+ disabled={isDisabled}
52
+ appearance={appearance}
53
+ data-qa-button-isloading={isLoading === true}
54
+ className={classes}
55
+ {...rest}
56
+ >
57
+ <Box position="relative">
58
+ <Box opacity={isLoading ? 0 : 1} aria-hidden={isLoading}>
59
+ {children}
60
+ </Box>
61
+ {isLoading && (
62
+ <Box position="absolute" top={-2} left={0} right={0} bottom={0}>
63
+ <Loader text={loaderLabel} size="small" delay={false} />
64
+ </Box>
65
+ )}
66
+ </Box>
67
+ </Button>
68
+ );
69
+ };
70
+
71
+ export default LoaderButtonTailwind;
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { render, screen } from "@sproutsocial/seeds-react-testing-library";
3
+ import LoaderButton from "../LoaderButton";
4
+
5
+ describe("LoaderButton Tailwind path", () => {
6
+ it("renders Button with the seeds-btn class when no styled props are used", () => {
7
+ render(<LoaderButton loaderLabel="loading">Go</LoaderButton>);
8
+ expect(screen.getByRole("button")).toHaveClass("seeds-btn");
9
+ });
10
+
11
+ it("applies the loader disabled dimming class when disabled", () => {
12
+ render(
13
+ <LoaderButton loaderLabel="loading" disabled>
14
+ Go
15
+ </LoaderButton>
16
+ );
17
+ const button = screen.getByRole("button");
18
+ expect(button).toHaveClass("seeds-loader-btn-disabled");
19
+ expect(button).toHaveClass("seeds-btn-disabled");
20
+ });
21
+
22
+ it("applies the loader disabled dimming class while loading", () => {
23
+ render(
24
+ <LoaderButton loaderLabel="loading" isLoading>
25
+ Go
26
+ </LoaderButton>
27
+ );
28
+ expect(screen.getByRole("button")).toHaveClass("seeds-loader-btn-disabled");
29
+ });
30
+ });
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Seeds LoaderButton component classes
3
+ * Layered on top of the Button (.seeds-btn*) classes to reproduce the disabled
4
+ * background dimming the styled-components LoaderButton applied.
5
+ *
6
+ * Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
7
+ * CSS variable definitions and dark mode support.
8
+ *
9
+ * Rules live in the Tailwind `components` layer so consumer utility classes
10
+ * (e.g. mx-200, p-300, inline-flex) win the cascade over these defaults.
11
+ */
12
+
13
+ @layer components {
14
+ /* Keep the loader fully visible by overriding .seeds-btn-disabled opacity: 0.5 */
15
+ .seeds-loader-btn-disabled.seeds-btn-disabled {
16
+ opacity: 1;
17
+ }
18
+
19
+ /* Disabled background: the appearance's base color at 40% alpha. */
20
+ .seeds-loader-btn-disabled.seeds-btn-primary {
21
+ background-color: color-mix(
22
+ in srgb,
23
+ var(--color-button-primary-bg-base) 40%,
24
+ transparent
25
+ );
26
+ }
27
+
28
+ .seeds-loader-btn-disabled.seeds-btn-destructive {
29
+ background-color: color-mix(
30
+ in srgb,
31
+ var(--color-button-destructive-bg-base) 40%,
32
+ transparent
33
+ );
34
+ }
35
+
36
+ /* Appearances whose base background is transparent resolve to transparent. */
37
+ .seeds-loader-btn-disabled.seeds-btn-secondary {
38
+ background-color: transparent;
39
+ }
40
+
41
+ .seeds-loader-btn-disabled.seeds-btn-placeholder {
42
+ background-color: transparent;
43
+ }
44
+
45
+ .seeds-loader-btn-disabled.seeds-btn-unstyled {
46
+ background-color: transparent;
47
+ }
48
+
49
+ .seeds-loader-btn-disabled.seeds-btn-pill {
50
+ background-color: transparent;
51
+ }
52
+ }