Module providing the internal functions to extend the diamond's upgrade functionality by adding, replacing, or removing facets.
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index 16d12212..eb246476 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -206,13 +206,18 @@ const config = {
// ],
// },
{
- type: 'custom-githubStars',
+ type: 'custom-icon',
position: 'right',
+ href: 'https://github.com/Perfect-Abstractions/Compose',
+ iconSrc: '/icons/github-white.svg',
+ label: 'GitHub',
},
{
+ type: 'custom-icon',
+ position: 'right',
href: 'https://discord.gg/DCBD2UKbxc',
+ iconSrc: '/icons/discord-white.svg',
label: 'Discord',
- position: 'right',
},
],
},
@@ -345,7 +350,7 @@ const config = {
enableInDevelopment: false,
capturePageLeave: true,
defaults: '2026-01-30',
- cookieless_mode: 'on_reject',
+ cookieless_mode: 'always',
},
],
]
diff --git a/website/src/components/docs/PackageImport/index.js b/website/src/components/docs/PackageImport/index.js
new file mode 100644
index 00000000..b1eca8e0
--- /dev/null
+++ b/website/src/components/docs/PackageImport/index.js
@@ -0,0 +1,44 @@
+import React, { useState } from 'react';
+import styles from './styles.module.css';
+
+function getRelativePath(gitSource) {
+ const marker = '/tree/main/src/';
+ const idx = gitSource.indexOf(marker);
+ if (idx === -1) return '';
+ const after = gitSource.slice(idx + marker.length);
+ return after;
+}
+
+export default function PackageImport({ gitSource }) {
+ const [copied, setCopied] = useState(false);
+
+ if (!gitSource) return null;
+
+ const relPath = getRelativePath(gitSource);
+
+ const handleCopy = async () => {
+ try {
+ await navigator.clipboard.writeText(`@perfect-abstractions/compose/${relPath}`);
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ } catch {
+ // silent
+ }
+ };
+
+ return (
+
+
+ {`@perfect-abstractions/compose/${relPath}`}
+
+
+
+ );
+}
diff --git a/website/src/components/docs/PackageImport/styles.module.css b/website/src/components/docs/PackageImport/styles.module.css
new file mode 100644
index 00000000..f67a4ae0
--- /dev/null
+++ b/website/src/components/docs/PackageImport/styles.module.css
@@ -0,0 +1,101 @@
+.packageImport {
+ display: flex;
+ align-items: center;
+ gap: 0.75rem;
+ overflow-x: auto;
+ padding-bottom: 1rem;
+}
+
+.label {
+ flex-shrink: 0;
+ font-size: 0.8125rem;
+ font-weight: 600;
+ color: var(--ifm-color-emphasis-500);
+ user-select: none;
+}
+
+.code {
+ font-family: var(--ifm-font-family-monospace);
+ font-size: 0.875rem;
+ line-height: 1.6;
+ white-space: pre;
+ color: var(--ifm-color-primary-dark);
+ background-color: var(--ifm-background-surface-color);
+}
+
+.copyButton {
+ flex-shrink: 0;
+ padding: 0.25rem 0.625rem;
+ background: transparent;
+ border: 1px solid var(--ifm-color-emphasis-300);
+ border-radius: 0.25rem;
+ color: var(--ifm-color-emphasis-600);
+ font-size: 0.75rem;
+ font-weight: 600;
+ cursor: pointer;
+ transition: all 0.15s ease;
+}
+
+.copyButton:hover {
+ background: var(--ifm-color-emphasis-200);
+ color: var(--ifm-color-emphasis-800);
+}
+
+.keyword {
+ color: #d946ef;
+}
+
+.brace {
+ color: var(--ifm-color-emphasis-700);
+}
+
+.name {
+ color: #06b6d4;
+}
+
+.string {
+ color: #10b981;
+}
+
+.semicolon {
+ color: var(--ifm-color-emphasis-600);
+}
+
+[data-theme='dark'] .packageImport {
+ border-color: #1e293b;
+ background: #0f172a;
+}
+
+[data-theme='dark'] .label {
+ color: #64748b;
+}
+
+[data-theme='dark'] .copyButton {
+ border-color: #334155;
+ color: #94a3b8;
+}
+
+[data-theme='dark'] .copyButton:hover {
+ background: #334155;
+ color: #ffffff;
+}
+
+@media (max-width: 768px) {
+ .packageImport {
+ border-radius: 0.375rem;
+ flex-wrap: wrap;
+ }
+
+ .label {
+ width: 100%;
+ margin-bottom: -0.25rem;
+ }
+
+ .code {
+ width: 100%;
+ }
+
+ .copyButton {
+ margin-left: auto;
+ }
+}
diff --git a/website/src/components/navigation/GithubStarsNavbarItem/index.js b/website/src/components/navigation/GithubStarsNavbarItem/index.js
deleted file mode 100644
index f10a0f5d..00000000
--- a/website/src/components/navigation/GithubStarsNavbarItem/index.js
+++ /dev/null
@@ -1,80 +0,0 @@
-import React from 'react';
-import clsx from 'clsx';
-import NavbarNavLink from '@theme/NavbarItem/NavbarNavLink';
-import {useGithubStarsCount} from '@site/src/hooks/useGithubStarsCount';
-import styles from './styles.module.css';
-
-function formatStarCount(n) {
- if (typeof n !== 'number' || !Number.isFinite(n)) return null;
- if (n < 10000) return n.toLocaleString();
- if (n < 1_000_000) return `${(n / 1000).toFixed(n % 1000 === 0 ? 0 : 1)}k`;
- return `${(n / 1_000_000).toFixed(1)}M`;
-}
-
-function StarGlyph({className}) {
- return (
-
- );
-}
-
-/**
- * Navbar item: GitHub repo link with live star count (GitHub REST API).
- * Use in docusaurus.config.js: { type: 'custom-githubStars', position: 'right' }.
- */
-export default function GithubStarsNavbarItem({
- mobile = false,
- position: _position,
- owner = 'Perfect-Abstractions',
- repo = 'Compose',
- className,
-}) {
- const href = `https://github.com/${owner}/${repo}`;
- const {count, isLoading} = useGithubStarsCount({owner, repo});
-
- const label = (
- <>
-
-
-
- {isLoading ? '…' : formatStarCount(count) ?? '—'}
-
-
- GitHub
- >
- );
-
- const link = (
-
- );
-
- if (mobile) {
- return {link};
- }
-
- return link;
-}
diff --git a/website/src/components/navigation/GithubStarsNavbarItem/styles.module.css b/website/src/components/navigation/GithubStarsNavbarItem/styles.module.css
deleted file mode 100644
index b30eab31..00000000
--- a/website/src/components/navigation/GithubStarsNavbarItem/styles.module.css
+++ /dev/null
@@ -1,115 +0,0 @@
-.link {
- display: inline-flex;
- align-items: center;
- gap: 0.4rem;
- transition:
- transform 160ms cubic-bezier(0.23, 1, 0.32, 1),
- color 160ms ease;
-}
-
-.link:active {
- transform: scale(0.97);
-}
-
-@media (prefers-reduced-motion: reduce) {
- .link {
- transition: color 160ms ease;
- }
-
- .link:active {
- transform: none;
- }
-
- .badge,
- .star {
- transition: none;
- }
-}
-
-.badge {
- display: inline-flex;
- align-items: center;
- gap: 0.3rem;
- margin-right: 0.5rem;
- padding: 0.12rem 0.45rem 0.12rem 0.38rem;
- border-radius: 9999px;
- font-size: 0.8rem;
- font-weight: 600;
- font-variant-numeric: tabular-nums;
- line-height: 1.2;
- color: #a16207;
- background: linear-gradient(
- 165deg,
- rgba(253, 224, 71, 0.35) 0%,
- rgba(251, 191, 36, 0.18) 45%,
- rgba(245, 158, 11, 0.12) 100%
- );
- border: 1px solid rgba(217, 119, 6, 0.35);
- box-shadow: 0 1px 0 rgba(255, 255, 255, 0.4) inset;
- transition:
- border-color 180ms cubic-bezier(0.23, 1, 0.32, 1),
- background 180ms cubic-bezier(0.23, 1, 0.32, 1),
- box-shadow 180ms cubic-bezier(0.23, 1, 0.32, 1);
-}
-
-[data-theme='dark'] .badge {
- color: #fde047;
- background: linear-gradient(
- 165deg,
- rgba(253, 224, 71, 0.14) 0%,
- rgba(245, 158, 11, 0.08) 50%,
- rgba(180, 83, 9, 0.12) 100%
- );
- border-color: rgba(250, 204, 21, 0.35);
- box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06) inset;
-}
-
-.star {
- flex-shrink: 0;
- width: 14px;
- height: 14px;
- color: #ca8a04;
- filter: drop-shadow(0 0 5px rgba(251, 191, 36, 0.35));
- transition: color 180ms ease, filter 180ms ease;
-}
-
-[data-theme='dark'] .star {
- color: #facc15;
- filter: drop-shadow(0 0 6px rgba(250, 204, 21, 0.25));
-}
-
-.count {
- min-width: 1ch;
-}
-
-@media (hover: hover) and (pointer: fine) {
- .link:hover .badge {
- border-color: rgba(217, 119, 6, 0.55);
- background: linear-gradient(
- 165deg,
- rgba(253, 224, 71, 0.45) 0%,
- rgba(251, 191, 36, 0.26) 45%,
- rgba(245, 158, 11, 0.18) 100%
- );
- }
-
- .link:hover .star {
- color: #b45309;
- filter: drop-shadow(0 0 7px rgba(251, 191, 36, 0.5));
- }
-
- [data-theme='dark'] .link:hover .badge {
- border-color: rgba(253, 224, 71, 0.5);
- background: linear-gradient(
- 165deg,
- rgba(253, 224, 71, 0.22) 0%,
- rgba(245, 158, 11, 0.12) 50%,
- rgba(180, 83, 9, 0.18) 100%
- );
- }
-
- [data-theme='dark'] .link:hover .star {
- color: #fef08a;
- filter: drop-shadow(0 0 8px rgba(253, 224, 71, 0.35));
- }
-}
diff --git a/website/src/components/navigation/IconNavbarItem/index.js b/website/src/components/navigation/IconNavbarItem/index.js
new file mode 100644
index 00000000..d9b15bed
--- /dev/null
+++ b/website/src/components/navigation/IconNavbarItem/index.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import clsx from 'clsx';
+import styles from './styles.module.css';
+
+export default function IconNavbarItem({
+ mobile = false,
+ position: _position,
+ href,
+ iconSrc,
+ label,
+ className,
+}) {
+ const icon = (
+
+ );
+
+ const link = (
+
+ {icon}
+
+ );
+
+ if (mobile) {
+ return {link};
+ }
+
+ return link;
+}
diff --git a/website/src/components/navigation/IconNavbarItem/styles.module.css b/website/src/components/navigation/IconNavbarItem/styles.module.css
new file mode 100644
index 00000000..ad950938
--- /dev/null
+++ b/website/src/components/navigation/IconNavbarItem/styles.module.css
@@ -0,0 +1,35 @@
+.link {
+ display: inline-flex;
+ align-items: center;
+ transition: transform 160ms cubic-bezier(0.23, 1, 0.32, 1);
+}
+
+.link:active {
+ transform: scale(0.97);
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .link {
+ transition: none;
+ }
+
+ .link:active {
+ transform: none;
+ }
+}
+
+.icon {
+ filter: brightness(0);
+ opacity: 0.65;
+ transition: opacity 160ms ease;
+}
+
+[data-theme='dark'] .icon {
+ filter: brightness(0) invert(1);
+}
+
+@media (hover: hover) and (pointer: fine) {
+ .link:hover .icon {
+ opacity: 1;
+ }
+}
diff --git a/website/src/theme/NavbarItem/ComponentTypes.js b/website/src/theme/NavbarItem/ComponentTypes.js
index 5592fe9f..ba3615ee 100644
--- a/website/src/theme/NavbarItem/ComponentTypes.js
+++ b/website/src/theme/NavbarItem/ComponentTypes.js
@@ -1,7 +1,7 @@
import baseComponentTypes from '@docusaurus/theme-classic/lib/theme/NavbarItem/ComponentTypes';
-import GithubStarsNavbarItem from '@site/src/components/navigation/GithubStarsNavbarItem';
+import IconNavbarItem from '@site/src/components/navigation/IconNavbarItem';
export default {
...baseComponentTypes,
- 'custom-githubStars': GithubStarsNavbarItem,
+ 'custom-icon': IconNavbarItem,
};
diff --git a/website/src/theme/Root.js b/website/src/theme/Root.js
index 111a8ce9..2111760e 100644
--- a/website/src/theme/Root.js
+++ b/website/src/theme/Root.js
@@ -5,7 +5,6 @@
import React from 'react';
import { Toaster } from 'react-hot-toast';
import NavbarEnhancements from '@site/src/components/navigation/NavbarEnhancements';
-import CookieConsentBanner from '@site/src/components/consent/CookieConsentBanner';
export default function Root({children}) {
return (
@@ -79,7 +78,6 @@ export default function Root({children}) {
},
}}
/>
-
{children}
>
);
diff --git a/website/static/icons/discord-white.svg b/website/static/icons/discord-white.svg
new file mode 100644
index 00000000..7f4360c2
--- /dev/null
+++ b/website/static/icons/discord-white.svg
@@ -0,0 +1,3 @@
+
diff --git a/website/static/icons/github-white.svg b/website/static/icons/github-white.svg
new file mode 100644
index 00000000..83841fa0
--- /dev/null
+++ b/website/static/icons/github-white.svg
@@ -0,0 +1,3 @@
+