mirror of
https://github.com/karl0ss/homepage.git
synced 2025-05-10 00:41:32 +01:00
Feature: add category icons (#301)
* Update setting.yaml mapping * Implement adding icon to categoryTitle * Move resolveIcon func to utils for reusability * Turn off default export eslint rule * Fix util typo * Revert "Turn off default export eslint rule" This reverts commit e8dd853ba6fac1d33253667ffe9e02010a8dcfd6. * fix resolveIcon export * Revert "Update setting.yaml mapping" This reverts commit 78c947766951e14d1f6db290c0ab03ccc8f1ebc3. * Revert "Implement adding icon to categoryTitle" * Use settings layout for group icon * Revert "Fix util typo" This reverts commit ab49b426ec6d925d7938c3ddec753a0e7c8759af. * ResolvedIcon component Co-authored-by: Mindfreak9100 <dhoom_rik@yahoo.com> Co-authored-by: Michael Shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
parent
bfd4e7e890
commit
71faaa56dc
@ -2,7 +2,7 @@ import { useTranslation } from "react-i18next";
|
|||||||
import { useEffect, useState, useRef, useCallback, useContext } from "react";
|
import { useEffect, useState, useRef, useCallback, useContext } from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import { resolveIcon } from "./services/item";
|
import ResolvedIcon from "./resolvedicon";
|
||||||
|
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
import { SettingsContext } from "utils/contexts/settings";
|
||||||
|
|
||||||
@ -135,7 +135,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
|
|||||||
)} onClick={handleItemClick}>
|
)} onClick={handleItemClick}>
|
||||||
<div className="flex flex-row items-center mr-4 pointer-events-none">
|
<div className="flex flex-row items-center mr-4 pointer-events-none">
|
||||||
<div className="w-5 text-xs mr-4">
|
<div className="w-5 text-xs mr-4">
|
||||||
{r.icon && resolveIcon(r.icon)}
|
{r.icon && <ResolvedIcon icon={r.icon} />}
|
||||||
{r.abbr && r.abbr}
|
{r.abbr && r.abbr}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
|
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
|
||||||
|
35
src/components/resolvedicon.jsx
Normal file
35
src/components/resolvedicon.jsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import Image from "next/future/image";
|
||||||
|
|
||||||
|
export default function ResolvedIcon({ icon }) {
|
||||||
|
// direct or relative URLs
|
||||||
|
if (icon.startsWith("http") || icon.startsWith("/")) {
|
||||||
|
return <Image src={`${icon}`} width={32} height={32} alt="logo" />;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mdi- prefixed, material design icons
|
||||||
|
if (icon.startsWith("mdi-")) {
|
||||||
|
const iconName = icon.replace("mdi-", "").replace(".svg", "");
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: 32,
|
||||||
|
height: 32,
|
||||||
|
background: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))",
|
||||||
|
mask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`,
|
||||||
|
WebkitMask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// fallback to dashboard-icons
|
||||||
|
const iconName = icon.replace(".png", "");
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
||||||
|
width={32}
|
||||||
|
height={32}
|
||||||
|
alt="logo"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
|
|
||||||
import List from "components/services/list";
|
import List from "components/services/list";
|
||||||
|
import ResolvedIcon from "components/resolvedicon";
|
||||||
|
|
||||||
export default function ServicesGroup({ services, layout }) {
|
export default function ServicesGroup({ services, layout }) {
|
||||||
return (
|
return (
|
||||||
@ -11,7 +12,14 @@ export default function ServicesGroup({ services, layout }) {
|
|||||||
"flex-1 p-1"
|
"flex-1 p-1"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
<div className="flex select-none items-center">
|
||||||
|
{layout?.icon &&
|
||||||
|
<div className="flex-shrink-0 mr-2 w-7 h-7">
|
||||||
|
<ResolvedIcon icon={layout.icon} />
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{services.name}</h2>
|
||||||
|
</div>
|
||||||
<List services={services.services} layout={layout} />
|
<List services={services.services} layout={layout} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import Image from "next/future/image";
|
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { useContext, useState } from "react";
|
import { useContext, useState } from "react";
|
||||||
|
|
||||||
@ -7,40 +6,7 @@ import Widget from "./widget";
|
|||||||
|
|
||||||
import Docker from "widgets/docker/component";
|
import Docker from "widgets/docker/component";
|
||||||
import { SettingsContext } from "utils/contexts/settings";
|
import { SettingsContext } from "utils/contexts/settings";
|
||||||
|
import ResolvedIcon from "components/resolvedicon";
|
||||||
export function resolveIcon(icon) {
|
|
||||||
// direct or relative URLs
|
|
||||||
if (icon.startsWith("http") || icon.startsWith("/")) {
|
|
||||||
return <Image src={`${icon}`} width={32} height={32} alt="logo" />;
|
|
||||||
}
|
|
||||||
|
|
||||||
// mdi- prefixed, material design icons
|
|
||||||
if (icon.startsWith("mdi-")) {
|
|
||||||
const iconName = icon.replace("mdi-", "").replace(".svg", "");
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 32,
|
|
||||||
height: 32,
|
|
||||||
background: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))",
|
|
||||||
mask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`,
|
|
||||||
WebkitMask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fallback to dashboard-icons
|
|
||||||
const iconName = icon.replace(".png", "");
|
|
||||||
return (
|
|
||||||
<Image
|
|
||||||
src={`https://cdn.jsdelivr.net/gh/walkxcode/dashboard-icons/png/${iconName}.png`}
|
|
||||||
width={32}
|
|
||||||
height={32}
|
|
||||||
alt="logo"
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function Item({ service }) {
|
export default function Item({ service }) {
|
||||||
const hasLink = service.href && service.href !== "#";
|
const hasLink = service.href && service.href !== "#";
|
||||||
@ -75,10 +41,12 @@ export default function Item({ service }) {
|
|||||||
rel="noreferrer"
|
rel="noreferrer"
|
||||||
className="flex-shrink-0 flex items-center justify-center w-12 "
|
className="flex-shrink-0 flex items-center justify-center w-12 "
|
||||||
>
|
>
|
||||||
{resolveIcon(service.icon)}
|
<ResolvedIcon icon={service.icon} />
|
||||||
</a>
|
</a>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex-shrink-0 flex items-center justify-center w-12 ">{resolveIcon(service.icon)}</div>
|
<div className="flex-shrink-0 flex items-center justify-center w-12 ">
|
||||||
|
<ResolvedIcon icon={service.icon} />
|
||||||
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
||||||
{hasLink ? (
|
{hasLink ? (
|
||||||
|
Loading…
x
Reference in New Issue
Block a user