enhance tabindex + float button + utm + i18n

* tabindex is working with banner
* add new lang and it is working
* enhance some tabindex
*add utm to blog posts
This commit is contained in:
Jordan Blasenhauer 2024-05-21 15:19:54 +02:00
parent 9caa00c4c6
commit 75e483405d
11 changed files with 196 additions and 42 deletions

View file

@ -13,7 +13,7 @@
}
* {
@apply focus:outline-2 focus:outline-secondary focus:outline-offset-4;
@apply focus:outline-4 focus:outline-secondary focus:outline-offset-4;
}
.ace_editor,
@ -111,11 +111,11 @@ body {
/* HEADER */
.header-container {
@apply col-span-12 w-full relative h-full max-h-screen transition-all duration-200 ease-in-out rounded-xl;
@apply w-full relative h-full max-h-screen transition-all duration-200 ease-in-out xl:ml-68 rounded-xl;
}
.header-el {
@apply relative flex flex-wrap items-center justify-between px-0 py-2 mr-6 transition-all ease-in shadow-none duration-250 rounded-2xl lg:flex-nowrap lg:justify-start;
@apply relative flex flex-wrap items-center justify-between px-0 pb-2 sm:mx-6 transition-all ease-in shadow-none duration-250 rounded-2xl lg:flex-nowrap lg:justify-start;
}
.header-wrap {
@ -127,7 +127,7 @@ body {
}
.header-breadcrumb-container {
@apply flex flex-col xs:flex-row flex-wrap pt-1 mr-12 bg-transparent rounded-lg sm:mr-16;
@apply flex flex-wrap pt-1 mr-12 bg-transparent rounded-lg sm:mr-16;
}
.header-breadcrumb-item {
@ -440,6 +440,13 @@ body {
@apply dark:brightness-125 font-medium underline text-gray-100 dark:text-gray-50 hover:no-underline;
}
.banner-tabindex-highlight {
@apply !transition-none !fixed !left-0 !opacity-100 z-20;
}
.banner-tabindex-hide {
@apply !transition-none !fixed !opacity-100 z-10;
}
/* MENU */
.menu-account-title-container {
@ -455,7 +462,7 @@ body {
}
.menu-float-btn {
@apply transition-all scale-90 sm:scale-100 dark:brightness-95 dark:hover:brightness-105 hover:brightness-75 xl:hidden fixed p-3 text-xl bg-white shadow cursor-pointer right-5 sm:right-[5.5rem] z-990 rounded-circle text-slate-700 flex justify-center items-center;
@apply transition-all scale-90 sm:scale-100 dark:brightness-95 dark:hover:brightness-105 hover:brightness-75 xl:hidden fixed p-3 text-xl bg-white shadow cursor-pointer right-4 sm:right-[9.75rem] xl:right-24 z-990 rounded-circle text-slate-700 flex justify-center items-center;
}
.menu-float-btn-svg {
@ -463,11 +470,11 @@ body {
}
.no-banner.menu-float-btn {
@apply top-2;
@apply top-[4rem] sm:top-2;
}
.banner.menu-float-btn {
@apply top-[4.5rem];
@apply top-[8rem] sm:top-[4.5rem];
}
.menu-close-btn {
@ -786,7 +793,7 @@ body {
}
.footer-list-item {
@apply hover:italic hover:brightness-90 block sm:px-4 pt-1 pb-0 lg:pb-1 text-xs lg:text-sm tracking-wide font-normal transition duration-300 ease-in-out text-white dark:text-white;
@apply capitalize-first hover:italic hover:brightness-90 block sm:px-4 py-1 lg:pt-1 lg:pb-1 text-sm tracking-wide font-normal transition duration-300 ease-in-out text-white dark:text-white;
}
/* CARD STAT COMPONENT */
@ -1141,15 +1148,15 @@ body {
/* FEEDBACK */
.feedback-float-btn-container {
@apply transition-all hover:brightness-75 dark:hover:brightness-105 fixed right-4 sm:right-[9.75rem] xl:right-24 z-990;
@apply transition-all hover:brightness-75 dark:hover:brightness-105 fixed right-5 sm:right-[5.5rem] z-990;
}
.no-banner.feedback-float-btn-container {
@apply top-[4rem] sm:top-2;
@apply top-2;
}
.banner.feedback-float-btn-container {
@apply top-[8rem] sm:top-[4.5rem];
@apply top-[4.5rem];
}
.feedback-float-btn {
@ -1204,10 +1211,6 @@ body {
@apply flex flex-col justify-start items-center h-full m-2 overflow-y-auto;
}
.feedback-alert-container {
@apply flex justify-center w-full;
}

File diff suppressed because one or more lines are too long

View file

@ -16,21 +16,22 @@ const banner = reactive({
visibleId: 1,
default : [
{
title: "title_1",
link: "link_1",
linkText: "link_text_1",
title: "Get the most of BunkerWeb by upgrading to the PRO version. More info and free trial",
link: "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#pro",
linkText: "here",
},
{
title: "title_2",
link: "link_2",
linkText: "link_text_2",
title: "Need premium support or tailored consulting around BunkerWeb ? Check out our",
link: "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui#services",
linkText: "professional services.",
},
{
title: "title_3",
link: "link_3",
linkText: "link_text_3",
title: "Be part of the Bunker community by joining the",
link: "Discord chat.",
linkText: "https://discord.bunkerweb.io",
},
],
isTabIndex: false,
api: [],
apiFormat : computed(() => {
if(banner.api.length === 0) return [];
@ -44,9 +45,6 @@ const banner = reactive({
}),
});
const data = [{
"content": "<p class='p-0 mx-'>content_1</p>",
}]
// I want to replace the content class content by banner-item-text
function setupBanner() {
@ -65,6 +63,7 @@ function setupBanner() {
banner.api =
JSON.parse(sessionStorage.getItem("bannerNews"))
banner.default = [];
runBanner();
return;
}
// Try to fetch api data
@ -93,10 +92,10 @@ function setupBanner() {
// Banner animation effect
function runBanner() {
const nextDelay = 14000;
const transDuration = 10000;
const nextDelay = 8000;
const transDuration = 1000;
// Switch item every interval and
setInterval(() => {
setTimeout(() => {
const prev = banner.visibleId;
banner.visibleId = banner.visibleId === 3 ? 1 : banner.visibleId + 1;
const next = banner.visibleId;
@ -122,17 +121,21 @@ function runBanner() {
newItem.classList.add("transition-all");
newItem.classList.add("left-0");
newItem.classList.remove("left-full");
runBanner();
}, nextDelay);
}
// Observe banner and set is visible or not to
// Update float button and menu position
let options = {
function observeBanner() {
const options = {
root: null,
rootMargin: "0px",
threshold: 0.35,
};
let observer = new IntersectionObserver((entries, observer) => {
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) bannerStore.setBannerVisible(true);
if (!entry.isIntersecting) bannerStore.setBannerVisible(false);
@ -142,13 +145,52 @@ function runBanner() {
observer.observe(document.getElementById("banner"));
}
function noTabindex() {
const bannerItems = document.querySelectorAll(".banner-item");
bannerItems.forEach((item) => {
item.classList.remove("banner-tabindex-highlight", 'banner-tabindex-hide');
});
}
function isTabindex() {
const activeElement = document.activeElement;
const bannerItems = document.querySelectorAll(".banner-item");
bannerItems.forEach((item) => {
item.classList.add("banner-tabindex-hide");
item.classList.remove("banner-tabindex-highlight");
});
// Higher z-index for the focused element
activeElement.closest('.banner-item').classList.add("banner-tabindex-highlight");
activeElement.closest('.banner-item').classList.remove("banner-tabindex-hide");
}
// Focus with tabindex break banner animation
// When a banner is focused, we need to add in front of the current banner the focus element
// And remove it when the focus is lost
function handleTabIndex() {
// Get the active element after tabindex click
document.addEventListener("keyup", (e) => {
if(e.key !== "Tab" && !document.activeElement.classList.contains("banner-item-text")) return;
if(document.activeElement.classList.contains("banner-item-text")) {
isTabindex();
return;
} else {
noTabindex();
}
});
}
onMounted(() => {
observeBanner();
setupBanner();
handleTabIndex();
});
</script>
<template>
<div id="banner" tabindex="-1" role="list" class="banner-container">
<div id="banner" role="list" class="banner-container">
<div role="img" aria-hidden="true" class="banner-bg"></div>
<div
v-for="(bannerEl, index) in banner.default"

View file

@ -34,7 +34,7 @@ function updateLangStorage(lang) {
:aria-checked="$i18n.locale === locale ? 'true' : 'false'"
>
<button
:tabindex="lang.isOpen ? langIndex : -1"
:tabindex="lang.isOpen ? langIndex : '-1'"
@click="
() => {
lang.isOpen = false;

View file

@ -8,6 +8,7 @@ import News from "@components/dashboard/News.vue";
import Header from "@components/dashboard/Header.vue";
import Banner from "@components/dashboard/Banner.vue";
import Feedback from "@components/dashboard/Feedback.vue";
import { onMounted } from "vue";
/**
@name Dashboard/Layout.vue

View file

@ -268,7 +268,7 @@ onBeforeMount(() => {
<h1 class="menu-account-title">
{{ menu.username }}
</h1>
<a class="menu-account-link" href="/account">manage account </a>
<a :tabindex=" menu.isDesktop ? menuIndex : menu.isActive ? menuIndex : '-1'" class="menu-account-link" href="/account">manage account </a>
</div>
<hr class="menu-separator" />
<!-- end logo version -->

View file

@ -136,7 +136,7 @@ onMounted(() => {
<p v-if="news.posts.length === 0" class="news-sidebar-no-posts-content">
{{ $t("dashboard_news_fetch_error") }}
</p>
<a :href="`https://www.bunkerweb.io/blog/post/bunkerweb/${post.slug}`" class="news-sidebar-post"
<a :tabindex="news.isActive ? newsIndex : '-1'" :href="`https://www.bunkerweb.io/blog/post/bunkerweb/${post.slug}?utm_campaign=self&utm_source=ui`" class="news-sidebar-post"
v-for="(post, index) in news.posts" :key="index"
>
<div>

View file

@ -37,8 +37,6 @@
"dashboard_menu_discord_label": "Redirect to BunkerWeb Discord",
"dashboard_menu_github_label": "Redirect to BunkerWeb Github",
"dashboard_menu_plugins_title": "plugin pages",
"dashboard_menu_plugins_none": "Want custom plugins ?",
"dashboard_menu_plugins_none_doc": "check doc",
"dashboard_menu_mode_light": "light mode",
"dashboard_menu_mode_dark": "dark mode",
"dashboard_menu_log_out": "log out",

View file

@ -0,0 +1,109 @@
{
"dashboard_logo_alt": "Image du logo BunkerWeb",
"dashboard_logo_link_label": "Rediriger vers la page d'accueil",
"dashboard_bw": "BunkerWeb",
"dashboard_docs": "documents",
"dashboard_blog": "blog",
"dashboard_privacy": "confidentialité",
"dashboard_license": "licence",
"dashboard_sitemap": "plan du site",
"dashboard_default": "défautt",
"dashboard_info": "info",
"dashboard_filter": "filtres",
"dashboard_advanced": "avancé",
"dashboard_loading": "chargement",
"dashboard_lang_dropdown_button_desc": "Basculer entre cacher/afficher le groupe de boutons radio (menu déroulant) pour changer la langue.",
"dashboard_home": "accueil",
"dashboard_instances": "instances",
"dashboard_global_config": "config globale",
"dashboard_services": "services",
"dashboard_configs": "configs",
"dashboard_plugins": "plugins",
"dashboard_jobs": "jobs",
"dashboard_bans": "bans",
"dashboard_actions": "actions",
"dashboard_account": "compte",
"dashboard_reports": "rapports",
"dashboard_cache": "cache",
"dashboard_logs": "journaux",
"dashboard_feedback_toggle_sidebar": "Basculer la barre latérale de feedback.",
"dashboard_feedback_close_sidebar": "Fermer la barre latérale de feedback.",
"dashboard_feedback_title": "Feedback",
"dashboard_feedback_subtitle": "Actions BunkerWeb",
"dashboard_menu_toggle_sidebar": "Basculer la barre latérale du menu.",
"dashboard_menu_close_sidebar": "Fermer la barre latérale du menu.",
"dashboard_menu_twitter_label": "Rediriger vers le Twitter de BunkerWeb",
"dashboard_menu_linkedin_label": "Rediriger vers le Linkedin de BunkerWeb",
"dashboard_menu_discord_label": "Rediriger vers le Discord de BunkerWeb",
"dashboard_menu_github_label": "Rediriger vers le Github de BunkerWeb",
"dashboard_menu_plugins_title": "Pages des plugins",
"dashboard_menu_plugins_none": "Vous voulez des plugins personnalisés ?",
"dashboard_menu_plugins_none_doc": "consulter la documentation",
"dashboard_menu_mode_light": "mode clair",
"dashboard_menu_mode_dark": "mode sombre",
"dashboard_menu_log_out": "se déconnecter",
"dashboard_ui": "ui",
"dashboard_scheduler": "scheduler",
"dashboard_autoconf": "autoconf",
"dashboard_core": "core",
"dashboard_global": "global",
"dashboard_news_toggle_sidebar": "Basculer la barre latérale des nouvelles.",
"dashboard_news_close_sidebar": "Fermer la barre latérale des nouvelles.",
"dashboard_news_title": "news",
"dashboard_news_subtitle": "Stay up to date !",
"dashboard_news_fetch_error": "Impossible to retrieve news",
"dashboard_newsletter_title": "Join newsletter",
"dashboard_newsletter_placeholder": "john.doe{'@'}example.com",
"dashboard_newsletter_privacy_text": "I'v read and agree",
"dashboard_newsletter_privacy_text_link": "the privacy policy",
"dashboard_newsletter_subscribe_button": "subscribe",
"dashboard_feedback_alert_desc": "Own actions feedbacks.",
"dashboard_feedback_logs_desc": "BunkerWeb actions feedbacks.",
"dashboard_popover_button_desc": "Show setting details on hover.",
"dashboard_popover_button": "Show popover with setting details.",
"dashboard_popover_detail_desc": "Container with setting details.",
"dashboard_up": "up",
"dashboard_down": "down",
"dashboard_banner_title_1": "Need premium support ?",
"dashboard_banner_title_2": "Try BunkerWeb on our",
"dashboard_banner_title_3": "All informations about BunkerWeb on our",
"dashboard_banner_link_1": "https://panel.bunkerweb.io/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_2": "https://demo.bunkerweb.io/link/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_3": "https://www.bunkerweb.io/?utm_campaign=self&utm_source=ui",
"dashboard_banner_link_text_1": "Check BunkerWeb Panel",
"dashboard_banner_link_text_2": "demo wep app !",
"dashboard_banner_link_text_3": "website !",
"home_version_is_latest": "is the latest version",
"home_version_latest_version": "latest version",
"home_version": "version",
"home_internal": "internal",
"home_external": "external",
"home_card_link_label": "Redirect to page with related data.",
"instances_hostname": "hostname",
"instances_hostname_placeholder": "bwapi",
"instances_method": "method",
"instances_port": "port",
"instances_port_placeholder": "5000",
"instances_active": "Instance is active.",
"instances_inactive": "Instance is inactive.",
"instances_modal_delete_msg": "Are you sure to delete instance with hostname {hostname} ?",
"instances_server_name": "server name",
"instances_server_name_placeholder": "www.example.com",
"action_send": "send {name}",
"action_disable": "disable {name}",
"action_enable": "enable {name}",
"action_save": "save {name}",
"action_add": "add {name}",
"action_close": "close {name}",
"action_delete": "delete {name}",
"action_link": "link",
"action_edit": "edit {name}",
"action_download": "download {name}",
"action_create": "create {name}",
"action_view": "view {name}",
"action_stop": "stop {name}",
"action_ping": "ping {name}",
"action_reload": "reload {name}",
"action_upload": "upload {name}",
"action_delete_all": "delete all {name}"
}

View file

@ -9,11 +9,12 @@ import { createI18n } from "vue-i18n";
*/
import en from "@lang/en.json" assert { type: "json" };
import fr from "@lang/fr.json" assert { type: "json" };
const availablesLangs = ["en"];
const availablesLangs = ["en", "fr"];
function getAllLang() {
return { en: en };
return { en: en, fr : fr };
}
function getAllLangCurrPage(pagesArr) {

View file

@ -6,7 +6,6 @@
This is useful for people with disabilities or people who prefer to use the keyboard instead of the mouse.
*/
const bannerIndex = "-1";
const footerIndex = "0";
const menuIndex = "1";
const langIndex = "2";
const menuFloatIndex = "3";
@ -14,6 +13,7 @@ const refreshIndex = "4";
const feedbackIndex = "5";
const newsIndex = "6";
const contentIndex = "7";
const footerIndex = "8";
export {
bannerIndex,