@ably/ui 14.1.0-dev.30520a8 → 14.1.0-dev.708de27

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 (309) hide show
  1. package/core/icons/icon-gui-dropdown-arrow.svg +3 -0
  2. package/core/sprites.svg +1 -1
  3. package/core/styles/forms.css +3 -8
  4. package/package.json +2 -1
  5. package/src/.DS_Store +0 -0
  6. package/src/core/.DS_Store +0 -0
  7. package/src/core/Accordion/.DS_Store +0 -0
  8. package/src/core/Accordion/Accordion.stories.tsx +39 -0
  9. package/src/core/Accordion.tsx +149 -0
  10. package/src/core/Code/.DS_Store +0 -0
  11. package/src/core/Code/Code.stories.tsx +71 -0
  12. package/src/core/Code/component.css +1 -0
  13. package/src/core/Code/component.js +27 -0
  14. package/src/core/Code.tsx +44 -0
  15. package/src/core/ConnectStateWrapper.tsx +43 -0
  16. package/src/core/ContactFooter/.DS_Store +0 -0
  17. package/src/core/ContactFooter/ContactFooter.stories.tsx +11 -0
  18. package/src/core/ContactFooter/component.css +11 -0
  19. package/src/core/ContactFooter/component.js +2 -0
  20. package/src/core/ContactFooter.tsx +91 -0
  21. package/src/core/CookieMessage/.DS_Store +0 -0
  22. package/src/core/CookieMessage/CookieMessage.stories.tsx +12 -0
  23. package/src/core/CookieMessage/component.css +15 -0
  24. package/src/core/CookieMessage.tsx +52 -0
  25. package/src/core/CustomerLogos/.DS_Store +0 -0
  26. package/src/core/CustomerLogos/CustomerLogos.stories.tsx +43 -0
  27. package/src/core/CustomerLogos.tsx +35 -0
  28. package/src/core/DropdownMenu/.DS_Store +0 -0
  29. package/src/core/DropdownMenu/DropdownMenu.stories.tsx +48 -0
  30. package/src/core/DropdownMenu.tsx +140 -0
  31. package/src/core/Expander/Expander.stories.tsx +132 -0
  32. package/src/core/Expander.tsx +63 -0
  33. package/src/core/FeaturedLink/.DS_Store +0 -0
  34. package/src/core/FeaturedLink/FeaturedLink.stories.tsx +43 -0
  35. package/src/core/FeaturedLink.tsx +93 -0
  36. package/src/core/Flash/.DS_Store +0 -0
  37. package/src/core/Flash/Flash.stories.tsx +37 -0
  38. package/src/core/Flash/component.css +28 -0
  39. package/src/core/Flash.tsx +233 -0
  40. package/src/core/Footer/.DS_Store +0 -0
  41. package/src/core/Footer/Footer.stories.tsx +26 -0
  42. package/src/core/Footer/component.css +33 -0
  43. package/src/core/Footer.tsx +535 -0
  44. package/src/core/Icon/.DS_Store +0 -0
  45. package/src/core/Icon/Icon.stories.tsx +151 -0
  46. package/src/core/Icon.tsx +26 -0
  47. package/src/core/Loader/.DS_Store +0 -0
  48. package/src/core/Loader/Loader.stories.tsx +21 -0
  49. package/src/core/Loader.tsx +52 -0
  50. package/src/core/Logo/.DS_Store +0 -0
  51. package/src/core/Logo/Logo.stories.tsx +12 -0
  52. package/src/core/Logo.tsx +29 -0
  53. package/src/core/Meganav/.DS_Store +0 -0
  54. package/src/core/Meganav/Meganav.stories.tsx +86 -0
  55. package/src/core/Meganav/component.css +114 -0
  56. package/src/core/Meganav/component.js +150 -0
  57. package/src/core/Meganav/component.json +37 -0
  58. package/src/core/Meganav.tsx +225 -0
  59. package/src/core/MeganavBlogPostsList/.DS_Store +0 -0
  60. package/src/core/MeganavBlogPostsList/component.js +43 -0
  61. package/src/core/MeganavBlogPostsList.tsx +41 -0
  62. package/src/core/MeganavContentCompany.tsx +166 -0
  63. package/src/core/MeganavContentDevelopers.tsx +210 -0
  64. package/src/core/MeganavContentProducts.tsx +163 -0
  65. package/src/core/MeganavContentUseCases.tsx +244 -0
  66. package/src/core/MeganavControl/.DS_Store +0 -0
  67. package/src/core/MeganavControl/component.js +117 -0
  68. package/src/core/MeganavControl.tsx +39 -0
  69. package/src/core/MeganavControlMobileDropdown/.DS_Store +0 -0
  70. package/src/core/MeganavControlMobileDropdown/component.js +46 -0
  71. package/src/core/MeganavControlMobileDropdown.tsx +31 -0
  72. package/src/core/MeganavControlMobilePanelClose/.DS_Store +0 -0
  73. package/src/core/MeganavControlMobilePanelClose/component.js +36 -0
  74. package/src/core/MeganavControlMobilePanelClose.tsx +34 -0
  75. package/src/core/MeganavControlMobilePanelOpen/.DS_Store +0 -0
  76. package/src/core/MeganavControlMobilePanelOpen/component.js +59 -0
  77. package/src/core/MeganavControlMobilePanelOpen.tsx +31 -0
  78. package/src/core/MeganavItemsDesktop.tsx +68 -0
  79. package/src/core/MeganavItemsMobile.tsx +197 -0
  80. package/src/core/MeganavItemsSignedIn.tsx +130 -0
  81. package/src/core/MeganavSearch.tsx +36 -0
  82. package/src/core/MeganavSearchAutocomplete/.DS_Store +0 -0
  83. package/src/core/MeganavSearchAutocomplete/component.js +177 -0
  84. package/src/core/MeganavSearchAutocomplete.tsx +12 -0
  85. package/src/core/MeganavSearchPanel.tsx +52 -0
  86. package/src/core/MeganavSearchSuggestions/.DS_Store +0 -0
  87. package/src/core/MeganavSearchSuggestions/component.js +133 -0
  88. package/src/core/MeganavSearchSuggestions.tsx +62 -0
  89. package/src/core/Notice/.DS_Store +0 -0
  90. package/src/core/Notice/component.css +7 -0
  91. package/src/core/Notice/component.js +154 -0
  92. package/src/core/Notice.tsx +102 -0
  93. package/src/core/SignOutLink.tsx +51 -0
  94. package/src/core/Slider/.DS_Store +0 -0
  95. package/src/core/Slider/Slider.stories.tsx +98 -0
  96. package/src/core/Slider/component.css +40 -0
  97. package/src/core/Slider/component.js +105 -0
  98. package/src/core/Slider.tsx +224 -0
  99. package/src/core/Table/.DS_Store +0 -0
  100. package/src/core/Table/Table.stories.tsx +12 -0
  101. package/src/core/Table/Table.tsx +58 -0
  102. package/src/core/Table/TableCell.tsx +71 -0
  103. package/src/core/Table/TableRow.tsx +25 -0
  104. package/src/core/Table/data.tsx +133 -0
  105. package/src/core/Table.tsx +15 -0
  106. package/src/core/Tooltip/.DS_Store +0 -0
  107. package/src/core/Tooltip/Tooltip.stories.tsx +27 -0
  108. package/src/core/Tooltip.tsx +88 -0
  109. package/src/core/css.js +3 -0
  110. package/src/core/dom-query.js +5 -0
  111. package/src/core/fonts/NEXT-Book-Light-Italic.eot +0 -0
  112. package/src/core/fonts/NEXT-Book-Light-Italic.otf +0 -0
  113. package/src/core/fonts/NEXT-Book-Light-Italic.woff +0 -0
  114. package/src/core/fonts/NEXT-Book-Light-Italic.woff2 +0 -0
  115. package/src/core/fonts/NEXT-Book-Light.eot +0 -0
  116. package/src/core/fonts/NEXT-Book-Light.otf +0 -0
  117. package/src/core/fonts/NEXT-Book-Light.woff +0 -0
  118. package/src/core/fonts/NEXT-Book-Light.woff2 +0 -0
  119. package/src/core/fonts/NEXT-Book-Medium-Italic.eot +0 -0
  120. package/src/core/fonts/NEXT-Book-Medium-Italic.otf +0 -0
  121. package/src/core/fonts/NEXT-Book-Medium-Italic.woff +0 -0
  122. package/src/core/fonts/NEXT-Book-Medium-Italic.woff2 +0 -0
  123. package/src/core/fonts/NEXT-Book-Medium.eot +0 -0
  124. package/src/core/fonts/NEXT-Book-Medium.otf +0 -0
  125. package/src/core/fonts/NEXT-Book-Medium.woff +0 -0
  126. package/src/core/fonts/NEXT-Book-Medium.woff2 +0 -0
  127. package/src/core/fonts/jetBrains-mono.css +3 -0
  128. package/src/core/fonts/manrope.css +3 -0
  129. package/src/core/fonts/next.css +63 -0
  130. package/src/core/fonts/source-code-pro.css +3 -0
  131. package/src/core/hubspot-chat-toggle.js +67 -0
  132. package/src/core/icons/discord.svg +10 -0
  133. package/src/core/icons/facebook.svg +4 -0
  134. package/src/core/icons/github.svg +3 -0
  135. package/src/core/icons/glassdoor.svg +3 -0
  136. package/src/core/icons/google.svg +3 -0
  137. package/src/core/icons/icon-display-48hrs.svg +3 -0
  138. package/src/core/icons/icon-display-about-ably-col.svg +4 -0
  139. package/src/core/icons/icon-display-api-keys.svg +3 -0
  140. package/src/core/icons/icon-display-api.svg +3 -0
  141. package/src/core/icons/icon-display-asset-tracking-col.svg +18 -0
  142. package/src/core/icons/icon-display-browser.svg +10 -0
  143. package/src/core/icons/icon-display-calendar.svg +3 -0
  144. package/src/core/icons/icon-display-call-mobile.svg +3 -0
  145. package/src/core/icons/icon-display-careers-col.svg +9 -0
  146. package/src/core/icons/icon-display-case-studies-col.svg +5 -0
  147. package/src/core/icons/icon-display-chat-col.svg +4 -0
  148. package/src/core/icons/icon-display-chat-stack-col.svg +4 -0
  149. package/src/core/icons/icon-display-chat-stack.svg +4 -0
  150. package/src/core/icons/icon-display-cloud-servers.svg +3 -0
  151. package/src/core/icons/icon-display-compare-tech-col.svg +9 -0
  152. package/src/core/icons/icon-display-customers-col.svg +15 -0
  153. package/src/core/icons/icon-display-data-broadcast-col.svg +26 -0
  154. package/src/core/icons/icon-display-data-synchronization-col.svg +14 -0
  155. package/src/core/icons/icon-display-docs-col.svg +7 -0
  156. package/src/core/icons/icon-display-documentation.svg +3 -0
  157. package/src/core/icons/icon-display-events-col.svg +13 -0
  158. package/src/core/icons/icon-display-examples-col.svg +11 -0
  159. package/src/core/icons/icon-display-gdpr.svg +3 -0
  160. package/src/core/icons/icon-display-general-comms.svg +3 -0
  161. package/src/core/icons/icon-display-hipaa.svg +10 -0
  162. package/src/core/icons/icon-display-integrations-col.svg +8 -0
  163. package/src/core/icons/icon-display-it-support-access.svg +3 -0
  164. package/src/core/icons/icon-display-it-support-helpdesk.svg +3 -0
  165. package/src/core/icons/icon-display-kafka-at-the-edge-col.svg +8 -0
  166. package/src/core/icons/icon-display-laptop.svg +10 -0
  167. package/src/core/icons/icon-display-lightbulb-col.svg +10 -0
  168. package/src/core/icons/icon-display-live-chat.svg +3 -0
  169. package/src/core/icons/icon-display-map-pin.svg +3 -0
  170. package/src/core/icons/icon-display-message.svg +3 -0
  171. package/src/core/icons/icon-display-padlock-closed.svg +3 -0
  172. package/src/core/icons/icon-display-platform.svg +22 -0
  173. package/src/core/icons/icon-display-play.svg +3 -0
  174. package/src/core/icons/icon-display-privacy-shield-framework.svg +7 -0
  175. package/src/core/icons/icon-display-push-notifications-col.svg +6 -0
  176. package/src/core/icons/icon-display-quickstart-guides-col.svg +8 -0
  177. package/src/core/icons/icon-display-resources-col.svg +21 -0
  178. package/src/core/icons/icon-display-sdks-col.svg +11 -0
  179. package/src/core/icons/icon-display-servers.svg +3 -0
  180. package/src/core/icons/icon-display-shopping-cart.svg +10 -0
  181. package/src/core/icons/icon-display-sla.svg +3 -0
  182. package/src/core/icons/icon-display-soc2-type2.svg +3 -0
  183. package/src/core/icons/icon-display-tech-account-comms.svg +3 -0
  184. package/src/core/icons/icon-display-tutorials-demos-col.svg +25 -0
  185. package/src/core/icons/icon-display-virtual-events-col.svg +12 -0
  186. package/src/core/icons/icon-display-virtual-events.svg +12 -0
  187. package/src/core/icons/icon-gui-ably-badge.svg +3 -0
  188. package/src/core/icons/icon-gui-arrow-bidirectional-horizontal.svg +3 -0
  189. package/src/core/icons/icon-gui-arrow-bidirectional-vertical.svg +3 -0
  190. package/src/core/icons/icon-gui-arrow-down.svg +3 -0
  191. package/src/core/icons/icon-gui-arrow-left.svg +3 -0
  192. package/src/core/icons/icon-gui-arrow-right.svg +3 -0
  193. package/src/core/icons/icon-gui-arrow-up.svg +3 -0
  194. package/src/core/icons/icon-gui-burger-menu.svg +5 -0
  195. package/src/core/icons/icon-gui-check-circled-fill-black.svg +4 -0
  196. package/src/core/icons/icon-gui-check-circled-fill.svg +4 -0
  197. package/src/core/icons/icon-gui-check-circled.svg +3 -0
  198. package/src/core/icons/icon-gui-checklist-checked.svg +3 -0
  199. package/src/core/icons/icon-gui-clock.svg +3 -0
  200. package/src/core/icons/icon-gui-close.svg +3 -0
  201. package/src/core/icons/icon-gui-copy.svg +10 -0
  202. package/src/core/icons/icon-gui-cross-circled-fill.svg +4 -0
  203. package/src/core/icons/icon-gui-cross-circled.svg +3 -0
  204. package/src/core/icons/icon-gui-dash-circled.svg +3 -0
  205. package/src/core/icons/icon-gui-disclosure-arrow.svg +3 -0
  206. package/src/core/icons/icon-gui-document-generic.svg +3 -0
  207. package/src/core/icons/icon-gui-dropdown-arrow.svg +3 -0
  208. package/src/core/icons/icon-gui-enlarge.svg +3 -0
  209. package/src/core/icons/icon-gui-external-link.svg +3 -0
  210. package/src/core/icons/icon-gui-filter-flow-step-1.svg +5 -0
  211. package/src/core/icons/icon-gui-filter-flow-step-2.svg +5 -0
  212. package/src/core/icons/icon-gui-filter-flow-step-3.svg +5 -0
  213. package/src/core/icons/icon-gui-history.svg +3 -0
  214. package/src/core/icons/icon-gui-info.svg +3 -0
  215. package/src/core/icons/icon-gui-link-arrow.svg +3 -0
  216. package/src/core/icons/icon-gui-link.svg +4 -0
  217. package/src/core/icons/icon-gui-live-chat.svg +3 -0
  218. package/src/core/icons/icon-gui-minus.svg +3 -0
  219. package/src/core/icons/icon-gui-partial.svg +4 -0
  220. package/src/core/icons/icon-gui-plus.svg +3 -0
  221. package/src/core/icons/icon-gui-quote-marks-solid.svg +3 -0
  222. package/src/core/icons/icon-gui-refresh.svg +10 -0
  223. package/src/core/icons/icon-gui-resources.svg +3 -0
  224. package/src/core/icons/icon-gui-search.svg +3 -0
  225. package/src/core/icons/icon-gui-tick.svg +3 -0
  226. package/src/core/icons/icon-gui-warning.svg +5 -0
  227. package/src/core/icons/icon-live-updates-results-metrics-col.svg +26 -0
  228. package/src/core/icons/icon-multi-user-spaces-col.svg +13 -0
  229. package/src/core/icons/icon-social-x.svg +3 -0
  230. package/src/core/icons/icon-tech-apachekafka.svg +3 -0
  231. package/src/core/icons/linkedin.svg +3 -0
  232. package/src/core/icons/quote.svg +3 -0
  233. package/src/core/icons/stackoverflow.svg +3 -0
  234. package/src/core/icons/twitter.svg +3 -0
  235. package/src/core/icons/youtube.svg +11 -0
  236. package/src/core/icons.js +6 -0
  237. package/src/core/images/ably-logo.png +0 -0
  238. package/src/core/images/ably-logo.svg +15 -0
  239. package/src/core/images/ably-stack.svg +14 -0
  240. package/src/core/images/best-support-2023.svg +1 -0
  241. package/src/core/images/cust-logo-ao-col-pos.png +0 -0
  242. package/src/core/images/cust-logo-ao-col-pos@2x.png +0 -0
  243. package/src/core/images/cust-logo-ausopen-col-pos.png +0 -0
  244. package/src/core/images/cust-logo-ausopen-col-pos@2x.png +0 -0
  245. package/src/core/images/cust-logo-ausopen-mono-pos.svg +5 -0
  246. package/src/core/images/cust-logo-bloomberg-mono-pos.svg +11 -0
  247. package/src/core/images/cust-logo-hopin-mono-pos.svg +4 -0
  248. package/src/core/images/cust-logo-hubspot-col-pos.png +0 -0
  249. package/src/core/images/cust-logo-hubspot-col-pos@2x.png +0 -0
  250. package/src/core/images/cust-logo-hubspot-mono-pos.svg +4 -0
  251. package/src/core/images/cust-logo-lightspeed-col-pos.png +0 -0
  252. package/src/core/images/cust-logo-lightspeed-col-pos@2x.png +0 -0
  253. package/src/core/images/cust-logo-lightspeed-syst-col-pos.png +0 -0
  254. package/src/core/images/cust-logo-lightspeed-syst-col-pos@2x.png +0 -0
  255. package/src/core/images/cust-logo-mentimeter-mono-pos.svg +17 -0
  256. package/src/core/images/cust-logo-split-col-pos.png +0 -0
  257. package/src/core/images/cust-logo-split-col-pos@2x.png +0 -0
  258. package/src/core/images/cust-logo-split-mono-pos.svg +9 -0
  259. package/src/core/images/cust-logo-toyota-mono-pos.svg +18 -0
  260. package/src/core/images/cust-logo-vitac-col-pos.png +0 -0
  261. package/src/core/images/cust-logo-vitac-col-pos@2x.png +0 -0
  262. package/src/core/images/cust-logo-webflow-col-pos.svg +3 -0
  263. package/src/core/images/cust-photo-hubspot-max-freiert.jpg +0 -0
  264. package/src/core/images/cust-photo-split-pato-echague.jpg +0 -0
  265. package/src/core/images/cust-photo-vitac-joe-antonio.jpg +0 -0
  266. package/src/core/images/fastest-implementation-2023.svg +1 -0
  267. package/src/core/images/flexible-companies.png +0 -0
  268. package/src/core/images/high-performer-2022.png +0 -0
  269. package/src/core/images/high-performer-2023.svg +1 -0
  270. package/src/core/images/highest-user-adoption-2022.png +0 -0
  271. package/src/core/images/highest-user-adoption-2023.svg +1 -0
  272. package/src/core/images/icon-tech-aws.svg +4 -0
  273. package/src/core/images/rocket-list-2021.png +0 -0
  274. package/src/core/images/scale-motif-open-empathetic.svg +1 -0
  275. package/src/core/images/technical-support-01-800x533.jpg +0 -0
  276. package/src/core/images/users-love-us-2022.png +0 -0
  277. package/src/core/load-sprites.js +11 -0
  278. package/src/core/react-renderer.tsx +29 -0
  279. package/src/core/remote-blogs-posts.js +42 -0
  280. package/src/core/remote-data-store.js +34 -0
  281. package/src/core/remote-data-util.js +4 -0
  282. package/src/core/remote-session-data.js +58 -0
  283. package/src/core/scripts.js +10 -0
  284. package/src/core/styles/Dropdown.stories.tsx +49 -0
  285. package/src/core/styles/Toggle.stories.tsx +41 -0
  286. package/src/core/styles/buttons.css +124 -0
  287. package/src/core/styles/forms.css +83 -0
  288. package/src/core/styles/layout.css +21 -0
  289. package/src/core/styles/properties.css +278 -0
  290. package/src/core/styles/text.css +168 -0
  291. package/src/core/styles/toggles.css +38 -0
  292. package/src/core/styles.base.css +1 -0
  293. package/src/core/styles.components.css +44 -0
  294. package/src/core/styles.css +2 -0
  295. package/src/core/url-base.js +7 -0
  296. package/src/core/utils/syntax-highlighter-registry.js +63 -0
  297. package/src/core/utils/syntax-highlighter.css +71 -0
  298. package/src/core/utils/syntax-highlighter.js +103 -0
  299. package/src/pages/Buttons.mdx +121 -0
  300. package/src/pages/Chips.mdx +136 -0
  301. package/src/pages/Colour.mdx +23 -0
  302. package/src/pages/Forms.mdx +219 -0
  303. package/src/pages/Layout.mdx +58 -0
  304. package/src/pages/Typography.mdx +206 -0
  305. package/src/pages/utils.ts +80 -0
  306. package/src/reset/scripts.js +1 -0
  307. package/src/reset/styles/normalize.css +353 -0
  308. package/src/reset/styles/reset.css +139 -0
  309. package/src/reset/styles.css +2 -0
@@ -0,0 +1,102 @@
1
+ import React, { ReactNode, useEffect } from "react";
2
+
3
+ import NoticeScripts from "./Notice/component.js";
4
+ import Icon from "./Icon";
5
+ type ContentWrapperProps = {
6
+ buttonLink: string;
7
+ children: ReactNode;
8
+ };
9
+
10
+ // TODO(jamiehenson):
11
+ // This type is a bit messed up currently due to the NoticeScripts import being interpreted as NoticeProps.
12
+ // Plan is to TS-ify the JS assets too, so this can be rectified then. The NoticeScripts-oriented props are
13
+ // the ones after the line break.
14
+ type NoticeProps = {
15
+ buttonLink?: string;
16
+ buttonLabel?: string;
17
+ bodyText?: string;
18
+ title?: string;
19
+ closeBtn?: boolean;
20
+ config?: {
21
+ collapse: boolean;
22
+ noticeId: string;
23
+ cookieId: string;
24
+ };
25
+ bgColor?: string;
26
+ textColor?: string;
27
+
28
+ bannerContainer?: Element | null;
29
+ cookieId?: string;
30
+ noticeId?: string;
31
+ options?: { collapse: boolean };
32
+ };
33
+
34
+ const contentWrapperClasses = "w-full pr-8 ui-text-p3 self-center";
35
+
36
+ const ContentWrapper = ({ buttonLink, children }: ContentWrapperProps) =>
37
+ buttonLink ? (
38
+ <a href={buttonLink} className={contentWrapperClasses}>
39
+ {children}
40
+ </a>
41
+ ) : (
42
+ <div className={contentWrapperClasses}>{children}</div>
43
+ );
44
+
45
+ const Notice = ({
46
+ buttonLink,
47
+ buttonLabel,
48
+ bodyText,
49
+ title,
50
+ config,
51
+ closeBtn,
52
+ bgColor = "bg-gradient-active-orange",
53
+ textColor = "text-white",
54
+ }: NoticeProps) => {
55
+ useEffect(() => {
56
+ NoticeScripts({
57
+ bannerContainer: document.querySelector('[data-id="ui-notice"]'),
58
+ cookieId: config?.cookieId,
59
+ noticeId: config?.noticeId,
60
+ options: {
61
+ collapse: config?.collapse || false,
62
+ },
63
+ });
64
+ }, []);
65
+
66
+ const wrapperClasses = ["ui-announcement", bgColor, textColor].join(" ");
67
+
68
+ return (
69
+ <div
70
+ className={wrapperClasses}
71
+ data-id="ui-notice"
72
+ style={{ maxHeight: 0, overflow: "hidden" }}
73
+ >
74
+ <div className="ui-grid-px py-16 max-w-screen-xl mx-auto flex items-start">
75
+ <ContentWrapper buttonLink={buttonLink ?? "#"}>
76
+ <strong className="font-bold whitespace-nowrap pr-4">{title}</strong>
77
+ <span className="pr-4">{bodyText}</span>
78
+ {buttonLabel && (
79
+ <span className="underline cursor-pointer whitespace-nowrap">
80
+ {buttonLabel}
81
+ </span>
82
+ )}
83
+ </ContentWrapper>
84
+
85
+ {closeBtn && (
86
+ <button
87
+ type="button"
88
+ className="ml-auto h-20 w-20 border-none bg-none self-baseline"
89
+ >
90
+ <Icon
91
+ name="icon-gui-close"
92
+ size="1.25rem"
93
+ color="text-cool-black"
94
+ />
95
+ </button>
96
+ )}
97
+ </div>
98
+ </div>
99
+ );
100
+ };
101
+
102
+ export default Notice;
@@ -0,0 +1,51 @@
1
+ import React, { MouseEventHandler, ReactNode, useRef } from "react";
2
+ import { AbsUrl } from "./Meganav";
3
+
4
+ type SignOutLinkProps = {
5
+ token: string;
6
+ href: string;
7
+ text: string;
8
+ children: ({
9
+ href,
10
+ text,
11
+ onClick,
12
+ }: {
13
+ href: string;
14
+ text: string;
15
+ onClick: MouseEventHandler<HTMLAnchorElement>;
16
+ }) => ReactNode;
17
+ absUrl: AbsUrl;
18
+ };
19
+
20
+ const SignOutLink = ({
21
+ token,
22
+ href,
23
+ text,
24
+ children,
25
+ absUrl,
26
+ }: SignOutLinkProps) => {
27
+ const formRef = useRef<HTMLFormElement>(null);
28
+
29
+ const onClick = (e) => {
30
+ formRef.current?.submit();
31
+ e.preventDefault();
32
+ };
33
+
34
+ return (
35
+ <>
36
+ <form
37
+ ref={formRef}
38
+ method="post"
39
+ action={absUrl(href)}
40
+ className="hidden"
41
+ >
42
+ <input name="_method" value="delete" type="hidden" />
43
+ <input name="authenticity_token" value={token} type="hidden" />
44
+ </form>
45
+
46
+ {children({ href, text, onClick })}
47
+ </>
48
+ );
49
+ };
50
+
51
+ export default SignOutLink;
Binary file
@@ -0,0 +1,98 @@
1
+ import React from "react";
2
+ import Slider from "../Slider";
3
+ import Icon from "../Icon";
4
+
5
+ const Slide = ({ name }: { name: string }) => (
6
+ <div className="relative ">
7
+ <div className="relative w-full sm:w-[560px] md:w-[784px] lg:w-[960px] bg-white overflow-hidden flex gap-40 rounded-3xl shadow-container-subtle">
8
+ <div className="w-full md:w-2/3 flex flex-col gap-24 pr-40 md:pr-0 pt-40 pl-40 pb-40 sm:pb-[120px] md:pb-40">
9
+ <h2 className="ui-text-h2 font-medium text-neutral-1000">
10
+ “Ably seamlessly absorbs sudden bursts in load during unexpected
11
+ client events. The integration was easy and we were live in under a
12
+ month.”
13
+ </h2>
14
+ <div className="flex flex-col sm:flex-row gap-32">
15
+ <div className="flex gap-8">
16
+ <div className="static self-center sm:absolute sm:-bottom-48 sm:-right-[56px] rounded-full bg-gradient-to-l from-neutral-200 to-50% to-neutral-500 w-[48px] h-[48px] sm:w-[201px] sm:h-[201px] md:w-[257px] md:h-[257px] lg:w-[280px] lg:h-[280px] overflow-hidden flex items-center justify-center sm:border-[16px] border-neutral-200">
17
+ <img src="https://picsum.photos/id/64/200" alt="test-image" />
18
+ </div>
19
+ <div className="sm:py-16">
20
+ <p className="ui-text-p1 text-neutral-1300">{name}</p>
21
+ <p className="ui-text-p3 text-neutral-800">
22
+ Co-Founder & Technical Leader
23
+ </p>
24
+ </div>
25
+ </div>
26
+
27
+ <div className="w-[80px] h-1 sm:w-1 sm:h-full bg-neutral-500"></div>
28
+ <div className="flex items-center gap-4">
29
+ <img src="https://picsum.photos/id/145/40" alt="test-image" />
30
+ <p className="ui-text-h4 font-bold">Mentimeter</p>
31
+ </div>
32
+ </div>
33
+ <a href="/case-study" className="ui-btn self-start">
34
+ Read case study
35
+ <Icon
36
+ name="icon-gui-arrow-right"
37
+ size="1.25rem"
38
+ additionalCSS="ml-4"
39
+ />
40
+ </a>
41
+ </div>
42
+ </div>
43
+
44
+ <div className="absolute h-256 -z-10 -bottom-48 -left-36 w-1/5 rounded-full blur-xl opacity-50 transform -rotate-45 bg-gradient-to-bl from-bg-glow-green to-bg-glow-teal"></div>
45
+ <div className="absolute h-256 -z-10 -top-48 -right-48 w-3/5 rounded-full blur-xl opacity-50 transform rotate-12 bg-gradient-to-br from-bg-glow-green to-bg-glow-teal"></div>
46
+ </div>
47
+ );
48
+
49
+ const slides = [
50
+ <Slide key="1" name={"Johan Bengtsson"} />,
51
+ <Slide key="2" name={"Mirko Bergman"} />,
52
+ <Slide key="3" name={"Stefania Lombardo"} />,
53
+ <Slide key="4" name={"Aleksandar Kostadinov"} />,
54
+ ];
55
+
56
+ export default {
57
+ title: "JS Components/Slider",
58
+ component: Slider,
59
+ args: {
60
+ children: slides,
61
+ options: {
62
+ interval: 10000,
63
+ intervalIndicator: true,
64
+ controlPosition: "floating",
65
+ },
66
+ },
67
+ };
68
+
69
+ export const FloatingControlPosition = {
70
+ args: {
71
+ children: slides,
72
+ options: {
73
+ interval: 10000,
74
+ intervalIndicator: true,
75
+ controlPosition: "floating",
76
+ },
77
+ },
78
+ };
79
+
80
+ export const InlineControlPosition = {
81
+ args: {
82
+ options: {
83
+ interval: 10000,
84
+ intervalIndicator: true,
85
+ controlPosition: "inline",
86
+ },
87
+ },
88
+ };
89
+
90
+ export const WithoutIntervalIndicator = {
91
+ args: {
92
+ options: {
93
+ interval: 10000,
94
+ intervalIndicator: false,
95
+ controlPosition: "floating",
96
+ },
97
+ },
98
+ };
@@ -0,0 +1,40 @@
1
+ @layer components {
2
+ .ui-slider-marker {
3
+ font-size: 0.5rem;
4
+ top: -1px;
5
+
6
+ @apply leading-none px-4 relative;
7
+ }
8
+
9
+ @keyframes fillAnimation {
10
+ 0% {
11
+ width: 0%;
12
+ }
13
+ 100% {
14
+ width: 100%;
15
+ }
16
+ }
17
+
18
+ .ui-icon-cta {
19
+ @apply cursor-pointer overflow-hidden;
20
+ @apply rounded border-2 border-mid-grey hover:border-active-orange;
21
+ transition: all 0.4s;
22
+ }
23
+
24
+ @screen sm {
25
+ .ui-icon-cta-left:hover .ui-icon-cta-holder {
26
+ transform: translateX(-100%);
27
+ }
28
+ .ui-icon-cta-right .ui-icon-cta-holder {
29
+ transform: translateX(-100%);
30
+ }
31
+ .ui-icon-cta-right:hover .ui-icon-cta-holder {
32
+ transform: translateX(0%);
33
+ }
34
+ }
35
+
36
+ .ui-icon-cta-holder {
37
+ @apply w-full h-full;
38
+ transition: all 0.4s;
39
+ }
40
+ }
@@ -0,0 +1,105 @@
1
+ import throttle from "lodash.throttle";
2
+
3
+ import { queryId, queryIdAll } from "../dom-query";
4
+
5
+ const mdBreakpoint = () => window.matchMedia("(min-width: 48rem)").matches;
6
+ const DRAG_BUFFER = 20;
7
+
8
+ const init = (slidesContainer) => {
9
+ const transformContainer = queryId("slider-strip", slidesContainer);
10
+ const slides = Array.from(queryIdAll("slider-slide", slidesContainer));
11
+ const slideLeftChevron = queryId("slider-previous", slidesContainer);
12
+ const slideRightChevron = queryId("slider-next", slidesContainer);
13
+ const slideMarkers = Array.from(queryIdAll("slider-marker", slidesContainer));
14
+ const sliderControls = queryId("slider-controls", slidesContainer);
15
+
16
+ sliderControls.classList.replace("hidden", "flex");
17
+ const slidesLength = slides.length;
18
+
19
+ const slidesWidth = slidesContainer.getBoundingClientRect().width;
20
+ const { width: slideWidth, left: slideLeftDistance } =
21
+ slides[0].getBoundingClientRect();
22
+ const { left: slideLeftDistanceSecond } = slides[1].getBoundingClientRect();
23
+ const slideGap = slideLeftDistanceSecond - slideLeftDistance - slideWidth;
24
+ const adjustment = (slidesWidth - slideWidth) / 2;
25
+
26
+ let currentIndex = 0;
27
+ let touchStartX = 0;
28
+
29
+ const calculateTransform = (index) =>
30
+ index * -slideWidth + adjustment + index * -slideGap;
31
+
32
+ const updateSlide = (index) =>
33
+ (transformContainer.style.transform = `translateX(${calculateTransform(
34
+ index,
35
+ )}px)`);
36
+
37
+ const updateMarkers = (index) => {
38
+ slideMarkers.forEach((marker) =>
39
+ marker.classList.remove("text-active-orange"),
40
+ );
41
+ slideMarkers[index].classList.remove("text-cool-black");
42
+ slideMarkers[index].classList.add("text-active-orange");
43
+ };
44
+
45
+ const slideLeft = () => {
46
+ currentIndex = currentIndex - 1 <= 0 ? 0 : currentIndex - 1;
47
+ updateSlide(currentIndex);
48
+ updateMarkers(currentIndex);
49
+ };
50
+
51
+ const slideRight = () => {
52
+ currentIndex =
53
+ currentIndex + 1 >= slidesLength ? currentIndex : currentIndex + 1;
54
+ updateSlide(currentIndex);
55
+ updateMarkers(currentIndex);
56
+ };
57
+
58
+ updateSlide(0);
59
+ updateMarkers(0);
60
+
61
+ slideLeftChevron.addEventListener("click", slideLeft);
62
+
63
+ transformContainer.addEventListener("touchstart", (e) => {
64
+ touchStartX = e.touches[0]?.clientX;
65
+ });
66
+
67
+ transformContainer.addEventListener("touchend", (e) => {
68
+ const distance = e.changedTouches[0]?.clientX - touchStartX;
69
+
70
+ // Prevent sliding on clicks
71
+ if (Math.abs(distance) < DRAG_BUFFER) return;
72
+
73
+ const direction = distance > 0 ? slideLeft : slideRight;
74
+ direction();
75
+ });
76
+
77
+ slideRightChevron.addEventListener("click", slideRight);
78
+
79
+ return () => {
80
+ transformContainer.style.transform = null;
81
+ sliderControls.classList.replace("flex", "hidden");
82
+ };
83
+ };
84
+
85
+ const Slider = ({ container, mqEnableThreshold }) => {
86
+ if (!container) return;
87
+
88
+ const breakpointCheck = mqEnableThreshold || (() => !mdBreakpoint());
89
+
90
+ let unmount = () => {};
91
+ if (breakpointCheck()) unmount = init(container);
92
+
93
+ window.addEventListener(
94
+ "resize",
95
+ throttle(() => {
96
+ if (breakpointCheck()) {
97
+ unmount = init(container);
98
+ } else {
99
+ unmount();
100
+ }
101
+ }, 100),
102
+ );
103
+ };
104
+
105
+ export default Slider;
@@ -0,0 +1,224 @@
1
+ import React, { useState, useEffect, useRef, ReactNode } from "react";
2
+ import Icon from "./Icon";
3
+
4
+ interface SliderProps {
5
+ children: ReactNode[];
6
+ options?: {
7
+ interval?: number;
8
+ controlPosition?: "inline" | "floating";
9
+ intervalIndicator?: boolean;
10
+ };
11
+ }
12
+
13
+ interface SliderIndicatorProps {
14
+ numSlides: number;
15
+ activeIndex: number;
16
+ interval: number;
17
+ intervalIndicator?: boolean;
18
+ isInline?: boolean;
19
+ }
20
+
21
+ const SLIDE_TRANSITION_LENGTH = 300;
22
+
23
+ const SlideIndicator = ({
24
+ numSlides,
25
+ activeIndex,
26
+ interval,
27
+ intervalIndicator,
28
+ isInline,
29
+ }: SliderIndicatorProps) => {
30
+ return (
31
+ <ul
32
+ className={`flex gap-4 left-1/2 ${
33
+ isInline ? "bottom-0" : "absolute bottom-0 transform -translate-x-1/2"
34
+ }`}
35
+ >
36
+ {Array.from({ length: numSlides }, (_, i) =>
37
+ intervalIndicator ? (
38
+ <li
39
+ key={i}
40
+ className="relative w-40 h-4 mx-1 rounded-full bg-neutral-500"
41
+ >
42
+ {i === activeIndex && (
43
+ <span
44
+ className="absolute inset-0 rounded-full bg-active-orange"
45
+ style={{
46
+ animation: `fillAnimation ${interval}ms linear`,
47
+ }}
48
+ ></span>
49
+ )}
50
+ </li>
51
+ ) : (
52
+ <li key={i}>
53
+ <span
54
+ className={`ui-slider-marker ${
55
+ i === activeIndex ? "text-active-orange" : "text-cool-black"
56
+ }`}
57
+ data-id="slider-marker"
58
+ >
59
+ &#x2b24;
60
+ </span>
61
+ </li>
62
+ ),
63
+ )}
64
+ </ul>
65
+ );
66
+ };
67
+
68
+ const setupSlides = (children: ReactNode[], activeIndex: number) => [
69
+ children[activeIndex === 0 ? children.length - 1 : activeIndex - 1],
70
+ children[activeIndex],
71
+ children[activeIndex === children.length - 1 ? 0 : activeIndex + 1],
72
+ ];
73
+
74
+ const Slider = ({ children, options }: SliderProps) => {
75
+ const [activeIndex, setActiveIndex] = useState(0);
76
+ const [touchStartX, setTouchStartX] = useState(0);
77
+ const [touchEndX, setTouchEndX] = useState(0);
78
+ const [slides, setSlides] = useState<ReactNode[]>(
79
+ setupSlides(children, activeIndex),
80
+ );
81
+ const [translationCoefficient, setTranslationCoefficient] = useState(0);
82
+ const timerRef = useRef<NodeJS.Timeout | null>(null);
83
+ const [slideLock, setSlideLock] = useState(false);
84
+
85
+ const isInline = options?.controlPosition === "inline";
86
+
87
+ const next = () => {
88
+ if (!slideLock) {
89
+ setActiveIndex((prevIndex) => (prevIndex + 1) % children.length);
90
+ setTranslationCoefficient(1);
91
+ resetInterval();
92
+ setSlideLock(true);
93
+ }
94
+ };
95
+
96
+ const prev = () => {
97
+ if (!slideLock) {
98
+ setActiveIndex((prevIndex) =>
99
+ prevIndex > 0 ? prevIndex - 1 : children.length - 1,
100
+ );
101
+ setTranslationCoefficient(-1);
102
+ resetInterval();
103
+ setSlideLock(true);
104
+ }
105
+ };
106
+
107
+ const resetInterval = () => {
108
+ if (timerRef.current) clearInterval(timerRef.current);
109
+ timerRef.current = setInterval(next, options?.interval ?? 10000);
110
+ };
111
+
112
+ const handleTouchStart = (e) => {
113
+ setTouchStartX(e.touches[0].clientX);
114
+ };
115
+
116
+ const handleTouchMove = (e) => {
117
+ setTouchEndX(e.touches[0].clientX);
118
+ };
119
+
120
+ const handleTouchEnd = () => {
121
+ if (touchStartX - touchEndX > 50) {
122
+ next();
123
+ }
124
+ if (touchStartX - touchEndX < -50) {
125
+ prev();
126
+ }
127
+ };
128
+
129
+ useEffect(() => {
130
+ resetInterval();
131
+ return () => {
132
+ if (timerRef.current) clearInterval(timerRef.current);
133
+ };
134
+ }, [children.length, options?.interval]);
135
+
136
+ useEffect(() => {
137
+ setTimeout(() => {
138
+ setSlides(setupSlides(children, activeIndex));
139
+ setTranslationCoefficient(0);
140
+ setSlideLock(false);
141
+ }, SLIDE_TRANSITION_LENGTH);
142
+ }, [activeIndex]);
143
+
144
+ return (
145
+ <div
146
+ className="relative"
147
+ onTouchStart={handleTouchStart}
148
+ onTouchMove={handleTouchMove}
149
+ onTouchEnd={handleTouchEnd}
150
+ >
151
+ <div className="overflow-y-visible overflow-x-clip w-full py-40">
152
+ <div
153
+ className={`flex items-center ${
154
+ translationCoefficient !== 0
155
+ ? `transition-transform ease-in-out duration-${SLIDE_TRANSITION_LENGTH}`
156
+ : ""
157
+ } `}
158
+ style={{
159
+ transform: `translateX(-${(translationCoefficient + 1) * 100}%)`,
160
+ }}
161
+ >
162
+ {slides.map((child, index) => (
163
+ <div
164
+ key={index}
165
+ className="w-full flex-shrink-0 flex justify-center sm:px-60"
166
+ >
167
+ {child}
168
+ </div>
169
+ ))}
170
+ </div>
171
+ </div>
172
+
173
+ <div
174
+ className={`flex items-center pointer-events-none ${
175
+ isInline
176
+ ? "ui-standard-container justify-center gap-24 -mt-16"
177
+ : "sm:flex sm:absolute inset-0 justify-between"
178
+ }`}
179
+ >
180
+ <button
181
+ className={`${
182
+ isInline ? "w-32 h-32" : "hidden sm:flex w-48 h-48"
183
+ } pointer-events-auto rounded border border-mid-grey hover:border-active-orange flex justify-center items-center ui-icon-cta ui-icon-cta-left`}
184
+ onClick={prev}
185
+ >
186
+ <div className="ui-icon-cta-holder flex w-48">
187
+ <div className="w-full h-full flex-shrink-0 flex items-center justify-center">
188
+ <Icon name="icon-gui-arrow-left" size="1.5rem" />
189
+ </div>
190
+ <div className="w-full h-full flex-shrink-0 flex items-center justify-center">
191
+ <Icon name="icon-gui-arrow-left" size="1.5rem" />
192
+ </div>
193
+ </div>
194
+ </button>
195
+
196
+ <SlideIndicator
197
+ numSlides={children.length}
198
+ activeIndex={activeIndex}
199
+ interval={options?.interval ?? 10000}
200
+ intervalIndicator={options?.intervalIndicator}
201
+ isInline={isInline}
202
+ />
203
+
204
+ <button
205
+ className={`${
206
+ isInline ? "w-32 h-32" : "hidden sm:flex w-48 h-48"
207
+ } pointer-events-auto rounded border border-mid-grey hover:border-active-orange justify-center items-center ui-icon-cta ui-icon-cta-right`}
208
+ onClick={next}
209
+ >
210
+ <div className="ui-icon-cta-holder flex w-48">
211
+ <div className="w-full h-full flex-shrink-0 flex items-center justify-center">
212
+ <Icon name="icon-gui-arrow-right" size="1.5rem" />
213
+ </div>
214
+ <div className="w-full h-full flex-shrink-0 flex items-center justify-center">
215
+ <Icon name="icon-gui-arrow-right" size="1.5rem" />
216
+ </div>
217
+ </div>
218
+ </button>
219
+ </div>
220
+ </div>
221
+ );
222
+ };
223
+
224
+ export default Slider;
Binary file
@@ -0,0 +1,12 @@
1
+ import { PricingPageTable } from "./data";
2
+
3
+ export default {
4
+ title: "JS Components/Table",
5
+ component: PricingPageTable,
6
+ tags: ["autodocs"],
7
+ parameters: {
8
+ layout: "fullscreen",
9
+ },
10
+ };
11
+
12
+ export const PricingPage = {};
@@ -0,0 +1,58 @@
1
+ import React, {
2
+ PropsWithChildren,
3
+ ReactElement,
4
+ TableHTMLAttributes,
5
+ cloneElement,
6
+ } from "react";
7
+
8
+ type TableProps = {
9
+ id?: string;
10
+ };
11
+
12
+ export const Table = ({
13
+ id,
14
+ children,
15
+ ...rest
16
+ }: PropsWithChildren<TableProps & TableHTMLAttributes<HTMLTableElement>>) => (
17
+ <table
18
+ id={id}
19
+ {...rest}
20
+ className={`ui-standard-container mb-4 sm:table-fixed ${
21
+ rest?.className ?? ""
22
+ }`}
23
+ >
24
+ {children}
25
+ </table>
26
+ );
27
+
28
+ export const TableBody = ({
29
+ children,
30
+ ...rest
31
+ }: PropsWithChildren<TableHTMLAttributes<HTMLTableSectionElement>>) => (
32
+ <tbody {...rest}>{children}</tbody>
33
+ );
34
+
35
+ export const TableHeader = ({
36
+ children,
37
+ ...rest
38
+ }: PropsWithChildren<TableHTMLAttributes<HTMLTableSectionElement>>) => (
39
+ <thead
40
+ {...rest}
41
+ className={`sticky bg-white z-10 top-0 ${rest?.className ?? ""}`}
42
+ >
43
+ {cloneElement(children as ReactElement, { isHeader: true })}
44
+ </thead>
45
+ );
46
+
47
+ export const TableRowHeader = ({
48
+ children,
49
+ ...rest
50
+ }: PropsWithChildren<TableHTMLAttributes<HTMLTableRowElement>>) => (
51
+ <tr
52
+ className={`-ml-24 mt-8 sm:ml-0 sm:mt-0 sm:sticky z-10 ${
53
+ rest?.className ?? ""
54
+ }`}
55
+ >
56
+ {cloneElement(children as ReactElement, { isRowHeader: true })}
57
+ </tr>
58
+ );