From 89594e9da17719e9cb92e7a6c1503483c51c105d Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Fri, 26 Jan 2024 15:26:37 +0100 Subject: [PATCH 1/7] docs: update README.md --- README.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53459f6..bbc7391 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,30 @@ Check the page that opens if the Header is properly rendered and if the latest p It will create a `build` folder with the compiled assets. -## URL +## How to use -https://traefik.github.io/traefiklabs-hub-button-app/main-v1.js -https://traefik.github.io/traefiklabs-hub-button-app/main-v1.js.map +Put the full URL of the script file in the `src` attribute of a ` +``` + +You can place the script reference in head or body tag, as you like. + +Then, you can use the **hub-button-app** custom element wherever you need it. +Please notice the custom element exposes a property called **theme** to control its appearance; possible values can be +`dark` or `light`, with light as the default value. + +The script (and its sourcemap) can be also embedded in another project codebase; this can be useful as a local fallback +in case the remote source became unavailable. +While doing this please remember to update, in both the script and its sourcemap, the following lines: + +| File | Line | Key | +| - | - | - | +| main-v1.js | 3 | `sourceMappingURL` | +| main-v1.js.map | 1 | `file` | + +### Deployments URLs + +- https://traefik.github.io/traefiklabs-hub-button-app/main-v1.js +- https://traefik.github.io/traefiklabs-hub-button-app/main-v1.js.map From 650c0503ec12845becdb37de85a4c0557b939b1b Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Mon, 29 Jan 2024 16:11:17 +0100 Subject: [PATCH 2/7] feat: update UI --- src/App.tsx | 4 +- src/components/HubButton.tsx | 305 +++++++++--------- src/components/icons/CheckIcon.tsx | 16 - .../icons/TraefikEnterpriseIcon.tsx | 26 ++ src/components/icons/TraefikHubIcon.tsx | 24 +- src/components/icons/TraefikProxyIcon.tsx | 26 ++ src/components/icons/index.ts | 5 +- src/components/images/CTAImage.tsx | 31 -- src/components/images/index.ts | 3 - src/components/themes.ts | 17 +- 10 files changed, 230 insertions(+), 227 deletions(-) delete mode 100644 src/components/icons/CheckIcon.tsx create mode 100644 src/components/icons/TraefikEnterpriseIcon.tsx create mode 100644 src/components/icons/TraefikProxyIcon.tsx delete mode 100644 src/components/images/CTAImage.tsx delete mode 100644 src/components/images/index.ts diff --git a/src/App.tsx b/src/App.tsx index ec4ccfc..3502721 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,10 +2,10 @@ import HubButton from 'components/HubButton' import { darkTheme, lightTheme } from 'components/themes' import { ThemeProvider } from 'styled-components' -export const App = ({ theme = 'light' }: { theme?: string }) => { +export const App = ({ theme = 'light' }: { theme?: 'light' | 'dark' }) => { return ( - + ) } diff --git a/src/components/HubButton.tsx b/src/components/HubButton.tsx index 3b903d1..694f9c3 100644 --- a/src/components/HubButton.tsx +++ b/src/components/HubButton.tsx @@ -1,5 +1,5 @@ -import { CheckIcon, TraefikHubIcon } from 'components/icons' -import { CTAImage } from 'components/images' +import { TraefikEnterpriseIcon, TraefikHubIcon, TraefikProxyIcon } from 'components/icons' +import { ReactNode } from 'react' import styled from 'styled-components' const Tooltip = styled.div` @@ -7,7 +7,7 @@ const Tooltip = styled.div` &:hover { .btn-hub { - background-color: #485162; + background-color: #54b4cd; transition: background-color 0.3s; } @@ -20,14 +20,14 @@ const Tooltip = styled.div` .btn-hub { display: inline-block; - padding: 9px 16px; + padding: 13px 12px; border-radius: 8px; - background-color: #222b3c; - color: #fff; - font-size: 16px; + background-color: #54b4cd; + color: #03192d; + font-size: 1rem; font-weight: 700; - line-height: inherit; + line-height: 1.38; text-decoration: none; position: relative; @@ -36,27 +36,20 @@ const Tooltip = styled.div` content: ''; visibility: hidden; position: absolute; - top: 88%; - right: calc(50% - 7px); + top: 87%; + right: calc(50% - 8px); z-index: 2; - border-left: 7px solid transparent; - border-right: 7px solid transparent; - border-bottom: 10px solid ${({ theme }) => theme.contentBackgroundColor}; + border-style: solid; + border-width: 0 8px 14px 8px; + border-color: transparent transparent ${({ theme }) => theme.contentBackgroundColor} transparent; opacity: 0; transition: opacity 0.3s; } - .btn-hub-inner { - display: flex; - align-items: center; - flex-wrap: nowrap !important; - gap: 8px; - - label { - cursor: pointer; - text-align: center; - } + label { + cursor: pointer; + text-align: center; } } @@ -68,109 +61,69 @@ const Tooltip = styled.div` z-index: 1; top: inherit; right: 0; - width: 836px; + width: 400px; opacity: 0; transition: opacity 0.3s; visibility: hidden; .spacer { - height: 5px; + height: 8px; } .content { display: flex; font-size: 16px; - border-radius: 16px; + border-radius: 8px; background-color: ${({ theme }) => theme.contentBackgroundColor}; box-shadow: ${({ theme }) => theme.contentBoxShadow}; overflow: hidden; - .left { - flex-shrink: 0; - padding: 9px 22px 40px 22px; - background-color: #060b21; - text-align: center; - - svg { - flex-shrink: 0; - } - - p { - max-width: 288px; - margin: 13px auto 31px auto; - color: #f9fafa; - font-size: 2.25rem; - font-weight: 900; - line-height: 1.33; - text-align: center; - } + .products { + display: flex; + flex-direction: column; + gap: 8px; + width: 100%; + margin: 16px; - .sign-up { - display: inline-block; - padding: 11px 25px 10px 25px; - color: #03192d; - background-color: #d5ea48; + .product { + display: flex; + gap: 16px; + padding: 16px; border-radius: 8px; - font-size: 0.875rem; - font-weight: 900; - line-height: normal; - text-align: center; - text-decoration: none; - transition: background-color 0.25s linear; + transition: background-color 0.3s; &:hover { - background-color: #e5f291; + background-color: ${({ theme }) => theme.productBackgroundColor}; } - } - } - - .right { - padding: 48px 32px; - - .features { - display: flex; - flex-direction: column; - gap: 26px; - margin: 7px 5px 53px 0; - - .feature { - display: flex; - gap: 16px; - svg { - flex-shrink: 0; - } + svg { + flex-shrink: 0; + } - h3 { - color: ${({ theme }) => theme.featureHColor}; - font-size: 1rem; - font-weight: 900; - line-height: 22px; - margin: 0; - } + h3 { + color: ${({ theme }) => theme.productNameColor}; + font-size: 1rem; + font-weight: 900; + line-height: 22px; + margin: 2px 0 0 0; + } - p { - color: ${({ theme }) => theme.featurePColor}; - line-height: 1.5; - margin: 0; - } + p { + color: ${({ theme }) => theme.productDescColor}; + line-height: 1.5; + margin: 0 0 10px 0; } - } - .learn-more { - display: block; - margin: 0 auto; - color: ${({ theme }) => theme.learnMoreColor}; - font-size: 1rem; - font-weight: 900; - line-height: 22px; - text-align: center; - text-decoration: none; - transition: opacity 0.25s linear; + a { + font-weight: 900; + line-height: 22px; + text-decoration: none; + transition: opacity 0.25s linear; - &:hover { - opacity: 0.7; + &:hover { + opacity: 0.7; + } } } } @@ -180,33 +133,20 @@ const Tooltip = styled.div` @media screen and (max-width: 768px) { .btn-hub { line-height: 1em; - - .btn-hub-inner { - gap: 8px; - } } .tooltip { - right: 140px; - width: 768px; + right: 16px; .spacer { height: 3px; } - - .content .left svg { - width: 300px; - } } } @media screen and (min-width: 769px) and (max-width: 1024px) { .btn-hub { line-height: 1.25em; - - .btn-hub-inner { - gap: 4px; - } } .tooltip .spacer { @@ -215,69 +155,116 @@ const Tooltip = styled.div` } ` -const features = [ +type Product = { + icon: { + color: { + dark: string + light: string + } + el: ReactNode + } + name: string + desc: string + link: { + color: { + dark: string + light: string + } + href: string + text: string + } +} + +const products: Product[] = [ { - h: 'K8s-native API Management', - p: 'K8s services auto-discovery, 100% CRDs configuration, full GitOps compliance.', + icon: { + color: { + dark: '#2aa2c1', + light: '#21819a', + }, + el: , + }, + name: 'Traefik Proxy', + desc: 'OSS Cloud-Native Application Proxy', + link: { + color: { + dark: '#2aa2c1', + light: '#21819a', + }, + text: 'Get Commercial Support', + href: 'https://traefik.io/get-traefik-commercial-support/', + }, }, { - h: 'Central Control Plane', - p: 'A simple management point for all APIs, users and infrastructure components.', + icon: { + color: { + dark: '#337fe6', + light: '#337fe6', + }, + el: , + }, + name: 'Traefik Enterprise', + desc: 'Enterprise-Grade API Gateway', + link: { + color: { + dark: '#337fe6', + light: '#337fe6', + }, + text: 'Learn more', + href: 'https://traefik.io/explore-traefik-enterprise/', + }, }, { - h: 'Self-serve API Portal', - p: 'API discovery, documentation, testing, and access control.', + icon: { + color: { + dark: '#d5ea48', + light: '#7f8c2b', + }, + el: , + }, + name: 'Traefik Hub', + desc: 'GitOps-Driven API Management', + link: { + color: { + dark: '#d5ea48', + light: '#555d1c', + }, + text: 'Learn more', + href: 'https://traefik.io/explore-traefik-hub/', + }, }, ] -const HubButton = () => { +const HubButton = ({ theme }: { theme: 'light' | 'dark' }) => { return ( -
- - -
+ Upgrade
-
- -

Your APIs deserve better

- - TRY TRAEFIK HUB - -
-
-
- {features.map((feature, index) => ( -
- -
-

{feature.h}

-

{feature.p}

-
+
+ {products.map((product, index) => ( +
+
{product.icon.el}
+
+

{product.name}

+

{product.desc}

+ + {product.link.text} → +
- ))} -
- - Learn more about Traefik Hub → - +
+ ))}
diff --git a/src/components/icons/CheckIcon.tsx b/src/components/icons/CheckIcon.tsx deleted file mode 100644 index 280be0a..0000000 --- a/src/components/icons/CheckIcon.tsx +++ /dev/null @@ -1,16 +0,0 @@ -export const CheckIcon = () => ( - - - - - - -) - -export default CheckIcon diff --git a/src/components/icons/TraefikEnterpriseIcon.tsx b/src/components/icons/TraefikEnterpriseIcon.tsx new file mode 100644 index 0000000..2be958d --- /dev/null +++ b/src/components/icons/TraefikEnterpriseIcon.tsx @@ -0,0 +1,26 @@ +export const TraefikEnterpriseIcon = () => ( + + + + + + + + + + + +) + +export default TraefikEnterpriseIcon diff --git a/src/components/icons/TraefikHubIcon.tsx b/src/components/icons/TraefikHubIcon.tsx index ad5b197..8421bbe 100644 --- a/src/components/icons/TraefikHubIcon.tsx +++ b/src/components/icons/TraefikHubIcon.tsx @@ -1,11 +1,23 @@ export const TraefikHubIcon = () => ( - - - + + + + + + + + diff --git a/src/components/icons/TraefikProxyIcon.tsx b/src/components/icons/TraefikProxyIcon.tsx new file mode 100644 index 0000000..03521a7 --- /dev/null +++ b/src/components/icons/TraefikProxyIcon.tsx @@ -0,0 +1,26 @@ +export const TraefikProxyIcon = () => ( + + + + + + + + + + + +) + +export default TraefikProxyIcon diff --git a/src/components/icons/index.ts b/src/components/icons/index.ts index 5d5cec2..4bb3aad 100644 --- a/src/components/icons/index.ts +++ b/src/components/icons/index.ts @@ -1,4 +1,5 @@ -import CheckIcon from './CheckIcon' +import TraefikEnterpriseIcon from './TraefikEnterpriseIcon' import TraefikHubIcon from './TraefikHubIcon' +import TraefikProxyIcon from './TraefikProxyIcon' -export { CheckIcon, TraefikHubIcon } +export { TraefikEnterpriseIcon, TraefikHubIcon, TraefikProxyIcon } diff --git a/src/components/images/CTAImage.tsx b/src/components/images/CTAImage.tsx deleted file mode 100644 index 8ec7eaf..0000000 --- a/src/components/images/CTAImage.tsx +++ /dev/null @@ -1,31 +0,0 @@ -export const CTAImage = () => ( - - - - - - - - - - - - - - - -) - -export default CTAImage diff --git a/src/components/images/index.ts b/src/components/images/index.ts deleted file mode 100644 index f0ff609..0000000 --- a/src/components/images/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -import CTAImage from './CTAImage' - -export { CTAImage } diff --git a/src/components/themes.ts b/src/components/themes.ts index 75e6b40..cab32a6 100644 --- a/src/components/themes.ts +++ b/src/components/themes.ts @@ -1,15 +1,16 @@ export const lightTheme = { contentBackgroundColor: '#fff', - contentBoxShadow: '0 0 6px rgba(0, 0, 0, 0.16), 0 0 6px rgba(0, 0, 0, 0.23)', - featureHColor: '#03192d', - featurePColor: '#677581', - learnMoreColor: '#03192d', + contentBoxShadow: + '0 11px 15px -7px rgba(0, 0, 0, 0.2), 0 9px 46px 8px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.14)', + productBackgroundColor: '#f4f5f6', + productNameColor: '#03192d', + productDescColor: '#677581', } export const darkTheme = { - contentBackgroundColor: '#060b21', + contentBackgroundColor: '#06102a', contentBoxShadow: '0 0 6px rgba(10, 18, 36, 0.16), 0 0 6px rgba(10, 18, 36, 0.23)', - featureHColor: '#f9fafa', - featurePColor: '#818c96', - learnMoreColor: '#f9fafa', + productBackgroundColor: 'rgba(244, 245, 246, 0.05)', + productNameColor: '#f9fafa', + productDescColor: '#818c96', } From 09f9633a4d4eb4c419a1cb6c0a0dc433fcc0ae2a Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Mon, 29 Jan 2024 18:05:19 +0100 Subject: [PATCH 3/7] feat: remove legacy media queries --- src/components/HubButton.tsx | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/components/HubButton.tsx b/src/components/HubButton.tsx index 694f9c3..377e013 100644 --- a/src/components/HubButton.tsx +++ b/src/components/HubButton.tsx @@ -131,26 +131,8 @@ const Tooltip = styled.div` } @media screen and (max-width: 768px) { - .btn-hub { - line-height: 1em; - } - .tooltip { right: 16px; - - .spacer { - height: 3px; - } - } - } - - @media screen and (min-width: 769px) and (max-width: 1024px) { - .btn-hub { - line-height: 1.25em; - } - - .tooltip .spacer { - height: 3px; } } ` From adb6b345019468260bfa7a44dd8fc3bb75938a70 Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Tue, 30 Jan 2024 09:43:09 +0100 Subject: [PATCH 4/7] feat: remove href from upgrade button --- src/components/HubButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/HubButton.tsx b/src/components/HubButton.tsx index 377e013..450f785 100644 --- a/src/components/HubButton.tsx +++ b/src/components/HubButton.tsx @@ -220,7 +220,7 @@ const products: Product[] = [ const HubButton = ({ theme }: { theme: 'light' | 'dark' }) => { return ( - + Upgrade
From ca565c482922a5bade7a5a4e0452f539c487b247 Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Tue, 30 Jan 2024 10:17:11 +0100 Subject: [PATCH 5/7] feat: add theme property checkup --- src/App.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 3502721..9b8e7c3 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,19 @@ import HubButton from 'components/HubButton' import { darkTheme, lightTheme } from 'components/themes' +import { useMemo } from 'react' import { ThemeProvider } from 'styled-components' export const App = ({ theme = 'light' }: { theme?: 'light' | 'dark' }) => { + const safeTheme = useMemo(() => { + if (!['light', 'dark'].includes(theme)) { + return 'light' + } + return theme + }, [theme]) + return ( - - + + ) } From e6832010e338568557b413d81850e0784f8d62b9 Mon Sep 17 00:00:00 2001 From: Massimiliano D'Elia Date: Tue, 30 Jan 2024 10:23:50 +0100 Subject: [PATCH 6/7] fix: local development error Unexpected token '<' --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index a237873..cc82b0c 100644 --- a/public/index.html +++ b/public/index.html @@ -9,7 +9,7 @@ point this script src to the local build -->