Tooltips in the top navigation bar

Added tooltips to icons in top navigation bar
This commit is contained in:
Cyril Šebek 2024-07-06 17:02:07 +02:00
parent 8a11f24244
commit d6d44fd9af
Signed by: blboun3
SSH Key Fingerprint: SHA256:n9dMtOPzgsD+CCerUJslEnU2dzVanbaIv0XDQVRVjeg
8 changed files with 243 additions and 64 deletions

View File

@ -14,9 +14,15 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from "./ui/dropdown-menu" } from "./ui/dropdown-menu"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "./ui/tooltip"
// Please note that clang = lang, it's just for more confusion // Please note that clang = lang, it's just for more confusion
export function LangSwitcher() { export function LangSwitcher({ tooltip }) {
function getClang(){ function getClang(){
const clang = window.location.pathname.substring(1,3); const clang = window.location.pathname.substring(1,3);
return clang return clang
@ -34,7 +40,18 @@ export function LangSwitcher() {
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<div>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Button variant="outline" size="icon" className="bg-inherit border-none text-content hover:text-bkg" dangerouslySetInnerHTML={{ __html: icons["lang"] }} /> <Button variant="outline" size="icon" className="bg-inherit border-none text-content hover:text-bkg" dangerouslySetInnerHTML={{ __html: icons["lang"] }} />
</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="w-56"> <DropdownMenuContent className="w-56">
<DropdownMenuRadioGroup value={clang} onValueChange={clinkClang}> <DropdownMenuRadioGroup value={clang} onValueChange={clinkClang}>

View File

@ -6,10 +6,26 @@ import { Button } from "./ui/button"
import { cn } from '../lib/utils' import { cn } from '../lib/utils'
import { icons } from "../lib/icons" import { icons } from "../lib/icons"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "./ui/tooltip"
export function NavButton({selected, variant}) { export function NavButton({ selected, variant, tooltip }) {
return ( return (
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Button id={`${variant}Btn`} variant="outline" size="icon" className={cn("bg-inherit border-none text-content", selected ? "text-accent hover:text-bkg" : "text-content hover:text-bkg")} dangerouslySetInnerHTML={{ __html: icons[variant] }} /> <Button id={`${variant}Btn`} variant="outline" size="icon" className={cn("bg-inherit border-none text-content", selected ? "text-accent hover:text-bkg" : "text-content hover:text-bkg")} dangerouslySetInnerHTML={{ __html: icons[variant] }} />
</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
) )
} }

View File

@ -3,6 +3,7 @@ import { ThemeSelector } from "./ThemeSelector"
import NavbarSkeleton from "./NavbarSkeleton.astro"; import NavbarSkeleton from "./NavbarSkeleton.astro";
import { LangSwitcher } from "./LangSwitcher"; import { LangSwitcher } from "./LangSwitcher";
import { NavButton } from "./NavButton"; import { NavButton } from "./NavButton";
import { useTranslations, getLangFromUrl } from "../i18n/utils";
function selected(path) { function selected(path) {
var currentURL = Astro.url.pathname var currentURL = Astro.url.pathname
@ -17,18 +18,20 @@ function selected(path) {
const locale = Astro.currentLocale ? Astro.currentLocale : "en" const locale = Astro.currentLocale ? Astro.currentLocale : "en"
const t = useTranslations(getLangFromUrl(Astro.url));
--- ---
<NavbarSkeleton> <NavbarSkeleton>
<!-- Page Navigation --> <!-- Page Navigation -->
<div class="flex gap-1"> <div class="flex gap-1">
<a href={`/${locale}/`}> <a href={`/${locale}/`}>
<NavButton selected={selected("/")} variant="home"/> <NavButton selected={selected("/")} variant="home" tooltip={t("navbar")["home"]} client:load />
</a> </a>
<a href={`/${locale}/blog`}> <a href={`/${locale}/blog`}>
<NavButton selected={selected("/blog")} variant="blog"/> <NavButton selected={selected("/blog")} variant="blog" tooltip={t("navbar")["blog"]} client:load />
</a> </a>
<a href={`/${locale}/music`}> <a href={`/${locale}/music`}>
<NavButton selected={selected("/music")} variant="music"/> <NavButton selected={selected("/music")} variant="music" tooltip={t("navbar")["music"]} client:load/>
</a> </a>
</div> </div>
@ -39,7 +42,7 @@ const locale = Astro.currentLocale ? Astro.currentLocale : "en"
<!-- Options (language, light/dark mode) --> <!-- Options (language, light/dark mode) -->
<div class="flex gap-1"> <div class="flex gap-1">
<LangSwitcher client:load client:only="react"/> <LangSwitcher tooltip={t("navbar")["lang"]} client:load client:only="react"/>
<ThemeSelector client:load client:only="react"/> <ThemeSelector tooltip={t("navbar")["mode"]} client:load client:only="react"/>
</div> </div>
</NavbarSkeleton> </NavbarSkeleton>

View File

@ -1,4 +1,4 @@
"use client"
import * as React from "react" import * as React from "react"
@ -12,9 +12,16 @@ import {
DropdownMenuTrigger, DropdownMenuTrigger,
} from "./ui/dropdown-menu" } from "./ui/dropdown-menu"
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from "./ui/tooltip"
// Please note that clang = lang, it's just for more confusion // Please note that clang = lang, it's just for more confusion
export function ThemeSelector() { export function ThemeSelector({ tooltip }) {
function getTheme() { function getTheme() {
console.log(localStorage.getItem("data-theme")); console.log(localStorage.getItem("data-theme"));
const theme = localStorage.getItem("data-theme") || document.documentElement.getAttribute("data-theme"); const theme = localStorage.getItem("data-theme") || document.documentElement.getAttribute("data-theme");
@ -33,7 +40,18 @@ export function ThemeSelector() {
return ( return (
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>
<div>
<TooltipProvider>
<Tooltip>
<TooltipTrigger>
<Button variant="outline" size="icon" className="bg-inherit border-none text-content hover:text-bkg" dangerouslySetInnerHTML={{ __html: icons[theme] }} /> <Button variant="outline" size="icon" className="bg-inherit border-none text-content hover:text-bkg" dangerouslySetInnerHTML={{ __html: icons[theme] }} />
</TooltipTrigger>
<TooltipContent>
<p>{tooltip}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent className="w-20"> <DropdownMenuContent className="w-20">
<DropdownMenuRadioGroup value={theme} onValueChange={newTheme}> <DropdownMenuRadioGroup value={theme} onValueChange={newTheme}>

View File

@ -3,6 +3,18 @@ export const cs = {
description: "Personal website of one weird student", // HTML page description description: "Personal website of one weird student", // HTML page description
favicon: "/favicon.svg", favicon: "/favicon.svg",
/*
Top navigation bar
*/
navbar: {
home: "Domů",
blog: "Blog",
music: "Moje skladby",
lang: "Jazyky",
mode: "Režim"
},
/* /*
Hero module of the page Hero module of the page
*/ */

View File

@ -1,15 +1,49 @@
export const de = { export const de = {
title: "Lorem Ipsum", // Title of the main page in browser's handlebard title: "Cyril Šebek", // Title of the main page in browser's handlebard
description: "Page description here", // HTML page description description: "Personal website of one weird student", // HTML page description
favicon: "/favicon.svg",
/*
Top navigation bar
*/
navbar: {
home: "Home",
blog: "Blog",
music: "My compositions",
lang: "Languages",
mode: "Theme"
},
/* /*
Hero module of the page Hero module of the page
*/ */
hero: { hero: {
title: "Lorem", title: "Coding Rhythms and Melodic Algorithms",
content: "ipsum dolor", content: "Welcome to personal website & blog of one weird student from Czechia",
image: "/temp.jpg", image: "/frontpage.svg",
buttons: ["Button 1", "Button 2"], buttons: ["Read more", "Contact me"],
},
/*
Contact dialog from hero page
*/
contact: {
title: "Contact me",
description: "If you are interested in working with me or you just want to talk you can contact me using this form and I promise I will get back to you soon!",
name: "name",
nameDescription: "Name",
nameDefaultValue: "Beff Jazos",
email: "email",
emailDescription: "Email",
emailDefaultValue: "beff@sahara.com",
message: "message",
messageDescription: "Your message",
messageDefaultValue: "Hi there :)",
button: "Send"
}, },
/* /*
@ -18,30 +52,30 @@ export const de = {
about: [ about: [
{ {
// About page first block title // About page first block title
title: "Lorem", title: "Student",
// Content of about page first block // Content of about page first block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "Currently, I am a high school student with a passion for mathematics, physics and ICT, but I maintain excellent grades across all subjects.",
// Image // Image
image: "/temp.jpg", image: "/student.png",
}, },
{ {
// About page second block title // About page second block title
title: "Ipsum", title: "Programmer",
// Content of about page's second block // Content of about page's second block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "I started programming in my free time in 6th grade. After experimenting with various languages, I now primarily use Python for AI/ML and general scripting, and JavaScript for web development, along with other languages as needed for specific projects.",
// Image // Image
image: "/temp.jpg", image: "/programmer.svg",
}, },
{ {
// About page third block title // About page third block title
title: "Ipsum", title: "Musician",
// Content of about page's third block // Content of about page's third block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "I began playing the flute in the first grade and have since transitioned to playing the clarinet in multiple orchestras. I am deeply passionate about music and dedicate a portion of my free time to composing and studying film music.",
// Image // Image
image: "/temp.jpg", image: "/musician.png",
}, },
], ],
@ -50,37 +84,54 @@ export const de = {
*/ */
showcase: [ showcase: [
{ {
value: "first", value: "website",
handle: "Website", handle: "Website",
title: "My personal webpage", title: "My personal webpage",
href: "/potato",
description: description:
"My personal website, clearly you've found it. Made in Astro.js with help of shadcnui components.", "My personal website, clearly you've found it. Built using Astro.js and enhanced with Shadcn/UI components, this iteration marks its sixth version, yet it's the first one I've truly completed.",
image: "/temp.jpg", image: "/website.png",
imageAlt: "Screenshot of this website", imageAlt: "Screenshot of this website",
}, },
{ {
value: "second", value: "second",
title: "Self-hostable", title: "Self-hostable",
handle: "HomeLab", handle: "Homelab",
href: "/potat2",
description: description:
"It has now been a few years since I've started with selfhosting. It started as one single Raspberry Pi 4, then it grew to cluster of 4 Pis... and now I have 2 old IBM servers (x3550 m4).", "It's been a few years since I started self-hosting. What began with a single Raspberry Pi 4 has evolved into a cluster of four Pis. Now, I rely on two old IBM servers (x3550 M4) to host nearly everything I need: a video server, music server, Git repositories, and even a password manager. It's become a robust setup that meets all my requirements.",
image: "/temp.jpg", image: "/homelab.jpg",
imageAlt: "Photo of my personal homelab", imageAlt: "Photo of my personal homelab",
}, },
{ {
value: "third", value: "third",
title: "ESA's Astro Pi Challenge 2022/23", title: "ESA's Astro Pi Challenge 2022/23",
handle: "ESA Astro Pi", handle: "ESA Astro Pi",
href: "/kartoffeln",
description: description:
"Astro Pi is a competition for high school students by the European Space Agency. It's goal is to make it possible for students to run their code on the ISS. I was part of the Barrande team from our school. As our mission we chose Classification of Earth's topology using AI in Real-Time and I was the one tasked with programmign the AI. The mission was very successfull and we were nominated to 10 best teams. Reports and other data can be found on ESA's website.", "Astro Pi is a competition for high school students hosted by the European Space Agency. Its goal is to enable students to run their code aboard the ISS. I was part of the Barrande team from our school. For our mission, we chose \"Real-Time Classification of Earth\'s Topology using AI,\" and I was responsible for programming the AI. Our mission was highly successful, and we were nominated as one of the top 10 teams. Detailed reports and additional data can be found on the ESA\'s website.",
image: "/temp.jpg", image: "/astropi.png",
imageAlt: "Image for of our task and results explanation", imageAlt: "Image for of our task and results explanation",
}, },
], ],
/*
Blog page
*/
blog: {
title: "Blog @ Cyril Šebek",
description: "My personal blog, documenting some of my crazy ideas",
},
/*
Page with musical compositions
*/
music: {
pageTitle: "Music @ Cyril Šebek",
title: "My compositions",
description: "This is page is listing all my published musical compositions.",
downloadPDF: "Download PDF",
downloadMP3: "Download MP3",
downloadFLAC: "Download FLAC"
},
postsTagged: "All posts tagged with", postsTagged: "All posts tagged with",
}; };

View File

@ -3,6 +3,17 @@ export const en = {
description: "Personal website of one weird student", // HTML page description description: "Personal website of one weird student", // HTML page description
favicon: "/favicon.svg", favicon: "/favicon.svg",
/*
Top navigation bar
*/
navbar: {
home: "Home",
blog: "Blog",
music: "My compositions",
lang: "Languages",
mode: "Theme"
},
/* /*
Hero module of the page Hero module of the page
*/ */

View File

@ -1,15 +1,49 @@
export const fr = { export const fr = {
title: "Lorem Ipsum", // Title of the main page in browser's handlebard title: "Cyril Šebek", // Title of the main page in browser's handlebard
description: "Page description here", // HTML page description description: "Personal website of one weird student", // HTML page description
favicon: "/favicon.svg",
/*
Top navigation bar
*/
navbar: {
home: "Home",
blog: "Blog",
music: "My compositions",
lang: "Languages",
mode: "Theme"
},
/* /*
Hero module of the page Hero module of the page
*/ */
hero: { hero: {
title: "Lorem", title: "Coding Rhythms and Melodic Algorithms",
content: "ipsum dolor", content: "Welcome to personal website & blog of one weird student from Czechia",
image: "/temp.jpg", image: "/frontpage.svg",
buttons: ["Button 1", "Button 2"], buttons: ["Read more", "Contact me"],
},
/*
Contact dialog from hero page
*/
contact: {
title: "Contact me",
description: "If you are interested in working with me or you just want to talk you can contact me using this form and I promise I will get back to you soon!",
name: "name",
nameDescription: "Name",
nameDefaultValue: "Beff Jazos",
email: "email",
emailDescription: "Email",
emailDefaultValue: "beff@sahara.com",
message: "message",
messageDescription: "Your message",
messageDefaultValue: "Hi there :)",
button: "Send"
}, },
/* /*
@ -18,30 +52,30 @@ export const fr = {
about: [ about: [
{ {
// About page first block title // About page first block title
title: "Lorem", title: "Student",
// Content of about page first block // Content of about page first block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "Currently, I am a high school student with a passion for mathematics, physics and ICT, but I maintain excellent grades across all subjects.",
// Image // Image
image: "/temp.jpg", image: "/student.png",
}, },
{ {
// About page second block title // About page second block title
title: "Ipsum", title: "Programmer",
// Content of about page's second block // Content of about page's second block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "I started programming in my free time in 6th grade. After experimenting with various languages, I now primarily use Python for AI/ML and general scripting, and JavaScript for web development, along with other languages as needed for specific projects.",
// Image // Image
image: "/temp.jpg", image: "/programmer.svg",
}, },
{ {
// About page third block title // About page third block title
title: "Ipsum", title: "Musician",
// Content of about page's third block // Content of about page's third block
content: content:
"Lorem ipsum dolor sit amet consectetur, adipisicing elit. Atque consequatur voluptatibus nobis dolores repellendus similique, ut sit odit commodi optio tempore totam, quaerat at distinctio nisi dolore magnam quia perferendis.", "I began playing the flute in the first grade and have since transitioned to playing the clarinet in multiple orchestras. I am deeply passionate about music and dedicate a portion of my free time to composing and studying film music.",
// Image // Image
image: "/temp.jpg", image: "/musician.png",
}, },
], ],
@ -50,37 +84,54 @@ export const fr = {
*/ */
showcase: [ showcase: [
{ {
value: "first", value: "website",
handle: "Website", handle: "Website",
title: "My personal webpage", title: "My personal webpage",
href: "/potato",
description: description:
"My personal website, clearly you've found it. Made in Astro.js with help of shadcnui components.", "My personal website, clearly you've found it. Built using Astro.js and enhanced with Shadcn/UI components, this iteration marks its sixth version, yet it's the first one I've truly completed.",
image: "/temp.jpg", image: "/website.png",
imageAlt: "Screenshot of this website", imageAlt: "Screenshot of this website",
}, },
{ {
value: "second", value: "second",
title: "Self-hostable", title: "Self-hostable",
handle: "HomeLab", handle: "Homelab",
href: "/potat2",
description: description:
"It has now been a few years since I've started with selfhosting. It started as one single Raspberry Pi 4, then it grew to cluster of 4 Pis... and now I have 2 old IBM servers (x3550 m4).", "It's been a few years since I started self-hosting. What began with a single Raspberry Pi 4 has evolved into a cluster of four Pis. Now, I rely on two old IBM servers (x3550 M4) to host nearly everything I need: a video server, music server, Git repositories, and even a password manager. It's become a robust setup that meets all my requirements.",
image: "/temp.jpg", image: "/homelab.jpg",
imageAlt: "Photo of my personal homelab", imageAlt: "Photo of my personal homelab",
}, },
{ {
value: "third", value: "third",
title: "ESA's Astro Pi Challenge 2022/23", title: "ESA's Astro Pi Challenge 2022/23",
handle: "ESA Astro Pi", handle: "ESA Astro Pi",
href: "/kartoffeln",
description: description:
"Astro Pi is a competition for high school students by the European Space Agency. It's goal is to make it possible for students to run their code on the ISS. I was part of the Barrande team from our school. As our mission we chose Classification of Earth's topology using AI in Real-Time and I was the one tasked with programmign the AI. The mission was very successfull and we were nominated to 10 best teams. Reports and other data can be found on ESA's website.", "Astro Pi is a competition for high school students hosted by the European Space Agency. Its goal is to enable students to run their code aboard the ISS. I was part of the Barrande team from our school. For our mission, we chose \"Real-Time Classification of Earth\'s Topology using AI,\" and I was responsible for programming the AI. Our mission was highly successful, and we were nominated as one of the top 10 teams. Detailed reports and additional data can be found on the ESA\'s website.",
image: "/temp.jpg", image: "/astropi.png",
imageAlt: "Image for of our task and results explanation", imageAlt: "Image for of our task and results explanation",
}, },
], ],
/*
Blog page
*/
blog: {
title: "Blog @ Cyril Šebek",
description: "My personal blog, documenting some of my crazy ideas",
},
/*
Page with musical compositions
*/
music: {
pageTitle: "Music @ Cyril Šebek",
title: "My compositions",
description: "This is page is listing all my published musical compositions.",
downloadPDF: "Download PDF",
downloadMP3: "Download MP3",
downloadFLAC: "Download FLAC"
},
postsTagged: "All posts tagged with", postsTagged: "All posts tagged with",
}; };