@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.
Files changed (32) hide show
  1. package/build/system/Breadcrumbs/Breadcrumbs.d.ts +1 -0
  2. package/build/system/Breadcrumbs/Breadcrumbs.js +75 -20
  3. package/build/system/Breadcrumbs/Breadcrumbs.stories.d.ts +2 -0
  4. package/build/system/Breadcrumbs/Breadcrumbs.stories.js +47 -7
  5. package/build/system/Breadcrumbs/Breadcrumbs.test.js +72 -0
  6. package/build/system/Breadcrumbs/styles.d.ts +2 -0
  7. package/build/system/Breadcrumbs/styles.js +8 -2
  8. package/build/system/Link/Link.d.ts +11 -1
  9. package/build/system/Link/Link.js +16 -1
  10. package/build/system/Link/Link.stories.d.ts +14 -1
  11. package/build/system/Link/Link.stories.js +16 -3
  12. package/build/system/MobileMenu/MobileMenu.js +1 -0
  13. package/build/system/Nav/styles.js +2 -1
  14. package/build/system/Toolbar/Logo.js +1 -1
  15. package/build/system/theme/breakpoints.js +4 -1
  16. package/build/system/theme/index.d.ts +863 -3
  17. package/build/system/theme/index.js +5 -6
  18. package/build/system/utils/stories/CustomLink.d.ts +1 -0
  19. package/build/system/utils/stories/CustomLink.js +7 -1
  20. package/package.json +1 -1
  21. package/src/system/Breadcrumbs/Breadcrumbs.stories.tsx +32 -3
  22. package/src/system/Breadcrumbs/Breadcrumbs.test.tsx +60 -0
  23. package/src/system/Breadcrumbs/Breadcrumbs.tsx +100 -29
  24. package/src/system/Breadcrumbs/styles.ts +11 -0
  25. package/src/system/Link/Link.stories.tsx +42 -1
  26. package/src/system/Link/Link.tsx +17 -8
  27. package/src/system/MobileMenu/MobileMenu.tsx +1 -0
  28. package/src/system/Nav/styles.ts +1 -0
  29. package/src/system/Toolbar/Logo.tsx +1 -1
  30. package/src/system/theme/breakpoints.ts +7 -1
  31. package/src/system/theme/index.js +5 -6
  32. 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
- var penultimateLink = null;
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
- if (totalLinks === 1) {
40
- lastLink = links == null ? void 0 : links[0];
41
- otherLinks = [];
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: (_lastLink = lastLink) == null ? void 0 : _lastLink.label
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
- 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); }
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?: 'primary' | 'button-primary' | 'button-secondary' | 'button-tertiary' | 'button-ghost' | 'button-display' | 'button-danger';
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 _ = require("..");
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: _.Link
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)(_.Link, {
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
  };
@@ -25,7 +25,7 @@ var Logo = exports.Logo = function Logo(_ref) {
25
25
  sx: {
26
26
  width: 54,
27
27
  color: 'toolbar.brand',
28
- mr: 5,
28
+ flexShrink: 0,
29
29
  display: 'inline-block'
30
30
  },
31
31
  href: href,
@@ -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
  };