@ably/ui 7.10.0-dev.e980a00 → 8.0.0-dev.27cfcb9

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 (35) hide show
  1. package/core/Meganav/component.js +1 -1
  2. package/core/Meganav.jsx +8463 -6601
  3. package/core/MeganavContentPlatform.jsx +27 -20
  4. package/core/MeganavControlMobileDropdown/component.js +1 -1
  5. package/core/MeganavItemsMobile.jsx +7 -6
  6. package/core/MeganavItemsSignedIn.jsx +10 -9
  7. package/core/MeganavSearch.jsx +10 -9
  8. package/core/MeganavSearchAutocomplete/component.js +1 -1
  9. package/core/MeganavSearchPanel.jsx +8 -7
  10. package/core/MeganavSearchSuggestions/component.js +1 -1
  11. package/core/MeganavSearchSuggestions.jsx +6 -6
  12. package/core/fonts/source-code-pro.css +3 -0
  13. package/core/styles.css +17 -22
  14. package/package.json +2 -2
  15. package/src/core/Code/component.css +1 -3
  16. package/src/core/Meganav/component.js +8 -2
  17. package/src/core/Meganav/component.jsx +3 -2
  18. package/src/core/MeganavContentPlatform/component.html.erb +24 -18
  19. package/src/core/MeganavContentPlatform/component.jsx +25 -20
  20. package/src/core/MeganavControlMobileDropdown/component.js +0 -31
  21. package/src/core/MeganavItemsMobile/component.html.erb +1 -0
  22. package/src/core/MeganavItemsMobile/component.jsx +1 -0
  23. package/src/core/MeganavItemsSignedIn/component.html.erb +2 -2
  24. package/src/core/MeganavSearch/component.html.erb +2 -2
  25. package/src/core/MeganavSearch/component.jsx +2 -2
  26. package/src/core/MeganavSearchAutocomplete/component.js +18 -10
  27. package/src/core/MeganavSearchPanel/component.html.erb +4 -4
  28. package/src/core/MeganavSearchPanel/component.jsx +2 -2
  29. package/src/core/MeganavSearchSuggestions/component.html.erb +6 -6
  30. package/src/core/MeganavSearchSuggestions/component.js +123 -0
  31. package/src/core/MeganavSearchSuggestions/component.jsx +6 -6
  32. package/src/core/fonts/source-code-pro.css +3 -0
  33. package/src/core/styles/properties.css +4 -3
  34. package/src/core/styles/text.css +12 -16
  35. package/tailwind.config.js +12 -4
@@ -161,29 +161,29 @@ var MeganavSearchSuggestions = function MeganavSearchSuggestions(_ref) {
161
161
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", {
162
162
  className: "ui-text-overline2 text-cool-black py-12"
163
163
  }, "Popular pages"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
164
- className: "flex justify-between items-center overflow-x-scroll md:overflow-auto"
164
+ className: "flex justify-between items-center overflow-hidden"
165
165
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("ul", {
166
- className: "flex"
166
+ className: "flex transition-transform"
167
167
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
168
168
  className: "py-12 pr-8 flex-shrink-0"
169
169
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
170
170
  href: absUrl("/docs/how-ably-works"),
171
- className: "ui-text-p2"
171
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
172
172
  }, "How does Ably work?")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
173
173
  className: "py-12 px-8 flex-shrink-0"
174
174
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
175
175
  href: absUrl("/docs/quick-start-guide"),
176
- className: "ui-text-p2"
176
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
177
177
  }, "Quickstart guide")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
178
178
  className: "py-12 px-8 flex-shrink-0"
179
179
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
180
180
  href: absUrl("/docs/core-features/pubsub"),
181
- className: "ui-text-p2"
181
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
182
182
  }, "Publish/Subscribe Messaging")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
183
183
  className: "py-12 pl-8 flex-shrink-0"
184
184
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
185
185
  href: absUrl("/platform"),
186
- className: "ui-text-p2"
186
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
187
187
  }, "Platform"))), displaySupportLink ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_FeaturedLink_component_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
188
188
  url: absUrl("/support"),
189
189
  textSize: "text-p2"
@@ -430,10 +430,11 @@ var MeganavSearchPanel = function MeganavSearchPanel(_ref) {
430
430
  name: "q",
431
431
  className: "ui-input pl-48 h-48",
432
432
  placeholder: "Search",
433
+ autoComplete: "off",
433
434
  "data-id": "meganav-search-input"
434
435
  }), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MeganavSearchAutocomplete_component_jsx__WEBPACK_IMPORTED_MODULE_4__.default, null)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", {
435
436
  type: "submit",
436
- className: "ui-btn-secondary ml-8 sm:ml-16 md:ml-24 xl:ml-32"
437
+ className: "ui-btn-secondary flex-shrink-0 ml-8 sm:ml-16 md:ml-24 xl:ml-32"
437
438
  }, "Search")))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
438
439
  className: "col-span-12"
439
440
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MeganavSearchSuggestions_component_jsx__WEBPACK_IMPORTED_MODULE_3__.default, {
@@ -1 +1 @@
1
- !function(e,o){"object"==typeof exports&&"object"==typeof module?module.exports=o():"function"==typeof define&&define.amd?define([],o):"object"==typeof exports?exports.AblyUi=o():(e.AblyUi=e.AblyUi||{},e.AblyUi.Core=e.AblyUi.Core||{},e.AblyUi.Core.MeganavSearchSuggestions=o())}(this,(function(){return{}.default}));
1
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.AblyUi=t():(e.AblyUi=e.AblyUi||{},e.AblyUi.Core=e.AblyUi.Core||{},e.AblyUi.Core.MeganavSearchSuggestions=t())}(this,(function(){return(()=>{"use strict";var e={9581:(e,t,n)=>{n.d(t,{A:()=>r});var r=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document;return t.querySelector("[data-id=".concat(e,"]"))}}},t={};function n(r){var o=t[r];if(void 0!==o)return o.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,n),i.exports}n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{n.d(r,{default:()=>s});var e=n(9581),t=function(e){return new DOMMatrix(window.getComputedStyle(e).transform).e},o=function(e,t){return e.style.transform="translateX(".concat(t,"px)")},i=function(e,t){return e>=t},u=function(e,t,n,r){return Math.abs(e-n+r)>t},a=function(e,t){var n;return(null===(n=e.changedTouches[0])||void 0===n?void 0:n.clientX)-t},c=function(e){return Math.abs(e)<5};const s=function(){var n,r=(0,e.A)("meganav-mobile-search-input"),s=(0,e.A)("meganav-mobile-search-suggestions"),d=s.querySelector("ul"),l=d.querySelectorAll("li"),v=Array.from(l).map((function(e){return e.getBoundingClientRect().width})).reduce((function(e,t){return e+t}),0),f=function(e){var t;n=null===(t=e.touches[0])||void 0===t?void 0:t.clientX},h=function(e){var r=a(e,n);c(r)||(r>0?function(e,n){var r=t(d),u=Math.round(r+e);i(u,24)||o(d,u)}(r):function(e,n){var r=d.getBoundingClientRect().width,i=t(d),a=Math.round(i+e);u(a,v,r,96)||o(d,a)}(r))},m=function(e){var r=a(e,n);c(r)||(r>0?function(e,n){var r=t(d),u=Math.round(r+e);i(u,24)&&(u=0),o(d,u)}(r):function(e,n){var r=d.getBoundingClientRect().width,i=t(d),a=Math.round(i+e);u(a,v,r,48)&&(a=-(v-r+48)),o(d,a)}(r))},p=function(){s.classList.add("max-h-96")},y=function(e){e.relatedTarget!==s.querySelectorAll("a")[0]&&s.classList.remove("max-h-96")};return r.addEventListener("focus",p),r.addEventListener("blur",y),s.addEventListener("touchstart",f),s.addEventListener("touchmove",h),s.addEventListener("touchend",m),{teardown:function(){r.removeEventListener("focus",p),r.removeEventListener("blur",y),s.removeEventListener("touchstart",f),s.removeEventListener("touchmove",h),s.removeEventListener("touchend",m)},clear:function(){s.classList.remove("max-h-96"),d.style.transform="translateX(0px)"}}}})(),r.default})()}));
@@ -324,29 +324,29 @@ var MeganavSearchSuggestions = function MeganavSearchSuggestions(_ref) {
324
324
  return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement((react__WEBPACK_IMPORTED_MODULE_0___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("p", {
325
325
  className: "ui-text-overline2 text-cool-black py-12"
326
326
  }, "Popular pages"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
327
- className: "flex justify-between items-center overflow-x-scroll md:overflow-auto"
327
+ className: "flex justify-between items-center overflow-hidden"
328
328
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("ul", {
329
- className: "flex"
329
+ className: "flex transition-transform"
330
330
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
331
331
  className: "py-12 pr-8 flex-shrink-0"
332
332
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
333
333
  href: absUrl("/docs/how-ably-works"),
334
- className: "ui-text-p2"
334
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
335
335
  }, "How does Ably work?")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
336
336
  className: "py-12 px-8 flex-shrink-0"
337
337
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
338
338
  href: absUrl("/docs/quick-start-guide"),
339
- className: "ui-text-p2"
339
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
340
340
  }, "Quickstart guide")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
341
341
  className: "py-12 px-8 flex-shrink-0"
342
342
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
343
343
  href: absUrl("/docs/core-features/pubsub"),
344
- className: "ui-text-p2"
344
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
345
345
  }, "Publish/Subscribe Messaging")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("li", {
346
346
  className: "py-12 pl-8 flex-shrink-0"
347
347
  }, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("a", {
348
348
  href: absUrl("/platform"),
349
- className: "ui-text-p2"
349
+ className: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus"
350
350
  }, "Platform"))), displaySupportLink ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_FeaturedLink_component_jsx__WEBPACK_IMPORTED_MODULE_2__.default, {
351
351
  url: absUrl("/support"),
352
352
  textSize: "text-p2"
@@ -0,0 +1,3 @@
1
+ @layer base {
2
+ @import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@600&display=swap");
3
+ }
package/core/styles.css CHANGED
@@ -15,9 +15,10 @@
15
15
  --color-charcoal-grey: #292831;
16
16
  --color-gui-default: #0073e6;
17
17
  --color-gui-hover: #0867c4;
18
- --color-gui-focus: #80b9f2;
18
+ --color-gui-focus: #0073e6;
19
+ --color-gui-focus-outline: #80b9f2;
19
20
  --color-gui-active: #074095;
20
- --color-gui-viewed: #4887c2;
21
+ --color-gui-visited: #4887c2;
21
22
  --color-gui-unavailable: #a8a8a8;
22
23
  --color-gui-error: #fb0c0c;
23
24
  --color-gui-success: #11cb24;
@@ -157,7 +158,7 @@
157
158
  /* In components, when looking at implementing viewport margin and spacing between elements,
158
159
  the values in the comments can be used as guide as they represent the grid the elements (should) sit on.
159
160
  alternatively, look for ui-grid-* helpers. */
160
- --bp-xs: 375px; /* gutters 8px, side-margin 24px */
161
+ --bp-xs: 428px; /* gutters 8px, side-margin 24px */
161
162
  --bp-sm: 768px; /* gutters 16px, side-margin 32px */
162
163
  --bp-md: 1040px; /* gutters 24px, side-margin 40px, meganav desktop */
163
164
  --bp-lg: 1280px; /* gutters 24px, side-margin 64px */
@@ -345,17 +346,17 @@
345
346
  }
346
347
 
347
348
  .ui-text-p1 {
348
- @apply font-sans font-light text-cool-black;
349
+ @apply font-sans font-light text-charcoal-grey;
349
350
  @apply text-p1;
350
351
  }
351
352
 
352
353
  .ui-text-p2 {
353
- @apply font-sans font-light text-cool-black;
354
+ @apply font-sans font-light text-charcoal-grey;
354
355
  @apply text-p2;
355
356
  }
356
357
 
357
358
  .ui-text-p3 {
358
- @apply font-sans font-light text-cool-black;
359
+ @apply font-sans font-light text-charcoal-grey;
359
360
  @apply text-p3;
360
361
  }
361
362
 
@@ -461,24 +462,18 @@
461
462
  @apply list-square;
462
463
  }
463
464
 
464
- /* visited needs to come before :hover et all else it overrides them */
465
- .ui-link:visited {
466
- @apply text-gui-viewed;
465
+ .ui-link {
466
+ @apply visited:text-gui-visited;
467
+ @apply hover:text-gui-hover active:text-gui-active disabled:text-gui-unavailable;
468
+ @apply focus:text-gui-focus focus:outline-gui-focus;
469
+ @apply underline;
467
470
  }
468
471
 
469
- .ui-link {
470
- @apply hover:text-active-orange active:text-red-orange;
471
- -webkit-text-decoration-color: var(--color-active-orange);
472
- text-decoration-color: var(--color-active-orange);
473
- text-underline-offset: 4px; /* px used here as behaves weird with rem's */
474
- -webkit-text-decoration-line: underline;
475
- text-decoration-line: underline;
476
- text-decoration-thickness: 0.125rem;
477
- }
478
-
479
- .ui-link:focus {
480
- @apply focus:text-white focus:bg-active-orange focus:outline-none;
481
- text-decoration: none;
472
+ .ui-link-neutral {
473
+ @apply visited:text-dark-grey;
474
+ @apply hover:text-dark-grey active:text-cool-black disabled:text-gui-unavailable;
475
+ @apply focus:text-gui-focus focus:outline-gui-focus-neutral;
476
+ @apply underline;
482
477
  }
483
478
  }
484
479
  @layer components {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ably/ui",
3
- "version": "7.10.0-dev.e980a00",
3
+ "version": "8.0.0-dev.27cfcb9",
4
4
  "description": "Home of the Ably design system library ([design.ably.com](https://design.ably.com)). It provides a showcase, development/test environment and a publishing pipeline for different distributables.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -65,7 +65,7 @@
65
65
  "release": "./scripts/release.sh"
66
66
  },
67
67
  "dependencies": {
68
- "addsearch-js-client": "^0.6.7",
68
+ "addsearch-js-client": "^0.7.0",
69
69
  "array-flat-polyfill": "^1.0.1",
70
70
  "deepmerge": "^4.2.2",
71
71
  "dompurify": "^2.2.9",
@@ -1,6 +1,4 @@
1
- @layer base {
2
- @import url("https://fonts.googleapis.com/css2?family=Source+Code+Pro:wght@600&display=swap");
3
- }
1
+ @import "../fonts/source-code-pro.css";
4
2
 
5
3
  @layer components {
6
4
  .hljs {
@@ -18,6 +18,7 @@ import MeganavControlMobileDropdown from "../MeganavControlMobileDropdown/compon
18
18
  import MobilePanelOpenClick from "../MeganavControlMobilePanelOpen/component";
19
19
  import MobilePanelCloseClick from "../MeganavControlMobilePanelClose/component";
20
20
  import MeganavSearchAutocomplete from "../MeganavSearchAutocomplete/component";
21
+ import MeganavSearchSuggestions from "../MeganavSearchSuggestions/component";
21
22
 
22
23
  // Close menu when user clicks outside of viewport
23
24
  const windowOnBlur = (closeAll) => {
@@ -112,11 +113,14 @@ const documentScroll = (themeName) => {
112
113
  };
113
114
  };
114
115
 
115
- export default function Meganav({ themeName } = { themeName: null }) {
116
+ export default function Meganav(
117
+ { themeName, addSearchApiKey } = { themeName: null }
118
+ ) {
116
119
  const controls = MeganavControl();
117
120
  const panelOpenControls = MobilePanelOpenClick();
118
121
  const panelCloseControls = MobilePanelCloseClick();
119
- const search = MeganavSearchAutocomplete();
122
+ const search = MeganavSearchAutocomplete(addSearchApiKey);
123
+ const searchSuggestions = MeganavSearchSuggestions();
120
124
 
121
125
  const mobileDropdownControl = MeganavControlMobileDropdown({
122
126
  clearPanels: () =>
@@ -126,6 +130,7 @@ export default function Meganav({ themeName } = { themeName: null }) {
126
130
  const closeAll = () =>
127
131
  [
128
132
  mobileDropdownControl,
133
+ searchSuggestions,
129
134
  ...panelOpenControls,
130
135
  ...panelCloseControls,
131
136
  ...controls,
@@ -137,6 +142,7 @@ export default function Meganav({ themeName } = { themeName: null }) {
137
142
  documentClick(closeAll),
138
143
  windowOnBlur(closeAll),
139
144
  mobileDropdownControl,
145
+ searchSuggestions,
140
146
  ...controls,
141
147
  ...panelOpenControls,
142
148
  ...panelCloseControls,
@@ -64,7 +64,7 @@ const panels = {
64
64
  MeganavContentDevelopers: MeganavContentDevelopers,
65
65
  };
66
66
 
67
- export default function Meganav({ paths, themeName = "white", notice, loginLink = "/login", urlBase }) {
67
+ export default function Meganav({ paths, themeName = "white", notice, loginLink = "/login", urlBase, addSearchApiKey }) {
68
68
  const [sessionState, setSessionState] = useState(null);
69
69
 
70
70
  useEffect(() => {
@@ -74,7 +74,7 @@ export default function Meganav({ paths, themeName = "white", notice, loginLink
74
74
  }, []);
75
75
 
76
76
  useEffect(() => {
77
- const teardown = MeganavScripts({ themeName });
77
+ const teardown = MeganavScripts({ themeName, addSearchApiKey });
78
78
  return () => teardown();
79
79
  }, [sessionState]);
80
80
 
@@ -119,4 +119,5 @@ Meganav.propTypes = {
119
119
  }),
120
120
  loginLink: T.string,
121
121
  urlBase: T.string,
122
+ addSearchApiKey: T.string,
122
123
  };
@@ -14,41 +14,47 @@
14
14
  </div>
15
15
 
16
16
  <div>
17
- <h3 class="ui-meganav-overline" id="meganav-platform-panel-list-our-features">Our features</h3>
18
- <ul aria-labelledby="meganav-platform-panel-list-our-features">
17
+ <h3 class="ui-meganav-overline" id="meganav-platform-panel-list-examples">Examples</h3>
18
+ <ul aria-labelledby="meganav-platform-panel-list-examples">
19
19
  <li>
20
- <%= link_to abs_url("/pub-sub-messaging"), class: "ui-meganav-media group" do %>
21
- <p class="ui-meganav-media-heading">Publish/subscribe messaging</p>
22
- <p class="ui-meganav-media-copy">Feature-rich pub/sub messaging to power any realtime requirement.</p>
20
+ <%= link_to abs_url("/topic/avatar-stack"), class: "ui-meganav-media group" do %>
21
+ <p class="ui-meganav-media-heading">Avatar Stack</p>
22
+ <p class="ui-meganav-media-copy">See who is connected in a digital space.</p>
23
23
  <% end %>
24
24
  </li>
25
25
  <li>
26
- <%= link_to abs_url("/push-notifications"), class: "ui-meganav-media group" do %>
27
- <p class="ui-meganav-media-heading">Push notifications</p>
28
- <p class="ui-meganav-media-copy">Deliver native notifications at scale with our unified API.</p>
26
+ <%= link_to abs_url("/topic/emoji-reactions"), class: "ui-meganav-media group" do %>
27
+ <p class="ui-meganav-media-heading">Emoji Reactions</p>
28
+ <p class="ui-meganav-media-copy">React with an emoji to a message.</p>
29
29
  <% end %>
30
30
  </li>
31
31
  <li>
32
- <%= link_to abs_url("/integrations"), class: "ui-meganav-media group" do %>
33
- <p class="ui-meganav-media-heading">Third-party integrations</p>
34
- <p class="ui-meganav-media-copy">Integrate and extend Ably with cloud services like AWS Kinesis.</p>
32
+ <%= link_to abs_url("/topic/activity-feed"), class: "ui-meganav-media group" do %>
33
+ <p class="ui-meganav-media-heading">Activity Feed</p>
34
+ <p class="ui-meganav-media-copy">Display a list of user actions in realtime.</p>
35
35
  <% end %>
36
36
  </li>
37
37
  <li>
38
- <%= link_to abs_url("/protocols"), class: "ui-meganav-media group" do %>
39
- <p class="ui-meganav-media-heading">Multi-protocol messaging</p>
40
- <p class="ui-meganav-media-copy">We support pub/sub over WebSockets, MQTT, SSE, and more.</p>
38
+ <%= link_to abs_url("/topic/live-charts"), class: "ui-meganav-media group" do %>
39
+ <p class="ui-meganav-media-heading">Live Charts</p>
40
+ <p class="ui-meganav-media-copy">Visualise live metrics and data in a chart.</p>
41
41
  <% end %>
42
42
  </li>
43
43
  <li>
44
- <%= link_to abs_url("/hub"), class: "ui-meganav-media group" do %>
45
- <p class="ui-meganav-media-heading">Streaming data sources</p>
46
- <p class="ui-meganav-media-copy">Augment your apps with realtime updates like weather or transit.</p>
44
+ <%= link_to abs_url("/topic/live-cursors"), class: "ui-meganav-media group" do %>
45
+ <p class="ui-meganav-media-heading">Live Cursors</p>
46
+ <p class="ui-meganav-media-copy">Track all cursors in realtime.</p>
47
+ <% end %>
48
+ </li>
49
+ <li>
50
+ <%= link_to abs_url("/topic/typing-indicator"), class: "ui-meganav-media group" do %>
51
+ <p class="ui-meganav-media-heading">Typing Indicator</p>
52
+ <p class="ui-meganav-media-copy">See when a user is typing a message.</p>
47
53
  <% end %>
48
54
  </li>
49
55
  </ul>
50
56
 
51
- <%= render(AblyUi::Core::FeaturedLink.new(url: abs_url("/platform"))) do %>Explore all platform features<% end %>
57
+ <%= render(AblyUi::Core::FeaturedLink.new(url: abs_url("/topics/live-examples"))) do %>Explore all live examples<% end %>
52
58
  </div>
53
59
 
54
60
  <div>
@@ -19,43 +19,48 @@ const MeganavContentPlatform = ({ paths, absUrl }) => (
19
19
  </div>
20
20
 
21
21
  <div>
22
- <h3 className="ui-meganav-overline" id="meganav-platform-panel-list-our-features">
23
- Our features
22
+ <h3 className="ui-meganav-overline" id="meganav-platform-panel-list-examples">
23
+ Examples
24
24
  </h3>
25
- <ul aria-labelledby="meganav-platform-panel-list-our-features">
25
+ <ul aria-labelledby="meganav-platform-panel-list-examples">
26
26
  <li>
27
- <a href={absUrl("/pub-sub-messaging")} className="group ui-meganav-media">
28
- <p className="ui-meganav-media-heading">Publish/subscribe messaging</p>
29
- <p className="ui-meganav-media-copy">Feature-rich pub/sub messaging to power any realtime requirement.</p>
27
+ <a href={absUrl("/topic/avatar-stack")} className="group ui-meganav-media">
28
+ <p className="ui-meganav-media-heading">Avatar Stack</p>
29
+ <p className="ui-meganav-media-copy">See who is connected in a digital space.</p>
30
30
  </a>
31
31
  </li>
32
32
  <li>
33
- <a href={absUrl("/push-notifications")} className="ui-meganav-media group">
34
- <p className="ui-meganav-media-heading">Push notifications</p>
35
- <p className="ui-meganav-media-copy">Deliver native notifications at scale with our unified API.</p>
33
+ <a href={absUrl("/topic/emoji-reactions")} className="ui-meganav-media group">
34
+ <p className="ui-meganav-media-heading">Emoji Reactions</p>
35
+ <p className="ui-meganav-media-copy">React with an emoji to a message.</p>
36
36
  </a>
37
37
  </li>
38
38
  <li>
39
- <a href={absUrl("/integrations")} className="ui-meganav-media group">
40
- <p className="ui-meganav-media-heading">Third-party integrations</p>
41
- <p className="ui-meganav-media-copy">Integrate and extend Ably with cloud services like AWS Kinesis.</p>
39
+ <a href={absUrl("/topic/activity-feed")} className="ui-meganav-media group">
40
+ <p className="ui-meganav-media-heading">Activity Feed</p>
41
+ <p className="ui-meganav-media-copy">Display a list of user actions in realtime.</p>
42
42
  </a>
43
43
  </li>
44
44
  <li>
45
- <a href={absUrl("/protocols")} className="ui-meganav-media group">
46
- <p className="ui-meganav-media-heading">Multi-protocol messaging</p>
47
- <p className="ui-meganav-media-copy">We support pub/sub over WebSockets, MQTT, SSE, and more.</p>
45
+ <a href={absUrl("/topic/live-charts")} className="ui-meganav-media group">
46
+ <p className="ui-meganav-media-heading">Live Charts</p>
47
+ <p className="ui-meganav-media-copy">Visualise live metrics and data in a chart.</p>
48
48
  </a>
49
49
  </li>
50
50
  <li>
51
- <a href={absUrl("/hub")} className="ui-meganav-media group">
52
- <p className="ui-meganav-media-heading">Streaming data sources</p>
53
- <p className="ui-meganav-media-copy">Augment your apps with realtime updates like weather or transit.</p>
51
+ <a href={absUrl("/topic/live-cursors")} className="ui-meganav-media group">
52
+ <p className="ui-meganav-media-heading">Live Cursors</p>
53
+ <p className="ui-meganav-media-copy">Track all cursors in realtime.</p>
54
+ </a>
55
+ </li>
56
+ <li>
57
+ <a href={absUrl("/topic/typing-indicator")} className="ui-meganav-media group">
58
+ <p className="ui-meganav-media-heading">Typing Indicator</p>
59
+ <p className="ui-meganav-media-copy">See when a user is typing a message.</p>
54
60
  </a>
55
61
  </li>
56
62
  </ul>
57
-
58
- <FeaturedLink url={absUrl("/platform")}>Explore all platform features</FeaturedLink>
63
+ <FeaturedLink url={absUrl("/topics/live-examples")}>Explore all live examples</FeaturedLink>
59
64
  </div>
60
65
 
61
66
  <div>
@@ -7,8 +7,6 @@ const MeganavControlMobileDropdown = ({ clearPanels }) => {
7
7
  const dropdown = queryId("meganav-mobile-dropdown");
8
8
  const menuIcon = queryId("meganav-control-mobile-dropdown-menu");
9
9
  const closeIcon = queryId("meganav-control-mobile-dropdown-close");
10
- const meganavSearchSuggestionsToggle = queryId("meganav-mobile-search-input");
11
- const meganavSearchSuggestions = queryId("meganav-mobile-search-suggestions");
12
10
 
13
11
  const clickHandler = () => {
14
12
  const ariaExpanded = control.getAttribute("aria-expanded");
@@ -28,40 +26,12 @@ const MeganavControlMobileDropdown = ({ clearPanels }) => {
28
26
  closeIcon.classList.toggle("hidden");
29
27
  };
30
28
 
31
- const focusSuggestionsHandler = () => {
32
- meganavSearchSuggestions.classList.add("max-h-96");
33
- };
34
- const blurSuggestionsHandler = (event) => {
35
- if (
36
- event.relatedTarget === meganavSearchSuggestions.querySelectorAll("a")[0]
37
- ) {
38
- return;
39
- }
40
- meganavSearchSuggestions.classList.remove("max-h-96");
41
- };
42
-
43
29
  control.addEventListener("click", clickHandler);
44
- meganavSearchSuggestionsToggle.addEventListener(
45
- "focus",
46
- focusSuggestionsHandler
47
- );
48
- meganavSearchSuggestionsToggle.addEventListener(
49
- "blur",
50
- blurSuggestionsHandler
51
- );
52
30
 
53
31
  return {
54
32
  teardown: () => {
55
33
  control.removeEventListener("click", clickHandler);
56
34
  scrollLock.enablePageScroll();
57
- meganavSearchSuggestionsToggle.removeEventListener(
58
- "focus",
59
- focusSuggestionsHandler
60
- );
61
- meganavSearchSuggestionsToggle.removeEventListener(
62
- "blur",
63
- blurSuggestionsHandler
64
- );
65
35
  },
66
36
  clear: () => {
67
37
  dropdown.classList.replace("visible", "invisible");
@@ -69,7 +39,6 @@ const MeganavControlMobileDropdown = ({ clearPanels }) => {
69
39
  menuIcon.classList.remove("hidden");
70
40
  closeIcon.classList.add("hidden");
71
41
  scrollLock.enablePageScroll();
72
- meganavSearchSuggestions.classList.remove("max-h-96");
73
42
  },
74
43
  };
75
44
  };
@@ -28,6 +28,7 @@
28
28
  class="ui-input px-48 h-48"
29
29
  style={{ maxWidth: "none" }}
30
30
  placeholder="Search"
31
+ autocomplete="off"
31
32
  data-id="meganav-mobile-search-input"
32
33
  />
33
34
 
@@ -53,6 +53,7 @@ const MeganavItemsMobile = ({ panels, paths, sessionState, theme, loginLink, abs
53
53
  className="ui-input px-48 h-48"
54
54
  style={{ maxWidth: "none" }}
55
55
  placeholder="Search"
56
+ autoComplete="off"
56
57
  data-id="meganav-mobile-search-input"
57
58
  />
58
59
 
@@ -43,10 +43,10 @@
43
43
 
44
44
  <li>
45
45
  <%= render(AblyUi::Core::MeganavSearch.new(url_base: url_base)) %>
46
- <li>
46
+ </li>
47
47
 
48
48
  <% if account? %>
49
- <li class="ml-16">
49
+ <li>
50
50
  <%= link_to "Dashboard", @session_data[:account][:links][:dashboard][:href], class: "ui-btn-secondary p-btn-small" %>
51
51
  </li>
52
52
  <% end %>
@@ -2,12 +2,12 @@
2
2
  type="button"
3
3
  data-id="meganav-control"
4
4
  data-control="search"
5
- class="h-64 w-24 px-24 pr-48 py-20"
5
+ class="h-64 w-24 px-24 pr-48 py-20 group focus:outline-none"
6
6
  aria-expanded="false"
7
7
  aria-controls="panel-search"
8
8
  aria-label="Show Search Panel"
9
9
  >
10
- <%= render(AblyUi::Core::Icon.new(name: "icon-gui-search", size: "1.5rem", color: "text-cool-black", additional_css: "hover:text-gui-hover")) %>
10
+ <%= render(AblyUi::Core::Icon.new(name: "icon-gui-search", size: "1.5rem", color: "text-cool-black", additional_css: "group-hover:text-gui-hover group-focus:text-gui-focus")) %>
11
11
  </button>
12
12
 
13
13
  <div class="ui-meganav-panel invisible" id="panel-search" data-id="meganav-panel">
@@ -11,12 +11,12 @@ const MeganavSearch = ({ absUrl }) => {
11
11
  type="button"
12
12
  data-id="meganav-control"
13
13
  data-control="search"
14
- className="h-64 w-24 px-24 pr-48 py-20"
14
+ className="h-64 w-24 px-24 pr-48 py-20 group focus:outline-none"
15
15
  aria-expanded="false"
16
16
  aria-controls="panel-search"
17
17
  aria-label={`Show Search Panel`}
18
18
  >
19
- <Icon name="icon-gui-search" color="text-cool-black" size="1.5rem" additionalCSS="hover:text-gui-hover" />
19
+ <Icon name="icon-gui-search" color="text-cool-black" size="1.5rem" additionalCSS="group-hover:text-gui-hover group-focus:text-gui-focus" />
20
20
  </button>
21
21
 
22
22
  <div className="ui-meganav-panel invisible" id="panel-search" data-id="meganav-panel">
@@ -18,8 +18,8 @@ const init = ({ input, container, listContainer, clear, client }) => {
18
18
  }
19
19
  };
20
20
 
21
- const markQueryInSuggestion = (suggestion, query) => {
22
- return suggestion.value.replace(
21
+ const markQueryInSuggestion = (suggestionValue, query) => {
22
+ return suggestionValue.replace(
23
23
  query.toLowerCase(),
24
24
  `<span class="font-light">${query}</span>`
25
25
  );
@@ -47,9 +47,16 @@ const init = ({ input, container, listContainer, clear, client }) => {
47
47
 
48
48
  const renderResults =
49
49
  (query) =>
50
- (results = { suggestions: [] }) => {
50
+ (results = {}) => {
51
51
  toggleClearBtn(query);
52
52
 
53
+ // Prevent invalid access error when key is invalid
54
+ if (!Array.isArray(results.suggestions)) {
55
+ clearResults();
56
+ return;
57
+ }
58
+
59
+ // Prevent key error from invalid key
53
60
  if (results.suggestions.length === 0) {
54
61
  clearResults();
55
62
  return;
@@ -58,6 +65,7 @@ const init = ({ input, container, listContainer, clear, client }) => {
58
65
  const items = results.suggestions.map((suggestion, index) => {
59
66
  const li = document.createElement("li");
60
67
  const button = document.createElement("button");
68
+ button.type = "button";
61
69
 
62
70
  button.classList.add(
63
71
  "ui-text-menu2",
@@ -71,25 +79,25 @@ const init = ({ input, container, listContainer, clear, client }) => {
71
79
  "hover:bg-light-grey"
72
80
  );
73
81
 
74
- button.innerHTML = markQueryInSuggestion(suggestion, query);
82
+ button.innerHTML = markQueryInSuggestion(suggestion.value, query);
75
83
 
76
84
  button.dataset.suggestionIndex = index;
77
85
 
78
86
  button.addEventListener("click", () => {
79
- navigateToUrl(suggestion);
87
+ navigateToUrl(suggestion.value);
80
88
  });
81
89
 
82
90
  button.addEventListener("keydown", (e) => {
83
91
  const key = e.key;
84
92
 
85
93
  if (key === "ArrowDown") {
86
- focusNext();
94
+ focusNext(index);
87
95
  } else if (key === "ArrowUp" && index - 1 < 0) {
88
96
  input.focus();
89
97
  } else if (key === "ArrowUp" && index - 1 >= 0) {
90
- focusPrevious();
98
+ focusPrevious(index);
91
99
  } else if (key === "Enter" || key === "Space") {
92
- navigateToUrl(suggestion);
100
+ navigateToUrl(suggestion.value);
93
101
  }
94
102
  });
95
103
 
@@ -142,12 +150,12 @@ const init = ({ input, container, listContainer, clear, client }) => {
142
150
  };
143
151
  };
144
152
 
145
- export default () => {
146
- const apiKey = document.body.dataset.addSearchApiKey;
153
+ export default (apiKey) => {
147
154
  if (!apiKey) {
148
155
  console.log(`No AddSearch API key provided, skipping search suggestions.`);
149
156
  return [];
150
157
  }
158
+
151
159
  const client = new AddSearchClient(apiKey);
152
160
 
153
161
  return [