mirror of
https://github.com/walkxcode/dashboard-icons.git
synced 2025-06-28 23:40:21 +08:00
feat(icons): implement theme-aware icon variants in search and details components
This commit is contained in:
parent
bf78bc6a24
commit
62ab677ee3
@ -10,6 +10,7 @@ import Image from "next/image"
|
|||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
import { usePathname, useRouter, useSearchParams } from "next/navigation"
|
||||||
import { useCallback, useEffect, useRef, useState } from "react"
|
import { useCallback, useEffect, useRef, useState } from "react"
|
||||||
|
import { useTheme } from "next-themes"
|
||||||
|
|
||||||
export function IconSearch({ icons }: IconSearchProps) {
|
export function IconSearch({ icons }: IconSearchProps) {
|
||||||
const searchParams = useSearchParams()
|
const searchParams = useSearchParams()
|
||||||
@ -18,6 +19,7 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
const pathname = usePathname()
|
const pathname = usePathname()
|
||||||
const [searchQuery, setSearchQuery] = useState(initialQuery ?? "")
|
const [searchQuery, setSearchQuery] = useState(initialQuery ?? "")
|
||||||
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
const timeoutRef = useRef<NodeJS.Timeout | null>(null)
|
||||||
|
const { resolvedTheme } = useTheme()
|
||||||
const [filteredIcons, setFilteredIcons] = useState(() => {
|
const [filteredIcons, setFilteredIcons] = useState(() => {
|
||||||
if (!initialQuery?.trim()) return icons
|
if (!initialQuery?.trim()) return icons
|
||||||
|
|
||||||
@ -79,6 +81,23 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
// Helper function to get the appropriate icon variant based on theme
|
||||||
|
const getIconVariant = (name: string, data: any) => {
|
||||||
|
// Check if the icon has theme variants and use appropriate one
|
||||||
|
if (data.colors) {
|
||||||
|
// If in dark mode and a light variant exists, use the light variant
|
||||||
|
if (resolvedTheme === 'dark' && data.colors.light) {
|
||||||
|
return data.colors.light;
|
||||||
|
}
|
||||||
|
// If in light mode and a dark variant exists, use the dark variant
|
||||||
|
else if (resolvedTheme === 'light' && data.colors.dark) {
|
||||||
|
return data.colors.dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall back to the default name if no appropriate variant
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
if (!searchParams) return null
|
if (!searchParams) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -133,7 +152,7 @@ export function IconSearch({ icons }: IconSearchProps) {
|
|||||||
|
|
||||||
<div className="relative h-12 w-12 sm:h-16 sm:w-16 mb-2">
|
<div className="relative h-12 w-12 sm:h-16 sm:w-16 mb-2">
|
||||||
<Image
|
<Image
|
||||||
src={`${BASE_URL}/${data.base}/${name}.${data.base}`}
|
src={`${BASE_URL}/${data.base}/${getIconVariant(name, data)}.${data.base}`}
|
||||||
alt={`${name} icon`}
|
alt={`${name} icon`}
|
||||||
fill
|
fill
|
||||||
className="object-contain p-1 group-hover:scale-110 transition-transform duration-300"
|
className="object-contain p-1 group-hover:scale-110 transition-transform duration-300"
|
||||||
|
@ -13,6 +13,7 @@ import Link from "next/link"
|
|||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { toast } from "sonner"
|
import { toast } from "sonner"
|
||||||
import { Carbon } from "./carbon"
|
import { Carbon } from "./carbon"
|
||||||
|
import { useTheme } from "next-themes"
|
||||||
|
|
||||||
export type IconDetailsProps = {
|
export type IconDetailsProps = {
|
||||||
icon: string
|
icon: string
|
||||||
@ -21,6 +22,7 @@ export type IconDetailsProps = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
||||||
|
const { resolvedTheme } = useTheme()
|
||||||
const authorName = authorData.name || authorData.login || ""
|
const authorName = authorData.name || authorData.login || ""
|
||||||
const iconColorVariants = iconData.colors
|
const iconColorVariants = iconData.colors
|
||||||
const formattedDate = new Date(iconData.update.timestamp).toLocaleDateString("en-GB", {
|
const formattedDate = new Date(iconData.update.timestamp).toLocaleDateString("en-GB", {
|
||||||
@ -42,6 +44,23 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
const availableFormats = getAvailableFormats()
|
const availableFormats = getAvailableFormats()
|
||||||
const [copiedVariants, setCopiedVariants] = useState<Record<string, boolean>>({})
|
const [copiedVariants, setCopiedVariants] = useState<Record<string, boolean>>({})
|
||||||
|
|
||||||
|
// Helper function to get the appropriate icon variant based on theme
|
||||||
|
const getIconVariant = (iconName: string) => {
|
||||||
|
// Check if the icon has theme variants
|
||||||
|
if (iconColorVariants) {
|
||||||
|
// If in dark mode and a light variant exists, use the light variant
|
||||||
|
if (resolvedTheme === 'dark' && iconColorVariants.light) {
|
||||||
|
return iconColorVariants.light;
|
||||||
|
}
|
||||||
|
// If in light mode and a dark variant exists, use the dark variant
|
||||||
|
else if (resolvedTheme === 'light' && iconColorVariants.dark) {
|
||||||
|
return iconColorVariants.dark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Fall back to the default name if no appropriate variant
|
||||||
|
return iconName;
|
||||||
|
}
|
||||||
|
|
||||||
const handleCopy = (url: string, variantKey: string) => {
|
const handleCopy = (url: string, variantKey: string) => {
|
||||||
navigator.clipboard.writeText(url)
|
navigator.clipboard.writeText(url)
|
||||||
setCopiedVariants((prev) => ({
|
setCopiedVariants((prev) => ({
|
||||||
@ -168,7 +187,7 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
<div className="flex flex-col items-center">
|
<div className="flex flex-col items-center">
|
||||||
<div className="relative w-32 h-32 bg-background/90 rounded-xl overflow-hidden border flex items-center justify-center p-3 mb-4">
|
<div className="relative w-32 h-32 bg-background/90 rounded-xl overflow-hidden border flex items-center justify-center p-3 mb-4">
|
||||||
<Image
|
<Image
|
||||||
src={`${BASE_URL}/${iconData.base}/${icon}.${iconData.base}`}
|
src={`${BASE_URL}/${iconData.base}/${getIconVariant(icon)}.${iconData.base}`}
|
||||||
width={96}
|
width={96}
|
||||||
height={96}
|
height={96}
|
||||||
alt={icon}
|
alt={icon}
|
||||||
@ -332,7 +351,7 @@ export function IconDetails({ icon, iconData, authorData }: IconDetailsProps) {
|
|||||||
<h3 className="text-sm font-semibold text-muted-foreground">Source</h3>
|
<h3 className="text-sm font-semibold text-muted-foreground">Source</h3>
|
||||||
<Button variant="outline" className="w-full" asChild>
|
<Button variant="outline" className="w-full" asChild>
|
||||||
<Link
|
<Link
|
||||||
href={`${REPO_PATH}/tree/main/${iconData.base}/${icon}.${iconData.base}`}
|
href={`${REPO_PATH}/blob/main/meta/${icon}.json`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user