@sproutsocial/seeds-react-narrative-kit 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +11 -11
- package/CHANGELOG.md +12 -0
- package/dist/esm/index.js +101 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +64 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +103 -0
- package/dist/index.js.map +1 -1
- package/dist/narrative-attribution.css +56 -0
- package/dist/narrative-social-media-card.css +79 -0
- package/package.json +7 -3
- package/src/NarrativeAttribution/NarrativeAttribution.stories.tsx +78 -0
- package/src/NarrativeAttribution/NarrativeAttribution.tsx +54 -0
- package/src/NarrativeAttribution/NarrativeAttributionTypes.ts +13 -0
- package/src/NarrativeAttribution/index.ts +2 -0
- package/src/NarrativeSocialMediaCard/NarrativeSocialMediaCard.stories.tsx +111 -0
- package/src/NarrativeSocialMediaCard/NarrativeSocialMediaCard.tsx +80 -0
- package/src/NarrativeSocialMediaCard/NarrativeSocialMediaCardTypes.ts +30 -0
- package/src/NarrativeSocialMediaCard/__tests__/NarrativeSocialMediaCard.test.tsx +154 -0
- package/src/NarrativeSocialMediaCard/index.ts +5 -0
- package/src/Playground/Playground.stories.tsx +83 -0
- package/src/css.d.ts +1 -0
- package/src/index.ts +11 -0
- package/src/narrative-attribution.css +56 -0
- package/src/narrative-social-media-card.css +79 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "../_internal/cn";
|
|
3
|
+
import NarrativeAttribution from "../NarrativeAttribution/NarrativeAttribution";
|
|
4
|
+
import type { TypeNarrativeSocialMediaCardProps } from "./NarrativeSocialMediaCardTypes";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* NarrativeSocialMediaCard — a narrative primitive that displays a social media
|
|
8
|
+
* post card with a header (avatar + handle), content area, and footer with
|
|
9
|
+
* engagement metadata (replies, likes, reposts, etc.).
|
|
10
|
+
*
|
|
11
|
+
* Styled via narrative-social-media-card.css (Seeds CSS custom properties);
|
|
12
|
+
* consumers import the classes through @sproutsocial/racine/css/components.
|
|
13
|
+
* Layout is vertically stacked with clean typography and icon-based metadata in
|
|
14
|
+
* the footer. Default has a gray background; use appearance="no-background" to
|
|
15
|
+
* remove the background and blend seamlessly with the page.
|
|
16
|
+
*/
|
|
17
|
+
const NarrativeSocialMediaCard = React.forwardRef<
|
|
18
|
+
HTMLDivElement,
|
|
19
|
+
TypeNarrativeSocialMediaCardProps
|
|
20
|
+
>(
|
|
21
|
+
(
|
|
22
|
+
{
|
|
23
|
+
avatar,
|
|
24
|
+
avatarAlt,
|
|
25
|
+
displayName,
|
|
26
|
+
socialIcon,
|
|
27
|
+
image,
|
|
28
|
+
text,
|
|
29
|
+
meta,
|
|
30
|
+
appearance,
|
|
31
|
+
className,
|
|
32
|
+
...props
|
|
33
|
+
},
|
|
34
|
+
ref
|
|
35
|
+
) => {
|
|
36
|
+
return (
|
|
37
|
+
<div
|
|
38
|
+
ref={ref}
|
|
39
|
+
className={cn(
|
|
40
|
+
"seeds-narrative-social-media-card",
|
|
41
|
+
appearance === "no-background" &&
|
|
42
|
+
"seeds-narrative-social-media-card--no-background",
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
<NarrativeAttribution
|
|
48
|
+
avatarUrl={avatar}
|
|
49
|
+
avatarAlt={avatarAlt}
|
|
50
|
+
userName={displayName}
|
|
51
|
+
socialIcon={socialIcon}
|
|
52
|
+
/>
|
|
53
|
+
|
|
54
|
+
<div className="seeds-narrative-social-media-card-content">
|
|
55
|
+
{image}
|
|
56
|
+
{text}
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div className="seeds-narrative-social-media-card-footer">
|
|
60
|
+
{meta.map((item, index) => (
|
|
61
|
+
<div
|
|
62
|
+
key={index}
|
|
63
|
+
className="seeds-narrative-social-media-card-stat"
|
|
64
|
+
aria-label={item.label}
|
|
65
|
+
>
|
|
66
|
+
{item.icon}
|
|
67
|
+
<span className="seeds-narrative-social-media-card-stat-value">
|
|
68
|
+
{item.value}
|
|
69
|
+
</span>
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
NarrativeSocialMediaCard.displayName = "NarrativeSocialMediaCard";
|
|
79
|
+
|
|
80
|
+
export default NarrativeSocialMediaCard;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
|
|
3
|
+
export interface TypeNarrativeSocialMediaCardMeta {
|
|
4
|
+
/** Icon for the metadata (e.g., reply, heart, repost). */
|
|
5
|
+
icon: React.ReactNode;
|
|
6
|
+
/** Number or formatted string value for the metadata. */
|
|
7
|
+
value: number | string;
|
|
8
|
+
/** Optional accessible label for the metadata. */
|
|
9
|
+
label?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface TypeNarrativeSocialMediaCardProps
|
|
13
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, "children"> {
|
|
14
|
+
/** Avatar image URL for the social media profile. */
|
|
15
|
+
avatar: string;
|
|
16
|
+
/** Alt text for the avatar image. */
|
|
17
|
+
avatarAlt: string;
|
|
18
|
+
/** Display name for the social media profile. */
|
|
19
|
+
displayName: string;
|
|
20
|
+
/** Social media network icon (e.g., Twitter, Instagram, LinkedIn). */
|
|
21
|
+
socialIcon: React.ReactNode;
|
|
22
|
+
/** Optional image to display above the text content. */
|
|
23
|
+
image?: React.ReactNode;
|
|
24
|
+
/** The text content of the social media post. */
|
|
25
|
+
text: React.ReactNode;
|
|
26
|
+
/** Array of metadata with icons and values (e.g., replies, likes, reposts). */
|
|
27
|
+
meta: TypeNarrativeSocialMediaCardMeta[];
|
|
28
|
+
/** Visual appearance of the card. Default has gray background, "no-background" removes the background. */
|
|
29
|
+
appearance?: "no-background";
|
|
30
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@sproutsocial/seeds-react-testing-library";
|
|
3
|
+
import NarrativeSocialMediaCard from "../NarrativeSocialMediaCard";
|
|
4
|
+
import { PartnerLogo } from "@sproutsocial/seeds-react-partner-logo";
|
|
5
|
+
|
|
6
|
+
// Test meta icons
|
|
7
|
+
const TestIcon1 = () => (
|
|
8
|
+
<svg viewBox="0 0 16 16" aria-hidden focusable={false}>
|
|
9
|
+
<path d="M2 8H14" stroke="currentColor" strokeWidth="1.5" />
|
|
10
|
+
</svg>
|
|
11
|
+
);
|
|
12
|
+
|
|
13
|
+
const TestIcon2 = () => (
|
|
14
|
+
<svg viewBox="0 0 16 16" aria-hidden focusable={false}>
|
|
15
|
+
<circle cx="8" cy="8" r="6" stroke="currentColor" strokeWidth="1.5" />
|
|
16
|
+
</svg>
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const TestIcon3 = () => (
|
|
20
|
+
<svg viewBox="0 0 16 16" aria-hidden focusable={false}>
|
|
21
|
+
<rect
|
|
22
|
+
x="4"
|
|
23
|
+
y="4"
|
|
24
|
+
width="8"
|
|
25
|
+
height="8"
|
|
26
|
+
stroke="currentColor"
|
|
27
|
+
strokeWidth="1.5"
|
|
28
|
+
/>
|
|
29
|
+
</svg>
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
describe("NarrativeSocialMediaCard", () => {
|
|
33
|
+
const defaultProps = {
|
|
34
|
+
avatar: "https://example.com/avatar.jpg",
|
|
35
|
+
avatarAlt: "Profile avatar",
|
|
36
|
+
displayName: "Display Name",
|
|
37
|
+
socialIcon: <PartnerLogo partnerName="twitter" size="small" />,
|
|
38
|
+
text: "Test content",
|
|
39
|
+
meta: [
|
|
40
|
+
{ icon: <TestIcon1 />, value: 42, label: "Action 1" },
|
|
41
|
+
{ icon: <TestIcon2 />, value: 128, label: "Action 2" },
|
|
42
|
+
{ icon: <TestIcon3 />, value: 17, label: "Action 3" },
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
it("renders the avatar image", () => {
|
|
47
|
+
render(<NarrativeSocialMediaCard {...defaultProps} />);
|
|
48
|
+
|
|
49
|
+
const avatar = screen.getByRole("img");
|
|
50
|
+
expect(avatar).toBeInTheDocument();
|
|
51
|
+
expect(avatar).toHaveAttribute("src", "https://example.com/avatar.jpg");
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("renders the display name", () => {
|
|
55
|
+
render(<NarrativeSocialMediaCard {...defaultProps} />);
|
|
56
|
+
|
|
57
|
+
expect(screen.getByText("Display Name")).toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("renders the text content", () => {
|
|
61
|
+
render(
|
|
62
|
+
<NarrativeSocialMediaCard
|
|
63
|
+
{...defaultProps}
|
|
64
|
+
text="This is a test post with some content"
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
expect(
|
|
69
|
+
screen.getByText("This is a test post with some content")
|
|
70
|
+
).toBeInTheDocument();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it("renders the meta values in the footer", () => {
|
|
74
|
+
render(<NarrativeSocialMediaCard {...defaultProps} />);
|
|
75
|
+
|
|
76
|
+
expect(screen.getByText("42")).toBeInTheDocument();
|
|
77
|
+
expect(screen.getByText("128")).toBeInTheDocument();
|
|
78
|
+
expect(screen.getByText("17")).toBeInTheDocument();
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("accepts string values for meta values", () => {
|
|
82
|
+
render(
|
|
83
|
+
<NarrativeSocialMediaCard
|
|
84
|
+
avatar="https://example.com/avatar.jpg"
|
|
85
|
+
avatarAlt="Profile avatar"
|
|
86
|
+
displayName="Display Name"
|
|
87
|
+
socialIcon={<PartnerLogo partnerName="twitter" size="small" />}
|
|
88
|
+
text="Test content"
|
|
89
|
+
meta={[
|
|
90
|
+
{ icon: <TestIcon1 />, value: "1.2K", label: "Action 1" },
|
|
91
|
+
{ icon: <TestIcon2 />, value: "5.3K", label: "Action 2" },
|
|
92
|
+
{ icon: <TestIcon3 />, value: "842", label: "Action 3" },
|
|
93
|
+
]}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
expect(screen.getByText("1.2K")).toBeInTheDocument();
|
|
98
|
+
expect(screen.getByText("5.3K")).toBeInTheDocument();
|
|
99
|
+
expect(screen.getByText("842")).toBeInTheDocument();
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("renders the avatarAlt attribute", () => {
|
|
103
|
+
render(
|
|
104
|
+
<NarrativeSocialMediaCard
|
|
105
|
+
{...defaultProps}
|
|
106
|
+
avatarAlt="Custom avatar description"
|
|
107
|
+
/>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const avatar = screen.getByRole("img");
|
|
111
|
+
expect(avatar).toHaveAttribute("alt", "Custom avatar description");
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it("merges a consumer className with the base class", () => {
|
|
115
|
+
const { container } = render(
|
|
116
|
+
<NarrativeSocialMediaCard {...defaultProps} className="custom" />
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
const root = container.querySelector(".seeds-narrative-social-media-card");
|
|
120
|
+
expect(root).toBeInTheDocument();
|
|
121
|
+
expect(root).toHaveClass("custom");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("forwards extra props to the underlying element", () => {
|
|
125
|
+
render(
|
|
126
|
+
<NarrativeSocialMediaCard {...defaultProps} data-testid="social-card" />
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
expect(screen.getByTestId("social-card")).toBeInTheDocument();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("forwards its ref to the underlying div element", () => {
|
|
133
|
+
const ref = React.createRef<HTMLDivElement>();
|
|
134
|
+
render(<NarrativeSocialMediaCard {...defaultProps} ref={ref} />);
|
|
135
|
+
|
|
136
|
+
expect(ref.current).toBeInstanceOf(HTMLDivElement);
|
|
137
|
+
expect(ref.current?.tagName).toBe("DIV");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("renders image above text when image is provided", () => {
|
|
141
|
+
const { container } = render(
|
|
142
|
+
<NarrativeSocialMediaCard
|
|
143
|
+
{...defaultProps}
|
|
144
|
+
image={<img src="test.jpg" alt="test" />}
|
|
145
|
+
text="Text content"
|
|
146
|
+
/>
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
const content = container.querySelector(
|
|
150
|
+
".seeds-narrative-social-media-card-content"
|
|
151
|
+
);
|
|
152
|
+
expect(content?.firstChild).toHaveProperty("tagName", "IMG");
|
|
153
|
+
});
|
|
154
|
+
});
|
|
@@ -12,10 +12,13 @@ import NarrativeDivider from "../NarrativeDivider/NarrativeDivider";
|
|
|
12
12
|
import NarrativeSummary from "../NarrativeSummary/NarrativeSummary";
|
|
13
13
|
import NarrativeOrderedList from "../NarrativeOrderedList/NarrativeOrderedList";
|
|
14
14
|
import NarrativeDataCallout from "../NarrativeDataCallout/NarrativeDataCallout";
|
|
15
|
+
import NarrativeSocialMediaCard from "../NarrativeSocialMediaCard/NarrativeSocialMediaCard";
|
|
15
16
|
import Button from "@sproutsocial/seeds-react-button";
|
|
16
17
|
import Text from "@sproutsocial/seeds-react-text";
|
|
17
18
|
import { SparklineChart } from "@sproutsocial/seeds-react-data-viz/sparkline";
|
|
18
19
|
import { DonutChart } from "@sproutsocial/seeds-react-data-viz/donut";
|
|
20
|
+
import { PartnerLogo } from "@sproutsocial/seeds-react-partner-logo";
|
|
21
|
+
import Icon from "@sproutsocial/seeds-react-icon";
|
|
19
22
|
import "../narrative-container.css";
|
|
20
23
|
import "../narrative-headline.css";
|
|
21
24
|
import "../pull-quote.css";
|
|
@@ -25,6 +28,7 @@ import "../narrative-divider.css";
|
|
|
25
28
|
import "../narrative-summary.css";
|
|
26
29
|
import "../narrative-ordered-list.css";
|
|
27
30
|
import "../narrative-data-callout.css";
|
|
31
|
+
import "../narrative-social-media-card.css";
|
|
28
32
|
import "@sproutsocial/seeds-react-button/dist/button.css";
|
|
29
33
|
import "@sproutsocial/seeds-react-data-viz/sparkline.css";
|
|
30
34
|
|
|
@@ -204,8 +208,87 @@ const Brief = () => (
|
|
|
204
208
|
move the needle and sunsetting the low-leverage noise to land this
|
|
205
209
|
initiative ahead of the curve.
|
|
206
210
|
</NarrativeDataCallout>
|
|
211
|
+
|
|
212
|
+
<NarrativeDivider />
|
|
213
|
+
|
|
214
|
+
{/* Social media cards — a row of 3 sample posts -------------------- */}
|
|
215
|
+
<Grid columns={{ sm: 1, md: 2, lg: 3 }} gap={400}>
|
|
216
|
+
<NarrativeSocialMediaCard
|
|
217
|
+
avatar="https://api.dicebear.com/7.x/avataaars/svg?seed=Felix"
|
|
218
|
+
avatarAlt="Sprout Social avatar"
|
|
219
|
+
displayName="Sprout Social"
|
|
220
|
+
socialIcon={<PartnerLogo partnerName="twitter" size="small" />}
|
|
221
|
+
text="Just launched our new product! Check it out and let us know what you think."
|
|
222
|
+
meta={[
|
|
223
|
+
{
|
|
224
|
+
icon: <Icon name="reply-outline" />,
|
|
225
|
+
value: 12,
|
|
226
|
+
label: "Replies",
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
icon: <Icon name="heart-outline" />,
|
|
230
|
+
value: 128,
|
|
231
|
+
label: "Likes",
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
icon: <Icon name="repost-outline" />,
|
|
235
|
+
value: 42,
|
|
236
|
+
label: "Reposts",
|
|
237
|
+
},
|
|
238
|
+
]}
|
|
239
|
+
/>
|
|
240
|
+
<NarrativeSocialMediaCard
|
|
241
|
+
avatar="https://api.dicebear.com/7.x/avataaars/svg?seed=Jordan"
|
|
242
|
+
avatarAlt="Marketing Team avatar"
|
|
243
|
+
displayName="Marketing Team"
|
|
244
|
+
socialIcon={<PartnerLogo partnerName="linkedin" size="small" />}
|
|
245
|
+
text="Our most viral post ever! Thanks for all the engagement. The community response has been incredible and we're excited to keep the momentum going."
|
|
246
|
+
meta={[
|
|
247
|
+
{
|
|
248
|
+
icon: <Icon name="reply-outline" />,
|
|
249
|
+
value: 45,
|
|
250
|
+
label: "Comments",
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
icon: <Icon name="heart-outline" />,
|
|
254
|
+
value: 892,
|
|
255
|
+
label: "Likes",
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
icon: <Icon name="repost-outline" />,
|
|
259
|
+
value: 156,
|
|
260
|
+
label: "Shares",
|
|
261
|
+
},
|
|
262
|
+
]}
|
|
263
|
+
/>
|
|
264
|
+
<NarrativeSocialMediaCard
|
|
265
|
+
avatar="https://api.dicebear.com/7.x/avataaars/svg?seed=Alex"
|
|
266
|
+
avatarAlt="Brand Studio avatar"
|
|
267
|
+
displayName="Brand Studio"
|
|
268
|
+
socialIcon={<PartnerLogo partnerName="instagram" size="small" />}
|
|
269
|
+
text="Behind the scenes of today's campaign launch. Swipe to see the creative process!"
|
|
270
|
+
meta={[
|
|
271
|
+
{
|
|
272
|
+
icon: <Icon name="reply-outline" />,
|
|
273
|
+
value: 89,
|
|
274
|
+
label: "Comments",
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
icon: <Icon name="heart-outline" />,
|
|
278
|
+
value: 1240,
|
|
279
|
+
label: "Likes",
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
icon: <Icon name="repost-outline" />,
|
|
283
|
+
value: 203,
|
|
284
|
+
label: "Shares",
|
|
285
|
+
},
|
|
286
|
+
]}
|
|
287
|
+
/>
|
|
288
|
+
</Grid>
|
|
207
289
|
</Grid>
|
|
208
290
|
</NarrativeContainer>
|
|
291
|
+
|
|
209
292
|
<NarrativeContainer>
|
|
210
293
|
<NarrativeOrderedList
|
|
211
294
|
orientation="horizontal"
|
package/src/css.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "*.css";
|
package/src/index.ts
CHANGED
|
@@ -50,4 +50,15 @@ export {
|
|
|
50
50
|
|
|
51
51
|
export { AIContainer, type TypeAIContainerProps } from "./AIContainer";
|
|
52
52
|
|
|
53
|
+
export {
|
|
54
|
+
NarrativeSocialMediaCard,
|
|
55
|
+
type TypeNarrativeSocialMediaCardProps,
|
|
56
|
+
type TypeNarrativeSocialMediaCardMeta,
|
|
57
|
+
} from "./NarrativeSocialMediaCard";
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
NarrativeAttribution,
|
|
61
|
+
type TypeNarrativeAttributionProps,
|
|
62
|
+
} from "./NarrativeAttribution";
|
|
63
|
+
|
|
53
64
|
export type { TypeNarrativeTone } from "./_internal/types";
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds NarrativeAttribution 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
|
+
* Usage:
|
|
9
|
+
* <div class="seeds-narrative-attribution">
|
|
10
|
+
* <img class="seeds-narrative-attribution-avatar" />
|
|
11
|
+
* <div class="seeds-narrative-attribution-social-icon">...</div>
|
|
12
|
+
* <span class="seeds-narrative-attribution-user-name">...</span>
|
|
13
|
+
* </div>
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
@layer components {
|
|
17
|
+
|
|
18
|
+
/* Main container — horizontal layout with avatar, social icon, and user name. */
|
|
19
|
+
.seeds-narrative-attribution {
|
|
20
|
+
box-sizing: border-box;
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
gap: var(--space-300); /* 8px */;
|
|
24
|
+
font-family: var(--font-family);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Circular avatar image — fixed size with rounded corners. */
|
|
28
|
+
.seeds-narrative-attribution-avatar {
|
|
29
|
+
width: var(--space-450); /* 24px */
|
|
30
|
+
height: var(--space-450); /* 24px */
|
|
31
|
+
border-radius: var(--radius-circular); /* 50% */
|
|
32
|
+
object-fit: cover;
|
|
33
|
+
flex-shrink: 0;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* Social network icon container — flexible sizing for partner logos. */
|
|
37
|
+
.seeds-narrative-attribution-social-icon {
|
|
38
|
+
flex-shrink: 0;
|
|
39
|
+
display: flex;
|
|
40
|
+
align-items: center;
|
|
41
|
+
justify-content: center;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* User name text — bold headline text with ellipsis overflow. */
|
|
45
|
+
.seeds-narrative-attribution-user-name {
|
|
46
|
+
overflow: hidden;
|
|
47
|
+
color: var(--color-text-headline);
|
|
48
|
+
text-overflow: ellipsis;
|
|
49
|
+
font-family: var(--font-family);
|
|
50
|
+
font-size: var(--text-base-font-size, 14px);
|
|
51
|
+
font-style: normal;
|
|
52
|
+
font-weight: var(--font-weight-bold, 700);
|
|
53
|
+
line-height: var(--text-base-line-height, 24px);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Seeds NarrativeSocialMediaCard 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
|
+
* Usage:
|
|
9
|
+
* <div class="seeds-narrative-social-media-card">
|
|
10
|
+
* <div class="seeds-narrative-social-media-card-header">...</div>
|
|
11
|
+
* <div class="seeds-narrative-social-media-card-content">...</div>
|
|
12
|
+
* <div class="seeds-narrative-social-media-card-footer">...</div>
|
|
13
|
+
* </div>
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
@layer components {
|
|
17
|
+
|
|
18
|
+
/* Main card container — gray background with rounded corners and padding.
|
|
19
|
+
Uses Seeds tokens for spacing, colors, and radius to match the design system. */
|
|
20
|
+
.seeds-narrative-social-media-card {
|
|
21
|
+
box-sizing: border-box;
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
align-items: flex-start;
|
|
25
|
+
max-width: 320px;
|
|
26
|
+
padding: var(--space-450); /* 24px */
|
|
27
|
+
border-radius: var(--radius-500); /* 6px */
|
|
28
|
+
background-color: var(--color-app-bg-base);
|
|
29
|
+
font-family: var(--font-family);
|
|
30
|
+
color: var(--color-text-body);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/* No background — transparent background for cards that blend seamlessly with the page. */
|
|
34
|
+
.seeds-narrative-social-media-card--no-background {
|
|
35
|
+
background-color: transparent;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Main content area — standard body text styling. */
|
|
39
|
+
.seeds-narrative-social-media-card-content {
|
|
40
|
+
flex: 1;
|
|
41
|
+
margin-top: var(--space-400); /* 16px */
|
|
42
|
+
font-family: var(--font-family);
|
|
43
|
+
font-size: 14px;
|
|
44
|
+
font-style: normal;
|
|
45
|
+
font-weight: 400;
|
|
46
|
+
line-height: 24px;
|
|
47
|
+
color: var(--color-text-body);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* Footer section — horizontal layout for stats with equal spacing. */
|
|
51
|
+
.seeds-narrative-social-media-card-footer {
|
|
52
|
+
display: flex;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--space-400); /* 16px */
|
|
55
|
+
margin-top: var(--space-400); /* 16px */;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/* Hide footer when empty (no metadata items). */
|
|
59
|
+
.seeds-narrative-social-media-card-footer:empty {
|
|
60
|
+
display: none;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Individual stat container — icon + value in horizontal layout. */
|
|
64
|
+
.seeds-narrative-social-media-card-stat {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: var(--space-200); /* 4px */
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* Stat value text — monospace font for numeric values. */
|
|
71
|
+
.seeds-narrative-social-media-card-stat-value {
|
|
72
|
+
font-family: var(--font-family-mono, ui-monospace, "SF Mono", SFMono-Regular, Menlo, monospace); font-size: 14px;
|
|
73
|
+
font-style: normal;
|
|
74
|
+
font-weight: 400;
|
|
75
|
+
line-height: 24px;
|
|
76
|
+
color: var(--color-text-body);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
}
|