@sproutsocial/seeds-react-content-block 0.5.3 → 0.5.14
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/dist/content-block.css +48 -0
- package/dist/esm/index.js +221 -32
- package/dist/esm/index.js.map +1 -1
- package/dist/index.d.mts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +218 -32
- package/dist/index.js.map +1 -1
- package/package.json +21 -9
- package/.eslintignore +0 -6
- package/.eslintrc.js +0 -4
- package/.turbo/turbo-build.log +0 -21
- package/CHANGELOG.md +0 -324
- package/jest.config.js +0 -9
- package/src/ContentBlock.stories.tsx +0 -189
- package/src/ContentBlock.tsx +0 -198
- package/src/__tests__/content-block.test.tsx +0 -280
- package/src/index.ts +0 -6
- package/src/styled.d.ts +0 -7
- package/src/styles.ts +0 -19
- package/tsconfig.json +0 -9
- package/tsup.config.ts +0 -12
|
@@ -1,280 +0,0 @@
|
|
|
1
|
-
import React, { useState } from "react";
|
|
2
|
-
import {
|
|
3
|
-
render,
|
|
4
|
-
screen,
|
|
5
|
-
fireEvent,
|
|
6
|
-
} from "@sproutsocial/seeds-react-testing-library";
|
|
7
|
-
import ContentBlock from "../ContentBlock";
|
|
8
|
-
|
|
9
|
-
describe("ContentBlock Features", () => {
|
|
10
|
-
test("renders title and subtitle with correct semantic elements", () => {
|
|
11
|
-
render(
|
|
12
|
-
<ContentBlock
|
|
13
|
-
title="Test Title"
|
|
14
|
-
subtitle="Test Subtitle"
|
|
15
|
-
titleAs="h1"
|
|
16
|
-
subtitleAs="h2"
|
|
17
|
-
>
|
|
18
|
-
Content
|
|
19
|
-
</ContentBlock>
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
const titleElement = screen.getByText("Test Title");
|
|
23
|
-
const subtitleElement = screen.getByText("Test Subtitle");
|
|
24
|
-
|
|
25
|
-
expect(titleElement.tagName).toBe("H1");
|
|
26
|
-
expect(subtitleElement.tagName).toBe("H2");
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test("renders without subtitle when not provided", () => {
|
|
30
|
-
render(
|
|
31
|
-
<ContentBlock title="Test Title" titleAs="h1">
|
|
32
|
-
Content
|
|
33
|
-
</ContentBlock>
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
expect(screen.getByText("Test Title")).toBeInTheDocument();
|
|
37
|
-
expect(screen.queryByText("Test Subtitle")).not.toBeInTheDocument();
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test("renders content when not loading", () => {
|
|
41
|
-
render(
|
|
42
|
-
<ContentBlock
|
|
43
|
-
title="Test Title"
|
|
44
|
-
subtitle="Test Subtitle"
|
|
45
|
-
titleAs="h2"
|
|
46
|
-
subtitleAs="h3"
|
|
47
|
-
isLoading={false}
|
|
48
|
-
>
|
|
49
|
-
<div>Loaded Content</div>
|
|
50
|
-
</ContentBlock>
|
|
51
|
-
);
|
|
52
|
-
expect(screen.getByText("Loaded Content")).toBeInTheDocument();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test("renders loader when loading", () => {
|
|
56
|
-
render(
|
|
57
|
-
<ContentBlock
|
|
58
|
-
title="Test Title"
|
|
59
|
-
subtitle="Test Subtitle"
|
|
60
|
-
titleAs="h2"
|
|
61
|
-
subtitleAs="h3"
|
|
62
|
-
isLoading={true}
|
|
63
|
-
>
|
|
64
|
-
<div>Loaded Content</div>
|
|
65
|
-
</ContentBlock>
|
|
66
|
-
);
|
|
67
|
-
|
|
68
|
-
expect(
|
|
69
|
-
screen.getByDataQaLabel({
|
|
70
|
-
loader: "",
|
|
71
|
-
})
|
|
72
|
-
).toBeInTheDocument();
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe("ContentBlock Footer", () => {
|
|
77
|
-
test("renders footerContent when provided", () => {
|
|
78
|
-
render(
|
|
79
|
-
<ContentBlock title="Title" footerContent={<span>Footer text</span>}>
|
|
80
|
-
Content
|
|
81
|
-
</ContentBlock>
|
|
82
|
-
);
|
|
83
|
-
expect(screen.getByText("Footer text")).toBeInTheDocument();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("renders footerActions when provided", () => {
|
|
87
|
-
render(
|
|
88
|
-
<ContentBlock
|
|
89
|
-
title="Title"
|
|
90
|
-
footerActions={<button>Footer action</button>}
|
|
91
|
-
>
|
|
92
|
-
Content
|
|
93
|
-
</ContentBlock>
|
|
94
|
-
);
|
|
95
|
-
expect(screen.getByText("Footer action")).toBeInTheDocument();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("renders both footerContent and footerActions together", () => {
|
|
99
|
-
render(
|
|
100
|
-
<ContentBlock
|
|
101
|
-
title="Title"
|
|
102
|
-
footerContent={<span>Footer text</span>}
|
|
103
|
-
footerActions={<button>Footer action</button>}
|
|
104
|
-
>
|
|
105
|
-
Content
|
|
106
|
-
</ContentBlock>
|
|
107
|
-
);
|
|
108
|
-
expect(screen.getByText("Footer text")).toBeInTheDocument();
|
|
109
|
-
expect(screen.getByText("Footer action")).toBeInTheDocument();
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test("does not render footer when neither prop is provided", () => {
|
|
113
|
-
render(<ContentBlock title="Title">Content</ContentBlock>);
|
|
114
|
-
expect(screen.queryByText("Footer text")).not.toBeInTheDocument();
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
test("collapsible footer is visible when open and hidden when collapsed", () => {
|
|
118
|
-
render(
|
|
119
|
-
<ContentBlock
|
|
120
|
-
title="Title"
|
|
121
|
-
isCollapsible
|
|
122
|
-
footerContent={<span>Footer text</span>}
|
|
123
|
-
>
|
|
124
|
-
Content
|
|
125
|
-
</ContentBlock>
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
expect(screen.getByText("Footer text")).toBeInTheDocument();
|
|
129
|
-
|
|
130
|
-
fireEvent.click(screen.getByRole("button"));
|
|
131
|
-
expect(screen.queryByText("Footer text")).not.toBeInTheDocument();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe("ContentBlock Collapsible", () => {
|
|
136
|
-
test("does not render chevron when not collapsible", () => {
|
|
137
|
-
render(
|
|
138
|
-
<ContentBlock title="Title" subtitle="Subtitle">
|
|
139
|
-
Content
|
|
140
|
-
</ContentBlock>
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
expect(screen.queryByRole("button")).not.toBeInTheDocument();
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test("renders chevron icon when collapsible", () => {
|
|
147
|
-
render(
|
|
148
|
-
<ContentBlock title="Title" subtitle="Subtitle" isCollapsible>
|
|
149
|
-
Content
|
|
150
|
-
</ContentBlock>
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const trigger = screen.getByRole("button");
|
|
154
|
-
expect(trigger).toBeInTheDocument();
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test("defaults to open when collapsible", () => {
|
|
158
|
-
render(
|
|
159
|
-
<ContentBlock title="Title" subtitle="Subtitle" isCollapsible>
|
|
160
|
-
Visible Content
|
|
161
|
-
</ContentBlock>
|
|
162
|
-
);
|
|
163
|
-
|
|
164
|
-
const trigger = screen.getByRole("button");
|
|
165
|
-
expect(trigger).toHaveAttribute("aria-expanded", "true");
|
|
166
|
-
expect(screen.getByText("Visible Content")).toBeInTheDocument();
|
|
167
|
-
});
|
|
168
|
-
|
|
169
|
-
test("can default to closed", () => {
|
|
170
|
-
render(
|
|
171
|
-
<ContentBlock
|
|
172
|
-
title="Title"
|
|
173
|
-
subtitle="Subtitle"
|
|
174
|
-
isCollapsible
|
|
175
|
-
defaultOpen={false}
|
|
176
|
-
>
|
|
177
|
-
Hidden Content
|
|
178
|
-
</ContentBlock>
|
|
179
|
-
);
|
|
180
|
-
|
|
181
|
-
const trigger = screen.getByRole("button");
|
|
182
|
-
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("toggles content on trigger click", () => {
|
|
186
|
-
render(
|
|
187
|
-
<ContentBlock title="Title" subtitle="Subtitle" isCollapsible>
|
|
188
|
-
Toggle Content
|
|
189
|
-
</ContentBlock>
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
const trigger = screen.getByRole("button");
|
|
193
|
-
expect(trigger).toHaveAttribute("aria-expanded", "true");
|
|
194
|
-
|
|
195
|
-
fireEvent.click(trigger);
|
|
196
|
-
expect(trigger).toHaveAttribute("aria-expanded", "false");
|
|
197
|
-
|
|
198
|
-
fireEvent.click(trigger);
|
|
199
|
-
expect(trigger).toHaveAttribute("aria-expanded", "true");
|
|
200
|
-
});
|
|
201
|
-
|
|
202
|
-
test("controlled mode respects isOpen prop", () => {
|
|
203
|
-
const ControlledContentBlock = () => {
|
|
204
|
-
const [open, setOpen] = useState(false);
|
|
205
|
-
return (
|
|
206
|
-
<>
|
|
207
|
-
<button onClick={() => setOpen(!open)}>External Toggle</button>
|
|
208
|
-
<ContentBlock
|
|
209
|
-
title="Title"
|
|
210
|
-
subtitle="Subtitle"
|
|
211
|
-
isCollapsible
|
|
212
|
-
isOpen={open}
|
|
213
|
-
onOpenChange={setOpen}
|
|
214
|
-
>
|
|
215
|
-
Controlled Content
|
|
216
|
-
</ContentBlock>
|
|
217
|
-
</>
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
render(<ControlledContentBlock />);
|
|
222
|
-
|
|
223
|
-
const trigger = screen.getByRole("button", { name: /External Toggle/i });
|
|
224
|
-
const collapsibleTrigger = screen
|
|
225
|
-
.getAllByRole("button")
|
|
226
|
-
.find((btn) => btn.getAttribute("aria-expanded") !== null);
|
|
227
|
-
|
|
228
|
-
expect(collapsibleTrigger).toHaveAttribute("aria-expanded", "false");
|
|
229
|
-
|
|
230
|
-
fireEvent.click(trigger);
|
|
231
|
-
expect(collapsibleTrigger).toHaveAttribute("aria-expanded", "true");
|
|
232
|
-
});
|
|
233
|
-
|
|
234
|
-
test("headerActions render alongside trigger and do not toggle collapse", () => {
|
|
235
|
-
const actionClick = jest.fn();
|
|
236
|
-
|
|
237
|
-
render(
|
|
238
|
-
<ContentBlock
|
|
239
|
-
title="Title"
|
|
240
|
-
subtitle="Subtitle"
|
|
241
|
-
isCollapsible
|
|
242
|
-
headerActions={<button onClick={actionClick}>Action</button>}
|
|
243
|
-
>
|
|
244
|
-
Content
|
|
245
|
-
</ContentBlock>
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
const actionButton = screen.getByText("Action");
|
|
249
|
-
expect(actionButton).toBeInTheDocument();
|
|
250
|
-
|
|
251
|
-
const collapsibleTrigger = screen
|
|
252
|
-
.getAllByRole("button")
|
|
253
|
-
.find((btn) => btn.getAttribute("aria-expanded") !== null);
|
|
254
|
-
expect(collapsibleTrigger).toHaveAttribute("aria-expanded", "true");
|
|
255
|
-
|
|
256
|
-
fireEvent.click(actionButton);
|
|
257
|
-
expect(actionClick).toHaveBeenCalledTimes(1);
|
|
258
|
-
// Collapse state should not change from clicking the action
|
|
259
|
-
expect(collapsibleTrigger).toHaveAttribute("aria-expanded", "true");
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
test("calls onOpenChange when toggled", () => {
|
|
263
|
-
const onOpenChange = jest.fn();
|
|
264
|
-
|
|
265
|
-
render(
|
|
266
|
-
<ContentBlock
|
|
267
|
-
title="Title"
|
|
268
|
-
subtitle="Subtitle"
|
|
269
|
-
isCollapsible
|
|
270
|
-
onOpenChange={onOpenChange}
|
|
271
|
-
>
|
|
272
|
-
Content
|
|
273
|
-
</ContentBlock>
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
const trigger = screen.getByRole("button");
|
|
277
|
-
fireEvent.click(trigger);
|
|
278
|
-
expect(onOpenChange).toHaveBeenCalledWith(false);
|
|
279
|
-
});
|
|
280
|
-
});
|
package/src/index.ts
DELETED
package/src/styled.d.ts
DELETED
package/src/styles.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import styled from "styled-components";
|
|
2
|
-
import { Box } from "@sproutsocial/seeds-react-box";
|
|
3
|
-
|
|
4
|
-
export const ContentBlockContent = styled(Box)`
|
|
5
|
-
padding: ${({ theme }) => theme.space[400]};
|
|
6
|
-
`;
|
|
7
|
-
|
|
8
|
-
export const FooterContainer = styled.div`
|
|
9
|
-
box-sizing: border-box;
|
|
10
|
-
display: flex;
|
|
11
|
-
justify-content: space-between;
|
|
12
|
-
align-items: center;
|
|
13
|
-
width: 100%;
|
|
14
|
-
padding: ${({ theme }) => theme.space[400]};
|
|
15
|
-
border-top: ${({ theme }) => theme.borderWidths[500]} solid
|
|
16
|
-
${({ theme }) => theme.colors.container.border.base};
|
|
17
|
-
border-bottom-left-radius: ${({ theme }) => theme.radii.outer};
|
|
18
|
-
border-bottom-right-radius: ${({ theme }) => theme.radii.outer};
|
|
19
|
-
`;
|
package/tsconfig.json
DELETED
package/tsup.config.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsup";
|
|
2
|
-
|
|
3
|
-
export default defineConfig((options) => ({
|
|
4
|
-
entry: ["src/index.ts"],
|
|
5
|
-
format: ["cjs", "esm"],
|
|
6
|
-
clean: true,
|
|
7
|
-
legacyOutput: true,
|
|
8
|
-
dts: options.dts,
|
|
9
|
-
external: ["react"],
|
|
10
|
-
sourcemap: true,
|
|
11
|
-
metafile: options.metafile,
|
|
12
|
-
}));
|