@ably/ui 7.9.4 → 7.10.0-dev.d8911c4

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 (69) hide show
  1. package/core/Meganav/component.css +5 -1
  2. package/core/Meganav/component.js +2 -1
  3. package/core/Meganav/component.js.LICENSE.txt +7 -0
  4. package/core/Meganav.jsx +6162 -2856
  5. package/core/MeganavContentWhyAbly.jsx +2 -2
  6. package/core/MeganavControl/component.js +1 -1
  7. package/core/MeganavControl.jsx +5 -3
  8. package/core/MeganavControlMobileDropdown/component.js +1 -1
  9. package/core/MeganavItemsDesktop.jsx +5 -3
  10. package/core/MeganavItemsMobile.jsx +188 -11
  11. package/core/MeganavItemsSignedIn.jsx +259 -7
  12. package/core/MeganavSearch/component.js +1 -0
  13. package/core/MeganavSearch.jsx +504 -0
  14. package/core/MeganavSearchAutocomplete/component.js +2 -0
  15. package/core/MeganavSearchAutocomplete/component.js.LICENSE.txt +7 -0
  16. package/core/MeganavSearchAutocomplete.jsx +117 -0
  17. package/core/MeganavSearchPanel/component.js +1 -0
  18. package/core/MeganavSearchPanel.jsx +455 -0
  19. package/core/MeganavSearchSuggestions/component.js +1 -0
  20. package/core/MeganavSearchSuggestions.jsx +366 -0
  21. package/core/fonts/.DS_Store +0 -0
  22. package/core/images/.DS_Store +0 -0
  23. package/core/scripts.js +1 -1
  24. package/core/styles.css +2 -15
  25. package/package.json +2 -1
  26. package/preview/vendor/bundle/ruby/3.0.0/bundler/gems/ably-ui-abffd210ec0f/preview/log/.keep +0 -0
  27. package/preview/vendor/bundle/ruby/3.0.0/bundler/gems/ably-ui-abffd210ec0f/preview/tmp/.keep +0 -0
  28. package/preview/vendor/bundle/ruby/3.0.0/bundler/gems/ably-ui-abffd210ec0f/preview/tmp/pids/.keep +0 -0
  29. package/src/.DS_Store +0 -0
  30. package/src/core/.DS_Store +0 -0
  31. package/src/core/Meganav/component.css +5 -1
  32. package/src/core/Meganav/component.html.erb +10 -5
  33. package/src/core/Meganav/component.js +4 -0
  34. package/src/core/Meganav/component.jsx +12 -5
  35. package/src/core/MeganavContentWhyAbly/component.html.erb +1 -1
  36. package/src/core/MeganavContentWhyAbly/component.jsx +1 -1
  37. package/src/core/MeganavControl/component.html.erb +2 -2
  38. package/src/core/MeganavControl/component.js +37 -12
  39. package/src/core/MeganavControl/component.jsx +3 -2
  40. package/src/core/MeganavControl/component.rb +3 -1
  41. package/src/core/MeganavControlMobileDropdown/component.js +122 -0
  42. package/src/core/MeganavItemsMobile/component.html.erb +30 -2
  43. package/src/core/MeganavItemsMobile/component.jsx +33 -2
  44. package/src/core/MeganavItemsSignedIn/component.html.erb +5 -1
  45. package/src/core/MeganavItemsSignedIn/component.jsx +7 -2
  46. package/src/core/MeganavSearch/component.html.erb +15 -0
  47. package/src/core/MeganavSearch/component.js +0 -0
  48. package/src/core/MeganavSearch/component.jsx +33 -0
  49. package/src/core/MeganavSearch/component.rb +13 -0
  50. package/src/core/MeganavSearchAutocomplete/component.html.erb +6 -0
  51. package/src/core/MeganavSearchAutocomplete/component.js +170 -0
  52. package/src/core/MeganavSearchAutocomplete/component.jsx +14 -0
  53. package/src/core/MeganavSearchAutocomplete/component.rb +6 -0
  54. package/src/core/MeganavSearchPanel/component.html.erb +22 -0
  55. package/src/core/MeganavSearchPanel/component.js +0 -0
  56. package/src/core/MeganavSearchPanel/component.jsx +39 -0
  57. package/src/core/MeganavSearchPanel/component.rb +13 -0
  58. package/src/core/MeganavSearchSuggestions/component.html.erb +22 -0
  59. package/src/core/MeganavSearchSuggestions/component.js +0 -0
  60. package/src/core/MeganavSearchSuggestions/component.jsx +49 -0
  61. package/src/core/MeganavSearchSuggestions/component.rb +18 -0
  62. package/src/core/fonts/.DS_Store +0 -0
  63. package/src/core/images/.DS_Store +0 -0
  64. package/src/core/remote-blogs-posts.js +1 -1
  65. package/src/core/remote-session-data.js +1 -1
  66. package/src/core/styles/properties.css +2 -0
  67. package/src/core/styles.components.css +0 -15
  68. package/src/reset/.DS_Store +0 -0
  69. package/tailwind.config.js +2 -0
@@ -42,7 +42,7 @@ const MeganavContentWhyAbly = ({ absUrl }) => {
42
42
  </li>
43
43
 
44
44
  <li>
45
- <a href={absUrl("/resources/datasheets")} className="group ui-meganav-media py-12">
45
+ <a href={absUrl("/resources")} className="group ui-meganav-media py-12">
46
46
  <p className="ui-meganav-media-heading">Resources</p>
47
47
  </a>
48
48
  </li>
@@ -1,6 +1,6 @@
1
1
  <%= button_tag(type: "button",
2
- class: ["ui-meganav-link", "h-64", "flex", "items-center", "group", theme(:text_color)],
2
+ class: ["ui-meganav-link", "h-64", "flex", "items-center", "group", theme(:text_color), additional_css],
3
3
  data: { id: "meganav-control" },
4
- aria: { expanded: false, controls: @aria_controls, label: "Show #{content}" }) do -%>
4
+ aria: { expanded: false, controls: aria_controls, label: "Show #{content}" }) do -%>
5
5
  <%= content -%><%= render(AblyUi::Core::Icon.new(name: "icon-gui-disclosure-arrow", size: "1.5rem", color: "text-cool-black", additional_css: "transform rotate-90 group-hover:text-gui-hover group-focus:text-gui-focus")) %>
6
6
  <% end %>
@@ -1,4 +1,4 @@
1
- import { queryIdAll } from "../dom-query";
1
+ import { queryId, queryIdAll } from "../dom-query";
2
2
 
3
3
  const MeganavControl = () => {
4
4
  const controls = Array.from(queryIdAll("meganav-control"));
@@ -12,11 +12,21 @@ const MeganavControl = () => {
12
12
  `(hover: hover) and (pointer: fine) and (min-width: ${mdBreakpoint})`
13
13
  ).matches;
14
14
 
15
+ const isSearchControl = (node) => node.dataset.control === "search";
16
+
17
+ const isSearchPanelOpen = () => {
18
+ const searchPanel = document.querySelector(
19
+ '[data-id="meganav-panel"]#panel-search'
20
+ );
21
+ if (!searchPanel) return;
22
+ return !searchPanel.classList.contains("invisible");
23
+ };
24
+
15
25
  const controlsHaveFocus = () =>
16
26
  controls.some((control) => control === document.activeElement);
17
27
 
18
28
  const hover = (control, panel, open) => {
19
- if (hoverEnabled() && !controlsHaveFocus()) {
29
+ if (hoverEnabled() && !controlsHaveFocus() && !isSearchPanelOpen()) {
20
30
  const classes = ["invisible", "visible"];
21
31
  panel.classList.replace(...(open ? classes : classes.reverse()));
22
32
  control.setAttribute("aria-expanded", open);
@@ -40,12 +50,20 @@ const MeganavControl = () => {
40
50
 
41
51
  const ariaExpanded = control.getAttribute("aria-expanded");
42
52
 
43
- if (ariaExpanded) {
53
+ if (ariaExpanded === "true") {
54
+ control.setAttribute("aria-expanded", false);
55
+ panel.classList.replace("visible", "invisible");
56
+ } else {
44
57
  control.setAttribute("aria-expanded", true);
45
58
  panel.classList.replace("invisible", "visible");
59
+ }
60
+
61
+ if (isSearchControl(control)) {
62
+ const searchInput = queryId("meganav-search-input", panel);
63
+ if (!searchInput) return;
64
+ searchInput.focus();
46
65
  } else {
47
- control.setAttribute("aria-expanded", false);
48
- panel.classList.replace("visible", "invisible");
66
+ control.focus();
49
67
  }
50
68
  };
51
69
 
@@ -56,18 +74,25 @@ const MeganavControl = () => {
56
74
  `#${control.getAttribute("aria-controls")}`
57
75
  );
58
76
  const click = clickHandler(control, panel);
59
- const mouseenter = mouseenterHandler(control, panel);
60
- const mouseleave = mouseleaveHandler(control, panel);
61
-
62
- item.addEventListener("mouseenter", mouseenter);
63
- item.addEventListener("mouseleave", mouseleave);
64
77
  control.addEventListener("click", click);
78
+ let mouseenter, mouseleave;
79
+
80
+ if (!isSearchControl(control)) {
81
+ mouseenter = mouseenterHandler(control, panel);
82
+ mouseleave = mouseleaveHandler(control, panel);
83
+
84
+ item.addEventListener("mouseenter", mouseenter);
85
+ item.addEventListener("mouseleave", mouseleave);
86
+ }
65
87
 
66
88
  return [
67
89
  {
68
90
  teardown: () => {
69
- item.removeEventListener("mouseenter", mouseenter);
70
- item.removeEventListener("mouseleave", mouseleave);
91
+ if (mouseenter && mouseleave) {
92
+ item.removeEventListener("mouseenter", mouseenter);
93
+ item.removeEventListener("mouseleave", mouseleave);
94
+ }
95
+
71
96
  control.removeEventListener("click", click);
72
97
  },
73
98
  clear: () => {
@@ -3,11 +3,11 @@ import T from "prop-types";
3
3
 
4
4
  import Icon from "../Icon/component.jsx";
5
5
 
6
- const MeganavControl = ({ ariaControls, children, theme }) => (
6
+ const MeganavControl = ({ ariaControls, children, theme, additionalCSS }) => (
7
7
  <button
8
8
  type="button"
9
9
  data-id="meganav-control"
10
- className={`ui-meganav-link h-64 flex items-center group ${theme.textColor}`}
10
+ className={`ui-meganav-link h-64 flex items-center group ${additionalCSS} ${theme.textColor}`}
11
11
  aria-expanded="false"
12
12
  aria-controls={ariaControls}
13
13
  aria-label={`Show ${children}`}
@@ -26,6 +26,7 @@ MeganavControl.propTypes = {
26
26
  ariaControls: T.string,
27
27
  children: T.node,
28
28
  theme: T.object,
29
+ additionalCSS: T.string,
29
30
  };
30
31
 
31
32
  export default MeganavControl;
@@ -2,9 +2,11 @@ module AblyUi
2
2
  module Core
3
3
  class MeganavControl < ViewComponent::Base
4
4
  include AblyUi::Core::MeganavConfig
5
+ attr_reader :aria_controls, :additional_css
5
6
 
6
- def initialize(aria_controls:, theme_name:)
7
+ def initialize(aria_controls:, theme_name:, additional_css: '')
7
8
  @aria_controls = aria_controls
9
+ @additional_css = additional_css
8
10
  theme_setup(theme_name)
9
11
  end
10
12
  end
@@ -2,11 +2,23 @@ import scrollLock from "scroll-lock";
2
2
 
3
3
  import { queryId } from "../dom-query";
4
4
 
5
+ const DRAG_BUFFER = 5;
6
+
5
7
  const MeganavControlMobileDropdown = ({ clearPanels }) => {
6
8
  const control = queryId("meganav-control-mobile-dropdown");
7
9
  const dropdown = queryId("meganav-mobile-dropdown");
8
10
  const menuIcon = queryId("meganav-control-mobile-dropdown-menu");
9
11
  const closeIcon = queryId("meganav-control-mobile-dropdown-close");
12
+ const meganavSearchSuggestionsToggle = queryId("meganav-mobile-search-input");
13
+ const meganavSearchSuggestions = queryId("meganav-mobile-search-suggestions");
14
+ const meganavSearchSuggestionsOverflow = document.querySelector(
15
+ "[data-id='meganav-mobile-search-suggestions'] ul"
16
+ );
17
+ const meganavSearchSuggestionsOverflowWidth = Array.from(
18
+ meganavSearchSuggestionsOverflow.querySelectorAll("li")
19
+ )
20
+ .map((item) => item.getBoundingClientRect().width)
21
+ .reduce((acc, val) => acc + val, 0);
10
22
 
11
23
  const clickHandler = () => {
12
24
  const ariaExpanded = control.getAttribute("aria-expanded");
@@ -26,12 +38,121 @@ const MeganavControlMobileDropdown = ({ clearPanels }) => {
26
38
  closeIcon.classList.toggle("hidden");
27
39
  };
28
40
 
41
+ const focusSuggestionsHandler = () => {
42
+ meganavSearchSuggestions.classList.add("max-h-96");
43
+ };
44
+ const blurSuggestionsHandler = (event) => {
45
+ if (
46
+ event.relatedTarget === meganavSearchSuggestions.querySelectorAll("a")[0]
47
+ ) {
48
+ return;
49
+ }
50
+ meganavSearchSuggestions.classList.remove("max-h-96");
51
+ };
52
+
29
53
  control.addEventListener("click", clickHandler);
54
+ meganavSearchSuggestionsToggle.addEventListener(
55
+ "focus",
56
+ focusSuggestionsHandler
57
+ );
58
+ meganavSearchSuggestionsToggle.addEventListener(
59
+ "blur",
60
+ blurSuggestionsHandler
61
+ );
62
+
63
+ const slideLeft = (distance, dragThreshold, dragReset) => {
64
+ const left = new DOMMatrix(
65
+ window.getComputedStyle(meganavSearchSuggestionsOverflow).transform
66
+ ).e;
67
+ let calculatedDistance = Math.round(left + distance);
68
+
69
+ if (calculatedDistance >= dragThreshold && dragReset) {
70
+ calculatedDistance = 0;
71
+ } else if (calculatedDistance >= dragThreshold) {
72
+ return;
73
+ }
74
+
75
+ meganavSearchSuggestionsOverflow.style.transform = `translateX(${calculatedDistance}px)`;
76
+ };
77
+
78
+ const slideRight = (distance, dragThreshold, dragReset) => {
79
+ const { width } = meganavSearchSuggestionsOverflow.getBoundingClientRect();
80
+ const left = new DOMMatrix(
81
+ window.getComputedStyle(meganavSearchSuggestionsOverflow).transform
82
+ ).e;
83
+ let calculatedDistance = Math.round(left + distance);
84
+
85
+ if (
86
+ Math.abs(left - width + distance + dragThreshold) >
87
+ meganavSearchSuggestionsOverflowWidth &&
88
+ dragReset
89
+ ) {
90
+ calculatedDistance = -(
91
+ meganavSearchSuggestionsOverflowWidth -
92
+ width +
93
+ dragThreshold
94
+ );
95
+ } else if (
96
+ Math.abs(left - width + distance + dragThreshold) >
97
+ meganavSearchSuggestionsOverflowWidth
98
+ ) {
99
+ return;
100
+ }
101
+
102
+ meganavSearchSuggestionsOverflow.style.transform = `translateX(${calculatedDistance}px)`;
103
+ };
104
+
105
+ let touchStartX;
106
+
107
+ const touchstartHandler = (e) => {
108
+ touchStartX = e.touches[0]?.clientX;
109
+ };
110
+
111
+ const touchmoveHandler = (e) => {
112
+ const distance = e.changedTouches[0]?.clientX - touchStartX;
113
+
114
+ // Prevent sliding on clicks
115
+ if (Math.abs(distance) < DRAG_BUFFER) return;
116
+
117
+ distance > 0 ? slideLeft(distance, 24) : slideRight(distance, 96);
118
+ };
119
+
120
+ const touchendHandler = (e) => {
121
+ const distance = e.changedTouches[0]?.clientX - touchStartX;
122
+
123
+ // Prevent sliding on clicks
124
+ if (Math.abs(distance) < DRAG_BUFFER) return;
125
+
126
+ distance > 0
127
+ ? slideLeft(distance, 24, true)
128
+ : slideRight(distance, 48, true);
129
+ };
130
+
131
+ meganavSearchSuggestions.addEventListener("touchstart", touchstartHandler);
132
+ meganavSearchSuggestions.addEventListener("touchmove", touchmoveHandler);
133
+ meganavSearchSuggestions.addEventListener("touchend", touchendHandler);
30
134
 
31
135
  return {
32
136
  teardown: () => {
33
137
  control.removeEventListener("click", clickHandler);
34
138
  scrollLock.enablePageScroll();
139
+ meganavSearchSuggestionsToggle.removeEventListener(
140
+ "focus",
141
+ focusSuggestionsHandler
142
+ );
143
+ meganavSearchSuggestionsToggle.removeEventListener(
144
+ "blur",
145
+ blurSuggestionsHandler
146
+ );
147
+ meganavSearchSuggestions.removeEventListener(
148
+ "touchstart",
149
+ touchstartHandler
150
+ );
151
+ meganavSearchSuggestions.removeEventListener(
152
+ "touchmove",
153
+ touchmoveHandler
154
+ );
155
+ meganavSearchSuggestions.removeEventListener("touchend", touchendHandler);
35
156
  },
36
157
  clear: () => {
37
158
  dropdown.classList.replace("visible", "invisible");
@@ -39,6 +160,7 @@ const MeganavControlMobileDropdown = ({ clearPanels }) => {
39
160
  menuIcon.classList.remove("hidden");
40
161
  closeIcon.classList.add("hidden");
41
162
  scrollLock.enablePageScroll();
163
+ meganavSearchSuggestions.classList.remove("max-h-96");
42
164
  },
43
165
  };
44
166
  };
@@ -11,8 +11,36 @@
11
11
  <%= render(AblyUi::Core::MeganavControlMobileDropdown.new(theme_name: @theme_name)) %>
12
12
 
13
13
  <div class="ui-meganav-mobile-dropdown invisible" id="meganav-mobile-dropdown" data-id="meganav-mobile-dropdown">
14
- <div class="py-16 ui-grid-px bg-white">
15
- <ul class="mb-16">
14
+ <div class="pt-24 pb-16 ui-grid-px bg-white">
15
+ <%= tag.form class: "mb-16", action: abs_url("/search"), method: "get" do %>
16
+ <div class="relative w-full">
17
+ <%= render(AblyUi::Core::Icon.new(name: "icon-gui-search", size: "1.5rem", color: "text-cool-black", additional_css: "absolute top-12 left-16 hover:text-gui-hover")) %>
18
+ <button
19
+ type="button"
20
+ class="absolute top-12 right-16 p-0 focus:outline-gui-focus m-0 md:hidden invisible"
21
+ data-id="meganav-search-input-clear"
22
+ >
23
+ <%= render(AblyUi::Core::Icon.new(name: "icon-gui-cross-circled-fill", size: "1.5rem", color: "text-dark-grey")) %>
24
+ </button>
25
+ <input
26
+ type="search"
27
+ name="q"
28
+ class="ui-input px-48 h-48"
29
+ style={{ maxWidth: "none" }}
30
+ placeholder="Search"
31
+ autocomplete="off"
32
+ data-id="meganav-mobile-search-input"
33
+ />
34
+
35
+ <%= render(AblyUi::Core::MeganavSearchAutocomplete.new) %>
36
+ </div>
37
+ <% end %>
38
+
39
+ <div class="max-h-0 overflow-hidden transition-all" data-id="meganav-mobile-search-suggestions">
40
+ <%= render(AblyUi::Core::MeganavSearchSuggestions.new(url_base: url_base, display_support_link: false)) %>
41
+ </div>
42
+
43
+ <ul class="mb-16" data-id="meganav-mobile-panel-controls">
16
44
  <% panels.each do |panel| %>
17
45
  <li class="ui-meganav-mobile-item">
18
46
  <%= render(AblyUi::Core::MeganavControlMobilePanelOpen.new(aria_controls: "#{panel[:id]}-mobile")) do %>
@@ -2,11 +2,14 @@ import React from "react";
2
2
  import T from "prop-types";
3
3
 
4
4
  import SignOutLink from "../SignOutLink/component.jsx";
5
+ import MeganavSearchSuggestions from "../MeganavSearchSuggestions/component.jsx";
6
+ import Icon from "../Icon/component.jsx";
5
7
 
6
8
  import MeganavData from "../Meganav/component.json";
7
9
  import MeganavControlMobileDropdown from "../MeganavControlMobileDropdown/component.jsx";
8
10
  import MeganavControlMobilePanelClose from "../MeganavControlMobilePanelClose/component.jsx";
9
11
  import MeganavControlMobilePanelOpen from "../MeganavControlMobilePanelOpen/component.jsx";
12
+ import MeganavSearchAutocomplete from "../MeganavSearchAutocomplete/component.jsx";
10
13
 
11
14
  const MeganavItemsMobile = ({ panels, paths, sessionState, theme, loginLink, absUrl }) => {
12
15
  const classNames = `ui-meganav-link ${theme.textColor}`;
@@ -33,8 +36,36 @@ const MeganavItemsMobile = ({ panels, paths, sessionState, theme, loginLink, abs
33
36
  <MeganavControlMobileDropdown theme={theme} />
34
37
 
35
38
  <div className="ui-meganav-mobile-dropdown invisible" id="meganav-mobile-dropdown" data-id="meganav-mobile-dropdown">
36
- <div className="py-16 ui-grid-px bg-white">
37
- <ul className="mb-16">
39
+ <div className="pt-24 pb-16 ui-grid-px bg-white">
40
+ <form className="mb-16" action={absUrl("/search")} method="get">
41
+ <div className="relative w-full">
42
+ <Icon name="icon-gui-search" color="text-cool-black" size="1.5rem" additionalCSS="absolute top-12 left-16 hover:text-gui-hover" />
43
+ <button
44
+ type="button"
45
+ className="absolute top-12 right-16 p-0 focus:outline-gui-focus m-0 md:hidden invisible"
46
+ data-id="meganav-search-input-clear"
47
+ >
48
+ <Icon name="icon-gui-cross-circled-fill" color="text-dark-grey" size="1.5rem" additionalCSS="" />
49
+ </button>
50
+ <input
51
+ type="search"
52
+ name="q"
53
+ className="ui-input px-48 h-48"
54
+ style={{ maxWidth: "none" }}
55
+ placeholder="Search"
56
+ autoComplete="off"
57
+ data-id="meganav-mobile-search-input"
58
+ />
59
+
60
+ <MeganavSearchAutocomplete />
61
+ </div>
62
+ </form>
63
+
64
+ <div className="max-h-0 overflow-hidden transition-all" data-id="meganav-mobile-search-suggestions">
65
+ <MeganavSearchSuggestions absUrl={absUrl} displaySupportLink={false} />
66
+ </div>
67
+
68
+ <ul className="mb-16" data-id="meganav-mobile-panel-controls">
38
69
  {MeganavData.panels.map((panel) => {
39
70
  const PanelComponent = panels[panel.component];
40
71
 
@@ -1,6 +1,6 @@
1
1
  <ul class="hidden md:flex items-center">
2
2
  <li class="ui-meganav-item relative">
3
- <%= render(AblyUi::Core::MeganavControl.new(aria_controls: "account-panel", theme_name: @theme_name)) do %>
3
+ <%= render(AblyUi::Core::MeganavControl.new(aria_controls: "account-panel", theme_name: @theme_name, additional_css: "mr-0")) do %>
4
4
  <%= account_name %>
5
5
  <% end %>
6
6
 
@@ -41,6 +41,10 @@
41
41
  </div>
42
42
  </li>
43
43
 
44
+ <li>
45
+ <%= render(AblyUi::Core::MeganavSearch.new(url_base: url_base)) %>
46
+ <li>
47
+
44
48
  <% if account? %>
45
49
  <li class="ml-16">
46
50
  <%= link_to "Dashboard", @session_data[:account][:links][:dashboard][:href], class: "ui-btn-secondary p-btn-small" %>
@@ -3,6 +3,7 @@ import T from "prop-types";
3
3
 
4
4
  import MeganavControl from "../MeganavControl/component.jsx";
5
5
  import SignOutLink from "../SignOutLink/component.jsx";
6
+ import MeganavSearch from "../MeganavSearch/component.jsx";
6
7
 
7
8
  const truncate = (string, length) => {
8
9
  return string?.length && string.length > length ? `${string.slice(0, length - 1)}…` : string;
@@ -16,7 +17,7 @@ const MeganavItemsSignedIn = ({ sessionState, theme, absUrl }) => {
16
17
  return (
17
18
  <ul className="hidden md:flex items-center">
18
19
  <li className="ui-meganav-item relative">
19
- <MeganavControl ariaControls="account-panel" theme={theme}>
20
+ <MeganavControl ariaControls="account-panel" theme={theme} additionalCSS="mr-0">
20
21
  {accountName}
21
22
  </MeganavControl>
22
23
 
@@ -70,8 +71,12 @@ const MeganavItemsSignedIn = ({ sessionState, theme, absUrl }) => {
70
71
  </div>
71
72
  </li>
72
73
 
74
+ <li>
75
+ <MeganavSearch absUrl={absUrl} />
76
+ </li>
77
+
73
78
  {sessionState.account && (
74
- <li className="ml-16">
79
+ <li>
75
80
  <a href={absUrl(sessionState.account.links.dashboard.href)} className="ui-btn-secondary p-btn-small">
76
81
  Dashboard
77
82
  </a>
@@ -0,0 +1,15 @@
1
+ <button
2
+ type="button"
3
+ data-id="meganav-control"
4
+ data-control="search"
5
+ class="h-64 w-24 px-24 pr-48 py-20"
6
+ aria-expanded="false"
7
+ aria-controls="panel-search"
8
+ aria-label="Show Search Panel"
9
+ >
10
+ <%= render(AblyUi::Core::Icon.new(name: "icon-gui-search", size: "1.5rem", color: "text-cool-black", additional_css: "hover:text-gui-hover")) %>
11
+ </button>
12
+
13
+ <div class="ui-meganav-panel invisible" id="panel-search" data-id="meganav-panel">
14
+ <%= render(AblyUi::Core::MeganavSearchPanel.new(url_base: url_base)) %>
15
+ </div>
File without changes
@@ -0,0 +1,33 @@
1
+ import React from "react";
2
+ import T from "prop-types";
3
+
4
+ import Icon from "../Icon/component.jsx";
5
+ import MeganavSearchPanel from "../MeganavSearchPanel/component.jsx";
6
+
7
+ const MeganavSearch = ({ absUrl }) => {
8
+ return (
9
+ <>
10
+ <button
11
+ type="button"
12
+ data-id="meganav-control"
13
+ data-control="search"
14
+ className="h-64 w-24 px-24 pr-48 py-20"
15
+ aria-expanded="false"
16
+ aria-controls="panel-search"
17
+ aria-label={`Show Search Panel`}
18
+ >
19
+ <Icon name="icon-gui-search" color="text-cool-black" size="1.5rem" additionalCSS="hover:text-gui-hover" />
20
+ </button>
21
+
22
+ <div className="ui-meganav-panel invisible" id="panel-search" data-id="meganav-panel">
23
+ <MeganavSearchPanel absUrl={absUrl} />
24
+ </div>
25
+ </>
26
+ );
27
+ };
28
+
29
+ MeganavSearch.propTypes = {
30
+ absUrl: T.func,
31
+ };
32
+
33
+ export default MeganavSearch;
@@ -0,0 +1,13 @@
1
+ module AblyUi
2
+ module Core
3
+ class MeganavSearch < ViewComponent::Base
4
+ include Util
5
+
6
+ attr_reader :url_base
7
+
8
+ def initialize(url_base:)
9
+ @url_base = url_base
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,6 @@
1
+ <div
2
+ class="absolute w-full mt-8 z-10 hidden shadow-container rounded-lg bg-white border border-mid-grey"
3
+ data-id="meganav-search-autocomplete-container"
4
+ >
5
+ <ol class="m-16" data-id="meganav-search-autocomplete-list"></ol>
6
+ </div>