@sproutsocial/seeds-react-banner 1.1.11 → 1.1.22
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 +10 -10
- package/CHANGELOG.md +97 -0
- package/dist/esm/index.js +100 -11
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +102 -13
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/Banner.stories.tsx +24 -0
- package/src/Banner.tsx +9 -93
- package/src/BannerHybrid.tsx +73 -0
- package/src/BannerTailwind.tsx +81 -0
- package/src/__tests__/features.test.tsx +7 -16
- package/src/__tests__/tailwind.test.tsx +32 -0
- package/src/banner.css +77 -0
- package/src/bannerIcon.ts +43 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -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
|
-
[
|
|
12
|
-
[
|
|
13
|
-
[
|
|
14
|
-
[
|
|
15
|
-
[
|
|
16
|
-
[
|
|
11
|
+
[32mCJS[39m [1mdist/index.js [22m[32m9.00 KB[39m
|
|
12
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m12.96 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 18ms
|
|
14
|
+
[32mESM[39m [1mdist/esm/index.js [22m[32m6.31 KB[39m
|
|
15
|
+
[32mESM[39m [1mdist/esm/index.js.map [22m[32m12.74 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 23ms
|
|
17
17
|
[34mDTS[39m Build start
|
|
18
|
-
[32mDTS[39m ⚡️ Build success in
|
|
19
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.
|
|
20
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.
|
|
21
|
-
Done in 6.
|
|
18
|
+
[32mDTS[39m ⚡️ Build success in 4528ms
|
|
19
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.42 KB[39m
|
|
20
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.42 KB[39m
|
|
21
|
+
Done in 6.22s.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,102 @@
|
|
|
1
1
|
# @sproutsocial/seeds-react-banner
|
|
2
2
|
|
|
3
|
+
## 1.1.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [69c9d02]
|
|
8
|
+
- @sproutsocial/seeds-react-icon@2.4.0
|
|
9
|
+
- @sproutsocial/seeds-react-button@2.2.1
|
|
10
|
+
|
|
11
|
+
## 1.1.21
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 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.
|
|
16
|
+
|
|
17
|
+
## 1.1.20
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- Updated dependencies [456a20f]
|
|
22
|
+
- Updated dependencies [5892f44]
|
|
23
|
+
- @sproutsocial/seeds-react-button@2.2.0
|
|
24
|
+
- @sproutsocial/seeds-react-system-props@3.1.1
|
|
25
|
+
- @sproutsocial/seeds-react-box@1.1.21
|
|
26
|
+
- @sproutsocial/seeds-react-icon@2.3.13
|
|
27
|
+
|
|
28
|
+
## 1.1.19
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- Updated dependencies [5114a32]
|
|
33
|
+
- Updated dependencies [a0fe3d3]
|
|
34
|
+
- @sproutsocial/seeds-react-theme@4.1.0
|
|
35
|
+
- @sproutsocial/seeds-react-button@2.1.3
|
|
36
|
+
- @sproutsocial/seeds-react-box@1.1.20
|
|
37
|
+
- @sproutsocial/seeds-react-icon@2.3.12
|
|
38
|
+
|
|
39
|
+
## 1.1.18
|
|
40
|
+
|
|
41
|
+
### Patch Changes
|
|
42
|
+
|
|
43
|
+
- Updated dependencies [cb27f07]
|
|
44
|
+
- @sproutsocial/seeds-react-button@2.1.2
|
|
45
|
+
|
|
46
|
+
## 1.1.17
|
|
47
|
+
|
|
48
|
+
### Patch Changes
|
|
49
|
+
|
|
50
|
+
- Updated dependencies [40d2dfe]
|
|
51
|
+
- @sproutsocial/seeds-react-button@2.1.1
|
|
52
|
+
|
|
53
|
+
## 1.1.16
|
|
54
|
+
|
|
55
|
+
### Patch Changes
|
|
56
|
+
|
|
57
|
+
- Updated dependencies [132ef9d]
|
|
58
|
+
- Updated dependencies [132ef9d]
|
|
59
|
+
- Updated dependencies [132ef9d]
|
|
60
|
+
- @sproutsocial/seeds-react-button@2.1.0
|
|
61
|
+
- @sproutsocial/seeds-react-theme@4.0.0
|
|
62
|
+
- @sproutsocial/seeds-react-system-props@3.1.0
|
|
63
|
+
- @sproutsocial/seeds-react-box@1.1.19
|
|
64
|
+
- @sproutsocial/seeds-react-icon@2.3.11
|
|
65
|
+
|
|
66
|
+
## 1.1.15
|
|
67
|
+
|
|
68
|
+
### Patch Changes
|
|
69
|
+
|
|
70
|
+
- @sproutsocial/seeds-react-icon@2.3.10
|
|
71
|
+
- @sproutsocial/seeds-react-button@2.0.8
|
|
72
|
+
|
|
73
|
+
## 1.1.14
|
|
74
|
+
|
|
75
|
+
### Patch Changes
|
|
76
|
+
|
|
77
|
+
- Updated dependencies [47c62b3]
|
|
78
|
+
- @sproutsocial/seeds-react-theme@3.7.1
|
|
79
|
+
- @sproutsocial/seeds-react-box@1.1.18
|
|
80
|
+
- @sproutsocial/seeds-react-icon@2.3.9
|
|
81
|
+
- @sproutsocial/seeds-react-button@2.0.7
|
|
82
|
+
|
|
83
|
+
## 1.1.13
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- Updated dependencies [06da9c2]
|
|
88
|
+
- @sproutsocial/seeds-react-theme@3.7.0
|
|
89
|
+
- @sproutsocial/seeds-react-box@1.1.17
|
|
90
|
+
- @sproutsocial/seeds-react-icon@2.3.8
|
|
91
|
+
- @sproutsocial/seeds-react-button@2.0.6
|
|
92
|
+
|
|
93
|
+
## 1.1.12
|
|
94
|
+
|
|
95
|
+
### Patch Changes
|
|
96
|
+
|
|
97
|
+
- @sproutsocial/seeds-react-icon@2.3.7
|
|
98
|
+
- @sproutsocial/seeds-react-button@2.0.5
|
|
99
|
+
|
|
3
100
|
## 1.1.11
|
|
4
101
|
|
|
5
102
|
### Patch Changes
|
package/dist/esm/index.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// src/Banner.tsx
|
|
2
2
|
import "react";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import
|
|
3
|
+
|
|
4
|
+
// src/BannerHybrid.tsx
|
|
5
|
+
import "react";
|
|
6
|
+
import Box2 from "@sproutsocial/seeds-react-box";
|
|
7
|
+
import Button2 from "@sproutsocial/seeds-react-button";
|
|
8
|
+
import Icon3 from "@sproutsocial/seeds-react-icon";
|
|
6
9
|
|
|
7
10
|
// src/styles.ts
|
|
8
11
|
import styled, { css } from "styled-components";
|
|
@@ -53,8 +56,13 @@ var StyledBannerIcon = styled(Icon)`
|
|
|
53
56
|
min-width: 16px;
|
|
54
57
|
`;
|
|
55
58
|
|
|
56
|
-
// src/
|
|
57
|
-
import
|
|
59
|
+
// src/BannerTailwind.tsx
|
|
60
|
+
import "react";
|
|
61
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
62
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
63
|
+
import Icon2 from "@sproutsocial/seeds-react-icon";
|
|
64
|
+
|
|
65
|
+
// src/bannerIcon.ts
|
|
58
66
|
var getBannerIconName = (type) => {
|
|
59
67
|
switch (type) {
|
|
60
68
|
case "success":
|
|
@@ -86,31 +94,51 @@ var getBannerIconColor = (type, variant) => {
|
|
|
86
94
|
return isGhostVariant ? "container.border.decorative.blue" : "icon.info";
|
|
87
95
|
}
|
|
88
96
|
};
|
|
89
|
-
|
|
97
|
+
|
|
98
|
+
// src/BannerTailwind.tsx
|
|
99
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
100
|
+
function cn(...inputs) {
|
|
101
|
+
const classes = [];
|
|
102
|
+
for (const input of inputs) {
|
|
103
|
+
if (!input) continue;
|
|
104
|
+
if (typeof input === "string") {
|
|
105
|
+
classes.push(input);
|
|
106
|
+
} else if (typeof input === "object") {
|
|
107
|
+
for (const [key, value] of Object.entries(input)) {
|
|
108
|
+
if (value) {
|
|
109
|
+
classes.push(key);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return classes.join(" ");
|
|
115
|
+
}
|
|
116
|
+
var BannerTailwind = ({
|
|
90
117
|
type = "info",
|
|
91
118
|
variant = "default",
|
|
92
119
|
text,
|
|
93
120
|
onClose,
|
|
94
121
|
closeButtonLabel = "Close",
|
|
95
122
|
typeIconProps,
|
|
123
|
+
className,
|
|
96
124
|
...rest
|
|
97
125
|
}) => {
|
|
126
|
+
const variantClass = variant === "ghost" ? "seeds-banner-ghost" : `seeds-banner-${type}`;
|
|
98
127
|
return /* @__PURE__ */ jsx(
|
|
99
|
-
|
|
128
|
+
"div",
|
|
100
129
|
{
|
|
101
|
-
|
|
102
|
-
variant,
|
|
130
|
+
className: cn("seeds-banner", variantClass, className),
|
|
103
131
|
"data-qa-alert": "",
|
|
104
132
|
"data-qa-alert-type": type,
|
|
105
133
|
"data-qa-alert-text": text,
|
|
106
134
|
...rest,
|
|
107
135
|
children: /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", width: 1, children: [
|
|
108
136
|
/* @__PURE__ */ jsx(
|
|
109
|
-
|
|
137
|
+
Icon2,
|
|
110
138
|
{
|
|
111
139
|
name: getBannerIconName(type),
|
|
112
140
|
color: getBannerIconColor(type, variant),
|
|
113
|
-
className: "Icon",
|
|
141
|
+
className: "Icon seeds-banner-icon",
|
|
114
142
|
fixedWidth: true,
|
|
115
143
|
mt: 100,
|
|
116
144
|
mr: 350,
|
|
@@ -123,6 +151,67 @@ var Banner = ({
|
|
|
123
151
|
}
|
|
124
152
|
);
|
|
125
153
|
};
|
|
154
|
+
var BannerTailwind_default = BannerTailwind;
|
|
155
|
+
|
|
156
|
+
// src/BannerHybrid.tsx
|
|
157
|
+
import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
|
|
158
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
159
|
+
var BannerHybrid = ({
|
|
160
|
+
type = "info",
|
|
161
|
+
variant = "default",
|
|
162
|
+
text,
|
|
163
|
+
onClose,
|
|
164
|
+
closeButtonLabel = "Close",
|
|
165
|
+
typeIconProps,
|
|
166
|
+
...rest
|
|
167
|
+
}) => {
|
|
168
|
+
if (hasStyledProps(rest)) {
|
|
169
|
+
return /* @__PURE__ */ jsx2(
|
|
170
|
+
styles_default,
|
|
171
|
+
{
|
|
172
|
+
type,
|
|
173
|
+
variant,
|
|
174
|
+
"data-qa-alert": "",
|
|
175
|
+
"data-qa-alert-type": type,
|
|
176
|
+
"data-qa-alert-text": text,
|
|
177
|
+
...rest,
|
|
178
|
+
children: /* @__PURE__ */ jsxs2(Box2, { display: "flex", alignItems: "center", width: 1, children: [
|
|
179
|
+
/* @__PURE__ */ jsx2(
|
|
180
|
+
StyledBannerIcon,
|
|
181
|
+
{
|
|
182
|
+
name: getBannerIconName(type),
|
|
183
|
+
color: getBannerIconColor(type, variant),
|
|
184
|
+
className: "Icon",
|
|
185
|
+
fixedWidth: true,
|
|
186
|
+
mt: 100,
|
|
187
|
+
mr: 350,
|
|
188
|
+
...typeIconProps
|
|
189
|
+
}
|
|
190
|
+
),
|
|
191
|
+
text,
|
|
192
|
+
onClose && /* @__PURE__ */ jsx2(Box2, { ml: "auto", pl: 400, alignSelf: "flex-start", children: /* @__PURE__ */ jsx2(Button2, { p: 0, onClick: onClose, ariaLabel: closeButtonLabel, children: /* @__PURE__ */ jsx2(Icon3, { name: "x-outline", "aria-hidden": true }) }) })
|
|
193
|
+
] })
|
|
194
|
+
}
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
return /* @__PURE__ */ jsx2(
|
|
198
|
+
BannerTailwind_default,
|
|
199
|
+
{
|
|
200
|
+
type,
|
|
201
|
+
variant,
|
|
202
|
+
text,
|
|
203
|
+
onClose,
|
|
204
|
+
closeButtonLabel,
|
|
205
|
+
typeIconProps,
|
|
206
|
+
...rest
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
};
|
|
210
|
+
var BannerHybrid_default = BannerHybrid;
|
|
211
|
+
|
|
212
|
+
// src/Banner.tsx
|
|
213
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
214
|
+
var Banner = (props) => /* @__PURE__ */ jsx3(BannerHybrid_default, { ...props });
|
|
126
215
|
var Banner_default = Banner;
|
|
127
216
|
|
|
128
217
|
// src/BannerTypes.ts
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/Banner.tsx","../../src/styles.ts","../../src/BannerTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { StyledBannerIcon } from \"./styles\";\nimport type {\n TypeBannerProps,\n EnumBannerType,\n EnumBannerVariant,\n} from \"./BannerTypes\";\n\nconst getBannerIconName = (type: EnumBannerType) => {\n switch (type) {\n case \"success\":\n return \"circle-check-outline\";\n case \"error\":\n return \"triangle-exclamation-outline\";\n case \"warning\":\n return \"triangle-exclamation-outline\";\n case \"opportunity\":\n return \"gem-outline\";\n case \"info\":\n default:\n return \"circle-i-outline\";\n }\n};\n\nconst getBannerIconColor = (\n type: EnumBannerType,\n variant: EnumBannerVariant\n) => {\n const isGhostVariant = variant === \"ghost\";\n switch (type) {\n case \"success\":\n return isGhostVariant\n ? \"container.border.decorative.green\"\n : \"icon.success\";\n case \"error\":\n return isGhostVariant ? \"container.border.decorative.red\" : \"icon.error\";\n case \"warning\":\n return isGhostVariant\n ? \"container.border.decorative.yellow\"\n : \"icon.warning\";\n case \"opportunity\":\n return isGhostVariant\n ? \"container.border.decorative.purple\"\n : \"icon.opportunity\";\n case \"info\":\n default:\n return isGhostVariant ? \"container.border.decorative.blue\" : \"icon.info\";\n }\n};\n\n/** TODO: change to 'info' type by default in future version */\nconst Banner = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n ...rest\n}: TypeBannerProps) => {\n return (\n <Container\n type={type}\n variant={variant}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...rest}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <StyledBannerIcon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </Container>\n );\n};\n\nexport default Banner;\n","import styled, { css } from \"styled-components\";\nimport {\n COMMON,\n LAYOUT,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\ntype TypeContainerProps = {\n type: EnumBannerType;\n variant: EnumBannerVariant;\n};\n\nconst Container = styled.div<TypeContainerProps>(\n (props) => css`\n display: flex;\n overflow: hidden;\n align-items: center;\n justify-content: space-between;\n color: ${props.theme.colors.text.body};\n border-radius: ${props.theme.radii.outer};\n font-family: ${props.theme.fontFamily};\n ${props.theme.typography[200]}\n padding: ${props.theme.space[300]};\n border: 1px solid\n ${props.variant === \"ghost\"\n ? props.theme.colors.container.border.base\n : props.theme.colors.container.border[props.type]};\n background-color: ${props.variant === \"ghost\"\n ? props.theme.colors.container.background.base\n : props.theme.colors.container.background[props.type]};\n\n a,\n button {\n font-weight: ${props.theme.fontWeights.semibold};\n color: ${props.theme.colors.text.body};\n font-size: inherit;\n &:hover {\n color: ${props.theme.colors.text.body};\n text-decoration: underline;\n }\n }\n\n > span:not(.Icon) {\n display: block;\n }\n\n ${COMMON}\n ${LAYOUT}\n ${FLEXBOX}\n `\n);\n\nexport default Container;\n\nexport const StyledBannerIcon = styled(Icon)`\n align-self: flex-start;\n min-width: 16px;\n`;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type {\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeIconProps } from \"@sproutsocial/seeds-react-icon\";\n\nexport type EnumBannerType =\n | \"success\"\n | \"info\"\n | \"error\"\n | \"warning\"\n | \"opportunity\";\n\nexport type EnumBannerVariant = \"default\" | \"ghost\";\n\nexport interface TypeBannerProps\n extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\">,\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n TypeStyledComponentsCommonProps {\n text: React.ReactNode;\n /** Type of banner. */\n type?: EnumBannerType;\n /** Variant of banner. */\n variant?: EnumBannerVariant;\n /** Show the close icon in the banner with an action when clicked */\n onClose?: () => void;\n /** Close icon aria label */\n closeButtonLabel?: string;\n /** Icon props that can be passed to the Type specific Icon */\n typeIconProps?: Partial<Omit<TypeIconProps, \"name\">>;\n}\n","import Banner from \"./Banner\";\n\nexport default Banner;\nexport { Banner };\nexport * from \"./BannerTypes\";\n"],"mappings":"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","names":["Icon","Icon"]}
|
|
1
|
+
{"version":3,"sources":["../../src/Banner.tsx","../../src/BannerHybrid.tsx","../../src/styles.ts","../../src/BannerTailwind.tsx","../../src/bannerIcon.ts","../../src/BannerTypes.ts","../../src/index.ts"],"sourcesContent":["import * as React from \"react\";\nimport BannerHybrid from \"./BannerHybrid\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\n\n/**\n * Banner component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props or a styled() extension).\n */\nconst Banner = (props: TypeBannerProps) => <BannerHybrid {...props} />;\n\nexport default Banner;\n","/**\n * Hybrid Banner Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { StyledBannerIcon } from \"./styles\"; // Styled-components version\nimport BannerTailwind from \"./BannerTailwind\"; // Tailwind version\nimport { getBannerIconName, getBannerIconColor } from \"./bannerIcon\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\n\n/** TODO: change to 'info' type by default in future version */\nconst BannerHybrid = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n ...rest\n}: TypeBannerProps) => {\n if (hasStyledProps(rest)) {\n return (\n <Container\n type={type}\n variant={variant}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...rest}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <StyledBannerIcon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </Container>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <BannerTailwind\n type={type}\n variant={variant}\n text={text}\n onClose={onClose}\n closeButtonLabel={closeButtonLabel}\n typeIconProps={typeIconProps}\n {...rest}\n />\n );\n};\n\nexport default BannerHybrid;\n","import styled, { css } from \"styled-components\";\nimport {\n COMMON,\n LAYOUT,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\ntype TypeContainerProps = {\n type: EnumBannerType;\n variant: EnumBannerVariant;\n};\n\nconst Container = styled.div<TypeContainerProps>(\n (props) => css`\n display: flex;\n overflow: hidden;\n align-items: center;\n justify-content: space-between;\n color: ${props.theme.colors.text.body};\n border-radius: ${props.theme.radii.outer};\n font-family: ${props.theme.fontFamily};\n ${props.theme.typography[200]}\n padding: ${props.theme.space[300]};\n border: 1px solid\n ${props.variant === \"ghost\"\n ? props.theme.colors.container.border.base\n : props.theme.colors.container.border[props.type]};\n background-color: ${props.variant === \"ghost\"\n ? props.theme.colors.container.background.base\n : props.theme.colors.container.background[props.type]};\n\n a,\n button {\n font-weight: ${props.theme.fontWeights.semibold};\n color: ${props.theme.colors.text.body};\n font-size: inherit;\n &:hover {\n color: ${props.theme.colors.text.body};\n text-decoration: underline;\n }\n }\n\n > span:not(.Icon) {\n display: block;\n }\n\n ${COMMON}\n ${LAYOUT}\n ${FLEXBOX}\n `\n);\n\nexport default Container;\n\nexport const StyledBannerIcon = styled(Icon)`\n align-self: flex-start;\n min-width: 16px;\n`;\n","/**\n * Tailwind CSS implementation of Banner component\n * Uses Seeds banner CSS classes from banner.css\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport { getBannerIconName, getBannerIconColor } from \"./bannerIcon\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\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\n/** TODO: change to 'info' type by default in future version */\nconst BannerTailwind = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n className,\n ...rest\n}: TypeBannerProps) => {\n const variantClass =\n variant === \"ghost\" ? \"seeds-banner-ghost\" : `seeds-banner-${type}`;\n\n return (\n <div\n className={cn(\"seeds-banner\", variantClass, className)}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...(rest as React.HTMLAttributes<HTMLDivElement>)}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <Icon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon seeds-banner-icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </div>\n );\n};\n\nexport default BannerTailwind;\n","import type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\nexport const getBannerIconName = (type: EnumBannerType) => {\n switch (type) {\n case \"success\":\n return \"circle-check-outline\";\n case \"error\":\n return \"triangle-exclamation-outline\";\n case \"warning\":\n return \"triangle-exclamation-outline\";\n case \"opportunity\":\n return \"gem-outline\";\n case \"info\":\n default:\n return \"circle-i-outline\";\n }\n};\n\nexport const getBannerIconColor = (\n type: EnumBannerType,\n variant: EnumBannerVariant\n) => {\n const isGhostVariant = variant === \"ghost\";\n switch (type) {\n case \"success\":\n return isGhostVariant\n ? \"container.border.decorative.green\"\n : \"icon.success\";\n case \"error\":\n return isGhostVariant ? \"container.border.decorative.red\" : \"icon.error\";\n case \"warning\":\n return isGhostVariant\n ? \"container.border.decorative.yellow\"\n : \"icon.warning\";\n case \"opportunity\":\n return isGhostVariant\n ? \"container.border.decorative.purple\"\n : \"icon.opportunity\";\n case \"info\":\n default:\n return isGhostVariant ? \"container.border.decorative.blue\" : \"icon.info\";\n }\n};\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type {\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeIconProps } from \"@sproutsocial/seeds-react-icon\";\n\nexport type EnumBannerType =\n | \"success\"\n | \"info\"\n | \"error\"\n | \"warning\"\n | \"opportunity\";\n\nexport type EnumBannerVariant = \"default\" | \"ghost\";\n\nexport interface TypeBannerProps\n extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\">,\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n TypeStyledComponentsCommonProps {\n text: React.ReactNode;\n /** Type of banner. */\n type?: EnumBannerType;\n /** Variant of banner. */\n variant?: EnumBannerVariant;\n /** Show the close icon in the banner with an action when clicked */\n onClose?: () => void;\n /** Close icon aria label */\n closeButtonLabel?: string;\n /** Icon props that can be passed to the Type specific Icon */\n typeIconProps?: Partial<Omit<TypeIconProps, \"name\">>;\n}\n","import Banner from \"./Banner\";\n\nexport default Banner;\nexport { Banner };\nexport * from \"./BannerTypes\";\n"],"mappings":"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","names":["Box","Button","Icon","Icon","Icon","jsx","jsxs","Box","Button","Icon","jsx"]}
|
package/dist/index.d.mts
CHANGED
|
@@ -19,7 +19,11 @@ interface TypeBannerProps extends Omit<React.ComponentPropsWithoutRef<"div">, "c
|
|
|
19
19
|
typeIconProps?: Partial<Omit<TypeIconProps, "name">>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Banner component. Automatically routes between the Tailwind implementation
|
|
24
|
+
* (preferred) and the styled-components implementation (for consumers using
|
|
25
|
+
* system props or a styled() extension).
|
|
26
|
+
*/
|
|
27
|
+
declare const Banner: (props: TypeBannerProps) => react_jsx_runtime.JSX.Element;
|
|
24
28
|
|
|
25
29
|
export { Banner, type EnumBannerType, type EnumBannerVariant, type TypeBannerProps, Banner as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,11 @@ interface TypeBannerProps extends Omit<React.ComponentPropsWithoutRef<"div">, "c
|
|
|
19
19
|
typeIconProps?: Partial<Omit<TypeIconProps, "name">>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Banner component. Automatically routes between the Tailwind implementation
|
|
24
|
+
* (preferred) and the styled-components implementation (for consumers using
|
|
25
|
+
* system props or a styled() extension).
|
|
26
|
+
*/
|
|
27
|
+
declare const Banner: (props: TypeBannerProps) => react_jsx_runtime.JSX.Element;
|
|
24
28
|
|
|
25
29
|
export { Banner, type EnumBannerType, type EnumBannerVariant, type TypeBannerProps, Banner as default };
|
package/dist/index.js
CHANGED
|
@@ -36,10 +36,13 @@ __export(index_exports, {
|
|
|
36
36
|
module.exports = __toCommonJS(index_exports);
|
|
37
37
|
|
|
38
38
|
// src/Banner.tsx
|
|
39
|
-
var
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
var
|
|
39
|
+
var React3 = require("react");
|
|
40
|
+
|
|
41
|
+
// src/BannerHybrid.tsx
|
|
42
|
+
var React2 = require("react");
|
|
43
|
+
var import_seeds_react_box2 = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
44
|
+
var import_seeds_react_button2 = __toESM(require("@sproutsocial/seeds-react-button"));
|
|
45
|
+
var import_seeds_react_icon3 = __toESM(require("@sproutsocial/seeds-react-icon"));
|
|
43
46
|
|
|
44
47
|
// src/styles.ts
|
|
45
48
|
var import_styled_components = __toESM(require("styled-components"));
|
|
@@ -86,8 +89,13 @@ var StyledBannerIcon = (0, import_styled_components.default)(import_seeds_react_
|
|
|
86
89
|
min-width: 16px;
|
|
87
90
|
`;
|
|
88
91
|
|
|
89
|
-
// src/
|
|
90
|
-
var
|
|
92
|
+
// src/BannerTailwind.tsx
|
|
93
|
+
var React = require("react");
|
|
94
|
+
var import_seeds_react_box = __toESM(require("@sproutsocial/seeds-react-box"));
|
|
95
|
+
var import_seeds_react_button = __toESM(require("@sproutsocial/seeds-react-button"));
|
|
96
|
+
var import_seeds_react_icon2 = __toESM(require("@sproutsocial/seeds-react-icon"));
|
|
97
|
+
|
|
98
|
+
// src/bannerIcon.ts
|
|
91
99
|
var getBannerIconName = (type) => {
|
|
92
100
|
switch (type) {
|
|
93
101
|
case "success":
|
|
@@ -119,31 +127,51 @@ var getBannerIconColor = (type, variant) => {
|
|
|
119
127
|
return isGhostVariant ? "container.border.decorative.blue" : "icon.info";
|
|
120
128
|
}
|
|
121
129
|
};
|
|
122
|
-
|
|
130
|
+
|
|
131
|
+
// src/BannerTailwind.tsx
|
|
132
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
133
|
+
function cn(...inputs) {
|
|
134
|
+
const classes = [];
|
|
135
|
+
for (const input of inputs) {
|
|
136
|
+
if (!input) continue;
|
|
137
|
+
if (typeof input === "string") {
|
|
138
|
+
classes.push(input);
|
|
139
|
+
} else if (typeof input === "object") {
|
|
140
|
+
for (const [key, value] of Object.entries(input)) {
|
|
141
|
+
if (value) {
|
|
142
|
+
classes.push(key);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return classes.join(" ");
|
|
148
|
+
}
|
|
149
|
+
var BannerTailwind = ({
|
|
123
150
|
type = "info",
|
|
124
151
|
variant = "default",
|
|
125
152
|
text,
|
|
126
153
|
onClose,
|
|
127
154
|
closeButtonLabel = "Close",
|
|
128
155
|
typeIconProps,
|
|
156
|
+
className,
|
|
129
157
|
...rest
|
|
130
158
|
}) => {
|
|
159
|
+
const variantClass = variant === "ghost" ? "seeds-banner-ghost" : `seeds-banner-${type}`;
|
|
131
160
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
132
|
-
|
|
161
|
+
"div",
|
|
133
162
|
{
|
|
134
|
-
|
|
135
|
-
variant,
|
|
163
|
+
className: cn("seeds-banner", variantClass, className),
|
|
136
164
|
"data-qa-alert": "",
|
|
137
165
|
"data-qa-alert-type": type,
|
|
138
166
|
"data-qa-alert-text": text,
|
|
139
167
|
...rest,
|
|
140
168
|
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_seeds_react_box.default, { display: "flex", alignItems: "center", width: 1, children: [
|
|
141
169
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
142
|
-
|
|
170
|
+
import_seeds_react_icon2.default,
|
|
143
171
|
{
|
|
144
172
|
name: getBannerIconName(type),
|
|
145
173
|
color: getBannerIconColor(type, variant),
|
|
146
|
-
className: "Icon",
|
|
174
|
+
className: "Icon seeds-banner-icon",
|
|
147
175
|
fixedWidth: true,
|
|
148
176
|
mt: 100,
|
|
149
177
|
mr: 350,
|
|
@@ -156,10 +184,71 @@ var Banner = ({
|
|
|
156
184
|
}
|
|
157
185
|
);
|
|
158
186
|
};
|
|
187
|
+
var BannerTailwind_default = BannerTailwind;
|
|
188
|
+
|
|
189
|
+
// src/BannerHybrid.tsx
|
|
190
|
+
var import_seeds_react_system_props2 = require("@sproutsocial/seeds-react-system-props");
|
|
191
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
192
|
+
var BannerHybrid = ({
|
|
193
|
+
type = "info",
|
|
194
|
+
variant = "default",
|
|
195
|
+
text,
|
|
196
|
+
onClose,
|
|
197
|
+
closeButtonLabel = "Close",
|
|
198
|
+
typeIconProps,
|
|
199
|
+
...rest
|
|
200
|
+
}) => {
|
|
201
|
+
if ((0, import_seeds_react_system_props2.hasStyledProps)(rest)) {
|
|
202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
203
|
+
styles_default,
|
|
204
|
+
{
|
|
205
|
+
type,
|
|
206
|
+
variant,
|
|
207
|
+
"data-qa-alert": "",
|
|
208
|
+
"data-qa-alert-type": type,
|
|
209
|
+
"data-qa-alert-text": text,
|
|
210
|
+
...rest,
|
|
211
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_seeds_react_box2.default, { display: "flex", alignItems: "center", width: 1, children: [
|
|
212
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
213
|
+
StyledBannerIcon,
|
|
214
|
+
{
|
|
215
|
+
name: getBannerIconName(type),
|
|
216
|
+
color: getBannerIconColor(type, variant),
|
|
217
|
+
className: "Icon",
|
|
218
|
+
fixedWidth: true,
|
|
219
|
+
mt: 100,
|
|
220
|
+
mr: 350,
|
|
221
|
+
...typeIconProps
|
|
222
|
+
}
|
|
223
|
+
),
|
|
224
|
+
text,
|
|
225
|
+
onClose && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_box2.default, { ml: "auto", pl: 400, alignSelf: "flex-start", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_button2.default, { p: 0, onClick: onClose, ariaLabel: closeButtonLabel, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_seeds_react_icon3.default, { name: "x-outline", "aria-hidden": true }) }) })
|
|
226
|
+
] })
|
|
227
|
+
}
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
231
|
+
BannerTailwind_default,
|
|
232
|
+
{
|
|
233
|
+
type,
|
|
234
|
+
variant,
|
|
235
|
+
text,
|
|
236
|
+
onClose,
|
|
237
|
+
closeButtonLabel,
|
|
238
|
+
typeIconProps,
|
|
239
|
+
...rest
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
};
|
|
243
|
+
var BannerHybrid_default = BannerHybrid;
|
|
244
|
+
|
|
245
|
+
// src/Banner.tsx
|
|
246
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
247
|
+
var Banner = (props) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BannerHybrid_default, { ...props });
|
|
159
248
|
var Banner_default = Banner;
|
|
160
249
|
|
|
161
250
|
// src/BannerTypes.ts
|
|
162
|
-
var
|
|
251
|
+
var React4 = require("react");
|
|
163
252
|
|
|
164
253
|
// src/index.ts
|
|
165
254
|
var index_default = Banner_default;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/Banner.tsx","../src/styles.ts","../src/BannerTypes.ts"],"sourcesContent":["import Banner from \"./Banner\";\n\nexport default Banner;\nexport { Banner };\nexport * from \"./BannerTypes\";\n","import * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { StyledBannerIcon } from \"./styles\";\nimport type {\n TypeBannerProps,\n EnumBannerType,\n EnumBannerVariant,\n} from \"./BannerTypes\";\n\nconst getBannerIconName = (type: EnumBannerType) => {\n switch (type) {\n case \"success\":\n return \"circle-check-outline\";\n case \"error\":\n return \"triangle-exclamation-outline\";\n case \"warning\":\n return \"triangle-exclamation-outline\";\n case \"opportunity\":\n return \"gem-outline\";\n case \"info\":\n default:\n return \"circle-i-outline\";\n }\n};\n\nconst getBannerIconColor = (\n type: EnumBannerType,\n variant: EnumBannerVariant\n) => {\n const isGhostVariant = variant === \"ghost\";\n switch (type) {\n case \"success\":\n return isGhostVariant\n ? \"container.border.decorative.green\"\n : \"icon.success\";\n case \"error\":\n return isGhostVariant ? \"container.border.decorative.red\" : \"icon.error\";\n case \"warning\":\n return isGhostVariant\n ? \"container.border.decorative.yellow\"\n : \"icon.warning\";\n case \"opportunity\":\n return isGhostVariant\n ? \"container.border.decorative.purple\"\n : \"icon.opportunity\";\n case \"info\":\n default:\n return isGhostVariant ? \"container.border.decorative.blue\" : \"icon.info\";\n }\n};\n\n/** TODO: change to 'info' type by default in future version */\nconst Banner = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n ...rest\n}: TypeBannerProps) => {\n return (\n <Container\n type={type}\n variant={variant}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...rest}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <StyledBannerIcon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </Container>\n );\n};\n\nexport default Banner;\n","import styled, { css } from \"styled-components\";\nimport {\n COMMON,\n LAYOUT,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\ntype TypeContainerProps = {\n type: EnumBannerType;\n variant: EnumBannerVariant;\n};\n\nconst Container = styled.div<TypeContainerProps>(\n (props) => css`\n display: flex;\n overflow: hidden;\n align-items: center;\n justify-content: space-between;\n color: ${props.theme.colors.text.body};\n border-radius: ${props.theme.radii.outer};\n font-family: ${props.theme.fontFamily};\n ${props.theme.typography[200]}\n padding: ${props.theme.space[300]};\n border: 1px solid\n ${props.variant === \"ghost\"\n ? props.theme.colors.container.border.base\n : props.theme.colors.container.border[props.type]};\n background-color: ${props.variant === \"ghost\"\n ? props.theme.colors.container.background.base\n : props.theme.colors.container.background[props.type]};\n\n a,\n button {\n font-weight: ${props.theme.fontWeights.semibold};\n color: ${props.theme.colors.text.body};\n font-size: inherit;\n &:hover {\n color: ${props.theme.colors.text.body};\n text-decoration: underline;\n }\n }\n\n > span:not(.Icon) {\n display: block;\n }\n\n ${COMMON}\n ${LAYOUT}\n ${FLEXBOX}\n `\n);\n\nexport default Container;\n\nexport const StyledBannerIcon = styled(Icon)`\n align-self: flex-start;\n min-width: 16px;\n`;\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type {\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeIconProps } from \"@sproutsocial/seeds-react-icon\";\n\nexport type EnumBannerType =\n | \"success\"\n | \"info\"\n | \"error\"\n | \"warning\"\n | \"opportunity\";\n\nexport type EnumBannerVariant = \"default\" | \"ghost\";\n\nexport interface TypeBannerProps\n extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\">,\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n TypeStyledComponentsCommonProps {\n text: React.ReactNode;\n /** Type of banner. */\n type?: EnumBannerType;\n /** Variant of banner. */\n variant?: EnumBannerVariant;\n /** Show the close icon in the banner with an action when clicked */\n onClose?: () => void;\n /** Close icon aria label */\n closeButtonLabel?: string;\n /** Icon props that can be passed to the Type specific Icon */\n typeIconProps?: Partial<Omit<TypeIconProps, \"name\">>;\n}\n"],"mappings":"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","names":["import_seeds_react_icon","styled","Icon","Box","Button","Icon","React"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/Banner.tsx","../src/BannerHybrid.tsx","../src/styles.ts","../src/BannerTailwind.tsx","../src/bannerIcon.ts","../src/BannerTypes.ts"],"sourcesContent":["import Banner from \"./Banner\";\n\nexport default Banner;\nexport { Banner };\nexport * from \"./BannerTypes\";\n","import * as React from \"react\";\nimport BannerHybrid from \"./BannerHybrid\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\n\n/**\n * Banner component. Automatically routes between the Tailwind implementation\n * (preferred) and the styled-components implementation (for consumers using\n * system props or a styled() extension).\n */\nconst Banner = (props: TypeBannerProps) => <BannerHybrid {...props} />;\n\nexport default Banner;\n","/**\n * Hybrid Banner Component\n * Automatically chooses between Tailwind and styled-components based on props.\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport Container, { StyledBannerIcon } from \"./styles\"; // Styled-components version\nimport BannerTailwind from \"./BannerTailwind\"; // Tailwind version\nimport { getBannerIconName, getBannerIconColor } from \"./bannerIcon\";\nimport { hasStyledProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\n\n/** TODO: change to 'info' type by default in future version */\nconst BannerHybrid = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n ...rest\n}: TypeBannerProps) => {\n if (hasStyledProps(rest)) {\n return (\n <Container\n type={type}\n variant={variant}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...rest}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <StyledBannerIcon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </Container>\n );\n }\n\n // Use Tailwind version (preferred - better performance)\n return (\n <BannerTailwind\n type={type}\n variant={variant}\n text={text}\n onClose={onClose}\n closeButtonLabel={closeButtonLabel}\n typeIconProps={typeIconProps}\n {...rest}\n />\n );\n};\n\nexport default BannerHybrid;\n","import styled, { css } from \"styled-components\";\nimport {\n COMMON,\n LAYOUT,\n FLEXBOX,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\ntype TypeContainerProps = {\n type: EnumBannerType;\n variant: EnumBannerVariant;\n};\n\nconst Container = styled.div<TypeContainerProps>(\n (props) => css`\n display: flex;\n overflow: hidden;\n align-items: center;\n justify-content: space-between;\n color: ${props.theme.colors.text.body};\n border-radius: ${props.theme.radii.outer};\n font-family: ${props.theme.fontFamily};\n ${props.theme.typography[200]}\n padding: ${props.theme.space[300]};\n border: 1px solid\n ${props.variant === \"ghost\"\n ? props.theme.colors.container.border.base\n : props.theme.colors.container.border[props.type]};\n background-color: ${props.variant === \"ghost\"\n ? props.theme.colors.container.background.base\n : props.theme.colors.container.background[props.type]};\n\n a,\n button {\n font-weight: ${props.theme.fontWeights.semibold};\n color: ${props.theme.colors.text.body};\n font-size: inherit;\n &:hover {\n color: ${props.theme.colors.text.body};\n text-decoration: underline;\n }\n }\n\n > span:not(.Icon) {\n display: block;\n }\n\n ${COMMON}\n ${LAYOUT}\n ${FLEXBOX}\n `\n);\n\nexport default Container;\n\nexport const StyledBannerIcon = styled(Icon)`\n align-self: flex-start;\n min-width: 16px;\n`;\n","/**\n * Tailwind CSS implementation of Banner component\n * Uses Seeds banner CSS classes from banner.css\n */\n\nimport * as React from \"react\";\nimport Box from \"@sproutsocial/seeds-react-box\";\nimport Button from \"@sproutsocial/seeds-react-button\";\nimport Icon from \"@sproutsocial/seeds-react-icon\";\nimport { getBannerIconName, getBannerIconColor } from \"./bannerIcon\";\nimport type { TypeBannerProps } from \"./BannerTypes\";\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\n/** TODO: change to 'info' type by default in future version */\nconst BannerTailwind = ({\n type = \"info\",\n variant = \"default\",\n text,\n onClose,\n closeButtonLabel = \"Close\",\n typeIconProps,\n className,\n ...rest\n}: TypeBannerProps) => {\n const variantClass =\n variant === \"ghost\" ? \"seeds-banner-ghost\" : `seeds-banner-${type}`;\n\n return (\n <div\n className={cn(\"seeds-banner\", variantClass, className)}\n data-qa-alert=\"\"\n data-qa-alert-type={type}\n data-qa-alert-text={text}\n {...(rest as React.HTMLAttributes<HTMLDivElement>)}\n >\n <Box display=\"flex\" alignItems=\"center\" width={1}>\n <Icon\n name={getBannerIconName(type)}\n color={getBannerIconColor(type, variant)}\n className=\"Icon seeds-banner-icon\"\n fixedWidth\n mt={100}\n mr={350}\n {...typeIconProps}\n />\n {text}\n {onClose && (\n <Box ml=\"auto\" pl={400} alignSelf=\"flex-start\">\n <Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>\n <Icon name=\"x-outline\" aria-hidden />\n </Button>\n </Box>\n )}\n </Box>\n </div>\n );\n};\n\nexport default BannerTailwind;\n","import type { EnumBannerType, EnumBannerVariant } from \"./BannerTypes\";\n\nexport const getBannerIconName = (type: EnumBannerType) => {\n switch (type) {\n case \"success\":\n return \"circle-check-outline\";\n case \"error\":\n return \"triangle-exclamation-outline\";\n case \"warning\":\n return \"triangle-exclamation-outline\";\n case \"opportunity\":\n return \"gem-outline\";\n case \"info\":\n default:\n return \"circle-i-outline\";\n }\n};\n\nexport const getBannerIconColor = (\n type: EnumBannerType,\n variant: EnumBannerVariant\n) => {\n const isGhostVariant = variant === \"ghost\";\n switch (type) {\n case \"success\":\n return isGhostVariant\n ? \"container.border.decorative.green\"\n : \"icon.success\";\n case \"error\":\n return isGhostVariant ? \"container.border.decorative.red\" : \"icon.error\";\n case \"warning\":\n return isGhostVariant\n ? \"container.border.decorative.yellow\"\n : \"icon.warning\";\n case \"opportunity\":\n return isGhostVariant\n ? \"container.border.decorative.purple\"\n : \"icon.opportunity\";\n case \"info\":\n default:\n return isGhostVariant ? \"container.border.decorative.blue\" : \"icon.info\";\n }\n};\n","import * as React from \"react\";\nimport type { TypeStyledComponentsCommonProps } from \"@sproutsocial/seeds-react-system-props\";\nimport type {\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n} from \"@sproutsocial/seeds-react-system-props\";\nimport type { TypeIconProps } from \"@sproutsocial/seeds-react-icon\";\n\nexport type EnumBannerType =\n | \"success\"\n | \"info\"\n | \"error\"\n | \"warning\"\n | \"opportunity\";\n\nexport type EnumBannerVariant = \"default\" | \"ghost\";\n\nexport interface TypeBannerProps\n extends Omit<React.ComponentPropsWithoutRef<\"div\">, \"color\">,\n TypeSystemCommonProps,\n TypeSystemLayoutProps,\n TypeSystemFlexboxProps,\n TypeStyledComponentsCommonProps {\n text: React.ReactNode;\n /** Type of banner. */\n type?: EnumBannerType;\n /** Variant of banner. */\n variant?: EnumBannerVariant;\n /** Show the close icon in the banner with an action when clicked */\n onClose?: () => void;\n /** Close icon aria label */\n closeButtonLabel?: string;\n /** Icon props that can be passed to the Type specific Icon */\n typeIconProps?: Partial<Omit<TypeIconProps, \"name\">>;\n}\n"],"mappings":"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","names":["React","React","import_seeds_react_box","import_seeds_react_button","import_seeds_react_icon","styled","Icon","import_seeds_react_icon","Box","Icon","Button","import_seeds_react_system_props","import_jsx_runtime","Box","Button","Icon","import_jsx_runtime","React"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sproutsocial/seeds-react-banner",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.22",
|
|
4
4
|
"description": "Seeds React Banner",
|
|
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": "^
|
|
22
|
-
"@sproutsocial/seeds-react-system-props": "^3.
|
|
23
|
-
"@sproutsocial/seeds-react-box": "^1.1.
|
|
24
|
-
"@sproutsocial/seeds-react-button": "^2.
|
|
25
|
-
"@sproutsocial/seeds-react-icon": "^2.
|
|
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-icon": "^2.4.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/react": "^18.0.0",
|
|
@@ -35,8 +35,8 @@
|
|
|
35
35
|
"@sproutsocial/seeds-tsconfig": "*",
|
|
36
36
|
"@sproutsocial/seeds-testing": "*",
|
|
37
37
|
"@sproutsocial/seeds-react-testing-library": "*",
|
|
38
|
-
"@sproutsocial/seeds-react-text": "^1.4.
|
|
39
|
-
"@sproutsocial/seeds-react-link": "^1.1.
|
|
38
|
+
"@sproutsocial/seeds-react-text": "^1.4.3",
|
|
39
|
+
"@sproutsocial/seeds-react-link": "^1.1.12"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"styled-components": "^5.2.3"
|
package/src/Banner.stories.tsx
CHANGED
|
@@ -157,3 +157,27 @@ export const HiddenIcon: Story = {
|
|
|
157
157
|
),
|
|
158
158
|
name: "With aria-hidden Icon",
|
|
159
159
|
};
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Demonstrates that Tailwind utility classes passed via `className` override the
|
|
163
|
+
* component's own CSS. Because `banner.css` lives in `@layer components`, the
|
|
164
|
+
* utilities below win the cascade: `bg-[#FF6B00]` paints a loud orange
|
|
165
|
+
* background over the banner's own decorative fill, `text-[#FFFFFF]` flips the
|
|
166
|
+
* text to white for contrast, `p-300` replaces the default `--space-300`
|
|
167
|
+
* padding, `mx-200` adds horizontal margin, and `inline-flex` overrides the
|
|
168
|
+
* default `display: flex`. If the `@layer components` wrapper were missing, the
|
|
169
|
+
* unlayered component rules would beat these utilities and the orange background
|
|
170
|
+
* would never show.
|
|
171
|
+
*/
|
|
172
|
+
export const TailwindOverrides: Story = {
|
|
173
|
+
render: (args) => (
|
|
174
|
+
<Banner
|
|
175
|
+
text={findText(args.type)}
|
|
176
|
+
type={args.type}
|
|
177
|
+
variant={args.variant}
|
|
178
|
+
typeIconProps={{ "aria-label": args.type }}
|
|
179
|
+
className="bg-[#FF6B00] text-[#FFFFFF] mx-200 p-300 inline-flex"
|
|
180
|
+
/>
|
|
181
|
+
),
|
|
182
|
+
name: "🚀 Tailwind class overrides",
|
|
183
|
+
};
|
package/src/Banner.tsx
CHANGED
|
@@ -1,96 +1,12 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const getBannerIconName = (type: EnumBannerType) => {
|
|
13
|
-
switch (type) {
|
|
14
|
-
case "success":
|
|
15
|
-
return "circle-check-outline";
|
|
16
|
-
case "error":
|
|
17
|
-
return "triangle-exclamation-outline";
|
|
18
|
-
case "warning":
|
|
19
|
-
return "triangle-exclamation-outline";
|
|
20
|
-
case "opportunity":
|
|
21
|
-
return "gem-outline";
|
|
22
|
-
case "info":
|
|
23
|
-
default:
|
|
24
|
-
return "circle-i-outline";
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
const getBannerIconColor = (
|
|
29
|
-
type: EnumBannerType,
|
|
30
|
-
variant: EnumBannerVariant
|
|
31
|
-
) => {
|
|
32
|
-
const isGhostVariant = variant === "ghost";
|
|
33
|
-
switch (type) {
|
|
34
|
-
case "success":
|
|
35
|
-
return isGhostVariant
|
|
36
|
-
? "container.border.decorative.green"
|
|
37
|
-
: "icon.success";
|
|
38
|
-
case "error":
|
|
39
|
-
return isGhostVariant ? "container.border.decorative.red" : "icon.error";
|
|
40
|
-
case "warning":
|
|
41
|
-
return isGhostVariant
|
|
42
|
-
? "container.border.decorative.yellow"
|
|
43
|
-
: "icon.warning";
|
|
44
|
-
case "opportunity":
|
|
45
|
-
return isGhostVariant
|
|
46
|
-
? "container.border.decorative.purple"
|
|
47
|
-
: "icon.opportunity";
|
|
48
|
-
case "info":
|
|
49
|
-
default:
|
|
50
|
-
return isGhostVariant ? "container.border.decorative.blue" : "icon.info";
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/** TODO: change to 'info' type by default in future version */
|
|
55
|
-
const Banner = ({
|
|
56
|
-
type = "info",
|
|
57
|
-
variant = "default",
|
|
58
|
-
text,
|
|
59
|
-
onClose,
|
|
60
|
-
closeButtonLabel = "Close",
|
|
61
|
-
typeIconProps,
|
|
62
|
-
...rest
|
|
63
|
-
}: TypeBannerProps) => {
|
|
64
|
-
return (
|
|
65
|
-
<Container
|
|
66
|
-
type={type}
|
|
67
|
-
variant={variant}
|
|
68
|
-
data-qa-alert=""
|
|
69
|
-
data-qa-alert-type={type}
|
|
70
|
-
data-qa-alert-text={text}
|
|
71
|
-
{...rest}
|
|
72
|
-
>
|
|
73
|
-
<Box display="flex" alignItems="center" width={1}>
|
|
74
|
-
<StyledBannerIcon
|
|
75
|
-
name={getBannerIconName(type)}
|
|
76
|
-
color={getBannerIconColor(type, variant)}
|
|
77
|
-
className="Icon"
|
|
78
|
-
fixedWidth
|
|
79
|
-
mt={100}
|
|
80
|
-
mr={350}
|
|
81
|
-
{...typeIconProps}
|
|
82
|
-
/>
|
|
83
|
-
{text}
|
|
84
|
-
{onClose && (
|
|
85
|
-
<Box ml="auto" pl={400} alignSelf="flex-start">
|
|
86
|
-
<Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>
|
|
87
|
-
<Icon name="x-outline" aria-hidden />
|
|
88
|
-
</Button>
|
|
89
|
-
</Box>
|
|
90
|
-
)}
|
|
91
|
-
</Box>
|
|
92
|
-
</Container>
|
|
93
|
-
);
|
|
94
|
-
};
|
|
2
|
+
import BannerHybrid from "./BannerHybrid";
|
|
3
|
+
import type { TypeBannerProps } from "./BannerTypes";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Banner component. Automatically routes between the Tailwind implementation
|
|
7
|
+
* (preferred) and the styled-components implementation (for consumers using
|
|
8
|
+
* system props or a styled() extension).
|
|
9
|
+
*/
|
|
10
|
+
const Banner = (props: TypeBannerProps) => <BannerHybrid {...props} />;
|
|
95
11
|
|
|
96
12
|
export default Banner;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hybrid Banner Component
|
|
3
|
+
* Automatically chooses between Tailwind and styled-components based on props.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
8
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
9
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
10
|
+
import Container, { StyledBannerIcon } from "./styles"; // Styled-components version
|
|
11
|
+
import BannerTailwind from "./BannerTailwind"; // Tailwind version
|
|
12
|
+
import { getBannerIconName, getBannerIconColor } from "./bannerIcon";
|
|
13
|
+
import { hasStyledProps } from "@sproutsocial/seeds-react-system-props";
|
|
14
|
+
import type { TypeBannerProps } from "./BannerTypes";
|
|
15
|
+
|
|
16
|
+
/** TODO: change to 'info' type by default in future version */
|
|
17
|
+
const BannerHybrid = ({
|
|
18
|
+
type = "info",
|
|
19
|
+
variant = "default",
|
|
20
|
+
text,
|
|
21
|
+
onClose,
|
|
22
|
+
closeButtonLabel = "Close",
|
|
23
|
+
typeIconProps,
|
|
24
|
+
...rest
|
|
25
|
+
}: TypeBannerProps) => {
|
|
26
|
+
if (hasStyledProps(rest)) {
|
|
27
|
+
return (
|
|
28
|
+
<Container
|
|
29
|
+
type={type}
|
|
30
|
+
variant={variant}
|
|
31
|
+
data-qa-alert=""
|
|
32
|
+
data-qa-alert-type={type}
|
|
33
|
+
data-qa-alert-text={text}
|
|
34
|
+
{...rest}
|
|
35
|
+
>
|
|
36
|
+
<Box display="flex" alignItems="center" width={1}>
|
|
37
|
+
<StyledBannerIcon
|
|
38
|
+
name={getBannerIconName(type)}
|
|
39
|
+
color={getBannerIconColor(type, variant)}
|
|
40
|
+
className="Icon"
|
|
41
|
+
fixedWidth
|
|
42
|
+
mt={100}
|
|
43
|
+
mr={350}
|
|
44
|
+
{...typeIconProps}
|
|
45
|
+
/>
|
|
46
|
+
{text}
|
|
47
|
+
{onClose && (
|
|
48
|
+
<Box ml="auto" pl={400} alignSelf="flex-start">
|
|
49
|
+
<Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>
|
|
50
|
+
<Icon name="x-outline" aria-hidden />
|
|
51
|
+
</Button>
|
|
52
|
+
</Box>
|
|
53
|
+
)}
|
|
54
|
+
</Box>
|
|
55
|
+
</Container>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Use Tailwind version (preferred - better performance)
|
|
60
|
+
return (
|
|
61
|
+
<BannerTailwind
|
|
62
|
+
type={type}
|
|
63
|
+
variant={variant}
|
|
64
|
+
text={text}
|
|
65
|
+
onClose={onClose}
|
|
66
|
+
closeButtonLabel={closeButtonLabel}
|
|
67
|
+
typeIconProps={typeIconProps}
|
|
68
|
+
{...rest}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default BannerHybrid;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailwind CSS implementation of Banner component
|
|
3
|
+
* Uses Seeds banner CSS classes from banner.css
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as React from "react";
|
|
7
|
+
import Box from "@sproutsocial/seeds-react-box";
|
|
8
|
+
import Button from "@sproutsocial/seeds-react-button";
|
|
9
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
10
|
+
import { getBannerIconName, getBannerIconColor } from "./bannerIcon";
|
|
11
|
+
import type { TypeBannerProps } from "./BannerTypes";
|
|
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
|
+
/** TODO: change to 'info' type by default in future version */
|
|
37
|
+
const BannerTailwind = ({
|
|
38
|
+
type = "info",
|
|
39
|
+
variant = "default",
|
|
40
|
+
text,
|
|
41
|
+
onClose,
|
|
42
|
+
closeButtonLabel = "Close",
|
|
43
|
+
typeIconProps,
|
|
44
|
+
className,
|
|
45
|
+
...rest
|
|
46
|
+
}: TypeBannerProps) => {
|
|
47
|
+
const variantClass =
|
|
48
|
+
variant === "ghost" ? "seeds-banner-ghost" : `seeds-banner-${type}`;
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<div
|
|
52
|
+
className={cn("seeds-banner", variantClass, className)}
|
|
53
|
+
data-qa-alert=""
|
|
54
|
+
data-qa-alert-type={type}
|
|
55
|
+
data-qa-alert-text={text}
|
|
56
|
+
{...(rest as React.HTMLAttributes<HTMLDivElement>)}
|
|
57
|
+
>
|
|
58
|
+
<Box display="flex" alignItems="center" width={1}>
|
|
59
|
+
<Icon
|
|
60
|
+
name={getBannerIconName(type)}
|
|
61
|
+
color={getBannerIconColor(type, variant)}
|
|
62
|
+
className="Icon seeds-banner-icon"
|
|
63
|
+
fixedWidth
|
|
64
|
+
mt={100}
|
|
65
|
+
mr={350}
|
|
66
|
+
{...typeIconProps}
|
|
67
|
+
/>
|
|
68
|
+
{text}
|
|
69
|
+
{onClose && (
|
|
70
|
+
<Box ml="auto" pl={400} alignSelf="flex-start">
|
|
71
|
+
<Button p={0} onClick={onClose} ariaLabel={closeButtonLabel}>
|
|
72
|
+
<Icon name="x-outline" aria-hidden />
|
|
73
|
+
</Button>
|
|
74
|
+
</Box>
|
|
75
|
+
)}
|
|
76
|
+
</Box>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default BannerTailwind;
|
|
@@ -99,26 +99,17 @@ describe("Banner", () => {
|
|
|
99
99
|
});
|
|
100
100
|
|
|
101
101
|
describe("variant ghost", () => {
|
|
102
|
-
|
|
102
|
+
// The Tailwind path renders the banner as a plain element with the
|
|
103
|
+
// `seeds-banner-ghost` class. That class maps to the same base
|
|
104
|
+
// background/border tokens (var(--color-container-bg-base) /
|
|
105
|
+
// var(--color-container-border-base)) in banner.css, so we assert the
|
|
106
|
+
// class is applied rather than the styled-components computed rule.
|
|
107
|
+
it("should apply the ghost variant class", () => {
|
|
103
108
|
render(<Banner text="Warning: Banner Text" variant="ghost" />);
|
|
104
109
|
|
|
105
110
|
expect(
|
|
106
111
|
screen.getByDataQaLabel({ "alert-text": "Warning: Banner Text" })
|
|
107
|
-
).
|
|
108
|
-
"background-color",
|
|
109
|
-
theme.colors.container.background.base
|
|
110
|
-
);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it("should set the correct border color", () => {
|
|
114
|
-
render(<Banner text="Warning: Banner Text" variant="ghost" />);
|
|
115
|
-
|
|
116
|
-
expect(
|
|
117
|
-
screen.getByDataQaLabel({ "alert-text": "Warning: Banner Text" })
|
|
118
|
-
).toHaveStyleRule(
|
|
119
|
-
"border",
|
|
120
|
-
`1px solid ${theme.colors.container.border.base}`
|
|
121
|
-
);
|
|
112
|
+
).toHaveClass("seeds-banner-ghost");
|
|
122
113
|
});
|
|
123
114
|
|
|
124
115
|
it("should set the correct icon color", () => {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { render, screen } from "@sproutsocial/seeds-react-testing-library";
|
|
2
|
+
import Banner from "../Banner";
|
|
3
|
+
|
|
4
|
+
describe("Banner Tailwind path", () => {
|
|
5
|
+
it("renders with the seeds-banner and type class when no styled props are used", () => {
|
|
6
|
+
render(<Banner text="Tailwind Banner" />);
|
|
7
|
+
const el = screen.getByDataQaLabel({ "alert-text": "Tailwind Banner" });
|
|
8
|
+
expect(el).toHaveClass("seeds-banner");
|
|
9
|
+
expect(el).toHaveClass("seeds-banner-info");
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("applies the per-type class", () => {
|
|
13
|
+
render(<Banner text="Error Banner" type="error" />);
|
|
14
|
+
expect(
|
|
15
|
+
screen.getByDataQaLabel({ "alert-text": "Error Banner" })
|
|
16
|
+
).toHaveClass("seeds-banner-error");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("forwards a consumer className (styled() extension passthrough)", () => {
|
|
20
|
+
render(<Banner text="Class Banner" className="sc-extension" />);
|
|
21
|
+
const el = screen.getByDataQaLabel({ "alert-text": "Class Banner" });
|
|
22
|
+
expect(el).toHaveClass("seeds-banner");
|
|
23
|
+
expect(el).toHaveClass("sc-extension");
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it("routes system props (mt) to the styled-components path", () => {
|
|
27
|
+
render(<Banner text="Spaced Banner" mt={300} />);
|
|
28
|
+
expect(
|
|
29
|
+
screen.getByDataQaLabel({ "alert-text": "Spaced Banner" })
|
|
30
|
+
).not.toHaveClass("seeds-banner");
|
|
31
|
+
});
|
|
32
|
+
});
|
package/src/banner.css
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds Banner component classes
|
|
3
|
+
* Use these instead of writing out individual Tailwind utility classes.
|
|
4
|
+
*
|
|
5
|
+
* Requires @sproutsocial/seeds-react-theme/dist/theme-all.css imported for
|
|
6
|
+
* CSS variable definitions and dark mode support.
|
|
7
|
+
*
|
|
8
|
+
* Rules live in the Tailwind `components` layer so consumer utility classes
|
|
9
|
+
* (e.g. mx-200, p-300, inline-flex) win the cascade over these defaults.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
@layer components {
|
|
13
|
+
.seeds-banner {
|
|
14
|
+
display: flex;
|
|
15
|
+
overflow: hidden;
|
|
16
|
+
align-items: center;
|
|
17
|
+
justify-content: space-between;
|
|
18
|
+
color: var(--color-text-body);
|
|
19
|
+
border-radius: var(--radius-outer);
|
|
20
|
+
font-family: var(--font-family);
|
|
21
|
+
font-size: var(--font-size-200);
|
|
22
|
+
line-height: var(--line-height-200);
|
|
23
|
+
padding: var(--space-300);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.seeds-banner a,
|
|
27
|
+
.seeds-banner button {
|
|
28
|
+
font-weight: var(--font-weight-semibold);
|
|
29
|
+
color: var(--color-text-body);
|
|
30
|
+
font-size: inherit;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.seeds-banner a:hover,
|
|
34
|
+
.seeds-banner button:hover {
|
|
35
|
+
color: var(--color-text-body);
|
|
36
|
+
text-decoration: underline;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.seeds-banner > span:not(.Icon) {
|
|
40
|
+
display: block;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.seeds-banner-icon {
|
|
44
|
+
align-self: flex-start;
|
|
45
|
+
min-width: 16px;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.seeds-banner-ghost {
|
|
49
|
+
border: 1px solid var(--color-container-border-base);
|
|
50
|
+
background-color: var(--color-container-bg-base);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.seeds-banner-success {
|
|
54
|
+
border: 1px solid var(--color-container-border-success);
|
|
55
|
+
background-color: var(--color-container-bg-success);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.seeds-banner-info {
|
|
59
|
+
border: 1px solid var(--color-container-border-info);
|
|
60
|
+
background-color: var(--color-container-bg-info);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.seeds-banner-error {
|
|
64
|
+
border: 1px solid var(--color-container-border-error);
|
|
65
|
+
background-color: var(--color-container-bg-error);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.seeds-banner-warning {
|
|
69
|
+
border: 1px solid var(--color-container-border-warning);
|
|
70
|
+
background-color: var(--color-container-bg-warning);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.seeds-banner-opportunity {
|
|
74
|
+
border: 1px solid var(--color-container-border-opportunity);
|
|
75
|
+
background-color: var(--color-container-bg-opportunity);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { EnumBannerType, EnumBannerVariant } from "./BannerTypes";
|
|
2
|
+
|
|
3
|
+
export const getBannerIconName = (type: EnumBannerType) => {
|
|
4
|
+
switch (type) {
|
|
5
|
+
case "success":
|
|
6
|
+
return "circle-check-outline";
|
|
7
|
+
case "error":
|
|
8
|
+
return "triangle-exclamation-outline";
|
|
9
|
+
case "warning":
|
|
10
|
+
return "triangle-exclamation-outline";
|
|
11
|
+
case "opportunity":
|
|
12
|
+
return "gem-outline";
|
|
13
|
+
case "info":
|
|
14
|
+
default:
|
|
15
|
+
return "circle-i-outline";
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const getBannerIconColor = (
|
|
20
|
+
type: EnumBannerType,
|
|
21
|
+
variant: EnumBannerVariant
|
|
22
|
+
) => {
|
|
23
|
+
const isGhostVariant = variant === "ghost";
|
|
24
|
+
switch (type) {
|
|
25
|
+
case "success":
|
|
26
|
+
return isGhostVariant
|
|
27
|
+
? "container.border.decorative.green"
|
|
28
|
+
: "icon.success";
|
|
29
|
+
case "error":
|
|
30
|
+
return isGhostVariant ? "container.border.decorative.red" : "icon.error";
|
|
31
|
+
case "warning":
|
|
32
|
+
return isGhostVariant
|
|
33
|
+
? "container.border.decorative.yellow"
|
|
34
|
+
: "icon.warning";
|
|
35
|
+
case "opportunity":
|
|
36
|
+
return isGhostVariant
|
|
37
|
+
? "container.border.decorative.purple"
|
|
38
|
+
: "icon.opportunity";
|
|
39
|
+
case "info":
|
|
40
|
+
default:
|
|
41
|
+
return isGhostVariant ? "container.border.decorative.blue" : "icon.info";
|
|
42
|
+
}
|
|
43
|
+
};
|