@ably/ui 11.7.1 → 12.0.0-dev.31bc8d9

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 (128) hide show
  1. package/README.md +6 -9
  2. package/core/.DS_Store +0 -0
  3. package/core/Code/component.css +2 -0
  4. package/core/ContactFooter.jsx +8 -8
  5. package/core/DropdownMenu.jsx +1 -1
  6. package/core/FeaturedLink/component.css +0 -15
  7. package/core/FeaturedLink/component.js +1 -1
  8. package/core/FeaturedLink.jsx +17 -6
  9. package/core/Flash/component.css +0 -4
  10. package/core/Flash.jsx +1 -1
  11. package/core/Footer/component.css +3 -3
  12. package/core/Footer.jsx +14 -14
  13. package/core/Meganav/component.css +6 -6
  14. package/core/Meganav.jsx +23 -12
  15. package/core/MeganavBlogPostsList.jsx +17 -6
  16. package/core/MeganavContentCompany.jsx +17 -6
  17. package/core/MeganavContentProducts.jsx +19 -8
  18. package/core/MeganavItemsMobile.jsx +17 -6
  19. package/core/MeganavItemsSignedIn.jsx +17 -6
  20. package/core/MeganavSearch.jsx +17 -6
  21. package/core/MeganavSearchPanel.jsx +17 -6
  22. package/core/MeganavSearchSuggestions.jsx +17 -6
  23. package/core/Notice/component.js +1 -1
  24. package/core/Notice.jsx +4 -4
  25. package/core/Showcase/component.css +2 -0
  26. package/core/Showcase/component.js +6 -1
  27. package/core/Showcase.jsx +3 -0
  28. package/core/Uptime/component.css +4 -3
  29. package/core/Uptime/component.js +6 -1
  30. package/core/Uptime.jsx +65 -28
  31. package/core/fonts/jetBrains-mono.css +3 -0
  32. package/core/fonts/manrope.css +3 -0
  33. package/core/scripts.js +1 -1
  34. package/core/styles.css +232 -124
  35. package/package.json +2 -5
  36. package/src/core/.DS_Store +0 -0
  37. package/src/core/ContactFooter/component.jsx +8 -8
  38. package/src/core/DropdownMenu/component.jsx +1 -1
  39. package/src/core/FeaturedLink/component.js +0 -1
  40. package/src/core/FeaturedLink/component.jsx +27 -4
  41. package/src/core/Flash/component.css +0 -4
  42. package/src/core/Flash/component.jsx +1 -1
  43. package/src/core/Footer/component.css +3 -3
  44. package/src/core/Footer/component.jsx +14 -14
  45. package/src/core/Meganav/component.css +6 -6
  46. package/src/core/MeganavContentProducts/component.jsx +2 -2
  47. package/src/core/Notice/component.jsx +3 -3
  48. package/src/core/fonts/jetBrains-mono.css +3 -0
  49. package/src/core/fonts/manrope.css +3 -0
  50. package/src/core/react-renderer.js +7 -4
  51. package/src/core/styles/buttons.css +5 -5
  52. package/src/core/styles/forms.css +5 -5
  53. package/src/core/styles/properties.css +153 -52
  54. package/src/core/styles/text.css +68 -61
  55. package/src/core/styles.components.css +1 -1
  56. package/src/core/utils/syntax-highlighter.css +2 -0
  57. package/tailwind.config.js +194 -69
  58. package/tailwind.extend.js +1 -4
  59. package/src/core/Code/component.html.erb +0 -3
  60. package/src/core/Code/component.rb +0 -12
  61. package/src/core/ContactFooter/component.html.erb +0 -32
  62. package/src/core/ContactFooter/component.rb +0 -13
  63. package/src/core/CustomerLogos/component.html.erb +0 -9
  64. package/src/core/CustomerLogos/component.rb +0 -14
  65. package/src/core/FeatureFooter/component.html.erb +0 -54
  66. package/src/core/FeatureFooter/component.rb +0 -30
  67. package/src/core/FeaturedLink/component.css +0 -15
  68. package/src/core/FeaturedLink/component.html.erb +0 -6
  69. package/src/core/FeaturedLink/component.rb +0 -19
  70. package/src/core/Footer/component.html.erb +0 -256
  71. package/src/core/Footer/component.rb +0 -14
  72. package/src/core/Icon/component.html.erb +0 -3
  73. package/src/core/Icon/component.rb +0 -25
  74. package/src/core/Loader/component.html.erb +0 -18
  75. package/src/core/Loader/component.rb +0 -19
  76. package/src/core/Logo/component.html.erb +0 -3
  77. package/src/core/Logo/component.rb +0 -31
  78. package/src/core/Meganav/component.html.erb +0 -31
  79. package/src/core/Meganav/component.rb +0 -60
  80. package/src/core/MeganavBlogPostsList/component.html.erb +0 -5
  81. package/src/core/MeganavBlogPostsList/component.rb +0 -13
  82. package/src/core/MeganavContentCompany/component.html.erb +0 -90
  83. package/src/core/MeganavContentCompany/component.rb +0 -14
  84. package/src/core/MeganavContentDevelopers/component.html.erb +0 -129
  85. package/src/core/MeganavContentDevelopers/component.rb +0 -13
  86. package/src/core/MeganavContentProducts/component.html.erb +0 -83
  87. package/src/core/MeganavContentProducts/component.rb +0 -14
  88. package/src/core/MeganavContentUseCases/component.html.erb +0 -135
  89. package/src/core/MeganavContentUseCases/component.rb +0 -13
  90. package/src/core/MeganavControl/component.html.erb +0 -6
  91. package/src/core/MeganavControl/component.rb +0 -20
  92. package/src/core/MeganavControlMobileDropdown/component.html.erb +0 -7
  93. package/src/core/MeganavControlMobileDropdown/component.rb +0 -11
  94. package/src/core/MeganavControlMobilePanelClose/component.html.erb +0 -12
  95. package/src/core/MeganavControlMobilePanelClose/component.rb +0 -12
  96. package/src/core/MeganavControlMobilePanelOpen/component.html.erb +0 -7
  97. package/src/core/MeganavControlMobilePanelOpen/component.rb +0 -9
  98. package/src/core/MeganavItemsDesktop/component.html.erb +0 -17
  99. package/src/core/MeganavItemsDesktop/component.rb +0 -23
  100. package/src/core/MeganavItemsMobile/component.html.erb +0 -75
  101. package/src/core/MeganavItemsMobile/component.rb +0 -21
  102. package/src/core/MeganavItemsSignedIn/component.html.erb +0 -53
  103. package/src/core/MeganavItemsSignedIn/component.rb +0 -33
  104. package/src/core/MeganavSearch/component.html.erb +0 -15
  105. package/src/core/MeganavSearch/component.rb +0 -13
  106. package/src/core/MeganavSearchAutocomplete/component.html.erb +0 -6
  107. package/src/core/MeganavSearchAutocomplete/component.rb +0 -6
  108. package/src/core/MeganavSearchPanel/component.html.erb +0 -22
  109. package/src/core/MeganavSearchPanel/component.rb +0 -13
  110. package/src/core/MeganavSearchSuggestions/component.html.erb +0 -22
  111. package/src/core/MeganavSearchSuggestions/component.rb +0 -18
  112. package/src/core/Notice/component.html.erb +0 -16
  113. package/src/core/Notice/component.rb +0 -29
  114. package/src/core/Showcase/component.css +0 -30
  115. package/src/core/Showcase/component.html.erb +0 -76
  116. package/src/core/Showcase/component.js +0 -180
  117. package/src/core/Showcase/component.jsx +0 -0
  118. package/src/core/Showcase/component.rb +0 -190
  119. package/src/core/SignOutLink/component.html.erb +0 -1
  120. package/src/core/SignOutLink/component.rb +0 -17
  121. package/src/core/Slider/component.html.erb +0 -28
  122. package/src/core/Slider/component.rb +0 -38
  123. package/src/core/Uptime/component.css +0 -128
  124. package/src/core/Uptime/component.html.erb +0 -0
  125. package/src/core/Uptime/component.js +0 -1
  126. package/src/core/Uptime/component.jsx +0 -186
  127. package/src/core/Uptime/component.rb +0 -7
  128. package/src/core/core.rb +0 -81
@@ -1,75 +0,0 @@
1
- <ul class="flex md:hidden" data-id="meganav-items-mobile">
2
- <li>
3
- <% if @session_data[:signedIn] && @session_data[:logOut] %>
4
- <%= render(AblyUi::Core::SignOutLink.new(session_data: @session_data, classes: ["ui-meganav-link", theme(:text_color)], url_base: url_base)) %>
5
- <% else %>
6
- <%= link_to "Login", abs_url(login_link), data: { id: "meganav-link" }, class: ["ui-meganav-link", theme(:text_color)] %>
7
- <% end %>
8
- </li>
9
-
10
- <li class="ui-meganav-item">
11
- <%= render(AblyUi::Core::MeganavControlMobileDropdown.new(theme_name: @theme_name)) %>
12
-
13
- <div class="ui-meganav-mobile-dropdown invisible" id="meganav-mobile-dropdown" data-id="meganav-mobile-dropdown">
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">
44
- <% panels.each do |panel| %>
45
- <li class="ui-meganav-mobile-item">
46
- <%= render(AblyUi::Core::MeganavControlMobilePanelOpen.new(aria_controls: "#{panel[:id]}-mobile")) do %>
47
- <%= panel[:label] %>
48
- <% end %>
49
-
50
- <%= content_tag(:div, class: "ui-meganav-panel-mobile hidden", id: "#{panel[:id]}-mobile", data: { scroll_lock_scrollable: true }) do %>
51
- <%= render(AblyUi::Core::MeganavControlMobilePanelClose.new(aria_controls: "#{panel[:id]}-mobile", display_hr: display_hr(panel[:id]))) %>
52
- <%= render("AblyUi::Core::#{panel[:component]}".constantize.new(url_base: url_base)) %>
53
- <% end %>
54
- </li>
55
- <% end %>
56
- <li>
57
- <%= link_to "Pricing", abs_url("/pricing"), class: "ui-meganav-mobile-link" %>
58
- </li>
59
- </ul>
60
-
61
- <hr class="ui-meganav-hr mb-20" />
62
-
63
- <div class="flex justify-between items-center mb-16">
64
- <%= link_to "Contact us", abs_url("/contact"), class: "text-menu2 font-medium block ml-0 mr-8 lg:mx-12 p-0 hover:text-gui-hover focus:text-gui-focus focus:outline-none" %>
65
-
66
- <% if @session_data[:signedIn] && @session_data[:account] %>
67
- <%= link_to "Dashboard", abs_url(@session_data[:account][:links][:dashboard][:href]), class: "ui-btn-secondary" %>
68
- <% else %>
69
- <%= link_to "Sign up free", abs_url("/sign-up"), class: "ui-btn" %>
70
- <% end %>
71
- </div>
72
- </div>
73
- </div>
74
- </li>
75
- </ul>
@@ -1,21 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class MeganavItemsMobile < ViewComponent::Base
4
- include MeganavConfig
5
- include Util
6
-
7
- attr_reader :options, :login_link, :url_base
8
-
9
- def initialize(session_data:, theme_name:, login_link:, url_base:)
10
- @theme_name = theme_name
11
- @session_data = session_data
12
- @login_link = login_link
13
- @url_base = url_base
14
- end
15
-
16
- def display_hr(panel_id)
17
- %w[company-panel developers-panel].include?(panel_id)
18
- end
19
- end
20
- end
21
- end
@@ -1,53 +0,0 @@
1
- <ul class="hidden md:flex items-center">
2
- <li class="ui-meganav-item relative">
3
- <%= render(AblyUi::Core::MeganavControl.new(aria_controls: "account-panel", aria_label: "Account", theme_name: @theme_name, additional_css: "mr-0")) do %>
4
- <%= account_name %>
5
- <% end %>
6
-
7
- <div class="ui-meganav-panel-account invisible" id="account-panel" data-id="meganav-panel">
8
- <% if account? %>
9
- <p class="ui-meganav-overline mt-16 mx-16">Your account</p>
10
- <ul class="mb-16 mx-16">
11
- <% @session_data[:account][:links].each do |key, link| %>
12
- <li>
13
- <%= link_to link[:text], link[:href], class: "ui-meganav-account-link" %>
14
- </li>
15
- <% end %>
16
- </ul>
17
- <% end %>
18
-
19
- <p class="ui-meganav-overline mx-16"><%= preferred_email %></p>
20
- <ul class="mb-8 mx-16">
21
- <li>
22
- <%= link_to @session_data[:mySettings][:text], @session_data[:mySettings][:href], class: "ui-meganav-account-link" %>
23
- </li>
24
-
25
- <% if access_tokens? %>
26
- <li>
27
- <%= link_to @session_data[:myAccessTokens][:href], class: "ui-meganav-account-link" do %>
28
- <%= @session_data[:myAccessTokens][:text] %><span class="ui-version-tag">preview</span>
29
- <% end %>
30
- </li>
31
- <% end %>
32
- </ul>
33
-
34
- <hr class="ui-meganav-hr mb-16" />
35
-
36
- <div class="mb-16 px-16">
37
- <% if @session_data[:logOut] %>
38
- <%= render(AblyUi::Core::SignOutLink.new(session_data: @session_data, classes: "ui-meganav-account-link", url_base: url_base)) %>
39
- <% end %>
40
- </div>
41
- </div>
42
- </li>
43
-
44
- <li>
45
- <%= render(AblyUi::Core::MeganavSearch.new(url_base: url_base)) %>
46
- </li>
47
-
48
- <% if account? %>
49
- <li>
50
- <%= link_to "Dashboard", @session_data[:account][:links][:dashboard][:href], class: "ui-btn-secondary p-btn-small" %>
51
- </li>
52
- <% end %>
53
- </ul>
@@ -1,33 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class MeganavItemsSignedIn < ViewComponent::Base
4
- include MeganavConfig
5
- include Util
6
-
7
- attr_reader :url_base
8
-
9
- def initialize(session_data:, theme_name:, url_base:)
10
- @theme_name = theme_name
11
- @session_data = session_data
12
- @url_base = url_base
13
- end
14
-
15
- def account?
16
- @session_data[:account].present?
17
- end
18
-
19
- # Access tokens are behind a feature flag
20
- def access_tokens?
21
- @session_data[:myAccessTokens].present?
22
- end
23
-
24
- def account_name
25
- truncate(@session_data[:accountName], length: 20)
26
- end
27
-
28
- def preferred_email
29
- truncate(@session_data[:preferredEmail], length: 20)
30
- end
31
- end
32
- end
33
- end
@@ -1,15 +0,0 @@
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 group focus:outline-none"
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: "group-hover:text-gui-hover group-focus:text-gui-focus")) %>
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>
@@ -1,13 +0,0 @@
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
@@ -1,6 +0,0 @@
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>
@@ -1,6 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class MeganavSearchAutocomplete < ViewComponent::Base
4
- end
5
- end
6
- end
@@ -1,22 +0,0 @@
1
- <section class="ui-meganav-content grid-cols-12">
2
- <div class="col-span-8">
3
- <div class="mb-32">
4
- <%= tag.form class: "flex items-start", action: abs_url("/search"), method: "get" do %>
5
- <div class="relative w-full">
6
- <%= render(AblyUi::Core::Icon.new(name: "icon-gui-search", size: "1.5rem", color: "text-cool-black", additional_css:"absolute top-12 left-16")) %>
7
- <input type="search" name="q" class="ui-input pl-48 h-48" placeholder="Search" autocomplete="off" data-id="meganav-search-input" />
8
-
9
- <%= render(AblyUi::Core::MeganavSearchAutocomplete.new) %>
10
- </div>
11
-
12
- <button type="submit" class="ui-btn-secondary flex-shrink-0 ml-8 sm:ml-16 md:ml-24 xl:ml-32">
13
- Search
14
- </button>
15
- <% end %>
16
- </div>
17
- </div>
18
-
19
- <div class="col-span-12">
20
- <%= render(AblyUi::Core::MeganavSearchSuggestions.new(url_base: url_base)) %>
21
- </div>
22
- </section>
@@ -1,13 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class MeganavSearchPanel < 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
@@ -1,22 +0,0 @@
1
- <p class="ui-text-overline2 text-cool-black py-12">Popular pages</p>
2
-
3
- <div class="flex justify-between items-center overflow-hidden">
4
- <ul class="flex transition-transform">
5
- <li class="py-12 pr-8 flex-shrink-0">
6
- <%= link_to 'How does Ably work?', abs_url("/docs/how-ably-works"), class: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus" %>
7
- </li>
8
- <li class="py-12 px-8 flex-shrink-0">
9
- <%= link_to 'Quickstart guide', abs_url("/docs/quick-start-guide"), class: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus" %>
10
- </li>
11
- <li class="py-12 px-8 flex-shrink-0">
12
- <%= link_to 'Publish/Subscribe Messaging', abs_url("/docs/core-features/pubsub"), class: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus" %>
13
- </li>
14
- <li class="py-12 pl-8 flex-shrink-0">
15
- <%= link_to 'Platform', abs_url("/platform"), class: "ui-text-p2 hover:text-gui-hover active:text-gui-active focus:text-gui-focus" %>
16
- </li>
17
- </ul>
18
-
19
- <% if display_support_link? %>
20
- <%= render(AblyUi::Core::FeaturedLink.new(url: abs_url("/support"), text_size: "text-p2")) do %>Support<% end %>
21
- <% end %>
22
- </div>
@@ -1,18 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class MeganavSearchSuggestions < ViewComponent::Base
4
- include Util
5
-
6
- attr_reader :url_base
7
-
8
- def initialize(url_base:, display_support_link: true)
9
- @url_base = url_base
10
- @display_support_link = display_support_link
11
- end
12
-
13
- def display_support_link?
14
- @display_support_link
15
- end
16
- end
17
- end
18
- end
@@ -1,16 +0,0 @@
1
- <%# Note the style attribute is used for entry animation %>
2
- <%= tag.div class: "ui-announcement #{bg_color} #{text_color}", data: { id: "ui-notice" }, style: "max-height: 0; overflow: hidden" do %>
3
- <div class="ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start">
4
- <%= content_wrapper class: "font-light w-full pr-8 text-p3 self-center" do %>
5
- <strong class="font-medium whitespace-nowrap pr-4"><%= @contents[:title] %></strong>
6
- <span class="pr-4"><%= @contents[:body_text] %></span>
7
- <span class="underline cursor-pointer whitespace-nowrap"><%= @contents[:button_label] %></span>
8
- <% end %>
9
-
10
- <% if close_btn? %>
11
- <%= button_tag type: 'button', class: 'h-20 w-20 mt-4 ml-auto border-none bg-none self-baseline' do %>
12
- <%= render(AblyUi::Core::Icon.new(name: "icon-gui-close", size: "1.25rem", color: "text-white")) %>
13
- <% end %>
14
- <% end %>
15
- </div>
16
- <% end %>
@@ -1,29 +0,0 @@
1
- module AblyUi
2
- module Core
3
- class Notice < ViewComponent::Base
4
- def initialize(contents)
5
- @contents = contents
6
- end
7
-
8
- def close_btn?
9
- @contents[:close_btn]
10
- end
11
-
12
- def bg_color
13
- @contents[:bg_color] || 'bg-gradient-active-orange'
14
- end
15
-
16
- def text_color
17
- @contents[:text_color] || 'text-white'
18
- end
19
-
20
- def content_wrapper(*args, &block)
21
- if @contents[:button_link].present?
22
- link_to(@contents[:button_link], *args, &block)
23
- else
24
- tag.div(*args, &block)
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -1,30 +0,0 @@
1
- @layer components {
2
- .ui-showcase-overflow-container {
3
- -ms-overflow-style: none; /* Internet Explorer 10+ */
4
- scrollbar-width: none; /* Firefox */
5
-
6
- @apply overflow-x-auto;
7
- }
8
-
9
- .ui-showcase-overflow-container::-webkit-scrollbar {
10
- @apply hidden; /* Safari and Chrome */
11
- }
12
-
13
- .ui-showcase-logo-wrapper {
14
- @apply flex bg-white;
15
- }
16
-
17
- .ui-showcase-logo {
18
- min-width: var(--ui-showcase-client-logo-min-width);
19
- @apply w-full py-16 px-12 flex items-center justify-center;
20
- }
21
-
22
- .ui-showcase-logo-img {
23
- max-width: var(--ui-showcase-client-logo-max-width);
24
- @apply w-full;
25
- }
26
-
27
- .ui-showcase-index-bar {
28
- @apply bg-mid-grey;
29
- }
30
- }
@@ -1,76 +0,0 @@
1
- <section
2
- aria-roledescription="carousel"
3
- aria-label="Ably customers showcase"
4
- aria-live="off"
5
- class="font-sans antialiased rounded-sm shadow-container-subtle"
6
- data-id="showcase"
7
- >
8
- <div class="ui-showcase-overflow-container">
9
- <ol class="ui-showcase-logo-wrapper" data-id="showcase-controls">
10
- <% companies_data.each_with_index do |company, index| %>
11
- <li class="ui-showcase-logo">
12
- <%= tag.button class: ['focus:outline-gui-focus', 'border-none', 'p-0', 'transition-filter'],
13
- type: 'button',
14
- data: { id: 'showcase-control' },
15
- aria: { controls: @random_id } do %>
16
- <%= image_tag company[:logo], alt: "#{company[:name]} logo", class: ['ui-showcase-logo-img', index === 0 ? 'filter-none' : 'filter-grayscale', 'hover:filter-none'], srcset: [["#{company[:logo2x]}", "2x"]] %>
17
- <% end %>
18
- </li>
19
- <% end %>
20
- </ol>
21
-
22
- <div class="ui-showcase-index-bar">
23
- <div data-id="showcase-index-bar" class="transform transition-transform w-1/<%= companies_data.size %> h-4 bg-active-orange relative"></div>
24
- </div>
25
- </div>
26
-
27
- <div class="overflow-x-hidden">
28
- <ol class="flex transform transition-transform" data-id="showcase-slides" id="<%= @random_id %>">
29
- <% companies_data.each_with_index do |company, index| %>
30
- <li
31
- class="w-full flex-shrink-0 p-24 sm:p-32 xl:p-64 bg-white"
32
- role="group"
33
- aria-roledescription="slide"
34
- aria-label="<%= index + 1 %> of <%= companies_data.size %>"
35
- >
36
- <% if company[:layout] == "quotes" %>
37
- <%= render(AblyUi::Core::Icon.new(name: "quote", size: "1.25rem", color: "text-cool-black")) %>
38
-
39
- <p class="text-quote font-light mb-24"><%= company[:quote] %></p>
40
-
41
- <div class="flex items-center">
42
- <div class="flex-shrink-0 flex-grow-0 mr-16 overflow-hidden rounded-full flex align-center justify-center w-48 h-48">
43
- <%= image_tag company[:author][:thumbnail], alt: "Picture of #{company[:author][:name]}, #{company[:author][:title]}", class: "w-48 h-48 filter-grayscale" %>
44
- </div>
45
- <div>
46
- <p class="text-p2 font-medium"><%= company[:author][:name] %></p>
47
- <p class="text-p3 font-light"><%= company[:author][:title] %></p>
48
- </div>
49
- </div>
50
- <% end %>
51
-
52
- <% if company[:layout] == "casestudies" %>
53
- <div class="flex justify-evenly text-cool-black full-width flex-col md:flex-row" data-id="showcase-casestudy">
54
- <% company[:columns].each_with_index do |col, n| %>
55
- <% if company[:columns].last == col %>
56
- <div class="flex-1 mt-40 sm:mt-0 <%= col[:classname] %>" data-id="casestudy-column">
57
- <p class="text-h4 pb-24"><%= col[:heading] %></p>
58
- <p class="text-p1 font-light"><%= col[:text] %></p>
59
- <%- if col[:button] %>
60
- <a class="ui-btn self-start p-btn mt-24" href="<%= col[:button][:href] %>"><%= col[:button][:label] %></a>
61
- <% end %>
62
- </div>
63
- <% else %>
64
- <div class="flex-1 mt-40 sm:mt-0 mr-24 sm:mr-32 xl:mr-64 <%= col[:classname] %>" data-id="casestudy-column">
65
- <p class="text-title-xl font-extra-large"><%= col[:heading] %></p>
66
- <p class="text-p1 font-light mb-0 sm:mb-32"><%= col[:text] %></p>
67
- </div>
68
- <% end %>
69
- <% end %>
70
- </div>
71
- <% end %>
72
- </li>
73
- <% end %>
74
- </ol>
75
- </div>
76
- </section>
@@ -1,180 +0,0 @@
1
- import { queryId, queryIdAll } from "../dom-query";
2
- import { remsToPixelValue } from "../css";
3
-
4
- import "./component.css";
5
-
6
- const SLIDE_SHOW_INTERVAL = 5000;
7
-
8
- const updateLogoOpacity = (logos, currentIndex) => {
9
- const visible = ["filter-grayscale", "filter-none"];
10
- const opaque = [...visible].reverse();
11
- logos.forEach((logo, i) => {
12
- logo.classList.replace(...(i === currentIndex ? visible : opaque));
13
- });
14
- };
15
-
16
- const translateX = (el, currentIndex, direction = 1) => {
17
- const percent = currentIndex * 100 * direction;
18
- el.style.transform = `translateX(${percent}%)`;
19
- };
20
-
21
- const moveControlsContainer = (controlsContainer, currentIndex) => {
22
- const { parentNode, children } = controlsContainer;
23
- const parentCenter = parentNode.clientWidth / 2;
24
- const countChildren = children.length;
25
- const widthChildren = Array.from(children)
26
- .map((el) => el.clientWidth)
27
- .reduce((a, c) => a + c);
28
-
29
- const width = widthChildren / countChildren;
30
- const firstOrLast = !currentIndex || !(countChildren - currentIndex - 1);
31
- const offsetLeft = !firstOrLast ? parentCenter - width / 2 : 0;
32
- const left = currentIndex * width - (offsetLeft >> 0);
33
-
34
- parentNode.scrollTo({ left, behavior: "smooth" });
35
- };
36
-
37
- const propertyValue = (string) => {
38
- return window
39
- .getComputedStyle(document.documentElement)
40
- .getPropertyValue(string);
41
- };
42
-
43
- const mobileBreakpoint = (pixelWidth) => {
44
- if (typeof window === "undefined") return false;
45
-
46
- // Margin for small breakpoint, but could be different in practice
47
- const estimatedMargin = 64;
48
- const breakpointEstimate = `${pixelWidth + estimatedMargin}px`;
49
-
50
- return !window.matchMedia(`(min-width: ${breakpointEstimate})`).matches;
51
- };
52
-
53
- export default (node, enableSlideshow) => {
54
- const container = node || queryId("showcase");
55
- const controls = Array.from(queryIdAll("showcase-control", container));
56
- const logos = controls.map((control) => control.querySelector("img"));
57
- const controlsContainer = queryId("showcase-controls", container);
58
- const indexBar = queryId("showcase-index-bar", container);
59
- const slides = queryId("showcase-slides", container);
60
- const slideCount = slides.children.length;
61
-
62
- const logoWidth = propertyValue("--ui-showcase-client-logo-min-width");
63
- const pixelWidth = remsToPixelValue(logoWidth) * slideCount;
64
-
65
- // dynamically adjust container width
66
- [".ui-showcase-logo-wrapper", ".ui-showcase-index-bar"].forEach((s) => {
67
- const el = container.querySelector(s);
68
- const minWidth = `${pixelWidth}px`;
69
- el.style.minWidth = minWidth;
70
- });
71
-
72
- let currentIndex = 0;
73
- let mouseover = false;
74
- let updateSlideTimeoutId;
75
-
76
- const updateSlide = (index) => {
77
- translateX(slides, index, -1);
78
- translateX(indexBar, index, 1);
79
- updateLogoOpacity(logos, index);
80
-
81
- if (mobileBreakpoint(pixelWidth)) {
82
- moveControlsContainer(controlsContainer, index);
83
- }
84
- };
85
-
86
- const scheduleSlideMove = () =>
87
- (updateSlideTimeoutId = setTimeout(() => {
88
- if (mouseover) return;
89
- if (mobileBreakpoint(pixelWidth)) return;
90
-
91
- currentIndex = (currentIndex + 1) % controls.length;
92
-
93
- updateSlide(currentIndex);
94
- scheduleSlideMove();
95
- }, SLIDE_SHOW_INTERVAL));
96
-
97
- const logoClick = () => {
98
- const clickHandler = (index) => () => {
99
- currentIndex = index;
100
- updateSlide(currentIndex);
101
- };
102
-
103
- const handlers = controls.map((control, index) => {
104
- const handler = clickHandler(index);
105
- control.addEventListener("click", handler);
106
- return handler;
107
- });
108
-
109
- return () => {
110
- handlers.forEach((handler, i) =>
111
- controls[i].removeEventListener("click", handler)
112
- );
113
- };
114
- };
115
-
116
- const pointerOverContainer = () => {
117
- const handler = () => {
118
- mouseover = true;
119
- clearTimeout(updateSlideTimeoutId);
120
- };
121
- container.addEventListener("mouseover", handler);
122
- return () => container.removeEventListener("mouseover", handler);
123
- };
124
-
125
- const pointerLeftContainer = () => {
126
- const handler = () => {
127
- mouseover = false;
128
- scheduleSlideMove();
129
- };
130
- container.addEventListener("mouseleave", handler);
131
- return () => container.removeEventListener("mouseleave", handler);
132
- };
133
-
134
- const viewportResized = () => {
135
- const handler = () => {
136
- clearTimeout(updateSlideTimeoutId);
137
- scheduleSlideMove();
138
- };
139
- document.addEventListener("resize", handler);
140
- return () => document.removeEventListener("resize", handler);
141
- };
142
-
143
- const scrollOverContainer = () => {
144
- const handler = (event) => event.preventDefault();
145
- controlsContainer.parentNode.addEventListener("wheel", handler);
146
- return () =>
147
- controlsContainer.parentNode.removeEventListener("wheel", handler);
148
- };
149
-
150
- const logoClickTeardown = logoClick();
151
- const scrollOverContainerTeardown = scrollOverContainer();
152
-
153
- const slideshowInit = () => {
154
- if (enableSlideshow) {
155
- scheduleSlideMove();
156
- container.setAttribute("aria-live", "polite");
157
-
158
- const teardowns = [
159
- pointerOverContainer(),
160
- pointerLeftContainer(),
161
- viewportResized(),
162
- ];
163
- return () => teardowns.forEach((t) => t());
164
- } else {
165
- return () => {};
166
- }
167
- };
168
-
169
- const slideshowTeardown = slideshowInit();
170
-
171
- return function teardown() {
172
- // Restore initial position
173
- updateSlide(0);
174
- clearTimeout(updateSlideTimeoutId);
175
-
176
- logoClickTeardown();
177
- slideshowTeardown();
178
- scrollOverContainerTeardown();
179
- };
180
- };
File without changes