refactor(web): update text and descriptions for clarity and consistency across various components

This commit is contained in:
Bjorn Lammers
2025-04-22 23:55:40 +02:00
parent 293f67bcc8
commit d6cb15aab0
11 changed files with 134 additions and 87 deletions

View File

@@ -42,7 +42,7 @@ export async function generateMetadata({ params, searchParams }: Props, parent:
return {
title: `${formattedIconName} Icon | Dashboard Icons`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats for FREE. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Available for free in our collection of ${totalIcons} icons for dashboards and applications.`,
assets: [iconImageUrl],
category: "icons",
keywords: [
@@ -57,14 +57,14 @@ export async function generateMetadata({ params, searchParams }: Props, parent:
icons: {
icon: iconImageUrl,
},
abstract: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats for FREE. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
abstract: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Available for free in our collection of ${totalIcons} icons for dashboards and applications.`,
robots: {
index: true,
follow: true,
},
openGraph: {
title: `${formattedIconName} Icon | Dashboard Icons`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats for FREE. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Available for free in our collection of ${totalIcons} icons for dashboards and applications.`,
type: "article",
url: pageUrl,
authors: [authorName],
@@ -76,7 +76,7 @@ export async function generateMetadata({ params, searchParams }: Props, parent:
twitter: {
card: "summary_large_image",
title: `${formattedIconName} Icon | Dashboard Icons`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats for FREE. Part of a collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Download the ${formattedIconName} icon in SVG, PNG, and WEBP formats. Available for free in our collection of ${totalIcons} icons for dashboards and applications.`,
images: [iconImageUrl],
},
alternates: {

View File

@@ -228,11 +228,11 @@ export function IconSearch({ icons }: IconSearchProps) {
const getSortLabel = (sort: SortOption) => {
switch (sort) {
case "relevance":
return "Best match"
return "Relevance"
case "alphabetical-asc":
return "A to Z"
return "Name (A-Z)"
case "alphabetical-desc":
return "Z to A"
return "Name (Z-A)"
case "newest":
return "Newest first"
default:
@@ -265,7 +265,7 @@ export function IconSearch({ icons }: IconSearchProps) {
</div>
<Input
type="search"
placeholder="Search icons by name, alias, or category..."
placeholder="Search for icons..."
className="w-full h-10 pl-9 cursor-text transition-all duration-300 text-sm md:text-base border-border shadow-sm"
value={searchQuery}
onChange={(e) => handleSearch(e.target.value)}
@@ -279,7 +279,7 @@ export function IconSearch({ icons }: IconSearchProps) {
<DropdownMenuTrigger asChild>
<Button variant="outline" size="sm" className="flex-1 sm:flex-none cursor-pointer bg-background border-border shadow-sm ">
<Filter className="h-4 w-4 mr-2" />
<span>Filter</span>
<span>Categories</span>
{selectedCategories.length > 0 && (
<Badge variant="secondary" className="ml-2 px-1.5">
{selectedCategories.length}
@@ -288,7 +288,7 @@ export function IconSearch({ icons }: IconSearchProps) {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-64 sm:w-56">
<DropdownMenuLabel className="font-semibold">Categories</DropdownMenuLabel>
<DropdownMenuLabel className="font-semibold">Select Categories</DropdownMenuLabel>
<DropdownMenuSeparator />
<div className="max-h-[40vh] overflow-y-auto p-1">
@@ -314,7 +314,7 @@ export function IconSearch({ icons }: IconSearchProps) {
}}
className="cursor-pointer focus: focus:bg-rose-50 dark:focus:bg-rose-950/20"
>
Clear all filters
Clear categories
</DropdownMenuItem>
</>
)}
@@ -330,18 +330,18 @@ export function IconSearch({ icons }: IconSearchProps) {
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-56">
<DropdownMenuLabel className="font-semibold">Sort By</DropdownMenuLabel>
<DropdownMenuLabel className="font-semibold">Sort Icons</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup value={sortOption} onValueChange={(value) => handleSortChange(value as SortOption)}>
<DropdownMenuRadioItem value="relevance" className="cursor-pointer">
<Search className="h-4 w-4 mr-2" />
Best match
Relevance
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="alphabetical-asc" className="cursor-pointer">
<ArrowDownAZ className="h-4 w-4 mr-2" />A to Z
<ArrowDownAZ className="h-4 w-4 mr-2" />Name (A-Z)
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="alphabetical-desc" className="cursor-pointer">
<ArrowUpZA className="h-4 w-4 mr-2" />Z to A
<ArrowUpZA className="h-4 w-4 mr-2" />Name (Z-A)
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="newest" className="cursor-pointer">
<Calendar className="h-4 w-4 mr-2" />
@@ -355,7 +355,7 @@ export function IconSearch({ icons }: IconSearchProps) {
{(searchQuery || selectedCategories.length > 0 || sortOption !== "relevance") && (
<Button variant="outline" size="sm" onClick={clearFilters} className="flex-1 sm:flex-none cursor-pointer bg-background">
<X className="h-4 w-4 mr-2" />
<span>Clear all</span>
<span>Reset</span>
</Button>
)}
</div>
@@ -363,7 +363,7 @@ export function IconSearch({ icons }: IconSearchProps) {
{/* Active filter badges */}
{selectedCategories.length > 0 && (
<div className="flex flex-wrap items-center gap-2 mt-2">
<span className="text-sm text-muted-foreground">Filters:</span>
<span className="text-sm text-muted-foreground">Selected:</span>
<div className="flex flex-wrap gap-2">
{selectedCategories.map((category) => (
<Badge key={category} variant="secondary" className="flex items-center gap-1 pl-2 pr-1">
@@ -389,7 +389,7 @@ export function IconSearch({ icons }: IconSearchProps) {
}}
className="text-xs h-7 px-2 cursor-pointer"
>
Clear all
Clear
</Button>
</div>
)}
@@ -400,34 +400,39 @@ export function IconSearch({ icons }: IconSearchProps) {
{filteredIcons.length === 0 ? (
<div className="flex flex-col gap-8 py-12 max-w-2xl mx-auto items-center">
<div className="text-center">
<h2 className="text-3xl sm:text-5xl font-semibold">We don't have this one...yet!</h2>
<h2 className="text-3xl sm:text-5xl font-semibold">Icon not found</h2>
<p className="text-lg text-muted-foreground mt-2">Help us expand our collection</p>
</div>
<div className="flex flex-col gap-4 items-center w-full">
<IconSubmissionContent />
<div className="mt-4 flex items-center gap-2 justify-center">
<span className="text-sm text-muted-foreground">Need help?</span>
<Button
className="cursor-pointer"
variant="outline"
size="sm"
onClick={() => {
setIsLazyRequestSubmitted(true)
toast("Request submitted", {
description: `We've added "${searchQuery || "this icon"}" to our request list.`,
})
posthog.capture("lazy icon request", {
query: searchQuery,
categories: selectedCategories,
})
}}
disabled={isLazyRequestSubmitted}
>
Submit request
</Button>
</div>
</div>
<Button
className="cursor-pointer motion-preset-pop"
variant="default"
size="lg"
onClick={() => {
setIsLazyRequestSubmitted(true)
toast("We hear you!", {
description: `Okay, okay... we'll consider adding "${searchQuery || "that icon"}" just for you. 😉`,
})
posthog.capture("lazy icon request", {
query: searchQuery,
categories: selectedCategories,
})
}}
disabled={isLazyRequestSubmitted}
>
I want this icon added but I'm too lazy to add it myself
</Button>
<IconSubmissionContent />
</div>
) : (
<>
<div className="flex justify-between items-center pb-2">
<p className="text-sm text-muted-foreground">
Found {filteredIcons.length} icon
{filteredIcons.length !== 1 ? "s" : ""}.
{filteredIcons.length} {filteredIcons.length === 1 ? "icon" : "icons"} found
</p>
<div className="flex items-center gap-1 text-xs text-muted-foreground">
{getSortIcon(sortOption)}
@@ -445,11 +450,9 @@ export function IconSearch({ icons }: IconSearchProps) {
function IconCard({
name,
data: iconData,
matchedAlias,
}: {
name: string
data: Icon
matchedAlias?: string | null
}) {
return (
<MagicCard className="rounded-md shadow-md">
@@ -465,8 +468,6 @@ function IconCard({
<span className="text-xs sm:text-sm text-center truncate w-full capitalize group- dark:group-hover:text-rose-400 transition-colors duration-200 font-medium">
{name.replace(/-/g, " ")}
</span>
{matchedAlias && <span className="text-[10px] text-center truncate w-full mt-1">Alias: {matchedAlias}</span>}
</Link>
</MagicCard>
)
@@ -482,10 +483,10 @@ function IconsGrid({ filteredIcons, matchedAliases }: IconsGridProps) {
<>
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-8 gap-4 mt-2">
{filteredIcons.slice(0, 120).map(({ name, data }) => (
<IconCard key={name} name={name} data={data} matchedAlias={matchedAliases[name] || null} />
<IconCard key={name} name={name} data={data} />
))}
</div>
{filteredIcons.length > 120 && <p className="text-sm text-muted-foreground">And {filteredIcons.length - 120} more...</p>}
{filteredIcons.length > 120 && <p className="text-sm text-muted-foreground">{filteredIcons.length - 120} more icons available</p>}
</>
)
}

View File

@@ -9,7 +9,7 @@ export async function generateMetadata(): Promise<Metadata> {
return {
title: "Browse Icons | Free Dashboard Icons",
description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Browse our collection of ${totalIcons} icons for dashboards and applications. Available in SVG, PNG, and WEBP formats.`,
keywords: [
"browse icons",
"dashboard icons",
@@ -22,7 +22,7 @@ export async function generateMetadata(): Promise<Metadata> {
],
openGraph: {
title: "Browse Icons | Free Dashboard Icons",
description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Browse our collection of ${totalIcons} icons for dashboards and applications. Available in SVG, PNG, and WEBP formats.`,
type: "website",
url: `${BASE_URL}/icons`,
images: [
@@ -38,7 +38,7 @@ export async function generateMetadata(): Promise<Metadata> {
twitter: {
card: "summary_large_image",
title: "Browse Icons | Free Dashboard Icons",
description: `Search and browse through our collection of ${totalIcons} curated icons for services, applications and tools, designed specifically for dashboards and app directories.`,
description: `Browse our collection of ${totalIcons} icons for dashboards and applications. Available in SVG, PNG, and WEBP formats.`,
images: ["/og-image-browse.png"],
},
alternates: {
@@ -57,8 +57,8 @@ export default async function IconsPage() {
<div className="space-y-4 mb-8 mx-auto max-w-7xl">
<div className="flex flex-col sm:flex-row sm:items-center justify-between gap-4">
<div>
<h1 className="text-3xl font-bold">Browse icons</h1>
<p className="text-muted-foreground">Search through our collection of {icons.length} beautiful icons.</p>
<h1 className="text-3xl font-bold">Icons</h1>
<p className="text-muted-foreground">Search our collection of {icons.length} icons.</p>
</div>
</div>