mirror of
https://github.com/MeshEnvy/mesh-forge.git
synced 2026-05-10 07:14:47 +02:00
enh: add discord and github buttons
This commit is contained in:
@@ -37,3 +37,6 @@
|
||||
[submodule "vendor/meshtastic-web"]
|
||||
path = vendor/meshtastic-web
|
||||
url = git@github.com:meshtastic/web.git
|
||||
[submodule "vendor/lobbs-meshtastic-firmware"]
|
||||
path = vendor/lobbs-meshtastic-firmware
|
||||
url = git@github.com:benallfree/lobbs-meshtstic-firmware.git
|
||||
|
||||
@@ -13,14 +13,25 @@ interface DiscordButtonProps {
|
||||
variant?: "default" | "outline" | "ghost" | "link" | "destructive"
|
||||
size?: "default" | "sm" | "lg" | "icon"
|
||||
className?: string
|
||||
/** Icon only; link gets `aria-label` for accessibility */
|
||||
iconOnly?: boolean
|
||||
}
|
||||
|
||||
export function DiscordButton({ variant = "outline", size, className }: DiscordButtonProps) {
|
||||
export function DiscordButton({ variant = "outline", size, className, iconOnly }: DiscordButtonProps) {
|
||||
return (
|
||||
<a href="https://discord.gg/8KgJpvjfaJ" target="_blank" rel="noopener noreferrer">
|
||||
<Button variant={variant} size={size} className={cn("flex items-center gap-2", className)}>
|
||||
<DiscordIcon className="w-4 h-4" />
|
||||
Discord
|
||||
<a
|
||||
href="https://discord.gg/8KgJpvjfaJ"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={iconOnly ? "MeshForge on Discord" : undefined}
|
||||
>
|
||||
<Button
|
||||
variant={variant}
|
||||
size={iconOnly ? "icon" : size}
|
||||
className={cn(iconOnly ? "shrink-0" : "flex items-center gap-2", className)}
|
||||
>
|
||||
<DiscordIcon className={iconOnly ? "h-[18px] w-[18px]" : "w-4 h-4"} />
|
||||
{!iconOnly ? "Discord" : null}
|
||||
</Button>
|
||||
</a>
|
||||
)
|
||||
|
||||
+2
-20
@@ -1,14 +1,12 @@
|
||||
import favicon from "@/assets/favicon-96x96.png"
|
||||
import { DiscordButton } from "@/components/DiscordButton"
|
||||
import { RedditButton } from "@/components/RedditButton"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { api } from "@/convex/_generated/api"
|
||||
import { useAuthActions } from "@convex-dev/auth/react"
|
||||
import { Authenticated, Unauthenticated, useQuery } from "convex/react"
|
||||
import { Authenticated, useQuery } from "convex/react"
|
||||
import { Link } from "react-router-dom"
|
||||
|
||||
export default function Navbar() {
|
||||
const { signOut, signIn } = useAuthActions()
|
||||
const { signOut } = useAuthActions()
|
||||
const isAdmin = useQuery(api.admin.isAdmin)
|
||||
|
||||
return (
|
||||
@@ -33,22 +31,6 @@ export default function Navbar() {
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<DiscordButton
|
||||
variant="default"
|
||||
className="bg-gradient-to-r from-indigo-500 to-purple-600 hover:from-indigo-600 hover:to-purple-700 text-white border-0 shadow-lg shadow-purple-500/50"
|
||||
/>
|
||||
<RedditButton
|
||||
variant="default"
|
||||
className="bg-gradient-to-r from-orange-500 to-red-600 hover:from-orange-600 hover:to-red-700 text-white border-0 shadow-lg shadow-orange-500/50"
|
||||
/>
|
||||
<Unauthenticated>
|
||||
<Button
|
||||
onClick={() => signIn("github", { redirectTo: window.location.href })}
|
||||
className="bg-cyan-600 hover:bg-cyan-700"
|
||||
>
|
||||
Sign In
|
||||
</Button>
|
||||
</Unauthenticated>
|
||||
<Authenticated>
|
||||
<Button variant="outline" onClick={() => signOut()}>
|
||||
Sign Out
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useId } from "react"
|
||||
|
||||
function RedditIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
function RedditIcon(props: React.SVGProps<SVGSVGElement> & { maskId: string }) {
|
||||
const { maskId, ...rest } = props
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" {...props}>
|
||||
<mask id="SVGfUZuVbjp">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" {...rest}>
|
||||
<mask id={maskId}>
|
||||
<g fill="#fff">
|
||||
<path
|
||||
fillOpacity="0"
|
||||
@@ -72,7 +74,7 @@ function RedditIcon(props: React.SVGProps<SVGSVGElement>) {
|
||||
<animate fill="freeze" attributeName="stroke-dashoffset" begin="2s" dur="0.2s" values="10;0" />
|
||||
</path>
|
||||
</mask>
|
||||
<rect width="24" height="24" fill="currentColor" mask="url(#SVGfUZuVbjp)" />
|
||||
<rect width="24" height="24" fill="currentColor" mask={`url(#${maskId})`} />
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
@@ -81,14 +83,25 @@ interface RedditButtonProps {
|
||||
variant?: "default" | "outline" | "ghost" | "link" | "destructive"
|
||||
size?: "default" | "sm" | "lg" | "icon"
|
||||
className?: string
|
||||
iconOnly?: boolean
|
||||
}
|
||||
|
||||
export function RedditButton({ variant = "outline", size, className }: RedditButtonProps) {
|
||||
export function RedditButton({ variant = "outline", size, className, iconOnly }: RedditButtonProps) {
|
||||
const maskId = useId().replace(/:/g, "")
|
||||
return (
|
||||
<a href="https://www.reddit.com/r/MeshForge/" target="_blank" rel="noopener noreferrer">
|
||||
<Button variant={variant} size={size} className={cn("flex items-center gap-2", className)}>
|
||||
<RedditIcon className="w-4 h-4" />
|
||||
Reddit
|
||||
<a
|
||||
href="https://www.reddit.com/r/MeshForge/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
aria-label={iconOnly ? "r/MeshForge on Reddit" : undefined}
|
||||
>
|
||||
<Button
|
||||
variant={variant}
|
||||
size={iconOnly ? "icon" : size}
|
||||
className={cn(iconOnly ? "shrink-0" : "flex items-center gap-2", className)}
|
||||
>
|
||||
<RedditIcon maskId={maskId} className={iconOnly ? "h-[18px] w-[18px]" : "w-4 h-4"} />
|
||||
{!iconOnly ? "Reddit" : null}
|
||||
</Button>
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { DiscordButton } from "@/components/DiscordButton"
|
||||
import { RedditButton } from "@/components/RedditButton"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
export function SocialCornerBadges({ className }: { className?: string }) {
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"fixed right-3 top-3 z-50 flex items-center gap-2 sm:right-4 sm:top-4",
|
||||
className
|
||||
)}
|
||||
>
|
||||
<DiscordButton
|
||||
iconOnly
|
||||
variant="ghost"
|
||||
className="h-9 w-9 rounded-full border-0 bg-transparent text-slate-500 shadow-none hover:bg-transparent hover:text-slate-200"
|
||||
/>
|
||||
<RedditButton
|
||||
iconOnly
|
||||
variant="ghost"
|
||||
className="h-9 w-9 rounded-full border-0 bg-transparent text-slate-500 shadow-none hover:bg-transparent hover:text-slate-200"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import Footer from "@/components/Footer"
|
||||
import Navbar from "@/components/Navbar"
|
||||
import { SocialCornerBadges } from "@/components/SocialCornerBadges"
|
||||
import { Navigate, Route, Routes, useLocation } from "react-router-dom"
|
||||
import AdminPage from "./pages/AdminPage"
|
||||
import HomePage from "./pages/HomePage"
|
||||
@@ -14,6 +15,7 @@ function Layout({ children }: { children: React.ReactNode }) {
|
||||
const hideNav = loc.pathname === "/"
|
||||
return (
|
||||
<div className="min-h-screen flex flex-col">
|
||||
<SocialCornerBadges />
|
||||
{!hideNav && <Navbar />}
|
||||
<main className="flex-1">{children}</main>
|
||||
<Footer />
|
||||
|
||||
+1
Submodule vendor/lobbs-meshtastic-firmware added at 3a87e746a8
Reference in New Issue
Block a user