@automattic/vip-design-system 2.4.4 → 2.5.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/build/system/Breadcrumbs/Breadcrumbs.d.ts +1 -0
- package/build/system/Breadcrumbs/Breadcrumbs.js +75 -20
- package/build/system/Breadcrumbs/Breadcrumbs.stories.d.ts +2 -0
- package/build/system/Breadcrumbs/Breadcrumbs.stories.js +47 -7
- package/build/system/Breadcrumbs/Breadcrumbs.test.js +72 -0
- package/build/system/Breadcrumbs/styles.d.ts +2 -0
- package/build/system/Breadcrumbs/styles.js +8 -2
- package/build/system/Link/Link.d.ts +11 -1
- package/build/system/Link/Link.js +16 -1
- package/build/system/Link/Link.stories.d.ts +14 -1
- package/build/system/Link/Link.stories.js +16 -3
- package/build/system/MobileMenu/MobileMenu.js +1 -0
- package/build/system/Nav/styles.js +2 -1
- package/build/system/Toolbar/Logo.js +1 -1
- package/build/system/theme/breakpoints.js +4 -1
- package/build/system/theme/index.d.ts +863 -3
- package/build/system/theme/index.js +5 -6
- package/build/system/utils/stories/CustomLink.d.ts +1 -0
- package/build/system/utils/stories/CustomLink.js +7 -1
- package/package.json +1 -1
- package/src/system/Breadcrumbs/Breadcrumbs.stories.tsx +32 -3
- package/src/system/Breadcrumbs/Breadcrumbs.test.tsx +60 -0
- package/src/system/Breadcrumbs/Breadcrumbs.tsx +100 -29
- package/src/system/Breadcrumbs/styles.ts +11 -0
- package/src/system/Link/Link.stories.tsx +42 -1
- package/src/system/Link/Link.tsx +17 -8
- package/src/system/MobileMenu/MobileMenu.tsx +1 -0
- package/src/system/Nav/styles.ts +1 -0
- package/src/system/Toolbar/Logo.tsx +1 -1
- package/src/system/theme/breakpoints.ts +7 -1
- package/src/system/theme/index.js +5 -6
- package/src/system/utils/stories/CustomLink.tsx +6 -0
|
@@ -13,6 +13,7 @@ export type BreadcrumbsLinkProps = {
|
|
|
13
13
|
export interface BreacrumbsProps extends NavigationMenu.NavigationMenuProps {
|
|
14
14
|
className?: string;
|
|
15
15
|
label?: string;
|
|
16
|
+
wrapMode?: 'collapsible' | 'lastItem';
|
|
16
17
|
LinkComponent: NavItemProps['as'];
|
|
17
18
|
links?: BreadcrumbsLinkProps[];
|
|
18
19
|
}
|
|
@@ -5,6 +5,7 @@ exports.VIP_BREACRUMBS = exports.Breadcrumbs = void 0;
|
|
|
5
5
|
var NavigationMenu = _interopRequireWildcard(require("@radix-ui/react-navigation-menu"));
|
|
6
6
|
var _matchMedia = require("@theme-ui/match-media");
|
|
7
7
|
var _classnames = _interopRequireDefault(require("classnames"));
|
|
8
|
+
var _i18nCalypso = require("i18n-calypso");
|
|
8
9
|
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _styles = require("./styles");
|
|
10
11
|
var _NavItem = require("../Nav/NavItem");
|
|
@@ -15,39 +16,82 @@ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return
|
|
|
15
16
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
|
16
17
|
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); } /** @jsxImportSource theme-ui */
|
|
17
18
|
var VIP_BREACRUMBS = exports.VIP_BREACRUMBS = 'vip-breadcrumbs-component';
|
|
19
|
+
var breadcrumbLinks = function breadcrumbLinks(links, isSmallestScreen, wrapMode, showAllItems) {
|
|
20
|
+
if (isSmallestScreen === void 0) {
|
|
21
|
+
isSmallestScreen = false;
|
|
22
|
+
}
|
|
23
|
+
if (showAllItems === void 0) {
|
|
24
|
+
showAllItems = false;
|
|
25
|
+
}
|
|
26
|
+
var separatorLink = false;
|
|
27
|
+
var lastLink = null;
|
|
28
|
+
var otherLinks = [];
|
|
29
|
+
var totalLinks = links == null ? void 0 : links.length;
|
|
30
|
+
if (totalLinks === 1) {
|
|
31
|
+
lastLink = links == null ? void 0 : links[0];
|
|
32
|
+
otherLinks = [];
|
|
33
|
+
}
|
|
34
|
+
if (totalLinks > 1) {
|
|
35
|
+
var otherLinksRaw = links == null ? void 0 : links.slice(0, totalLinks - 1);
|
|
36
|
+
lastLink = links == null ? void 0 : links[totalLinks - 1];
|
|
37
|
+
if (wrapMode === 'lastItem') {
|
|
38
|
+
var penultimateLink = links == null ? void 0 : links[totalLinks - 2];
|
|
39
|
+
lastLink = isSmallestScreen ? null : links == null ? void 0 : links[totalLinks - 1];
|
|
40
|
+
otherLinks = isSmallestScreen ? [_extends({}, penultimateLink, {
|
|
41
|
+
active: true,
|
|
42
|
+
sx: _styles.smallestScreenItemStyles
|
|
43
|
+
})] : otherLinksRaw;
|
|
44
|
+
} else if (wrapMode === 'collapsible') {
|
|
45
|
+
separatorLink = isSmallestScreen && !showAllItems && totalLinks > 2;
|
|
46
|
+
otherLinks = isSmallestScreen && !showAllItems ? [links == null ? void 0 : links[0]] : otherLinksRaw;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return {
|
|
50
|
+
separatorLink: separatorLink,
|
|
51
|
+
lastLink: lastLink,
|
|
52
|
+
otherLinks: otherLinks
|
|
53
|
+
};
|
|
54
|
+
};
|
|
18
55
|
var Breadcrumbs = exports.Breadcrumbs = /*#__PURE__*/(0, _react.forwardRef)(function (_ref, ref) {
|
|
19
|
-
var _lastLink;
|
|
20
56
|
var className = _ref.className,
|
|
21
57
|
_ref$links = _ref.links,
|
|
22
58
|
links = _ref$links === void 0 ? [] : _ref$links,
|
|
23
59
|
_ref$label = _ref.label,
|
|
24
60
|
label = _ref$label === void 0 ? 'Breadcrumbs' : _ref$label,
|
|
25
61
|
_ref$LinkComponent = _ref.LinkComponent,
|
|
26
|
-
LinkComponent = _ref$LinkComponent === void 0 ? _NavItem.NavRawLink : _ref$LinkComponent
|
|
62
|
+
LinkComponent = _ref$LinkComponent === void 0 ? _NavItem.NavRawLink : _ref$LinkComponent,
|
|
63
|
+
_ref$wrapMode = _ref.wrapMode,
|
|
64
|
+
wrapMode = _ref$wrapMode === void 0 ? 'lastItem' : _ref$wrapMode;
|
|
65
|
+
var breadcrumbsListRef = (0, _react.useRef)(null);
|
|
66
|
+
var _useState = (0, _react.useState)(false),
|
|
67
|
+
showAllItems = _useState[0],
|
|
68
|
+
setShowAllItems = _useState[1];
|
|
69
|
+
var translate = (0, _i18nCalypso.useTranslate)();
|
|
70
|
+
|
|
71
|
+
// Focus on the next link when the collapsible separator is true
|
|
72
|
+
(0, _react.useEffect)(function () {
|
|
73
|
+
if (wrapMode !== 'collapsible') {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
var breadcrumbList = breadcrumbsListRef == null ? void 0 : breadcrumbsListRef.current;
|
|
77
|
+
if (showAllItems && breadcrumbList) {
|
|
78
|
+
var nextActiveLink = breadcrumbList.querySelector('li:nth-child(2) a');
|
|
79
|
+
nextActiveLink == null || nextActiveLink.focus();
|
|
80
|
+
}
|
|
81
|
+
}, [showAllItems, wrapMode]);
|
|
82
|
+
|
|
27
83
|
// The breadcrumb shrinks on smaller screens (mobile) and we need to hide some links
|
|
28
84
|
var bpIndex = (0, _matchMedia.useBreakpointIndex)({
|
|
29
85
|
defaultIndex: 1
|
|
30
86
|
});
|
|
31
87
|
var isSmallestScreen = bpIndex < 3;
|
|
32
|
-
|
|
33
|
-
var lastLink = null;
|
|
34
|
-
var otherLinks = [];
|
|
35
|
-
var totalLinks = (links == null ? void 0 : links.length) || 0;
|
|
36
|
-
if (totalLinks === 0) {
|
|
88
|
+
if ((links == null ? void 0 : links.length) === 0) {
|
|
37
89
|
return null;
|
|
38
90
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (totalLinks > 1) {
|
|
44
|
-
penultimateLink = links == null ? void 0 : links[totalLinks - 2];
|
|
45
|
-
otherLinks = isSmallestScreen ? [_extends({}, penultimateLink, {
|
|
46
|
-
active: true,
|
|
47
|
-
sx: _styles.smallestScreenItemStyles
|
|
48
|
-
})] : links == null ? void 0 : links.slice(0, totalLinks - 1);
|
|
49
|
-
lastLink = isSmallestScreen ? null : links == null ? void 0 : links[totalLinks - 1];
|
|
50
|
-
}
|
|
91
|
+
var _breadcrumbLinks = breadcrumbLinks(links, isSmallestScreen, wrapMode, showAllItems),
|
|
92
|
+
separatorLink = _breadcrumbLinks.separatorLink,
|
|
93
|
+
lastLink = _breadcrumbLinks.lastLink,
|
|
94
|
+
otherLinks = _breadcrumbLinks.otherLinks;
|
|
51
95
|
return (0, _jsxRuntime.jsx)(NavigationMenu.Root, {
|
|
52
96
|
"aria-label": label,
|
|
53
97
|
ref: ref,
|
|
@@ -56,6 +100,7 @@ var Breadcrumbs = exports.Breadcrumbs = /*#__PURE__*/(0, _react.forwardRef)(func
|
|
|
56
100
|
children: (0, _jsxRuntime.jsx)(NavigationMenu.List, {
|
|
57
101
|
className: (0, _classnames["default"])(VIP_BREACRUMBS + "-list"),
|
|
58
102
|
sx: (0, _styles2.navMenuListStyles)('horizontal'),
|
|
103
|
+
ref: breadcrumbsListRef,
|
|
59
104
|
asChild: true,
|
|
60
105
|
children: (0, _jsxRuntime.jsxs)("ol", {
|
|
61
106
|
children: [otherLinks.map(function (link) {
|
|
@@ -66,12 +111,22 @@ var Breadcrumbs = exports.Breadcrumbs = /*#__PURE__*/(0, _react.forwardRef)(func
|
|
|
66
111
|
href: link.href,
|
|
67
112
|
children: link.label
|
|
68
113
|
}, link.href);
|
|
114
|
+
}), separatorLink && (0, _jsxRuntime.jsx)("li", {
|
|
115
|
+
sx: _extends({}, (0, _styles2.navItemStyles)('horizontal', 'breadcrumbs')),
|
|
116
|
+
children: (0, _jsxRuntime.jsx)("button", {
|
|
117
|
+
sx: _styles.collapsibleSeparatorStyles,
|
|
118
|
+
"aria-label": translate('Press to show more breadcrumbs'),
|
|
119
|
+
onClick: function onClick() {
|
|
120
|
+
return setShowAllItems(true);
|
|
121
|
+
},
|
|
122
|
+
children: "\u2026"
|
|
123
|
+
})
|
|
69
124
|
}), lastLink && (0, _jsxRuntime.jsx)("li", {
|
|
70
125
|
sx: _extends({}, (0, _styles2.navItemStyles)('horizontal', 'breadcrumbs'), {
|
|
71
126
|
color: 'text'
|
|
72
127
|
}),
|
|
73
128
|
"aria-current": "page",
|
|
74
|
-
children:
|
|
129
|
+
children: lastLink == null ? void 0 : lastLink.label
|
|
75
130
|
})]
|
|
76
131
|
})
|
|
77
132
|
})
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** @jsxImportSource theme-ui */
|
|
1
2
|
import React from 'react';
|
|
2
3
|
import { Breadcrumbs as Breadcrumbs } from './Breadcrumbs';
|
|
3
4
|
import type { StoryObj } from '@storybook/react';
|
|
@@ -15,3 +16,4 @@ declare const _default: {
|
|
|
15
16
|
export default _default;
|
|
16
17
|
type Story = StoryObj<typeof Breadcrumbs>;
|
|
17
18
|
export declare const Default: Story;
|
|
19
|
+
export declare const Collapsible: Story;
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports["default"] = exports.Default = void 0;
|
|
4
|
+
exports["default"] = exports.Default = exports.Collapsible = void 0;
|
|
5
5
|
var _react = _interopRequireDefault(require("react"));
|
|
6
6
|
var _Breadcrumbs = require("./Breadcrumbs");
|
|
7
|
+
var _Box = require("../Box");
|
|
8
|
+
var _CustomLink = require("../utils/stories/CustomLink");
|
|
7
9
|
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
8
10
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
9
|
-
|
|
10
|
-
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
|
11
|
-
var CustomLink = function CustomLink(props) {
|
|
12
|
-
return (0, _jsxRuntime.jsx)("a", _extends({}, props));
|
|
13
|
-
};
|
|
11
|
+
/** @jsxImportSource theme-ui */
|
|
14
12
|
var _default = exports["default"] = {
|
|
15
13
|
title: 'Navigation/Breadcrumbs',
|
|
16
14
|
component: _Breadcrumbs.Breadcrumbs,
|
|
@@ -25,7 +23,7 @@ var _default = exports["default"] = {
|
|
|
25
23
|
var Default = exports.Default = {
|
|
26
24
|
render: function render() {
|
|
27
25
|
return (0, _jsxRuntime.jsx)(_Breadcrumbs.Breadcrumbs, {
|
|
28
|
-
LinkComponent: CustomLink,
|
|
26
|
+
LinkComponent: _CustomLink.CustomLink,
|
|
29
27
|
label: "Nav Breadcrumbs",
|
|
30
28
|
links: [{
|
|
31
29
|
href: 'https://wordpress.com',
|
|
@@ -39,4 +37,46 @@ var Default = exports.Default = {
|
|
|
39
37
|
}]
|
|
40
38
|
});
|
|
41
39
|
}
|
|
40
|
+
};
|
|
41
|
+
var Collapsible = exports.Collapsible = {
|
|
42
|
+
render: function render() {
|
|
43
|
+
return (0, _jsxRuntime.jsxs)(_Box.Box, {
|
|
44
|
+
sx: {
|
|
45
|
+
display: 'flex',
|
|
46
|
+
flexDirection: 'column',
|
|
47
|
+
gap: 4
|
|
48
|
+
},
|
|
49
|
+
children: [(0, _jsxRuntime.jsx)("p", {
|
|
50
|
+
children: "When entering Mobile views, the first and the last link will appear. A button with a \u2026 will also be visible. Once pressed, the rest of the links become available, and the focus is moved to the next link."
|
|
51
|
+
}), (0, _jsxRuntime.jsx)("hr", {
|
|
52
|
+
sx: {
|
|
53
|
+
width: '100%',
|
|
54
|
+
my: 4
|
|
55
|
+
}
|
|
56
|
+
}), (0, _jsxRuntime.jsx)(_Breadcrumbs.Breadcrumbs, {
|
|
57
|
+
wrapMode: "collapsible",
|
|
58
|
+
LinkComponent: _CustomLink.CustomLinkComponentized,
|
|
59
|
+
label: "Nav Breadcrumbs",
|
|
60
|
+
links: [{
|
|
61
|
+
href: '/',
|
|
62
|
+
label: 'Home'
|
|
63
|
+
}, {
|
|
64
|
+
href: 'https://datadog.com/',
|
|
65
|
+
label: 'Data dog'
|
|
66
|
+
}, {
|
|
67
|
+
href: 'https://newrelic.com/',
|
|
68
|
+
label: 'New Relic'
|
|
69
|
+
}, {
|
|
70
|
+
href: 'https://rollbar.com/',
|
|
71
|
+
label: 'Rollbar'
|
|
72
|
+
}, {
|
|
73
|
+
href: 'https://areallylong.com/',
|
|
74
|
+
label: 'A really long name'
|
|
75
|
+
}, {
|
|
76
|
+
href: 'https://google.com/',
|
|
77
|
+
label: 'I am the last item'
|
|
78
|
+
}]
|
|
79
|
+
})]
|
|
80
|
+
});
|
|
81
|
+
}
|
|
42
82
|
};
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _react = require("@testing-library/react");
|
|
4
|
+
var _userEvent = _interopRequireDefault(require("@testing-library/user-event"));
|
|
5
|
+
var matchMedia = _interopRequireWildcard(require("@theme-ui/match-media"));
|
|
4
6
|
var _jestAxe = require("jest-axe");
|
|
5
7
|
var _themeUi = require("theme-ui");
|
|
6
8
|
var _Breadcrumbs = require("./Breadcrumbs");
|
|
7
9
|
var _ = require("../");
|
|
8
10
|
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
11
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
|
|
12
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { "default": e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n["default"] = e, t && t.set(e, n), n; }
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
|
9
14
|
function _regeneratorRuntime() { "use strict"; /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */ _regeneratorRuntime = function _regeneratorRuntime() { return e; }; var t, e = {}, r = Object.prototype, n = r.hasOwnProperty, o = Object.defineProperty || function (t, e, r) { t[e] = r.value; }, i = "function" == typeof Symbol ? Symbol : {}, a = i.iterator || "@@iterator", c = i.asyncIterator || "@@asyncIterator", u = i.toStringTag || "@@toStringTag"; function define(t, e, r) { return Object.defineProperty(t, e, { value: r, enumerable: !0, configurable: !0, writable: !0 }), t[e]; } try { define({}, ""); } catch (t) { define = function define(t, e, r) { return t[e] = r; }; } function wrap(t, e, r, n) { var i = e && e.prototype instanceof Generator ? e : Generator, a = Object.create(i.prototype), c = new Context(n || []); return o(a, "_invoke", { value: makeInvokeMethod(t, r, c) }), a; } function tryCatch(t, e, r) { try { return { type: "normal", arg: t.call(e, r) }; } catch (t) { return { type: "throw", arg: t }; } } e.wrap = wrap; var h = "suspendedStart", l = "suspendedYield", f = "executing", s = "completed", y = {}; function Generator() {} function GeneratorFunction() {} function GeneratorFunctionPrototype() {} var p = {}; define(p, a, function () { return this; }); var d = Object.getPrototypeOf, v = d && d(d(values([]))); v && v !== r && n.call(v, a) && (p = v); var g = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(p); function defineIteratorMethods(t) { ["next", "throw", "return"].forEach(function (e) { define(t, e, function (t) { return this._invoke(e, t); }); }); } function AsyncIterator(t, e) { function invoke(r, o, i, a) { var c = tryCatch(t[r], t, o); if ("throw" !== c.type) { var u = c.arg, h = u.value; return h && "object" == typeof h && n.call(h, "__await") ? e.resolve(h.__await).then(function (t) { invoke("next", t, i, a); }, function (t) { invoke("throw", t, i, a); }) : e.resolve(h).then(function (t) { u.value = t, i(u); }, function (t) { return invoke("throw", t, i, a); }); } a(c.arg); } var r; o(this, "_invoke", { value: function value(t, n) { function callInvokeWithMethodAndArg() { return new e(function (e, r) { invoke(t, n, e, r); }); } return r = r ? r.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg(); } }); } function makeInvokeMethod(e, r, n) { var o = h; return function (i, a) { if (o === f) throw new Error("Generator is already running"); if (o === s) { if ("throw" === i) throw a; return { value: t, done: !0 }; } for (n.method = i, n.arg = a;;) { var c = n.delegate; if (c) { var u = maybeInvokeDelegate(c, n); if (u) { if (u === y) continue; return u; } } if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) { if (o === h) throw o = s, n.arg; n.dispatchException(n.arg); } else "return" === n.method && n.abrupt("return", n.arg); o = f; var p = tryCatch(e, r, n); if ("normal" === p.type) { if (o = n.done ? s : l, p.arg === y) continue; return { value: p.arg, done: n.done }; } "throw" === p.type && (o = s, n.method = "throw", n.arg = p.arg); } }; } function maybeInvokeDelegate(e, r) { var n = r.method, o = e.iterator[n]; if (o === t) return r.delegate = null, "throw" === n && e.iterator["return"] && (r.method = "return", r.arg = t, maybeInvokeDelegate(e, r), "throw" === r.method) || "return" !== n && (r.method = "throw", r.arg = new TypeError("The iterator does not provide a '" + n + "' method")), y; var i = tryCatch(o, e.iterator, r.arg); if ("throw" === i.type) return r.method = "throw", r.arg = i.arg, r.delegate = null, y; var a = i.arg; return a ? a.done ? (r[e.resultName] = a.value, r.next = e.nextLoc, "return" !== r.method && (r.method = "next", r.arg = t), r.delegate = null, y) : a : (r.method = "throw", r.arg = new TypeError("iterator result is not an object"), r.delegate = null, y); } function pushTryEntry(t) { var e = { tryLoc: t[0] }; 1 in t && (e.catchLoc = t[1]), 2 in t && (e.finallyLoc = t[2], e.afterLoc = t[3]), this.tryEntries.push(e); } function resetTryEntry(t) { var e = t.completion || {}; e.type = "normal", delete e.arg, t.completion = e; } function Context(t) { this.tryEntries = [{ tryLoc: "root" }], t.forEach(pushTryEntry, this), this.reset(!0); } function values(e) { if (e || "" === e) { var r = e[a]; if (r) return r.call(e); if ("function" == typeof e.next) return e; if (!isNaN(e.length)) { var o = -1, i = function next() { for (; ++o < e.length;) if (n.call(e, o)) return next.value = e[o], next.done = !1, next; return next.value = t, next.done = !0, next; }; return i.next = i; } } throw new TypeError(typeof e + " is not iterable"); } return GeneratorFunction.prototype = GeneratorFunctionPrototype, o(g, "constructor", { value: GeneratorFunctionPrototype, configurable: !0 }), o(GeneratorFunctionPrototype, "constructor", { value: GeneratorFunction, configurable: !0 }), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, u, "GeneratorFunction"), e.isGeneratorFunction = function (t) { var e = "function" == typeof t && t.constructor; return !!e && (e === GeneratorFunction || "GeneratorFunction" === (e.displayName || e.name)); }, e.mark = function (t) { return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, define(t, u, "GeneratorFunction")), t.prototype = Object.create(g), t; }, e.awrap = function (t) { return { __await: t }; }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, c, function () { return this; }), e.AsyncIterator = AsyncIterator, e.async = function (t, r, n, o, i) { void 0 === i && (i = Promise); var a = new AsyncIterator(wrap(t, r, n, o), i); return e.isGeneratorFunction(r) ? a : a.next().then(function (t) { return t.done ? t.value : a.next(); }); }, defineIteratorMethods(g), define(g, u, "Generator"), define(g, a, function () { return this; }), define(g, "toString", function () { return "[object Generator]"; }), e.keys = function (t) { var e = Object(t), r = []; for (var n in e) r.push(n); return r.reverse(), function next() { for (; r.length;) { var t = r.pop(); if (t in e) return next.value = t, next.done = !1, next; } return next.done = !0, next; }; }, e.values = values, Context.prototype = { constructor: Context, reset: function reset(e) { if (this.prev = 0, this.next = 0, this.sent = this._sent = t, this.done = !1, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(resetTryEntry), !e) for (var r in this) "t" === r.charAt(0) && n.call(this, r) && !isNaN(+r.slice(1)) && (this[r] = t); }, stop: function stop() { this.done = !0; var t = this.tryEntries[0].completion; if ("throw" === t.type) throw t.arg; return this.rval; }, dispatchException: function dispatchException(e) { if (this.done) throw e; var r = this; function handle(n, o) { return a.type = "throw", a.arg = e, r.next = n, o && (r.method = "next", r.arg = t), !!o; } for (var o = this.tryEntries.length - 1; o >= 0; --o) { var i = this.tryEntries[o], a = i.completion; if ("root" === i.tryLoc) return handle("end"); if (i.tryLoc <= this.prev) { var c = n.call(i, "catchLoc"), u = n.call(i, "finallyLoc"); if (c && u) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } else if (c) { if (this.prev < i.catchLoc) return handle(i.catchLoc, !0); } else { if (!u) throw new Error("try statement without catch or finally"); if (this.prev < i.finallyLoc) return handle(i.finallyLoc); } } } }, abrupt: function abrupt(t, e) { for (var r = this.tryEntries.length - 1; r >= 0; --r) { var o = this.tryEntries[r]; if (o.tryLoc <= this.prev && n.call(o, "finallyLoc") && this.prev < o.finallyLoc) { var i = o; break; } } i && ("break" === t || "continue" === t) && i.tryLoc <= e && e <= i.finallyLoc && (i = null); var a = i ? i.completion : {}; return a.type = t, a.arg = e, i ? (this.method = "next", this.next = i.finallyLoc, y) : this.complete(a); }, complete: function complete(t, e) { if ("throw" === t.type) throw t.arg; return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && e && (this.next = e), y; }, finish: function finish(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.finallyLoc === t) return this.complete(r.completion, r.afterLoc), resetTryEntry(r), y; } }, "catch": function _catch(t) { for (var e = this.tryEntries.length - 1; e >= 0; --e) { var r = this.tryEntries[e]; if (r.tryLoc === t) { var n = r.completion; if ("throw" === n.type) { var o = n.arg; resetTryEntry(r); } return o; } } throw new Error("illegal catch attempt"); }, delegateYield: function delegateYield(e, r, n) { return this.delegate = { iterator: values(e), resultName: r, nextLoc: n }, "next" === this.method && (this.arg = t), y; } }, e; }
|
|
10
15
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
11
16
|
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
12
17
|
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); } /** @jsxImportSource theme-ui */ /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck
|
|
18
|
+
jest.mock('@theme-ui/match-media');
|
|
19
|
+
var mockBreakpointIndex = matchMedia.useBreakpointIndex;
|
|
20
|
+
|
|
13
21
|
// eslint-disable-next-line jsx-a11y/anchor-has-content
|
|
14
22
|
var CustomLink = function CustomLink(props) {
|
|
15
23
|
return (0, _jsxRuntime.jsx)("a", _extends({}, props));
|
|
@@ -73,4 +81,68 @@ describe('<Breadcrumbs />', function () {
|
|
|
73
81
|
}
|
|
74
82
|
}, _callee);
|
|
75
83
|
})));
|
|
84
|
+
describe('wrapMode tests', function () {
|
|
85
|
+
beforeEach(function () {
|
|
86
|
+
mockBreakpointIndex.mockReset();
|
|
87
|
+
});
|
|
88
|
+
it('expands the breadcrumb items when clicking in the collapsible link', /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
|
|
89
|
+
var links, user, _renderWithTheme, container, navEl, pressToShowButton;
|
|
90
|
+
return _regeneratorRuntime().wrap(function _callee2$(_context2) {
|
|
91
|
+
while (1) switch (_context2.prev = _context2.next) {
|
|
92
|
+
case 0:
|
|
93
|
+
mockBreakpointIndex.mockReturnValue(0);
|
|
94
|
+
links = [{
|
|
95
|
+
label: 'Home',
|
|
96
|
+
href: '/'
|
|
97
|
+
}, {
|
|
98
|
+
label: 'Applications',
|
|
99
|
+
href: '/apps'
|
|
100
|
+
}, {
|
|
101
|
+
label: 'Applications 3',
|
|
102
|
+
href: '/apps/3'
|
|
103
|
+
}, {
|
|
104
|
+
label: 'Applications 4',
|
|
105
|
+
href: '/apps/4'
|
|
106
|
+
}, {
|
|
107
|
+
label: 'The last'
|
|
108
|
+
}];
|
|
109
|
+
user = _userEvent["default"].setup();
|
|
110
|
+
_renderWithTheme = renderWithTheme((0, _jsxRuntime.jsx)(_Breadcrumbs.Breadcrumbs, {
|
|
111
|
+
wrapMode: "collapsible",
|
|
112
|
+
label: "Main Collapsible Breadcrumb",
|
|
113
|
+
LinkComponent: CustomLink,
|
|
114
|
+
links: links
|
|
115
|
+
})), container = _renderWithTheme.container; // Should find the nav label
|
|
116
|
+
navEl = _react.screen.getByLabelText('Main Collapsible Breadcrumb');
|
|
117
|
+
expect(navEl).toBeInTheDocument();
|
|
118
|
+
|
|
119
|
+
// Contract should have
|
|
120
|
+
expect(navEl.querySelectorAll('li')).toHaveLength(3);
|
|
121
|
+
pressToShowButton = _react.screen.getByRole('button', {
|
|
122
|
+
name: 'Press to show more breadcrumbs'
|
|
123
|
+
}); // Should find all links
|
|
124
|
+
expect(_react.screen.getByText('Home')).toBeInTheDocument();
|
|
125
|
+
expect(pressToShowButton).toBeInTheDocument();
|
|
126
|
+
expect(_react.screen.getByText('The last')).toHaveAttribute('aria-current', 'page');
|
|
127
|
+
|
|
128
|
+
// Click to expand the breadcrumbs
|
|
129
|
+
_context2.next = 13;
|
|
130
|
+
return user.click(pressToShowButton);
|
|
131
|
+
case 13:
|
|
132
|
+
expect(navEl.querySelectorAll('li')).toHaveLength(5);
|
|
133
|
+
|
|
134
|
+
// Check for accessibility issues
|
|
135
|
+
_context2.t0 = expect;
|
|
136
|
+
_context2.next = 17;
|
|
137
|
+
return (0, _jestAxe.axe)(container);
|
|
138
|
+
case 17:
|
|
139
|
+
_context2.t1 = _context2.sent;
|
|
140
|
+
(0, _context2.t0)(_context2.t1).toHaveNoViolations();
|
|
141
|
+
case 19:
|
|
142
|
+
case "end":
|
|
143
|
+
return _context2.stop();
|
|
144
|
+
}
|
|
145
|
+
}, _callee2);
|
|
146
|
+
})));
|
|
147
|
+
});
|
|
76
148
|
});
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ThemeUIStyleObject } from 'theme-ui';
|
|
1
2
|
export declare const smallestScreenItemStyles: {
|
|
2
3
|
'&::before': {
|
|
3
4
|
display: string;
|
|
@@ -10,3 +11,4 @@ export declare const smallestScreenItemStyles: {
|
|
|
10
11
|
content: string;
|
|
11
12
|
};
|
|
12
13
|
};
|
|
14
|
+
export declare const collapsibleSeparatorStyles: ThemeUIStyleObject;
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.smallestScreenItemStyles = void 0;
|
|
4
|
+
exports.smallestScreenItemStyles = exports.collapsibleSeparatorStyles = void 0;
|
|
5
|
+
var _Link = require("../Link/Link");
|
|
6
|
+
var _breadcrumbs = require("../Nav/styles/variants/breadcrumbs");
|
|
7
|
+
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); }
|
|
5
8
|
var smallestScreenItemStyles = exports.smallestScreenItemStyles = {
|
|
6
9
|
'&::before': {
|
|
7
10
|
display: 'inline-block',
|
|
@@ -13,4 +16,7 @@ var smallestScreenItemStyles = exports.smallestScreenItemStyles = {
|
|
|
13
16
|
height: '0.8em',
|
|
14
17
|
content: "'←'"
|
|
15
18
|
}
|
|
16
|
-
};
|
|
19
|
+
};
|
|
20
|
+
var collapsibleSeparatorStyles = exports.collapsibleSeparatorStyles = _extends({
|
|
21
|
+
all: 'unset'
|
|
22
|
+
}, _breadcrumbs.breadcrumbsLinkStyles, _Link.linkUnderlineProperties);
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { LinkProps as ThemeLinkProps, ThemeUIStyleObject } from 'theme-ui';
|
|
3
|
+
export declare enum LinkVariant {
|
|
4
|
+
'primary' = 0,
|
|
5
|
+
'button-primary' = 1,
|
|
6
|
+
'button-secondary' = 2,
|
|
7
|
+
'button-tertiary' = 3,
|
|
8
|
+
'button-ghost' = 4,
|
|
9
|
+
'button-display' = 5,
|
|
10
|
+
'button-danger' = 6
|
|
11
|
+
}
|
|
3
12
|
export interface LinkProps extends ThemeLinkProps {
|
|
4
|
-
variant?:
|
|
13
|
+
variant?: keyof typeof LinkVariant;
|
|
5
14
|
}
|
|
15
|
+
export declare const linkUnderlineProperties: ThemeUIStyleObject;
|
|
6
16
|
export declare const defaultLinkComponentStyle: ThemeUIStyleObject;
|
|
7
17
|
export declare const Link: import("react").ForwardRefExoticComponent<Omit<LinkProps, "ref"> & import("react").RefAttributes<HTMLAnchorElement>>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.defaultLinkComponentStyle = exports.Link = void 0;
|
|
4
|
+
exports.linkUnderlineProperties = exports.defaultLinkComponentStyle = exports.LinkVariant = exports.Link = void 0;
|
|
5
5
|
var _react = require("react");
|
|
6
6
|
var _themeUi = require("theme-ui");
|
|
7
7
|
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
@@ -12,6 +12,21 @@ var _excluded = ["variant", "sx"];
|
|
|
12
12
|
// Temporary interface until we add types to the theme definition.
|
|
13
13
|
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); }
|
|
14
14
|
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; }
|
|
15
|
+
var LinkVariant = exports.LinkVariant = /*#__PURE__*/function (LinkVariant) {
|
|
16
|
+
LinkVariant[LinkVariant["primary"] = 0] = "primary";
|
|
17
|
+
LinkVariant[LinkVariant["button-primary"] = 1] = "button-primary";
|
|
18
|
+
LinkVariant[LinkVariant["button-secondary"] = 2] = "button-secondary";
|
|
19
|
+
LinkVariant[LinkVariant["button-tertiary"] = 3] = "button-tertiary";
|
|
20
|
+
LinkVariant[LinkVariant["button-ghost"] = 4] = "button-ghost";
|
|
21
|
+
LinkVariant[LinkVariant["button-display"] = 5] = "button-display";
|
|
22
|
+
LinkVariant[LinkVariant["button-danger"] = 6] = "button-danger";
|
|
23
|
+
return LinkVariant;
|
|
24
|
+
}({});
|
|
25
|
+
var linkUnderlineProperties = exports.linkUnderlineProperties = {
|
|
26
|
+
textDecorationLine: 'underline',
|
|
27
|
+
textDecorationThickness: '0.07rem',
|
|
28
|
+
textUnderlineOffset: '0.250rem'
|
|
29
|
+
};
|
|
15
30
|
var defaultLinkComponentStyle = exports.defaultLinkComponentStyle = {
|
|
16
31
|
'&:focus-visible': function focusVisible(theme) {
|
|
17
32
|
return theme.outline;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* External dependencies
|
|
4
4
|
*/
|
|
5
|
-
import { Link } from '
|
|
5
|
+
import { Link, LinkVariant } from './Link';
|
|
6
6
|
import type { LinkProps } from './Link';
|
|
7
7
|
import type { StoryObj } from '@storybook/react';
|
|
8
8
|
/**
|
|
@@ -11,6 +11,19 @@ import type { StoryObj } from '@storybook/react';
|
|
|
11
11
|
declare const _default: {
|
|
12
12
|
title: string;
|
|
13
13
|
component: import("react").ForwardRefExoticComponent<Omit<LinkProps, "ref"> & import("react").RefAttributes<HTMLAnchorElement>>;
|
|
14
|
+
argTypes: {
|
|
15
|
+
variant: {
|
|
16
|
+
type: string;
|
|
17
|
+
options: (string | LinkVariant)[];
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
parameters: {
|
|
21
|
+
docs: {
|
|
22
|
+
description: {
|
|
23
|
+
component: string;
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
};
|
|
14
27
|
};
|
|
15
28
|
export default _default;
|
|
16
29
|
type Story = StoryObj<typeof Link>;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
4
|
exports["default"] = exports.Default = exports.ButtonVariants = void 0;
|
|
5
|
-
var
|
|
5
|
+
var _Link = require("./Link");
|
|
6
6
|
var _Flex = require("../Flex/Flex");
|
|
7
7
|
var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
8
8
|
/**
|
|
@@ -13,7 +13,20 @@ var _jsxRuntime = require("theme-ui/jsx-runtime");
|
|
|
13
13
|
*/
|
|
14
14
|
var _default = exports["default"] = {
|
|
15
15
|
title: 'Navigation/Link',
|
|
16
|
-
component:
|
|
16
|
+
component: _Link.Link,
|
|
17
|
+
argTypes: {
|
|
18
|
+
variant: {
|
|
19
|
+
type: 'select',
|
|
20
|
+
options: Object.values(_Link.LinkVariant)
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component: "\n\nLinks are navigational elements that direct visitors to other locations, either on the same page or to a different page or site. They can be inline or separate from the text flow. Since every link is a potential user interaction, too many links can be overwhelming.\n\n## Guidance\n\n### When to use the link component\n\n- When you want to direct users to another page or site.\n- When you want to direct users to another section of the same page (anchors).\n\n### When to consider something else\n\n- When you want to trigger an action (use a button instead).\n- When you want to display a message (use a notification instead).\n\n### Accessibility\n\n- Don\u2019t rely on only color to distinguish links\n- Don\u2019t block external links with disruptive notifications\n- Icons can be helpful. Consider adding an icon to signal specific actions (Download, Open in a new window, etc).\n- Don\u2019t use the same link text for different URLs on the same page. This can confuse users and make it difficult for them to understand where the link will take them.\n\n-------\n\nThis documentation is heavily inspired by the [U.S Web Design System (USWDS)](https://designsystem.digital.gov/components/link/). We use USWDS as trusted source of truth for accessibility and usability best practices.\n\n## Component Properties\n"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
17
30
|
};
|
|
18
31
|
var Default = exports.Default = {
|
|
19
32
|
args: {
|
|
@@ -28,7 +41,7 @@ var ButtonVariants = exports.ButtonVariants = function ButtonVariants() {
|
|
|
28
41
|
gap: 2
|
|
29
42
|
},
|
|
30
43
|
children: buttonTypes.map(function (variant, index) {
|
|
31
|
-
return (0, _jsxRuntime.jsx)(
|
|
44
|
+
return (0, _jsxRuntime.jsx)(_Link.Link, {
|
|
32
45
|
href: "#!",
|
|
33
46
|
variant: variant,
|
|
34
47
|
children: "Hello"
|
|
@@ -98,6 +98,7 @@ var MobileMenuTrigger = exports.MobileMenuTrigger = function MobileMenuTrigger(_
|
|
|
98
98
|
sx: {
|
|
99
99
|
display: display,
|
|
100
100
|
alignItems: 'center',
|
|
101
|
+
flexShrink: 0,
|
|
101
102
|
color: variant === 'inverse' ? 'button.primary.label.default' : 'button.tertiary.label.default',
|
|
102
103
|
width: 38,
|
|
103
104
|
height: 38,
|
|
@@ -121,6 +121,7 @@ var navMenuListStyles = exports.navMenuListStyles = function navMenuListStyles(o
|
|
|
121
121
|
height: '100%',
|
|
122
122
|
gap: 1,
|
|
123
123
|
px: 0,
|
|
124
|
-
flexDirection: orientation === 'horizontal' ? 'row' : 'column'
|
|
124
|
+
flexDirection: orientation === 'horizontal' ? 'row' : 'column',
|
|
125
|
+
flexWrap: orientation === 'horizontal' ? 'wrap' : undefined
|
|
125
126
|
};
|
|
126
127
|
};
|
|
@@ -4,7 +4,10 @@ exports.__esModule = true;
|
|
|
4
4
|
exports.generateBreakpoints = void 0;
|
|
5
5
|
var generateBreakpoints = exports.generateBreakpoints = function generateBreakpoints(breakpoints) {
|
|
6
6
|
var values = Object.values(breakpoints);
|
|
7
|
-
return values.map(function (bp) {
|
|
7
|
+
return values.map(function (bp, index) {
|
|
8
|
+
if (index === 0) {
|
|
9
|
+
return "0px";
|
|
10
|
+
}
|
|
8
11
|
return bp + "px";
|
|
9
12
|
});
|
|
10
13
|
};
|