Skip to content

Commit

Permalink
feat: Added use-favicon.
Browse files Browse the repository at this point in the history
  • Loading branch information
Blankeos committed Oct 20, 2024
1 parent e415947 commit 1ed0d82
Show file tree
Hide file tree
Showing 8 changed files with 106 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Based on the [@mantine/hooks](https://github.com/mantinedev/mantine/tree/master/
- [ ] use-document-visibility
- [ ] use-event-listener
- [ ] use-eye-dropper
- [ ] use-favicon
- [x] use-favicon
- [ ] use-fetch
- [ ] use-focus-return
- [ ] use-focus-trap
Expand Down
9 changes: 5 additions & 4 deletions dev/components/examples/example-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export function ExampleBase(props: FlowProps<ExampleBaseProps>) {
const [viewing, setViewing] = createSignal<'code' | 'result'>('result');

return (
<div class="flex h-full max-h-[500px] w-full flex-col items-start gap-y-5 overflow-hidden rounded-xl border bg-white p-5">
<div class="flex h-full max-h-[500px] w-full flex-col items-start gap-y-3 overflow-hidden rounded-xl border bg-white p-5">
<div class="flex w-full items-center justify-between">
<h2 class="text-2xl font-bold">{props.title}</h2>
<h2 class="text-xl font-bold">{props.title}</h2>
<button
class={`rounded-md border p-2 transition active:scale-95 ${viewing() === 'code' ? 'bg-background text-white' : ''}`}
onClick={() => {
Expand All @@ -24,15 +24,16 @@ export function ExampleBase(props: FlowProps<ExampleBaseProps>) {
<IconCode class="h-5 w-5" />
</button>
</div>
<p>{props.description}</p>

<p class="text-sm">{props.description}</p>

<Show when={viewing() === 'result'}>
<div class="w-full flex-1 rounded-md">{props.children}</div>
</Show>

<div
style={{ display: viewing() === 'code' ? 'block' : 'none' }}
class="w-full flex-1 overflow-hidden rounded-md border bg-[#1c1e28] p-3 text-white"
class="w-full flex-1 overflow-auto rounded-md border bg-[#1c1e28] p-3 text-white"
>
{props.code}
</div>
Expand Down
12 changes: 12 additions & 0 deletions dev/components/examples/use-favicon/use-favicon.code.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
```tsx
const [favicon, setFavicon] = createSignal('https://docs.solidjs.com/favicon.svg');
const setXFavicon = () => setFavicon('https://x.com/favicon.ico');
const setSolidFavicon = () => setFavicon('https://docs.solidjs.com/favicon.svg');

useFavicon(favicon);

return (
<button onClick={setXFavicon}>Use X Favicon</button>
<button onClick={setSolidFavicon}>Use SolidJS Favicon</button>
)
```
41 changes: 41 additions & 0 deletions dev/components/examples/use-favicon/use-favicon.example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useFavicon } from 'src';
import { ExampleBase } from '../example-base';
import Code from './use-favicon.code.mdx';

import { createSignal } from 'solid-js';
import { useMDXComponents } from 'solid-jsx';

export function UseFaviconExample() {
const [favicon, setFavicon] = createSignal('https://docs.solidjs.com/favicon.svg');
const setXFavicon = () => setFavicon('https://x.com/favicon.ico');
const setSolidFavicon = () => setFavicon('https://docs.solidjs.com/favicon.svg');

useFavicon(favicon);

// @ts-ignore
const components: any = useMDXComponents();

return (
<ExampleBase
title="useFavicon"
description="Appends <link /> element to head component with given favicon url. The hook is not called during server side rendering."
code={<Code components={components} />}
>
<div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center text-sm">
<button
onClick={() => setXFavicon()}
class="rounded-md border px-2 py-1.5 transition active:scale-95"
>
X favicon
</button>

<button
onClick={() => setSolidFavicon()}
class="rounded-md border px-2 py-1.5 transition active:scale-95"
>
Solid favicon
</button>
</div>
</ExampleBase>
);
}
4 changes: 2 additions & 2 deletions dev/components/markdown/markdown.context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ export function MarkdownContextProvider(props: FlowProps) {
fallback={<IconCopy width={23} height={23} />}
/>
</button>
<div ref={setRef}>
{/* This will be replaced, but render it at first paint with opacity 0 so it takes up space. */}
<div ref={setRef} class="text-sm">
{/* This will be replaced with the code element, but render it at first paint with opacity 0 so it takes up space. */}
<div class="opacity-0">{props.children}</div>
</div>
</div>
Expand Down
20 changes: 6 additions & 14 deletions dev/pages/index/+Page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// import { createMemo, type Component } from 'solid-js';

// Hooks
import { ExampleBase } from 'dev/components/examples/example-base';
import { UseClickOutsideExample } from 'dev/components/examples/use-click-outside/use-click-outside.example';
import { UseElementSizeExample } from 'dev/components/examples/use-element-size/use-element-size.example';
import { UseFaviconExample } from 'dev/components/examples/use-favicon/use-favicon.example';
import { UseHotkeysExample } from 'dev/components/examples/use-hotkeys/use-hotkeys.example';
import { UseHoverExample } from 'dev/components/examples/use-hover/use-hover.example';
import { UseIdleExample } from 'dev/components/examples/use-idle/use-idle.example';
Expand All @@ -12,21 +12,9 @@ import { UseNetworkExample } from 'dev/components/examples/use-network/use-netwo
import { UseOsExample } from 'dev/components/examples/use-os/use-os.example';
import { UseResizeObserverExample } from 'dev/components/examples/use-resize-observer/use-resize-observer.example';
import { UseToggleExample } from 'dev/components/examples/use-toggle/use-toggle.example';
import { MarkdownContextProvider } from 'dev/components/markdown/markdown.context';
import { IconLogo } from 'dev/icons';
import { title } from 'process';
import { createMemo, createSignal, For } from 'solid-js';
import {
useClickOutside,
useElementSize,
useHotkeys,
useHover,
useIdle,
useNetwork,
useOs,
useResizeObserver,
useToggle,
} from 'src';
import { useOs } from 'src';

export default function HomePage() {
// // let ref = useClickOutside(() =>
Expand Down Expand Up @@ -91,6 +79,10 @@ export default function HomePage() {
title: 'useToggle',
example: <UseToggleExample />,
},
{
title: 'useFavicon',
example: <UseFaviconExample />,
},
];

const filteredList = createMemo(() => {
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './use-click-outside/use-click-outside';
export * from './use-favicon/use-favicon';
export * from './use-hotkeys/use-hotkeys';
export * from './use-hover/use-hover';
export * from './use-idle/use-idle';
Expand Down
38 changes: 38 additions & 0 deletions src/use-favicon/use-favicon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Accessor, createEffect, createSignal } from 'solid-js';

const MIME_TYPES: Record<string, string> = {
ico: 'image/x-icon',
png: 'image/png',
svg: 'image/svg+xml',
gif: 'image/gif',
};

/**
* A hook that sets the favicon of the page based on the url (accessor) passed.
*/
export function useFavicon(url: Accessor<string>) {
const [linkRef, setLinkRef] = createSignal<HTMLLinkElement>();

createEffect(() => {
if (!url()) {
return;
}

if (!linkRef()) {
const existingElements = document.querySelectorAll<HTMLLinkElement>('link[rel*="icon"]');
existingElements.forEach(element => document.head.removeChild(element));

const element = document.createElement('link');
element.rel = 'shortcut icon';
setLinkRef(element);
document.querySelector('head')!.appendChild(element);
}

const splittedUrl = url().split('.');
linkRef()?.setAttribute(
'type',
MIME_TYPES[splittedUrl?.[splittedUrl.length - 1]?.toLowerCase()!]!,
);
linkRef()?.setAttribute('href', url());
});
}

0 comments on commit 1ed0d82

Please sign in to comment.