@automattic/vip-design-system 2.6.1 → 2.8.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.
@@ -1,12 +1,22 @@
1
+ /** @jsxImportSource theme-ui */
1
2
  /// <reference types="react" />
2
3
  /**
3
4
  * External dependencies
4
5
  */
5
6
  import { Argument } from 'classnames';
6
7
  import { BoxProps } from 'theme-ui';
8
+ export declare enum CardVariant {
9
+ 'primary' = 0,
10
+ 'secondary' = 1,
11
+ 'notice' = 2,
12
+ 'indent' = 3
13
+ }
7
14
  export interface CardProps {
8
- variant?: string;
15
+ variant?: keyof typeof CardVariant;
9
16
  sx?: BoxProps['sx'];
10
17
  className?: Argument;
18
+ title?: string;
19
+ children?: React.ReactNode;
20
+ renderHeader?: (title?: string) => React.ReactNode;
11
21
  }
12
22
  export declare const Card: import("react").ForwardRefExoticComponent<CardProps & BoxProps & import("react").RefAttributes<HTMLElement>>;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports.Card = void 0;
4
+ exports.CardVariant = exports.Card = void 0;
5
5
  var _classnames = _interopRequireDefault(require("classnames"));
6
6
  var _react = require("react");
7
7
  var _ = require("..");
8
8
  var _jsxRuntime = require("theme-ui/jsx-runtime");
9
- var _excluded = ["variant", "sx", "className"];
9
+ var _excluded = ["variant", "title", "renderHeader", "sx", "className", "children"];
10
+ /** @jsxImportSource theme-ui */
10
11
  /**
11
12
  * External dependencies
12
13
  */
@@ -16,20 +17,43 @@ var _excluded = ["variant", "sx", "className"];
16
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
17
18
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
18
19
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
20
+ var CardVariant = exports.CardVariant = /*#__PURE__*/function (CardVariant) {
21
+ CardVariant[CardVariant["primary"] = 0] = "primary";
22
+ CardVariant[CardVariant["secondary"] = 1] = "secondary";
23
+ CardVariant[CardVariant["notice"] = 2] = "notice";
24
+ CardVariant[CardVariant["indent"] = 3] = "indent";
25
+ return CardVariant;
26
+ }({});
19
27
  var Card = exports.Card = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
20
28
  var _ref$variant = _ref.variant,
21
29
  variant = _ref$variant === void 0 ? 'primary' : _ref$variant,
30
+ title = _ref.title,
31
+ renderHeader = _ref.renderHeader,
22
32
  _ref$sx = _ref.sx,
23
33
  sx = _ref$sx === void 0 ? {} : _ref$sx,
24
34
  className = _ref.className,
35
+ children = _ref.children,
25
36
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
26
- return (0, _jsxRuntime.jsx)(_.Box, _extends({
37
+ return (0, _jsxRuntime.jsxs)(_.Box, _extends({
27
38
  ref: ref,
28
- sx: _extends({
29
- // pass variant prop to sx
39
+ sx: {
30
40
  variant: "cards." + variant
31
- }, sx),
41
+ },
32
42
  className: (0, _classnames["default"])('vip-card-component', className)
33
- }, props));
43
+ }, props, {
44
+ children: [renderHeader ? renderHeader(title) : '', title && !renderHeader && (0, _jsxRuntime.jsx)(_.Box, {
45
+ className: (0, _classnames["default"])('vip-card-header-component', className),
46
+ sx: {
47
+ variant: "cards." + variant + ".header"
48
+ },
49
+ children: title
50
+ }), (0, _jsxRuntime.jsx)(_.Box, {
51
+ className: (0, _classnames["default"])('vip-card-body-component', className),
52
+ sx: _extends({
53
+ variant: "cards." + variant + ".children"
54
+ }, sx),
55
+ children: children
56
+ })]
57
+ }));
34
58
  });
35
59
  Card.displayName = 'Card';
@@ -1,3 +1,4 @@
1
+ /** @jsxImportSource theme-ui */
1
2
  /// <reference types="react" />
2
3
  declare const _default: {
3
4
  title: string;
@@ -5,3 +6,8 @@ declare const _default: {
5
6
  };
6
7
  export default _default;
7
8
  export declare const Default: () => import("react").JSX.Element;
9
+ export declare const WithHeader: () => import("react").JSX.Element;
10
+ export declare const WithCustomHeader: () => import("react").JSX.Element;
11
+ export declare const DefaultSecondary: () => import("react").JSX.Element;
12
+ export declare const WithHeaderSecondary: () => import("react").JSX.Element;
13
+ export declare const DefaultIndent: () => import("react").JSX.Element;
@@ -1,18 +1,61 @@
1
1
  "use strict";
2
2
 
3
3
  exports.__esModule = true;
4
- exports["default"] = exports.Default = void 0;
4
+ exports["default"] = exports.WithHeaderSecondary = exports.WithHeader = exports.WithCustomHeader = exports.DefaultSecondary = exports.DefaultIndent = exports.Default = void 0;
5
5
  var _ = require("..");
6
6
  var _jsxRuntime = require("theme-ui/jsx-runtime");
7
- /**
8
- * Internal dependencies
9
- */
7
+ /** @jsxImportSource theme-ui */
10
8
  var _default = exports["default"] = {
11
9
  title: 'Card',
12
10
  component: _.Card
13
11
  };
14
12
  var Default = exports.Default = function Default() {
15
13
  return (0, _jsxRuntime.jsx)(_.Card, {
16
- children: " Hello "
14
+ children: "Hello"
15
+ });
16
+ };
17
+ var WithHeader = exports.WithHeader = function WithHeader() {
18
+ return (0, _jsxRuntime.jsx)(_.Card, {
19
+ title: "Header",
20
+ children: "This is a card with a header."
21
+ });
22
+ };
23
+ var WithCustomHeader = exports.WithCustomHeader = function WithCustomHeader() {
24
+ return (0, _jsxRuntime.jsx)(_.Box, {
25
+ sx: {
26
+ maxWidth: 500
27
+ },
28
+ children: (0, _jsxRuntime.jsx)(_.Card, {
29
+ title: "Screenshot of a website",
30
+ renderHeader: function renderHeader(title) {
31
+ return (0, _jsxRuntime.jsx)("img", {
32
+ src: "https://s0.wp.com/mshots/v1/https://google.com/",
33
+ sx: {
34
+ width: '100%'
35
+ },
36
+ alt: title
37
+ });
38
+ },
39
+ children: "This is a card with a customized header content."
40
+ })
41
+ });
42
+ };
43
+ var DefaultSecondary = exports.DefaultSecondary = function DefaultSecondary() {
44
+ return (0, _jsxRuntime.jsx)(_.Card, {
45
+ variant: "secondary",
46
+ children: "Hello"
47
+ });
48
+ };
49
+ var WithHeaderSecondary = exports.WithHeaderSecondary = function WithHeaderSecondary() {
50
+ return (0, _jsxRuntime.jsx)(_.Card, {
51
+ title: "Header",
52
+ variant: "secondary",
53
+ children: "This is a card with a header."
54
+ });
55
+ };
56
+ var DefaultIndent = exports.DefaultIndent = function DefaultIndent() {
57
+ return (0, _jsxRuntime.jsx)(_.Card, {
58
+ variant: "indent",
59
+ children: "Hello"
17
60
  });
18
61
  };
@@ -61,4 +61,29 @@ describe('<Card />', function () {
61
61
  }
62
62
  }, _callee2);
63
63
  })));
64
+ it('renders the Card component with a title', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
65
+ var _render3, container;
66
+ return _regeneratorRuntime().wrap(function _callee3$(_context3) {
67
+ while (1) switch (_context3.prev = _context3.next) {
68
+ case 0:
69
+ _render3 = (0, _react.render)((0, _jsxRuntime.jsx)(_Card.Card, {
70
+ title: "Card Header",
71
+ children: "Card text"
72
+ })), container = _render3.container;
73
+ expect(_react.screen.getByText('Card Header')).toBeInTheDocument();
74
+ expect(_react.screen.getByText('Card text')).toBeInTheDocument();
75
+
76
+ // Check for accessibility issues
77
+ _context3.t0 = expect;
78
+ _context3.next = 6;
79
+ return (0, _jestAxe.axe)(container);
80
+ case 6:
81
+ _context3.t1 = _context3.sent;
82
+ (0, _context3.t0)(_context3.t1).toHaveNoViolations();
83
+ case 8:
84
+ case "end":
85
+ return _context3.stop();
86
+ }
87
+ }, _callee3);
88
+ })));
64
89
  });
@@ -25,7 +25,7 @@ var NoticeIcon = function NoticeIcon(_ref) {
25
25
  color: color,
26
26
  flex: '0 0 auto'
27
27
  };
28
- var size = 20;
28
+ var size = 24;
29
29
  switch (variant) {
30
30
  case 'info':
31
31
  return (0, _jsxRuntime.jsx)(_md.MdInfo, {
@@ -68,15 +68,17 @@ var Notice = exports.Notice = /*#__PURE__*/_react["default"].forwardRef(function
68
68
  _ref2$variant = _ref2.variant,
69
69
  variant = _ref2$variant === void 0 ? 'warning' : _ref2$variant,
70
70
  props = _objectWithoutPropertiesLoose(_ref2, _excluded);
71
- return (0, _jsxRuntime.jsx)(_.Card, _extends({
71
+ return (0, _jsxRuntime.jsxs)(_.Card, _extends({
72
+ variant: "notice",
72
73
  sx: _extends({
73
74
  boxShadow: 'none',
74
75
  borderRadius: 2,
75
76
  bg: inline ? 'transparent' : "notice.background." + variant,
76
- padding: inline ? 0 : 3,
77
77
  color: "notice.text." + variant,
78
+ fontSize: 2,
78
79
  p: {
79
- color: "notice.text." + variant
80
+ color: "notice.text." + variant,
81
+ fontSize: 2
80
82
  },
81
83
  a: {
82
84
  color: "notice.link." + variant + ".default",
@@ -89,54 +91,50 @@ var Notice = exports.Notice = /*#__PURE__*/_react["default"].forwardRef(function
89
91
  '&:hover, &:focus': {
90
92
  color: "notice.link." + variant + ".hover"
91
93
  }
94
+ },
95
+ ul: {
96
+ pl: 5
92
97
  }
93
98
  }, sx),
94
99
  className: (0, _classnames["default"])('vip-notice-component', className),
95
100
  ref: forwardRef
96
101
  }, props, {
97
- children: (0, _jsxRuntime.jsxs)(_.Flex, {
102
+ children: [(0, _jsxRuntime.jsx)(_.Box, {
98
103
  sx: {
99
- height: '100%' // required for the dynamic height of the icon box to work
104
+ minWidth: '24px'
100
105
  },
101
- children: [(0, _jsxRuntime.jsx)(_.Box, {
106
+ children: (0, _jsxRuntime.jsxs)(_.Flex, {
102
107
  sx: {
103
- minWidth: '32px',
104
- mr: 3,
105
- mt: 0
108
+ flexDirection: 'column',
109
+ // the trick here is to have a flex column with the icon at the bottom and an empty div that fills the space
110
+ minHeight: '24px',
111
+ maxHeight: '32px',
112
+ // we're forcing the max height so that the icon is, at max, aligned between the first and the second line of text
113
+ alignItems: 'flex-end',
114
+ // we want the icon to be aligned to the bottom
115
+ height: '100%' // specifying the height will allow the box to match the height of the content.
106
116
  },
107
- children: (0, _jsxRuntime.jsxs)(_.Flex, {
108
- sx: {
109
- flexDirection: 'column',
110
- // the trick here is to have a flex column with the icon at the bottom and an empty div that fills the space
111
- minHeight: '20px',
112
- maxHeight: '32px',
113
- // we're forcing the max height so that the icon is, at max, aligned between the first and the second line of text
114
- alignItems: 'flex-end',
115
- // we want the icon to be aligned to the bottom
116
- height: '100%' // specifying the height will allow the box to match the height of the content.
117
- },
118
- children: [(0, _jsxRuntime.jsx)(_.Box, {
119
- sx: {
120
- flex: '1 100%' // we need this empty div to make the icon align to the bottom
121
- }
122
- }), (0, _jsxRuntime.jsx)(NoticeIcon, {
123
- color: "notice.icon." + variant,
124
- variant: variant
125
- })]
126
- })
127
- }), (0, _jsxRuntime.jsxs)(_.Box, {
128
- children: [title && (0, _jsxRuntime.jsx)(_.Heading, {
129
- as: headingVariant,
117
+ children: [(0, _jsxRuntime.jsx)(_.Box, {
130
118
  sx: {
131
- color: "notice.text." + variant,
132
- mb: 0,
133
- fontSize: 2,
134
- fontWeight: 'bold'
135
- },
136
- children: title
137
- }), children]
138
- })]
139
- })
119
+ flex: '1 100%' // we need this empty div to make the icon align to the bottom
120
+ }
121
+ }), (0, _jsxRuntime.jsx)(NoticeIcon, {
122
+ color: "notice.icon." + variant,
123
+ variant: variant
124
+ })]
125
+ })
126
+ }), (0, _jsxRuntime.jsxs)(_.Box, {
127
+ children: [title && (0, _jsxRuntime.jsx)(_.Heading, {
128
+ as: headingVariant,
129
+ sx: {
130
+ color: "notice.text." + variant,
131
+ mb: 0,
132
+ fontSize: 2,
133
+ fontWeight: 'bold'
134
+ },
135
+ children: title
136
+ }), children]
137
+ })]
140
138
  }));
141
139
  });
142
140
  Notice.displayName = 'Notice';
@@ -70,7 +70,6 @@ var WizardStep = exports.WizardStep = /*#__PURE__*/_react["default"].forwardRef(
70
70
  sx: {
71
71
  boxShadow: active ? 'low' : 'none',
72
72
  borderLeft: '2px solid',
73
- p: 4,
74
73
  backgroundColor: active ? 'background' : 'transparent',
75
74
  borderRadius: 0,
76
75
  borderBottom: active ? 'none' : '1px solid',
@@ -33,29 +33,86 @@ declare namespace _default {
33
33
  }
34
34
  export namespace cards {
35
35
  namespace primary {
36
- let padding: number;
37
- let borderRadius: number;
38
36
  let backgroundColor: string;
37
+ let borderRadius: number;
39
38
  let boxShadow: string;
39
+ namespace header {
40
+ let backgroundColor_1: string;
41
+ export { backgroundColor_1 as backgroundColor };
42
+ export let borderTopLeftRadius: number;
43
+ export let borderTopRightRadius: number;
44
+ export let py: number;
45
+ export let px: number;
46
+ export let gap: number;
47
+ export let fontWeight: string;
48
+ export let display: string;
49
+ export let minHeight: number;
50
+ }
51
+ namespace children {
52
+ export let padding: number;
53
+ let gap_1: number;
54
+ export { gap_1 as gap };
55
+ }
40
56
  }
41
57
  namespace secondary {
42
- let borderRadius_1: number;
43
- export { borderRadius_1 as borderRadius };
44
- export let p: number;
45
- let boxShadow_1: string;
46
- export { boxShadow_1 as boxShadow };
58
+ export let variant: string;
47
59
  export let border: string;
48
60
  export let borderColor: string;
61
+ let boxShadow_1: string;
62
+ export { boxShadow_1 as boxShadow };
63
+ export namespace header_1 {
64
+ let variant_1: string;
65
+ export { variant_1 as variant };
66
+ }
67
+ export { header_1 as header };
68
+ export namespace children_1 {
69
+ let variant_2: string;
70
+ export { variant_2 as variant };
71
+ }
72
+ export { children_1 as children };
73
+ }
74
+ namespace notice {
75
+ let boxShadow_2: string;
76
+ export { boxShadow_2 as boxShadow };
77
+ let borderRadius_1: number;
78
+ export { borderRadius_1 as borderRadius };
79
+ export let fontSize: number;
80
+ let padding_1: number;
81
+ export { padding_1 as padding };
82
+ export namespace children_2 {
83
+ export let height: string;
84
+ let display_1: string;
85
+ export { display_1 as display };
86
+ export let flexDirection: string;
87
+ let py_1: number;
88
+ export { py_1 as py };
89
+ let px_1: number;
90
+ export { px_1 as px };
91
+ let gap_2: number;
92
+ export { gap_2 as gap };
93
+ }
94
+ export { children_2 as children };
49
95
  }
50
96
  namespace indent {
51
97
  let borderRadius_2: number;
52
98
  export { borderRadius_2 as borderRadius };
53
- let p_1: number;
54
- export { p_1 as p };
55
- let boxShadow_2: string;
56
- export { boxShadow_2 as boxShadow };
57
- let backgroundColor_1: string;
58
- export { backgroundColor_1 as backgroundColor };
99
+ let boxShadow_3: string;
100
+ export { boxShadow_3 as boxShadow };
101
+ let backgroundColor_2: string;
102
+ export { backgroundColor_2 as backgroundColor };
103
+ export namespace header_2 {
104
+ let display_2: string;
105
+ export { display_2 as display };
106
+ let fontWeight_1: string;
107
+ export { fontWeight_1 as fontWeight };
108
+ export let p: number;
109
+ }
110
+ export { header_2 as header };
111
+ export namespace children_3 {
112
+ let p_1: number;
113
+ export { p_1 as p };
114
+ }
115
+ export { children_3 as children };
59
116
  }
60
117
  }
61
118
  export namespace buttons {
@@ -112,7 +169,7 @@ declare namespace _default {
112
169
  borderColor: string;
113
170
  };
114
171
  };
115
- export let display: {
172
+ let display_3: {
116
173
  variant: string;
117
174
  color: string;
118
175
  bg: string;
@@ -125,6 +182,7 @@ declare namespace _default {
125
182
  borderColor: string;
126
183
  };
127
184
  };
185
+ export { display_3 as display };
128
186
  export let ghost: {
129
187
  variant: string;
130
188
  color: string;
@@ -165,8 +223,9 @@ declare namespace _default {
165
223
  };
166
224
  export { border_1 as border };
167
225
  export namespace text {
168
- let variant: string;
169
- let color: string;
226
+ let variant_3: string;
227
+ export { variant_3 as variant };
228
+ export let color: string;
170
229
  }
171
230
  export let icon: {
172
231
  variant: string;
@@ -1081,41 +1140,42 @@ declare namespace _default {
1081
1140
  export let top: string;
1082
1141
  export let left: string;
1083
1142
  export let maxWidth: string;
1084
- let backgroundColor_2: string;
1085
- export { backgroundColor_2 as backgroundColor };
1086
- let boxShadow_3: string;
1087
- export { boxShadow_3 as boxShadow };
1143
+ let backgroundColor_3: string;
1144
+ export { backgroundColor_3 as backgroundColor };
1145
+ let boxShadow_4: string;
1146
+ export { boxShadow_4 as boxShadow };
1088
1147
  }
1089
1148
  export namespace sidebar_1 {
1090
1149
  let position_1: string;
1091
1150
  export { position_1 as position };
1092
1151
  let top_1: string;
1093
1152
  export { top_1 as top };
1094
- export let height: string;
1153
+ let height_1: string;
1154
+ export { height_1 as height };
1095
1155
  let left_1: string;
1096
1156
  export { left_1 as left };
1097
1157
  export let overflow: string;
1098
1158
  export let margin: number;
1099
1159
  let borderRadius_3: number;
1100
1160
  export { borderRadius_3 as borderRadius };
1101
- let boxShadow_4: string;
1102
- export { boxShadow_4 as boxShadow };
1103
- let backgroundColor_3: string;
1104
- export { backgroundColor_3 as backgroundColor };
1161
+ let boxShadow_5: string;
1162
+ export { boxShadow_5 as boxShadow };
1163
+ let backgroundColor_4: string;
1164
+ export { backgroundColor_4 as backgroundColor };
1105
1165
  }
1106
1166
  export { sidebar_1 as sidebar };
1107
1167
  export namespace cover {
1108
1168
  let position_2: string;
1109
1169
  export { position_2 as position };
1110
- let backgroundColor_4: string;
1111
- export { backgroundColor_4 as backgroundColor };
1170
+ let backgroundColor_5: string;
1171
+ export { backgroundColor_5 as backgroundColor };
1112
1172
  export let width: string;
1113
1173
  let left_2: number;
1114
1174
  export { left_2 as left };
1115
1175
  let top_2: number;
1116
1176
  export { top_2 as top };
1117
- let height_1: string;
1118
- export { height_1 as height };
1177
+ let height_2: string;
1178
+ export { height_2 as height };
1119
1179
  export let transform: string;
1120
1180
  let borderRadius_4: number;
1121
1181
  export { borderRadius_4 as borderRadius };
@@ -1171,11 +1231,12 @@ declare namespace _default {
1171
1231
  namespace root {
1172
1232
  export let fontFamily: string;
1173
1233
  export let lineHeight: string;
1174
- export let fontWeight: string;
1234
+ let fontWeight_2: string;
1235
+ export { fontWeight_2 as fontWeight };
1175
1236
  let color_1: string;
1176
1237
  export { color_1 as color };
1177
- let backgroundColor_5: string;
1178
- export { backgroundColor_5 as backgroundColor };
1238
+ let backgroundColor_6: string;
1239
+ export { backgroundColor_6 as backgroundColor };
1179
1240
  export let webkitFontSmoothing: string;
1180
1241
  export let mozOsxFontmoothing: string;
1181
1242
  export let a: {
@@ -1187,8 +1248,8 @@ declare namespace _default {
1187
1248
  };
1188
1249
  export namespace svg {
1189
1250
  export let fill: string;
1190
- let display_1: string;
1191
- export { display_1 as display };
1251
+ let display_4: string;
1252
+ export { display_4 as display };
1192
1253
  }
1193
1254
  export namespace pre {
1194
1255
  let fontFamily_1: string;
@@ -1207,8 +1268,8 @@ declare namespace outline {
1207
1268
  export let outlineStyle: string;
1208
1269
  export let outlineColor: any;
1209
1270
  export let outlineWidth: string;
1210
- let boxShadow_5: string;
1211
- export { boxShadow_5 as boxShadow };
1271
+ let boxShadow_6: string;
1272
+ export { boxShadow_6 as boxShadow };
1212
1273
  }
1213
1274
  declare namespace fonts {
1214
1275
  let body_1: string;
@@ -250,23 +250,63 @@ export default {
250
250
 
251
251
  cards: {
252
252
  primary: {
253
- padding: 3,
254
- borderRadius: 2,
255
253
  backgroundColor: 'layer.2',
254
+ borderRadius: 2,
256
255
  boxShadow: 'low',
256
+ header: {
257
+ backgroundColor: 'layer.1',
258
+ borderTopLeftRadius: 2,
259
+ borderTopRightRadius: 2,
260
+ py: 3,
261
+ px: 5,
262
+ gap: 2,
263
+ fontWeight: 'bold',
264
+ display: 'flex',
265
+ minHeight: 46,
266
+ },
267
+ children: {
268
+ padding: 5,
269
+ gap: 6,
270
+ },
257
271
  },
258
272
  secondary: {
259
- borderRadius: 2,
260
- p: 3,
261
- boxShadow: 'none',
273
+ variant: 'cards.primary',
262
274
  border: '1px solid',
263
275
  borderColor: 'borders.2',
276
+ boxShadow: 'none',
277
+ header: {
278
+ variant: 'cards.primary.header',
279
+ },
280
+ children: {
281
+ variant: 'cards.primary.children',
282
+ },
283
+ },
284
+ notice: {
285
+ boxShadow: 'none',
286
+ borderRadius: 2,
287
+ fontSize: 2,
288
+ padding: 0,
289
+ children: {
290
+ height: '100%',
291
+ display: 'flex',
292
+ flexDirection: 'row',
293
+ py: 3,
294
+ px: 4,
295
+ gap: 4,
296
+ },
264
297
  },
265
298
  indent: {
266
299
  borderRadius: 2,
267
- p: 3,
268
300
  boxShadow: 'none',
269
301
  backgroundColor: 'backgroundMuted',
302
+ header: {
303
+ display: 'flex',
304
+ fontWeight: 'bold',
305
+ p: 3,
306
+ },
307
+ children: {
308
+ p: 3,
309
+ },
270
310
  },
271
311
  },
272
312
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automattic/vip-design-system",
3
- "version": "2.6.1",
3
+ "version": "2.8.0",
4
4
  "main": "build/system/index.js",
5
5
  "scripts": {
6
6
  "build-storybook": "storybook build",
@@ -1,11 +1,39 @@
1
- /**
2
- * Internal dependencies
3
- */
4
- import { Card } from '..';
1
+ /** @jsxImportSource theme-ui */
2
+
3
+ import { Box, Card } from '..';
5
4
 
6
5
  export default {
7
6
  title: 'Card',
8
7
  component: Card,
9
8
  };
10
9
 
11
- export const Default = () => <Card> Hello </Card>;
10
+ export const Default = () => <Card>Hello</Card>;
11
+
12
+ export const WithHeader = () => <Card title="Header">This is a card with a header.</Card>;
13
+
14
+ export const WithCustomHeader = () => (
15
+ <Box sx={ { maxWidth: 500 } }>
16
+ <Card
17
+ title="Screenshot of a website"
18
+ renderHeader={ title => (
19
+ <img
20
+ src={ `https://s0.wp.com/mshots/v1/https://google.com/` }
21
+ sx={ { width: '100%' } }
22
+ alt={ title }
23
+ />
24
+ ) }
25
+ >
26
+ This is a card with a customized header content.
27
+ </Card>
28
+ </Box>
29
+ );
30
+
31
+ export const DefaultSecondary = () => <Card variant="secondary">Hello</Card>;
32
+
33
+ export const WithHeaderSecondary = () => (
34
+ <Card title="Header" variant="secondary">
35
+ This is a card with a header.
36
+ </Card>
37
+ );
38
+
39
+ export const DefaultIndent = () => <Card variant="indent">Hello</Card>;
@@ -29,4 +29,15 @@ describe( '<Card />', () => {
29
29
  // Check for accessibility issues
30
30
  expect( await axe( container ) ).toHaveNoViolations();
31
31
  } );
32
+
33
+ it( 'renders the Card component with a title', async () => {
34
+ const { container } = render( <Card title="Card Header">Card text</Card> );
35
+
36
+ expect( screen.getByText( 'Card Header' ) ).toBeInTheDocument();
37
+
38
+ expect( screen.getByText( 'Card text' ) ).toBeInTheDocument();
39
+
40
+ // Check for accessibility issues
41
+ expect( await axe( container ) ).toHaveNoViolations();
42
+ } );
32
43
  } );
@@ -1,3 +1,5 @@
1
+ /** @jsxImportSource theme-ui */
2
+
1
3
  /**
2
4
  * External dependencies
3
5
  */
@@ -10,30 +12,62 @@ import { BoxProps } from 'theme-ui';
10
12
  */
11
13
  import { Box } from '..';
12
14
 
15
+ export enum CardVariant {
16
+ 'primary',
17
+ 'secondary',
18
+ 'notice',
19
+ 'indent',
20
+ }
21
+
13
22
  export interface CardProps {
14
- variant?: string;
23
+ variant?: keyof typeof CardVariant;
15
24
  sx?: BoxProps[ 'sx' ];
16
25
  className?: Argument;
26
+ title?: string;
27
+ children?: React.ReactNode;
28
+ renderHeader?: ( title?: string ) => React.ReactNode;
17
29
  }
18
30
 
19
31
  type CardBoxProps = CardProps & BoxProps;
20
32
 
21
33
  export const Card = forwardRef< HTMLElement, CardBoxProps >(
22
34
  (
23
- { variant = 'primary', sx = {}, className, ...props }: CardBoxProps,
35
+ { variant = 'primary', title, renderHeader, sx = {}, className, children, ...props }: CardProps,
24
36
  ref: Ref< HTMLElement >
25
- ) => (
26
- <Box
27
- ref={ ref }
28
- sx={ {
29
- // pass variant prop to sx
30
- variant: `cards.${ variant }`,
31
- ...sx,
32
- } }
33
- className={ classNames( 'vip-card-component', className ) }
34
- { ...props }
35
- />
36
- )
37
+ ) => {
38
+ return (
39
+ <Box
40
+ ref={ ref }
41
+ sx={ {
42
+ variant: `cards.${ variant }`,
43
+ } }
44
+ className={ classNames( 'vip-card-component', className ) }
45
+ { ...props }
46
+ >
47
+ { renderHeader ? renderHeader( title ) : '' }
48
+ { title && ! renderHeader && (
49
+ <Box
50
+ className={ classNames( 'vip-card-header-component', className ) }
51
+ sx={ {
52
+ variant: `cards.${ variant }.header`,
53
+ } }
54
+ >
55
+ { title }
56
+ </Box>
57
+ ) }
58
+
59
+ <Box
60
+ className={ classNames( 'vip-card-body-component', className ) }
61
+ sx={ {
62
+ variant: `cards.${ variant }.children`,
63
+ ...sx,
64
+ } }
65
+ >
66
+ { children }
67
+ </Box>
68
+ </Box>
69
+ );
70
+ }
37
71
  );
38
72
 
39
73
  Card.displayName = 'Card';
@@ -31,7 +31,7 @@ type ColorVariants = 'warning' | 'error' | 'alert' | 'success' | 'info';
31
31
 
32
32
  const NoticeIcon = ( { color, variant }: NoticeIconProps ) => {
33
33
  const sx = { color, flex: '0 0 auto' };
34
- const size = 20;
34
+ const size = 24;
35
35
 
36
36
  switch ( variant ) {
37
37
  case 'info':
@@ -62,14 +62,16 @@ export const Notice = React.forwardRef< HTMLDivElement, NoticeProps >(
62
62
  ) => {
63
63
  return (
64
64
  <Card
65
+ variant="notice"
65
66
  sx={ {
66
67
  boxShadow: 'none',
67
68
  borderRadius: 2,
68
69
  bg: inline ? 'transparent' : `notice.background.${ variant }`,
69
- padding: inline ? 0 : 3,
70
70
  color: `notice.text.${ variant }`,
71
+ fontSize: 2,
71
72
  p: {
72
73
  color: `notice.text.${ variant }`,
74
+ fontSize: 2,
73
75
  },
74
76
  a: {
75
77
  color: `notice.link.${ variant }.default`,
@@ -83,52 +85,49 @@ export const Notice = React.forwardRef< HTMLDivElement, NoticeProps >(
83
85
  color: `notice.link.${ variant }.hover`,
84
86
  },
85
87
  },
88
+ ul: {
89
+ pl: 5,
90
+ },
86
91
  ...sx,
87
92
  } }
88
93
  className={ classNames( 'vip-notice-component', className ) }
89
94
  ref={ forwardRef }
90
95
  { ...props }
91
96
  >
92
- <Flex
93
- sx={ {
94
- height: '100%', // required for the dynamic height of the icon box to work
95
- } }
96
- >
97
- <Box sx={ { minWidth: '32px', mr: 3, mt: 0 } }>
98
- <Flex
97
+ <Box sx={ { minWidth: '24px' } }>
98
+ <Flex
99
+ sx={ {
100
+ flexDirection: 'column', // the trick here is to have a flex column with the icon at the bottom and an empty div that fills the space
101
+ minHeight: '24px',
102
+ maxHeight: '32px', // we're forcing the max height so that the icon is, at max, aligned between the first and the second line of text
103
+ alignItems: 'flex-end', // we want the icon to be aligned to the bottom
104
+ height: '100%', // specifying the height will allow the box to match the height of the content.
105
+ } }
106
+ >
107
+ <Box
108
+ sx={ {
109
+ flex: '1 100%', // we need this empty div to make the icon align to the bottom
110
+ } }
111
+ ></Box>
112
+ <NoticeIcon color={ `notice.icon.${ variant }` } variant={ variant } />
113
+ </Flex>
114
+ </Box>
115
+ <Box>
116
+ { title && (
117
+ <Heading
118
+ as={ headingVariant }
99
119
  sx={ {
100
- flexDirection: 'column', // the trick here is to have a flex column with the icon at the bottom and an empty div that fills the space
101
- minHeight: '20px',
102
- maxHeight: '32px', // we're forcing the max height so that the icon is, at max, aligned between the first and the second line of text
103
- alignItems: 'flex-end', // we want the icon to be aligned to the bottom
104
- height: '100%', // specifying the height will allow the box to match the height of the content.
120
+ color: `notice.text.${ variant }`,
121
+ mb: 0,
122
+ fontSize: 2,
123
+ fontWeight: 'bold',
105
124
  } }
106
125
  >
107
- <Box
108
- sx={ {
109
- flex: '1 100%', // we need this empty div to make the icon align to the bottom
110
- } }
111
- ></Box>
112
- <NoticeIcon color={ `notice.icon.${ variant }` } variant={ variant } />
113
- </Flex>
114
- </Box>
115
- <Box>
116
- { title && (
117
- <Heading
118
- as={ headingVariant }
119
- sx={ {
120
- color: `notice.text.${ variant }`,
121
- mb: 0,
122
- fontSize: 2,
123
- fontWeight: 'bold',
124
- } }
125
- >
126
- { title }
127
- </Heading>
128
- ) }
129
- { children }
130
- </Box>
131
- </Flex>
126
+ { title }
127
+ </Heading>
128
+ ) }
129
+ { children }
130
+ </Box>
132
131
  </Card>
133
132
  );
134
133
  }
@@ -88,7 +88,6 @@ export const WizardStep = React.forwardRef< HTMLDivElement, WizardStepProps >(
88
88
  sx={ {
89
89
  boxShadow: active ? 'low' : 'none',
90
90
  borderLeft: '2px solid',
91
- p: 4,
92
91
  backgroundColor: active ? 'background' : 'transparent',
93
92
  borderRadius: 0,
94
93
  borderBottom: active ? 'none' : '1px solid',
@@ -250,23 +250,63 @@ export default {
250
250
 
251
251
  cards: {
252
252
  primary: {
253
- padding: 3,
254
- borderRadius: 2,
255
253
  backgroundColor: 'layer.2',
254
+ borderRadius: 2,
256
255
  boxShadow: 'low',
256
+ header: {
257
+ backgroundColor: 'layer.1',
258
+ borderTopLeftRadius: 2,
259
+ borderTopRightRadius: 2,
260
+ py: 3,
261
+ px: 5,
262
+ gap: 2,
263
+ fontWeight: 'bold',
264
+ display: 'flex',
265
+ minHeight: 46,
266
+ },
267
+ children: {
268
+ padding: 5,
269
+ gap: 6,
270
+ },
257
271
  },
258
272
  secondary: {
259
- borderRadius: 2,
260
- p: 3,
261
- boxShadow: 'none',
273
+ variant: 'cards.primary',
262
274
  border: '1px solid',
263
275
  borderColor: 'borders.2',
276
+ boxShadow: 'none',
277
+ header: {
278
+ variant: 'cards.primary.header',
279
+ },
280
+ children: {
281
+ variant: 'cards.primary.children',
282
+ },
283
+ },
284
+ notice: {
285
+ boxShadow: 'none',
286
+ borderRadius: 2,
287
+ fontSize: 2,
288
+ padding: 0,
289
+ children: {
290
+ height: '100%',
291
+ display: 'flex',
292
+ flexDirection: 'row',
293
+ py: 3,
294
+ px: 4,
295
+ gap: 4,
296
+ },
264
297
  },
265
298
  indent: {
266
299
  borderRadius: 2,
267
- p: 3,
268
300
  boxShadow: 'none',
269
301
  backgroundColor: 'backgroundMuted',
302
+ header: {
303
+ display: 'flex',
304
+ fontWeight: 'bold',
305
+ p: 3,
306
+ },
307
+ children: {
308
+ p: 3,
309
+ },
270
310
  },
271
311
  },
272
312