@sproutsocial/seeds-react-card 1.0.0
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/.eslintignore +6 -0
- package/.eslintrc.js +4 -0
- package/.turbo/turbo-build.log +21 -0
- package/CHANGELOG.md +8 -0
- package/dist/esm/index.js +1357 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.d.mts +88 -0
- package/dist/index.d.ts +88 -0
- package/dist/index.js +1375 -0
- package/dist/index.js.map +1 -0
- package/jest.config.js +9 -0
- package/package.json +51 -0
- package/src/Card.feature +122 -0
- package/src/Card.stories.tsx +389 -0
- package/src/Card.tsx +73 -0
- package/src/CardTypes.ts +104 -0
- package/src/__tests__/Card.test.tsx +264 -0
- package/src/__tests__/CardTypes.typetest.tsx +76 -0
- package/src/index.ts +6 -0
- package/src/styles.tsx +171 -0
- package/src/subComponents.tsx +110 -0
- package/src/utils.ts +61 -0
- package/tsconfig.json +9 -0
- package/tsup.config.ts +12 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { Avatar } from "@sproutsocial/seeds-react-avatar";
|
|
3
|
+
import { Banner } from "@sproutsocial/seeds-react-banner";
|
|
4
|
+
import { Box } from "@sproutsocial/seeds-react-box";
|
|
5
|
+
import { Card } from "./";
|
|
6
|
+
import { Icon } from "@sproutsocial/seeds-react-icon";
|
|
7
|
+
import { Link } from "@sproutsocial/seeds-react-link";
|
|
8
|
+
import { PartnerLogo } from "@sproutsocial/seeds-react-partner-logo";
|
|
9
|
+
import type { EnumIllustrationNames } from "@sproutsocial/seeds-illustrations";
|
|
10
|
+
import { SpotIllustration } from "@sproutsocial/seeds-react-spot-illustration";
|
|
11
|
+
import { Text } from "@sproutsocial/seeds-react-text";
|
|
12
|
+
import styled from "styled-components";
|
|
13
|
+
import { CardHeader, CardContent, CardFooter, CardLink } from "./subComponents";
|
|
14
|
+
import type { Meta, StoryObj } from "@storybook/react";
|
|
15
|
+
|
|
16
|
+
const meta: Meta<typeof Card> = {
|
|
17
|
+
title: "Components/Card",
|
|
18
|
+
component: Card,
|
|
19
|
+
argTypes: {
|
|
20
|
+
elevation: {
|
|
21
|
+
options: ["low", "medium", "high", undefined],
|
|
22
|
+
control: { type: "select" },
|
|
23
|
+
},
|
|
24
|
+
disabled: {
|
|
25
|
+
control: "boolean",
|
|
26
|
+
},
|
|
27
|
+
selected: {
|
|
28
|
+
control: "boolean",
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
args: {
|
|
32
|
+
elevation: undefined,
|
|
33
|
+
disabled: false,
|
|
34
|
+
selected: false,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default meta;
|
|
39
|
+
|
|
40
|
+
type Story = StoryObj<typeof Card>;
|
|
41
|
+
|
|
42
|
+
export const AsLink: Story = {
|
|
43
|
+
render: (args) => (
|
|
44
|
+
<Card width={1 / 4} {...args}>
|
|
45
|
+
<Box display="flex" justifyContent="center" alignItems="center" my={400}>
|
|
46
|
+
<SpotIllustration
|
|
47
|
+
height="200px"
|
|
48
|
+
name="calendar-reporting"
|
|
49
|
+
aria-hidden
|
|
50
|
+
/>
|
|
51
|
+
</Box>
|
|
52
|
+
<Text.SmallByline>Reporting</Text.SmallByline>
|
|
53
|
+
<CardLink external affordance>
|
|
54
|
+
Visit calendar report
|
|
55
|
+
</CardLink>
|
|
56
|
+
</Card>
|
|
57
|
+
),
|
|
58
|
+
args: {
|
|
59
|
+
role: "link",
|
|
60
|
+
href: "https://seeds.sproutsocial.com/",
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const AsButton: Story = {
|
|
65
|
+
render: () => {
|
|
66
|
+
const [message, setMessage] = useState(false);
|
|
67
|
+
|
|
68
|
+
const _onClick = () => {
|
|
69
|
+
setMessage(true);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const showMessage = setTimeout(() => {
|
|
74
|
+
setMessage(false);
|
|
75
|
+
}, 4000);
|
|
76
|
+
|
|
77
|
+
return function cleanup() {
|
|
78
|
+
clearTimeout(showMessage);
|
|
79
|
+
};
|
|
80
|
+
}, [message]);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<>
|
|
84
|
+
{message ? (
|
|
85
|
+
<Box mb={400}>
|
|
86
|
+
<Banner text="Your click was successful." />
|
|
87
|
+
</Box>
|
|
88
|
+
) : (
|
|
89
|
+
<Box mb={400}>
|
|
90
|
+
<Banner
|
|
91
|
+
type="warning"
|
|
92
|
+
text={
|
|
93
|
+
<Box
|
|
94
|
+
width={1}
|
|
95
|
+
display="flex"
|
|
96
|
+
alignItems="center"
|
|
97
|
+
justifyContent="space-between"
|
|
98
|
+
>
|
|
99
|
+
<Text>
|
|
100
|
+
Avoid nesting interactive content inside a Card with
|
|
101
|
+
role='button'
|
|
102
|
+
</Text>
|
|
103
|
+
<Text>
|
|
104
|
+
<Link href="https://html.spec.whatwg.org/multipage/dom.html#interactive-content">
|
|
105
|
+
Learn more
|
|
106
|
+
<Icon
|
|
107
|
+
ml={200}
|
|
108
|
+
size="mini"
|
|
109
|
+
name="arrow-right-up-solid"
|
|
110
|
+
role={undefined}
|
|
111
|
+
svgProps={{
|
|
112
|
+
role: "img",
|
|
113
|
+
"aria-label": "opens in a new tab",
|
|
114
|
+
}}
|
|
115
|
+
/>
|
|
116
|
+
</Link>
|
|
117
|
+
</Text>
|
|
118
|
+
</Box>
|
|
119
|
+
}
|
|
120
|
+
/>
|
|
121
|
+
</Box>
|
|
122
|
+
)}
|
|
123
|
+
<Card role="button" onClick={_onClick} width={1 / 4}>
|
|
124
|
+
<Box mx="auto" mb={400}>
|
|
125
|
+
<PartnerLogo py={450} partnerName="facebook" size="jumbo" />
|
|
126
|
+
</Box>
|
|
127
|
+
<Text.SmallByline>Profile connect</Text.SmallByline>
|
|
128
|
+
<Text.Headline mb={300}>Facebook</Text.Headline>
|
|
129
|
+
<Text.BodyCopy>Click to connect your facebook account.</Text.BodyCopy>
|
|
130
|
+
</Card>
|
|
131
|
+
</>
|
|
132
|
+
);
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
export const AsPresentation: Story = {
|
|
137
|
+
render: (args) => (
|
|
138
|
+
<Card width={1 / 4} {...args}>
|
|
139
|
+
<Text.SmallByline>Analytics</Text.SmallByline>
|
|
140
|
+
<Text.Headline mb={300}>Google Analytics</Text.Headline>
|
|
141
|
+
<Box mx="auto" my={400}>
|
|
142
|
+
<PartnerLogo py={450} partnerName="google-analytics" size="jumbo" />
|
|
143
|
+
</Box>
|
|
144
|
+
<Text.BodyCopy mb={400}>
|
|
145
|
+
Learn more about how we track analytics.
|
|
146
|
+
</Text.BodyCopy>
|
|
147
|
+
<Link fontSize={300} href="https://google.com/" external>
|
|
148
|
+
Visit google
|
|
149
|
+
<Icon
|
|
150
|
+
mb={100}
|
|
151
|
+
ml={300}
|
|
152
|
+
size="mini"
|
|
153
|
+
name="arrow-right-outline"
|
|
154
|
+
role={undefined}
|
|
155
|
+
svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
|
|
156
|
+
/>
|
|
157
|
+
</Link>
|
|
158
|
+
</Card>
|
|
159
|
+
),
|
|
160
|
+
args: {
|
|
161
|
+
role: "presentation",
|
|
162
|
+
},
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
export const AsButtonDisabled: Story = {
|
|
166
|
+
render: () => {
|
|
167
|
+
const [message, setMessage] = useState(false);
|
|
168
|
+
|
|
169
|
+
const _onClick = () => {
|
|
170
|
+
setMessage(true);
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
useEffect(() => {
|
|
174
|
+
const showMessage = setTimeout(() => {
|
|
175
|
+
setMessage(false);
|
|
176
|
+
}, 4000);
|
|
177
|
+
|
|
178
|
+
return function cleanup() {
|
|
179
|
+
clearTimeout(showMessage);
|
|
180
|
+
};
|
|
181
|
+
}, [message]);
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<>
|
|
185
|
+
{message ? (
|
|
186
|
+
<Box mb={400}>
|
|
187
|
+
<Banner text="Your click was successful." />
|
|
188
|
+
</Box>
|
|
189
|
+
) : (
|
|
190
|
+
<Box mb={400}>
|
|
191
|
+
<Banner
|
|
192
|
+
type="warning"
|
|
193
|
+
text={
|
|
194
|
+
<Box
|
|
195
|
+
width={1}
|
|
196
|
+
display="flex"
|
|
197
|
+
alignItems="center"
|
|
198
|
+
justifyContent="space-between"
|
|
199
|
+
>
|
|
200
|
+
<Text>
|
|
201
|
+
Avoid nesting interactive content inside a Card with
|
|
202
|
+
role='button'
|
|
203
|
+
</Text>
|
|
204
|
+
<Text>
|
|
205
|
+
<Link href="https://html.spec.whatwg.org/multipage/dom.html#interactive-content">
|
|
206
|
+
Learn more
|
|
207
|
+
<Icon
|
|
208
|
+
ml={200}
|
|
209
|
+
size="mini"
|
|
210
|
+
name="arrow-right-up-solid"
|
|
211
|
+
role={undefined}
|
|
212
|
+
svgProps={{
|
|
213
|
+
role: "img",
|
|
214
|
+
"aria-label": "opens in a new tab",
|
|
215
|
+
}}
|
|
216
|
+
/>
|
|
217
|
+
</Link>
|
|
218
|
+
</Text>
|
|
219
|
+
</Box>
|
|
220
|
+
}
|
|
221
|
+
/>
|
|
222
|
+
</Box>
|
|
223
|
+
)}
|
|
224
|
+
<Card role="button" disabled={true} onClick={_onClick} width={1 / 4}>
|
|
225
|
+
<Box mx="auto" mb={400}>
|
|
226
|
+
<SpotIllustration height="200px" name="coffee-cup" />
|
|
227
|
+
</Box>
|
|
228
|
+
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
|
|
229
|
+
<Text.Headline mb={300}>Card component</Text.Headline>
|
|
230
|
+
<Text.BodyCopy>
|
|
231
|
+
The card component is a styled primitive container.
|
|
232
|
+
</Text.BodyCopy>
|
|
233
|
+
</Card>
|
|
234
|
+
</>
|
|
235
|
+
);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
export const ConfigurableShadow: Story = {
|
|
240
|
+
render: (args) => (
|
|
241
|
+
<Card width={1 / 4} {...args}>
|
|
242
|
+
<Text.SmallByline>SEEDS WEB</Text.SmallByline>
|
|
243
|
+
<Text.Headline mb={300}>Card component</Text.Headline>
|
|
244
|
+
<Box mx="auto" my={400}>
|
|
245
|
+
<SpotIllustration height="200px" name="coffee-cup" />
|
|
246
|
+
</Box>
|
|
247
|
+
<Text.BodyCopy mb={400}>
|
|
248
|
+
The card component is a styled primitive container.
|
|
249
|
+
</Text.BodyCopy>
|
|
250
|
+
<Link fontSize={300} href="https://google.com/" external>
|
|
251
|
+
Use now
|
|
252
|
+
<Icon
|
|
253
|
+
mb={100}
|
|
254
|
+
ml={300}
|
|
255
|
+
size="mini"
|
|
256
|
+
name="arrow-right-up-solid"
|
|
257
|
+
role={undefined}
|
|
258
|
+
svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
|
|
259
|
+
/>
|
|
260
|
+
</Link>
|
|
261
|
+
</Card>
|
|
262
|
+
),
|
|
263
|
+
args: {
|
|
264
|
+
role: "presentation",
|
|
265
|
+
elevation: "high",
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
export const SelectableComposition: Story = {
|
|
270
|
+
render: () => {
|
|
271
|
+
const [selected, setSelected] = useState(false);
|
|
272
|
+
const toggle = () => setSelected(!selected);
|
|
273
|
+
|
|
274
|
+
return (
|
|
275
|
+
<Card role="checkbox" selected={selected} onClick={toggle} width={1 / 3}>
|
|
276
|
+
<CardContent my={450} mx="auto">
|
|
277
|
+
<PartnerLogo partnerName="tiktok" size="jumbo" />
|
|
278
|
+
</CardContent>
|
|
279
|
+
<CardFooter flexDirection="column">
|
|
280
|
+
<Text.SmallSubHeadline>TikTok</Text.SmallSubHeadline>
|
|
281
|
+
<Text.SmallBodyCopy>
|
|
282
|
+
Select TikTok to start sharing content today.
|
|
283
|
+
</Text.SmallBodyCopy>
|
|
284
|
+
</CardFooter>
|
|
285
|
+
</Card>
|
|
286
|
+
);
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
export const CompositionUtilities: Story = {
|
|
291
|
+
render: () => (
|
|
292
|
+
<Card role="presentation">
|
|
293
|
+
<CardHeader>
|
|
294
|
+
<Avatar appearance="leaf" size="24px" name="Card Header" />
|
|
295
|
+
<Text.SubHeadline ml={300}>This is a card header</Text.SubHeadline>
|
|
296
|
+
</CardHeader>
|
|
297
|
+
<CardContent>
|
|
298
|
+
<Text.SmallBodyCopy as="p">
|
|
299
|
+
We can use the CardContent component to render cool content as seen
|
|
300
|
+
here:
|
|
301
|
+
</Text.SmallBodyCopy>
|
|
302
|
+
<Text.SmallBodyCopy as="p">
|
|
303
|
+
"Hi, Nard Dawg. I'm Lou Peachum!"
|
|
304
|
+
</Text.SmallBodyCopy>
|
|
305
|
+
</CardContent>
|
|
306
|
+
<CardFooter>
|
|
307
|
+
<Link external href="https://google.com">
|
|
308
|
+
Action in CardFooter
|
|
309
|
+
<Icon
|
|
310
|
+
ml={200}
|
|
311
|
+
size="mini"
|
|
312
|
+
name="arrow-right-up-solid"
|
|
313
|
+
role={undefined}
|
|
314
|
+
svgProps={{ role: "img", "aria-label": "opens in a new tab" }}
|
|
315
|
+
/>
|
|
316
|
+
</Link>
|
|
317
|
+
</CardFooter>
|
|
318
|
+
</Card>
|
|
319
|
+
),
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
export const Cards: Story = {
|
|
323
|
+
render: () => {
|
|
324
|
+
const cards: {
|
|
325
|
+
subhead: string;
|
|
326
|
+
reportName: string;
|
|
327
|
+
image: EnumIllustrationNames;
|
|
328
|
+
href: string;
|
|
329
|
+
}[] = [
|
|
330
|
+
{
|
|
331
|
+
subhead: "Reporting",
|
|
332
|
+
reportName: "Profile performance",
|
|
333
|
+
image: "reporting",
|
|
334
|
+
href: "https://app.sproutsocial.com/reports/group_report",
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
subhead: "Reporting",
|
|
338
|
+
reportName: "Post performance",
|
|
339
|
+
image: "reporting-folder",
|
|
340
|
+
href: "https://app.sproutsocial.com/reports/post_performance",
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
subhead: "Reporting",
|
|
344
|
+
reportName: "Tag performance",
|
|
345
|
+
image: "analytics-offering",
|
|
346
|
+
href: "https://app.sproutsocial.com/reports/tag_performance",
|
|
347
|
+
},
|
|
348
|
+
{
|
|
349
|
+
subhead: "Reporting",
|
|
350
|
+
reportName: "Paid performance",
|
|
351
|
+
image: "listening-tour",
|
|
352
|
+
href: "https://app.sproutsocial.com/reports/cross_network_campaign_performance",
|
|
353
|
+
},
|
|
354
|
+
];
|
|
355
|
+
|
|
356
|
+
const StyledList = styled.ul`
|
|
357
|
+
list-style: none;
|
|
358
|
+
display: flex;
|
|
359
|
+
flex-wrap: wrap;
|
|
360
|
+
`;
|
|
361
|
+
|
|
362
|
+
return (
|
|
363
|
+
<StyledList>
|
|
364
|
+
{cards.map((card) => (
|
|
365
|
+
<li key={card.href}>
|
|
366
|
+
<Card role="link" href={card.href} width="275px" mr={400} mb={400}>
|
|
367
|
+
<Box
|
|
368
|
+
display="flex"
|
|
369
|
+
justifyContent="center"
|
|
370
|
+
alignItems="center"
|
|
371
|
+
my={400}
|
|
372
|
+
>
|
|
373
|
+
<SpotIllustration
|
|
374
|
+
height="200px"
|
|
375
|
+
name={card.image}
|
|
376
|
+
aria-hidden
|
|
377
|
+
/>
|
|
378
|
+
</Box>
|
|
379
|
+
<Text.SmallByline>{card.subhead}</Text.SmallByline>
|
|
380
|
+
<CardLink external affordance>
|
|
381
|
+
Visit {card.reportName} report
|
|
382
|
+
</CardLink>
|
|
383
|
+
</Card>
|
|
384
|
+
</li>
|
|
385
|
+
))}
|
|
386
|
+
</StyledList>
|
|
387
|
+
);
|
|
388
|
+
},
|
|
389
|
+
};
|
package/src/Card.tsx
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import React, { useRef, useState } from "react";
|
|
2
|
+
import { StyledCard } from "./styles";
|
|
3
|
+
import type { TypeCardProps, TypeCardContext } from "./CardTypes";
|
|
4
|
+
import { SubComponentContext, onKeyDown } from "./utils";
|
|
5
|
+
import { SelectedIcon } from "./subComponents";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @link https://seeds.sproutsocial.com/components/card/
|
|
9
|
+
*
|
|
10
|
+
* Avoid nesting interactive content inside a Card with role='button'.
|
|
11
|
+
*
|
|
12
|
+
* Interactive content: "a", "audio", "button", "embed", "iframe", "img", "input", "label", "select", "textarea", "video"
|
|
13
|
+
* @see https://html.spec.whatwg.org/multipage/dom.html#interactive-content
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <Card role="button" onClick={_onClick}>
|
|
17
|
+
* <Button>Click me</Button>
|
|
18
|
+
* </Card>
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const Card = ({
|
|
22
|
+
children,
|
|
23
|
+
disabled = false,
|
|
24
|
+
elevation,
|
|
25
|
+
href,
|
|
26
|
+
onClick,
|
|
27
|
+
role = "presentation",
|
|
28
|
+
selected,
|
|
29
|
+
...rest
|
|
30
|
+
}: TypeCardProps) => {
|
|
31
|
+
const [hasSubComponent, setHasSubComponent] = useState<boolean>(false);
|
|
32
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
33
|
+
const linkRef = useRef<HTMLAnchorElement>(null);
|
|
34
|
+
const isRoleLink = role === "link";
|
|
35
|
+
const checkedConditions = role === "checkbox" ? selected : undefined;
|
|
36
|
+
|
|
37
|
+
const cardContext: TypeCardContext = {
|
|
38
|
+
setHasSubComponent: setHasSubComponent,
|
|
39
|
+
href: href,
|
|
40
|
+
linkRef: linkRef,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const handleClickConditions: React.MouseEventHandler = (e) =>
|
|
44
|
+
isRoleLink ? linkRef.current?.click() : onClick?.(e);
|
|
45
|
+
|
|
46
|
+
const handleKeyDown: React.KeyboardEventHandler<HTMLDivElement> = (e) =>
|
|
47
|
+
onKeyDown({ e, href, onClick, ref: containerRef, role });
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<StyledCard
|
|
51
|
+
tabIndex={isRoleLink ? -1 : 0}
|
|
52
|
+
role={isRoleLink ? undefined : role}
|
|
53
|
+
onClick={handleClickConditions}
|
|
54
|
+
onKeyDown={handleKeyDown}
|
|
55
|
+
$elevation={elevation}
|
|
56
|
+
ref={containerRef}
|
|
57
|
+
$selected={selected}
|
|
58
|
+
aria-checked={checkedConditions}
|
|
59
|
+
$disabled={disabled}
|
|
60
|
+
aria-disabled={disabled && disabled}
|
|
61
|
+
$compositionalComponents={hasSubComponent}
|
|
62
|
+
$isRoleLink={isRoleLink}
|
|
63
|
+
{...rest}
|
|
64
|
+
>
|
|
65
|
+
<SelectedIcon $selected={selected} />
|
|
66
|
+
<SubComponentContext.Provider value={cardContext}>
|
|
67
|
+
{children}
|
|
68
|
+
</SubComponentContext.Provider>
|
|
69
|
+
</StyledCard>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default Card;
|
package/src/CardTypes.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { TypeIconProps } from "@sproutsocial/seeds-react-icon";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import type { TypeStyledComponentsCommonProps } from "@sproutsocial/seeds-react-system-props";
|
|
4
|
+
import type {
|
|
5
|
+
TypeBorderSystemProps,
|
|
6
|
+
TypeColorSystemProps,
|
|
7
|
+
TypeFlexboxSystemProps,
|
|
8
|
+
TypeGridSystemProps,
|
|
9
|
+
TypeLayoutSystemProps,
|
|
10
|
+
TypePositionSystemProps,
|
|
11
|
+
TypeSpaceSystemProps,
|
|
12
|
+
TypeTypographySystemProps,
|
|
13
|
+
} from "@sproutsocial/seeds-react-system-props";
|
|
14
|
+
|
|
15
|
+
export interface TypeSharedCardSystemProps
|
|
16
|
+
extends Omit<React.ComponentPropsWithoutRef<"div">, "color">,
|
|
17
|
+
TypeStyledComponentsCommonProps,
|
|
18
|
+
TypeBorderSystemProps,
|
|
19
|
+
TypeColorSystemProps,
|
|
20
|
+
TypeFlexboxSystemProps,
|
|
21
|
+
TypeGridSystemProps,
|
|
22
|
+
TypeLayoutSystemProps,
|
|
23
|
+
TypePositionSystemProps,
|
|
24
|
+
TypeSpaceSystemProps {}
|
|
25
|
+
|
|
26
|
+
// consumer facing props that affect the styles of the component. We need to define these first so the user doesn't see our transient naming conventions.
|
|
27
|
+
export interface TypeCardStyleProps {
|
|
28
|
+
elevation?: "low" | "medium" | "high";
|
|
29
|
+
disabled?: boolean;
|
|
30
|
+
compositionalComponents?: boolean;
|
|
31
|
+
selected?: boolean;
|
|
32
|
+
isRoleLink?: boolean;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Since we only want to manage the style props in one place(above), we'll use this generic to prepend the properties of TypeCardStyleProps with $.
|
|
36
|
+
export type TypeStyleTransientProps<T> = {
|
|
37
|
+
[K in Extract<keyof T, string> as `$${K}`]: T[K];
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export type TypeCardStyleTransientProps =
|
|
41
|
+
TypeStyleTransientProps<TypeCardStyleProps>;
|
|
42
|
+
|
|
43
|
+
export interface TypeStyledCard
|
|
44
|
+
extends TypeSharedCardSystemProps,
|
|
45
|
+
TypeCardStyleTransientProps {}
|
|
46
|
+
|
|
47
|
+
export interface TypeCardStyles
|
|
48
|
+
extends TypeSharedCardSystemProps,
|
|
49
|
+
Omit<TypeCardStyleProps, "compositionalComponents"> {}
|
|
50
|
+
|
|
51
|
+
type TypeOnClick = (event: React.MouseEvent | React.KeyboardEvent) => void;
|
|
52
|
+
|
|
53
|
+
export type TypeCardConditions =
|
|
54
|
+
| {
|
|
55
|
+
role: "link";
|
|
56
|
+
href: string;
|
|
57
|
+
onClick?: never;
|
|
58
|
+
}
|
|
59
|
+
| {
|
|
60
|
+
role: "button";
|
|
61
|
+
href?: never;
|
|
62
|
+
onClick: TypeOnClick;
|
|
63
|
+
}
|
|
64
|
+
| {
|
|
65
|
+
role: "checkbox";
|
|
66
|
+
href?: never;
|
|
67
|
+
onClick: TypeOnClick;
|
|
68
|
+
selected: boolean;
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
role: "presentation";
|
|
72
|
+
href?: never;
|
|
73
|
+
/**
|
|
74
|
+
* **Warning:**
|
|
75
|
+
* `role='presentation'` is outside of the accessiblity tree. Using an `onClick` that performs a user action should likely be used
|
|
76
|
+
* with `role='button'` instead.
|
|
77
|
+
*/
|
|
78
|
+
onClick?: TypeOnClick;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export type TypeCardProps = TypeCardConditions &
|
|
82
|
+
React.PropsWithChildren<TypeCardStyles>;
|
|
83
|
+
|
|
84
|
+
export interface TypeCardArea extends TypeSharedCardSystemProps {
|
|
85
|
+
$divider?: "top" | "bottom";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface TypeStyledSelectedIcon extends TypeIconProps {
|
|
89
|
+
$selected?: TypeCardStyleTransientProps["$selected"];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface TypeCardContext {
|
|
93
|
+
setHasSubComponent?: React.Dispatch<React.SetStateAction<boolean>>;
|
|
94
|
+
href?: string;
|
|
95
|
+
linkRef: React.RefObject<HTMLAnchorElement> | null;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface TypeCardLink
|
|
99
|
+
extends Omit<React.ComponentPropsWithoutRef<"a">, "color">,
|
|
100
|
+
TypeColorSystemProps,
|
|
101
|
+
TypeTypographySystemProps {
|
|
102
|
+
affordance?: boolean;
|
|
103
|
+
external?: boolean;
|
|
104
|
+
}
|