docs: new theme footer (#9158)
https://linear.app/unleash/issue/2-3177/footer New docs theme footer. Kept [swizzling](https://docusaurus.io/docs/swizzling) to a minimum and instead tried to keep most things in CSS to avoid adding more complexity. Remember to test responsiveness by resizing your window, as well as dark mode. [Preview link](https://unleash-docs-git-docs-new-theme-footer-unleash-team.vercel.app/)
@ -52,7 +52,7 @@ const getUnleashRepoStars = async () => {
|
||||
const formattedStars =
|
||||
unleashRepoStars >= 1000
|
||||
? `${(unleashRepoStars / 1000).toFixed(1)}k`
|
||||
: unleashRepoStars.toString();
|
||||
: unleashRepoStars?.toString() || '';
|
||||
return formattedStars;
|
||||
};
|
||||
|
||||
@ -209,54 +209,181 @@ class="header-github-link"
|
||||
},
|
||||
],
|
||||
footer: {
|
||||
style: 'dark',
|
||||
links: [
|
||||
{
|
||||
title: 'Product',
|
||||
title: 'Server SDKs',
|
||||
items: [
|
||||
{
|
||||
label: 'Docs',
|
||||
to: '/',
|
||||
label: 'Node.js',
|
||||
to: '/reference/sdks/node',
|
||||
},
|
||||
{
|
||||
label: 'Unleash on GitHub',
|
||||
href: 'https://github.com/Unleash/unleash',
|
||||
label: 'Java',
|
||||
to: '/reference/sdks/java',
|
||||
},
|
||||
{
|
||||
label: 'Roadmap',
|
||||
href: 'https://github.com/orgs/Unleash/projects/10',
|
||||
label: 'Go',
|
||||
to: '/reference/sdks/go',
|
||||
},
|
||||
{
|
||||
label: 'Unleash help center',
|
||||
href: 'https://getunleash.zendesk.com/hc/en-gb',
|
||||
label: 'Rust',
|
||||
to: '/reference/sdks/rust',
|
||||
},
|
||||
{
|
||||
label: 'Ruby',
|
||||
to: '/reference/sdks/ruby',
|
||||
},
|
||||
{
|
||||
label: 'Python',
|
||||
to: '/reference/sdks/python',
|
||||
},
|
||||
{
|
||||
label: '.NET',
|
||||
to: '/reference/sdks/dotnet',
|
||||
},
|
||||
{
|
||||
label: 'PHP',
|
||||
to: '/reference/sdks/php',
|
||||
},
|
||||
{
|
||||
label: 'All SDKs',
|
||||
to: '/reference/sdks',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Community',
|
||||
title: 'Frontend SDKs',
|
||||
items: [
|
||||
{
|
||||
label: 'GitHub discussions',
|
||||
href: 'https://github.com/unleash/unleash/discussions/',
|
||||
label: 'JavaScript',
|
||||
to: '/reference/sdks/javascript-browser',
|
||||
},
|
||||
{
|
||||
label: 'Slack',
|
||||
href: 'https://slack.unleash.run/',
|
||||
label: 'React',
|
||||
to: '/reference/sdks/react',
|
||||
},
|
||||
{
|
||||
label: 'Stack Overflow',
|
||||
href: 'https://stackoverflow.com/questions/tagged/unleash',
|
||||
label: 'Next.js',
|
||||
to: '/reference/sdks/next-js',
|
||||
},
|
||||
{
|
||||
label: 'Twitter',
|
||||
href: 'https://twitter.com/getunleash',
|
||||
label: 'Vue',
|
||||
to: '/reference/sdks/vue',
|
||||
},
|
||||
{
|
||||
label: 'iOS',
|
||||
to: '/reference/sdks/ios-proxy',
|
||||
},
|
||||
{
|
||||
label: 'Android',
|
||||
to: '/reference/sdks/android-proxy',
|
||||
},
|
||||
{
|
||||
label: 'Flutter',
|
||||
to: '/reference/sdks/flutter',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Feature Flag use cases',
|
||||
items: [
|
||||
{
|
||||
label: 'Secure, scalable feature flags',
|
||||
to: '/topics/feature-flags/feature-flag-best-practices',
|
||||
},
|
||||
{
|
||||
label: 'Rollbacks',
|
||||
href: 'https://www.getunleash.io/feature-flag-use-cases-rollbacks',
|
||||
},
|
||||
{
|
||||
label: 'FedRAMP, SOC2, ISO2700 compliance',
|
||||
to: '/using-unleash/compliance/compliance-overview',
|
||||
},
|
||||
{
|
||||
label: 'Progressive or gradual rollouts',
|
||||
to: '/feature-flag-tutorials/use-cases/gradual-rollout',
|
||||
},
|
||||
{
|
||||
label: 'Trunk-based development',
|
||||
to: '/feature-flag-tutorials/use-cases/trunk-based-development',
|
||||
},
|
||||
{
|
||||
label: 'Software kill switches',
|
||||
href: 'https://www.getunleash.io/feature-flag-use-cases-software-kill-switches',
|
||||
},
|
||||
{
|
||||
label: 'A/B testing',
|
||||
to: '/feature-flag-tutorials/use-cases/a-b-testing',
|
||||
},
|
||||
{
|
||||
label: 'Feature management',
|
||||
href: 'https://www.getunleash.io/blog/feature-management',
|
||||
},
|
||||
{
|
||||
label: 'Canary releases',
|
||||
href: 'https://www.getunleash.io/blog/canary-deployment-what-is-it',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Product',
|
||||
items: [
|
||||
{
|
||||
label: 'Quickstart',
|
||||
to: '/quickstart',
|
||||
},
|
||||
{
|
||||
label: 'Unleash architecture',
|
||||
to: '/understanding-unleash/unleash-overview',
|
||||
},
|
||||
{
|
||||
label: 'Pricing',
|
||||
href: 'https://www.getunleash.io/pricing',
|
||||
},
|
||||
{
|
||||
label: 'Open live demo',
|
||||
href: 'https://app.unleash-hosted.com/demo/login',
|
||||
},
|
||||
{
|
||||
label: 'Open source',
|
||||
href: 'https://www.getunleash.io/open-source',
|
||||
},
|
||||
{
|
||||
label: 'Enterprise feature management platform',
|
||||
href: 'https://www.getunleash.io/enterprise-feature-management-platform',
|
||||
},
|
||||
{
|
||||
label: 'Unleash vs LaunchDarkly',
|
||||
href: 'https://www.getunleash.io/unleash-vs-launchdarkly',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Support',
|
||||
items: [
|
||||
{
|
||||
label: 'Help center',
|
||||
href: 'https://www.getunleash.io/support',
|
||||
},
|
||||
{
|
||||
label: 'Status',
|
||||
href: 'https://unleash.instatus.com',
|
||||
},
|
||||
{
|
||||
label: 'Roadmap',
|
||||
href: 'https://github.com/orgs/Unleash/projects/10/views/1',
|
||||
},
|
||||
{
|
||||
label: 'Changelog',
|
||||
href: 'https://github.com/Unleash/unleash/releases',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
copyright: `Copyright © ${new Date().getFullYear()} Unleash. Built with Docusaurus.`,
|
||||
logo: {
|
||||
src: 'img/logo.svg',
|
||||
src: 'img/unleash_logo_dark_no_label.svg',
|
||||
srcDark: 'img/unleash_logo_white_no_label.svg',
|
||||
alt: 'Unleash logo',
|
||||
},
|
||||
},
|
||||
|
@ -64,6 +64,8 @@ html[data-theme="light"] {
|
||||
--docsearch-searchbox-background: var(--ifm-background-color);
|
||||
|
||||
--unleash-color-header-separator: var(--unleash-color-green);
|
||||
|
||||
--unleash-color-footer-icon: #657a80;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] {
|
||||
@ -108,6 +110,8 @@ html[data-theme="dark"] {
|
||||
--unleash-logo: url("/img/unleash_logo_white.svg");
|
||||
|
||||
--unleash-color-header-separator: rgba(255, 255, 255, 0.3);
|
||||
|
||||
--unleash-color-footer-icon: var(--ifm-font-color-base);
|
||||
}
|
||||
|
||||
/* navbar */
|
||||
@ -353,7 +357,161 @@ main .theme-doc-breadcrumbs {
|
||||
}
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.footer-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 30px;
|
||||
}
|
||||
|
||||
.footer-content > .container {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer__links {
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.footer-separator {
|
||||
height: 1px;
|
||||
background: #d9d9d9;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
html[data-theme="dark"] .footer-separator {
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.footer-description {
|
||||
display: flex;
|
||||
align-items: start;
|
||||
gap: 16px;
|
||||
max-width: 500px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.footer-description .footer__logo {
|
||||
width: 50px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.footer-description p {
|
||||
line-height: 18px;
|
||||
font-weight: 400;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.footer-description > div {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.footer-description .link-icons {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.footer-description .link-icons img {
|
||||
max-width: unset;
|
||||
transition: opacity 0.2s;
|
||||
}
|
||||
|
||||
.footer-description .link-icons img:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.footer__col {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.footer__title {
|
||||
font-size: 12px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.footer__item {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.footer__link-item {
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.footer__link-item > svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.footer-bottom-made-with-love {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.footer-show-large {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer-show-small {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 1300px) {
|
||||
.footer-show-large {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.footer-show-small {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.footer-content > .container {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.footer-description > div {
|
||||
flex: unset;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 500px) {
|
||||
.footer-description {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.navbar {
|
||||
|
13
website/src/theme/Footer/Copyright/index.tsx
Normal file
@ -0,0 +1,13 @@
|
||||
import type { Props } from '@theme/Footer/Copyright';
|
||||
|
||||
export default function FooterCopyright({ copyright }: Props): JSX.Element {
|
||||
return (
|
||||
<div
|
||||
className='footer__copyright'
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: from swizzled docusaurus component
|
||||
dangerouslySetInnerHTML={{ __html: copyright }}
|
||||
/>
|
||||
);
|
||||
}
|
124
website/src/theme/Footer/Layout/index.tsx
Normal file
@ -0,0 +1,124 @@
|
||||
import clsx from 'clsx';
|
||||
import type { Props } from '@theme/Footer/Layout';
|
||||
|
||||
import ThemedImage from '@theme/ThemedImage';
|
||||
|
||||
import HeartIcon from '../icons/heart.svg';
|
||||
import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
|
||||
|
||||
type IconLink = {
|
||||
href: string;
|
||||
src: string;
|
||||
srcDark: string;
|
||||
alt: string;
|
||||
};
|
||||
|
||||
const linkIcons: IconLink[] = [
|
||||
{
|
||||
href: 'https://github.com/unleash/unleash',
|
||||
src: '/img/footer/githubLight.png',
|
||||
srcDark: '/img/footer/githubDark.png',
|
||||
alt: 'GitHub',
|
||||
},
|
||||
{
|
||||
href: 'https://www.linkedin.com/company/getunleash',
|
||||
src: '/img/footer/linkedinLight.png',
|
||||
srcDark: '/img/footer/linkedinDark.png',
|
||||
alt: 'LinkedIn',
|
||||
},
|
||||
{
|
||||
href: 'https://twitter.com/getunleash',
|
||||
src: '/img/footer/twitterLight.png',
|
||||
srcDark: '/img/footer/twitterDark.png',
|
||||
alt: 'Twitter',
|
||||
},
|
||||
{
|
||||
href: 'https://slack.unleash.run',
|
||||
src: '/img/footer/slackLight.png',
|
||||
srcDark: '/img/footer/slackDark.png',
|
||||
alt: 'Slack',
|
||||
},
|
||||
{
|
||||
href: 'https://stackoverflow.com/questions/tagged/unleash',
|
||||
src: '/img/footer/stackoverflowLight.png',
|
||||
srcDark: '/img/footer/stackoverflowDark.png',
|
||||
alt: 'Stack Overflow',
|
||||
},
|
||||
{
|
||||
href: 'https://www.youtube.com/channel/UCJjGVOc5QBbEje-r7nZEa4A',
|
||||
src: '/img/footer/youtubeLight.png',
|
||||
srcDark: '/img/footer/youtubeDark.png',
|
||||
alt: 'YouTube',
|
||||
},
|
||||
];
|
||||
|
||||
export default function FooterLayout({
|
||||
style,
|
||||
links,
|
||||
logo,
|
||||
copyright,
|
||||
}: Props): JSX.Element {
|
||||
const { withBaseUrl } = useBaseUrlUtils();
|
||||
|
||||
const description = (
|
||||
<div className='footer-description'>
|
||||
{logo}
|
||||
<div>
|
||||
<p>
|
||||
Unleash reduces the risk of releasing new features, drives
|
||||
innovation by streamlining the software release process, and
|
||||
increases revenue by optimizing end-user experience. While
|
||||
we serve the needs of the world's largest, most
|
||||
security-conscious organizations, we are also rated the
|
||||
“Easiest Feature Management system to use” by G2.
|
||||
</p>
|
||||
<div className='link-icons'>
|
||||
{linkIcons.map(({ href, src, srcDark, alt }) => (
|
||||
<a
|
||||
key={alt}
|
||||
href={href}
|
||||
target='_blank'
|
||||
rel='noopener noreferrer'
|
||||
>
|
||||
<ThemedImage
|
||||
alt={alt}
|
||||
sources={{
|
||||
light: withBaseUrl(src),
|
||||
dark: withBaseUrl(srcDark),
|
||||
}}
|
||||
width={40}
|
||||
height={40}
|
||||
/>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<footer
|
||||
className={clsx('footer', {
|
||||
'footer--dark': style === 'dark',
|
||||
})}
|
||||
>
|
||||
<div className='footer-body'>
|
||||
<div className='footer-content'>
|
||||
<div className='footer-show-large'>{description}</div>
|
||||
<div className='container container-fluid'>{links}</div>
|
||||
<div className='footer-show-small'>{description}</div>
|
||||
</div>
|
||||
<div className='footer-separator' />
|
||||
<div className='footer-bottom'>
|
||||
<div className='footer-bottom-made-with-love'>
|
||||
<HeartIcon /> Made in a cosy atmosphere in the Nordic
|
||||
countries.
|
||||
</div>
|
||||
{copyright && (
|
||||
<div className='footer__bottom'>{copyright}</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
28
website/src/theme/Footer/LinkItem/index.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import Link from '@docusaurus/Link';
|
||||
import useBaseUrl from '@docusaurus/useBaseUrl';
|
||||
import isInternalUrl from '@docusaurus/isInternalUrl';
|
||||
import IconExternalLink from '@theme/Icon/ExternalLink';
|
||||
import type { Props } from '@theme/Footer/LinkItem';
|
||||
|
||||
export default function FooterLinkItem({ item }: Props): JSX.Element {
|
||||
const { to, href, label, prependBaseUrlToHref, ...props } = item;
|
||||
const toUrl = useBaseUrl(to);
|
||||
const normalizedHref = useBaseUrl(href, { forcePrependBaseUrl: true });
|
||||
|
||||
return (
|
||||
<Link
|
||||
className='footer__link-item'
|
||||
{...(href
|
||||
? {
|
||||
href: prependBaseUrlToHref ? normalizedHref : href,
|
||||
}
|
||||
: {
|
||||
to: toUrl,
|
||||
})}
|
||||
{...props}
|
||||
>
|
||||
{label}
|
||||
{href && !isInternalUrl(href) && <IconExternalLink />}
|
||||
</Link>
|
||||
);
|
||||
}
|
46
website/src/theme/Footer/Links/MultiColumn/index.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import LinkItem from '@theme/Footer/LinkItem';
|
||||
import type { Props } from '@theme/Footer/Links/MultiColumn';
|
||||
|
||||
type ColumnType = Props['columns'][number];
|
||||
type ColumnItemType = ColumnType['items'][number];
|
||||
|
||||
function ColumnLinkItem({ item }: { item: ColumnItemType }) {
|
||||
return item.html ? (
|
||||
<li
|
||||
className='footer__item'
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: from swizzled docusaurus component
|
||||
dangerouslySetInnerHTML={{ __html: item.html }}
|
||||
/>
|
||||
) : (
|
||||
<li key={item.href ?? item.to} className='footer__item'>
|
||||
<LinkItem item={item} />
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
function Column({ column }: { column: ColumnType }) {
|
||||
return (
|
||||
<div className='col footer__col'>
|
||||
<div className='footer__title'>{column.title}</div>
|
||||
<ul className='footer__items clean-list'>
|
||||
{column.items.map((item, i) => (
|
||||
<ColumnLinkItem key={i} item={item} />
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function FooterLinksMultiColumn({
|
||||
columns,
|
||||
}: Props): JSX.Element {
|
||||
return (
|
||||
<div className='row footer__links'>
|
||||
{columns.map((column, i) => (
|
||||
<Column key={i} column={column} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
36
website/src/theme/Footer/Links/Simple/index.tsx
Normal file
@ -0,0 +1,36 @@
|
||||
import React from 'react';
|
||||
import LinkItem from '@theme/Footer/LinkItem';
|
||||
import type { Props } from '@theme/Footer/Links/Simple';
|
||||
|
||||
function Separator() {
|
||||
return <span className='footer__link-separator'>·</span>;
|
||||
}
|
||||
|
||||
function SimpleLinkItem({ item }: { item: Props['links'][number] }) {
|
||||
return item.html ? (
|
||||
<span
|
||||
className='footer__link-item'
|
||||
// Developer provided the HTML, so assume it's safe.
|
||||
// eslint-disable-next-line react/no-danger
|
||||
// biome-ignore lint/security/noDangerouslySetInnerHtml: from swizzled docusaurus component
|
||||
dangerouslySetInnerHTML={{ __html: item.html }}
|
||||
/>
|
||||
) : (
|
||||
<LinkItem item={item} />
|
||||
);
|
||||
}
|
||||
|
||||
export default function FooterLinksSimple({ links }: Props): JSX.Element {
|
||||
return (
|
||||
<div className='footer__links text--center'>
|
||||
<div className='footer__links'>
|
||||
{links.map((item, i) => (
|
||||
<React.Fragment key={i}>
|
||||
<SimpleLinkItem item={item} />
|
||||
{links.length !== i + 1 && <Separator />}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
12
website/src/theme/Footer/Links/index.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import { isMultiColumnFooterLinks } from '@docusaurus/theme-common';
|
||||
import FooterLinksMultiColumn from '@theme/Footer/Links/MultiColumn';
|
||||
import FooterLinksSimple from '@theme/Footer/Links/Simple';
|
||||
import type { Props } from '@theme/Footer/Links';
|
||||
|
||||
export default function FooterLinks({ links }: Props): JSX.Element {
|
||||
return isMultiColumnFooterLinks(links) ? (
|
||||
<FooterLinksMultiColumn columns={links} />
|
||||
) : (
|
||||
<FooterLinksSimple links={links} />
|
||||
);
|
||||
}
|
39
website/src/theme/Footer/Logo/index.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import clsx from 'clsx';
|
||||
import Link from '@docusaurus/Link';
|
||||
import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
|
||||
import ThemedImage from '@theme/ThemedImage';
|
||||
import type { Props } from '@theme/Footer/Logo';
|
||||
|
||||
import styles from './styles.module.css';
|
||||
|
||||
function LogoImage({ logo }: Props) {
|
||||
const { withBaseUrl } = useBaseUrlUtils();
|
||||
const sources = {
|
||||
light: withBaseUrl(logo.src),
|
||||
dark: withBaseUrl(logo.srcDark ?? logo.src),
|
||||
};
|
||||
return (
|
||||
<ThemedImage
|
||||
className={clsx('footer__logo', logo.className)}
|
||||
alt={logo.alt}
|
||||
sources={sources}
|
||||
width={logo.width}
|
||||
height={logo.height}
|
||||
style={logo.style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default function FooterLogo({ logo }: Props): JSX.Element {
|
||||
return logo.href ? (
|
||||
<Link
|
||||
href={logo.href}
|
||||
className={styles.footerLogoLink}
|
||||
target={logo.target}
|
||||
>
|
||||
<LogoImage logo={logo} />
|
||||
</Link>
|
||||
) : (
|
||||
<LogoImage logo={logo} />
|
||||
);
|
||||
}
|
9
website/src/theme/Footer/Logo/styles.module.css
Normal file
@ -0,0 +1,9 @@
|
||||
.footerLogoLink {
|
||||
opacity: 0.5;
|
||||
transition: opacity var(--ifm-transition-fast)
|
||||
var(--ifm-transition-timing-default);
|
||||
}
|
||||
|
||||
.footerLogoLink:hover {
|
||||
opacity: 1;
|
||||
}
|
64
website/src/theme/Footer/icons/heart.svg
Normal file
@ -0,0 +1,64 @@
|
||||
<svg
|
||||
width='21'
|
||||
height='21'
|
||||
viewBox='0 0 21 21'
|
||||
xmlns='http://www.w3.org/2000/svg'
|
||||
>
|
||||
<title>Heart</title>
|
||||
<path
|
||||
d='M17.0674 4.53516V10.5352H19.0674V4.53516H17.0674Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M1.06738 4.53516L1.06738 10.5352H3.06738L3.06738 4.53516H1.06738Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M17.0674 2.53516H13.0674V10.5352H17.0674V2.53516Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M7.06738 2.53516H3.06738V10.5352H7.06738V2.53516Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M13.0674 12.5352H5.06738V14.5352H13.0674V12.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M15.0674 10.5352H3.06738V12.5352H15.0674V10.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M11.0674 6.53516H9.06738V10.5352H11.0674V6.53516Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M13.0674 4.53516H11.0674V10.5352H13.0674V4.53516Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M9.06738 4.53516H7.06738V10.5352H9.06738V4.53516Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M11.0674 14.5352H7.06738V16.5352H11.0674V14.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M11.0674 16.5352H9.06738V18.5352H11.0674V16.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M13.0674 14.5352H11.0674V16.5352H13.0674V14.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M15.0674 12.5352H13.0674V14.5352H15.0674V12.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
<path
|
||||
d='M17.0674 10.5352H15.0674V12.5352H17.0674V10.5352Z'
|
||||
fill='#817AFE'
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
26
website/src/theme/Footer/index.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
|
||||
import { useThemeConfig } from '@docusaurus/theme-common';
|
||||
import FooterLinks from '@theme/Footer/Links';
|
||||
import FooterLogo from '@theme/Footer/Logo';
|
||||
import FooterCopyright from '@theme/Footer/Copyright';
|
||||
import FooterLayout from '@theme/Footer/Layout';
|
||||
|
||||
function Footer(): JSX.Element | null {
|
||||
const { footer } = useThemeConfig();
|
||||
if (!footer) {
|
||||
return null;
|
||||
}
|
||||
const { copyright, links, logo, style } = footer;
|
||||
|
||||
return (
|
||||
<FooterLayout
|
||||
style={style}
|
||||
links={links && links.length > 0 && <FooterLinks links={links} />}
|
||||
logo={logo && <FooterLogo logo={logo} />}
|
||||
copyright={copyright && <FooterCopyright copyright={copyright} />}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(Footer);
|
BIN
website/static/img/footer/githubDark.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
website/static/img/footer/githubLight.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
website/static/img/footer/linkedinDark.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
website/static/img/footer/linkedinLight.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
website/static/img/footer/slackDark.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
website/static/img/footer/slackLight.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
website/static/img/footer/stackoverflowDark.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
website/static/img/footer/stackoverflowLight.png
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
website/static/img/footer/twitterDark.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
website/static/img/footer/twitterLight.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
website/static/img/footer/youtubeDark.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
website/static/img/footer/youtubeLight.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
6
website/static/img/unleash_logo_dark_no_label.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M80 160C124.183 160 160 124.183 160 80C160 35.8172 124.183 0 80 0C35.8172 0 0 35.8172 0 80C0 124.183 35.8172 160 80 160Z" fill="#1A4049"/>
|
||||
<path d="M91.43 45.71V91.43H114.28V45.71H91.43ZM68.57 68.57V45.71H45.71V114.28H91.43V91.43H68.57V68.57Z" fill="white"/>
|
||||
<path d="M91.43 45.71V91.43H114.28V45.71H91.43ZM68.57 68.57V45.71H45.71V114.28H91.43V91.43H68.57V68.57Z" fill="white"/>
|
||||
<path d="M91.4299 91.43H114.29V114.29H91.4299V91.43Z" fill="#817AFE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 566 B |
6
website/static/img/unleash_logo_white_no_label.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="161" height="161" viewBox="0 0 161 161" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M80.6201 160.62C124.803 160.62 160.62 124.803 160.62 80.62C160.62 36.4372 124.803 0.619995 80.6201 0.619995C36.4373 0.619995 0.620117 36.4372 0.620117 80.62C0.620117 124.803 36.4373 160.62 80.6201 160.62Z" fill="white"/>
|
||||
<path d="M92.0501 46.33V92.05H114.9V46.33H92.0501ZM69.1901 69.19V46.33H46.3301V114.9H92.0501V92.05H69.1901V69.19Z" fill="white"/>
|
||||
<path d="M92.0501 46.33V92.05H114.9V46.33H92.0501ZM69.1901 69.19V46.33H46.3301V114.9H92.0501V92.05H69.1901V69.19Z" fill="#1A4049"/>
|
||||
<path d="M92.05 92.05H114.91V114.91H92.05V92.05Z" fill="#817AFE"/>
|
||||
</svg>
|
After Width: | Height: | Size: 666 B |