Skip to content

Commit

Permalink
Showing 34 changed files with 874 additions and 592 deletions.
20 changes: 18 additions & 2 deletions lib/app-setup/root.tsx
Original file line number Diff line number Diff line change
@@ -15,6 +15,8 @@ import { ReactNode, useEffect } from 'react';
import skeletonCSS from 'react-loading-skeleton/dist/skeleton.css';
import styleReactPulsable from 'react-pulsable/index.css';
import reactToast from 'react-toastify/dist/ReactToastify.css';
import styleZenerSelect from '@oshq/react-select/index.css';
import rcss from 'react-highlightjs-logs/dist/index.css';
import Container from '~/components/atoms/container';
import ProgressContainer, {
useProgress,
@@ -23,9 +25,7 @@ import Tooltip from '~/components/atoms/tooltip';
import { BrandLogo } from '~/components/branding/brand-logo';
import { ToastContainer } from '~/components/molecule/toast';
import { TopBar } from '~/components/organisms/top-bar';
import styleZenerSelect from '@oshq/react-select/index.css';
import stylesUrl from '~/design-system/index.css';
import rcss from 'react-highlightjs-logs/dist/index.css';
import tailwindBase from '~/design-system/tailwind-base.js';
import { ReloadIndicator } from '~/lib/client/components/reload-indicator';
import { isDev } from '~/lib/client/helpers/log';
@@ -196,6 +196,22 @@ const Root = ({
`,
}}
/>

<script
// @ts-ignore
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: `
try {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.querySelector('html').setAttribute('data-theme', 'dark')
} else {
document.querySelector('html').setAttribute('data-theme', 'light')
}
} catch (_) {}
`,
}}
/>
</head>
<body className="antialiased">
<div
95 changes: 95 additions & 0 deletions lib/client/hooks/useTheme.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import {
ReactNode,
createContext,
useContext,
useEffect,
useMemo,
useState,
} from 'react';

type ITheme = 'dark' | 'light' | 'system';
const ThemeContext = createContext<{
theme: ITheme;
binaryTheme: Omit<ITheme, 'system'>;
setTheme: (t: ITheme) => void;
}>({ theme: 'system', setTheme() {}, binaryTheme: 'light' });

const getTheme = () => {
const { theme } = localStorage;
if (theme === 'dark' || theme === 'light') {
return theme;
}
return 'system';
};

const saveTheme = (theme: ITheme) => {
if (theme === 'dark') {
document.querySelector('html')?.setAttribute('data-theme', 'dark');
} else if (theme === 'system') {
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.querySelector('html')?.setAttribute('data-theme', 'dark');
} else {
document.querySelector('html')?.setAttribute('data-theme', 'light');
}
} else {
document.querySelector('html')?.setAttribute('data-theme', 'light');
}
if (theme === 'system') {
localStorage.removeItem('theme');
} else {
localStorage.setItem('theme', theme);
}
};

const ThemeProvider = ({ children }: { children: ReactNode }) => {
const [theme, _setTheme] = useState<ITheme>('system');
const [binaryTheme, setBinaryTheme] =
useState<Omit<ITheme, 'system'>>('light');

useEffect(() => {
_setTheme(getTheme());
}, []);

const setTheme = (t: ITheme) => {
_setTheme(t);
saveTheme(t);
};

const gTheme = () => {
try {
if (theme === 'dark') {
return theme;
}
if (theme === 'system' && window !== undefined) {
if (window?.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark';
}
return 'light';
}
return 'light';
} catch {
return 'light';
}
};

useEffect(() => {
setBinaryTheme(gTheme());
}, [theme]);

return (
<ThemeContext.Provider
value={useMemo(
() => ({ theme, binaryTheme, setTheme }),
[theme, binaryTheme, setTheme]
)}
>
{children}
</ThemeContext.Provider>
);
};

export default ThemeProvider;

export const useTheme = () => {
return useContext(ThemeContext);
};
32 changes: 9 additions & 23 deletions src/apps/auth/components/container.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
import { Link } from '@remix-run/react';
import { ReactNode } from 'react';
import { Button } from '~/components/atoms/button';
import { cn } from '~/components/utils';
import Header from './header';
import Footer from './footer';

interface ContainerProps {
interface IContainer {
children: ReactNode;
footer?: {
message: string;
buttonText: string;
to: string;
};
headerExtra?: ReactNode;
}

const Container = ({ children, footer }: ContainerProps) => {
const Container = ({ children, headerExtra }: IContainer) => {
return (
<div className={cn('flex flex-col items-center justify-start h-full')}>
<div className="flex flex-col h-full">
<Header headerExtra={headerExtra} />
<div
className={cn(
'flex flex-1 flex-col items-center self-stretch justify-center px-3xl py-10xl'
'flex flex-1 flex-col md:items-center self-stretch justify-center px-3xl py-5xl md:py-9xl'
)}
>
{children}
</div>
{footer && (
<div className="py-5xl px-3xl flex flex-row items-center justify-center self-stretch border-t border-border-default sticky bottom-0 bg-surface-basic-default z-50">
<div className="bodyMd text-text-default">{footer?.message}</div>
<Button
content={footer?.buttonText}
variant="primary-plain"
size="md"
to={footer?.to}
linkComponent={Link}
/>
</div>
)}
<Footer />
</div>
);
};
114 changes: 114 additions & 0 deletions src/apps/auth/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { BrandLogo } from '~/components/branding/brand-logo';
import {
GithubLogoFill,
LinkedinLogoFill,
TwitterNewLogoFill,
} from '@jengaicons/react';
import { Button } from '~/components/atoms/button';
import { Link } from '@remix-run/react';
import Wrapper from './wrapper';
import { mainUrl } from '../consts';
import ThemeSwitcher from './theme-switcher';

const linkedinUrl = 'https://linkedin.com/company/kloudlite-io';
const gitUrl = 'https://github.com/kloudlite/kloudlite';
const xUrl = 'https://x.com/kloudlite';

const menu = [
{
title: 'Home',
to: mainUrl,
},
{
title: 'Documents',
to: `${mainUrl}/docs`,
},
{
title: 'Help & support',
to: `${mainUrl}/help-and-support`,
},
{
title: 'Contact us',
to: `${mainUrl}/contact-us`,
},
{
title: 'Blog',
to: `${mainUrl}/blog`,
},
{
title: 'Changelog',
to: '/',
},
{
title: 'Pricing',
to: '/',
},
{
title: 'Legal',
to: '/',
},
];

const SocialMenu = () => {
const socialIconSize = 18;
return (
<div className="flex flex-row items-center gap-2xl text-icon-soft shrink-0">
<a href={gitUrl} aria-label="kloudlite-github">
<GithubLogoFill size={socialIconSize} />
</a>
<a href={xUrl} aria-label="kloudlite-x">
<TwitterNewLogoFill size={socialIconSize} />
</a>
<a href={linkedinUrl} aria-label="kloudlite-linkedin">
<LinkedinLogoFill size={socialIconSize} />
</a>
</div>
);
};

const Footer = () => {
return (
<div className="bg-surface-basic-default">
<Wrapper className="py-6xl flex flex-col gap-4xl">
<div className="flex flex-row items-center justify-between">
<div className="flex flex-col md:flex-row md:items-center gap-lg">
<a href="/" aria-label="kloudlite">
<BrandLogo size={24} detailed />
</a>
<span className="text-text-soft bodyMd">
© {new Date().getFullYear()}
</span>
</div>
<div className="flex flex-row items-center gap-3xl">
<div className="hidden md:block lg:hidden">
<SocialMenu />
</div>
<ThemeSwitcher />
</div>
</div>
<div className="flex flex-col-reverse gap-4xl md:gap-0 md:flex-row md:items-center lg:justify-between">
<div className="md:hidden lg:block">
<SocialMenu />
</div>
<div className="flex flex-row flex-wrap gap-y-md lg:basis-auto items-center lg:gap-lg w-full lg:w-auto">
{menu.map((m) => (
<div
key={m.title}
className="basis-1/2 md:basis-1/4 lg:basis-auto"
>
<Button
to={m.to}
content={<span className="text-text-strong">{m.title}</span>}
variant="plain"
linkComponent={Link}
/>
</div>
))}
</div>
</div>
</Wrapper>
</div>
);
};

export default Footer;
33 changes: 33 additions & 0 deletions src/apps/auth/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Button } from '~/components/atoms/button';
import { BrandLogo } from '~/components/branding/brand-logo';
import { Link } from '@remix-run/react';
import { ReactNode } from 'react';
import Wrapper from './wrapper';

const Header = ({ headerExtra }: { headerExtra?: ReactNode }) => {
return (
<div className="sticky top-0 bg-surface-basic-subdued w-full border-b border-border-default z-50">
<Wrapper className="min-h-[68px] max-h-[68px] flex flex-row items-center justify-between">
<a href="/" aria-label="kloudlite">
<div className="hidden md:block">
<BrandLogo size={24} detailed />
</div>
<div className="md:hidden">
<BrandLogo size={24} />
</div>
</a>
<div className="flex flex-row gap-xl items-center">
<Button
variant="plain"
content="Contact us"
linkComponent={Link}
to="https://kloudlite.io/contact-us"
/>
{headerExtra}
</div>
</Wrapper>
</div>
);
};

export default Header;
23 changes: 23 additions & 0 deletions src/apps/auth/components/theme-switcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Monitor, Moon, Sun } from '@jengaicons/react';
import ButtonGroup from '~/components/atoms/button-group';
import { useTheme } from '~/root/lib/client/hooks/useTheme';

const ThemeSwitcher = () => {
const { theme, setTheme } = useTheme();
return (
<ButtonGroup.Root
variant="outline"
selectable
value={theme}
onValueChange={(v: any) => {
setTheme(v);
}}
>
<ButtonGroup.IconButton value="light" icon={<Sun />} />
<ButtonGroup.IconButton value="dark" icon={<Moon />} />
<ButtonGroup.IconButton value="system" icon={<Monitor />} />
</ButtonGroup.Root>
);
};

export default ThemeSwitcher;
23 changes: 23 additions & 0 deletions src/apps/auth/components/wrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ReactNode } from 'react';
import { cn } from '~/components/utils';

const Wrapper = ({
children,
className,
}: {
children: ReactNode;
className?: string;
}) => {
return (
<div
className={cn(
'lg:m-auto lg:max-w-[896px] w-full px-3xl md:px-5xl lg:px-8xl xl:px-11xl 2xl:px-12xl xl:max-w-[1024px] 2xl:max-w-[1120px] 3xl:min-w-[1408px] lg:box-content',
className
)}
>
{children}
</div>
);
};

export default Wrapper;
1 change: 1 addition & 0 deletions src/apps/auth/consts.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const mainUrl = 'https://kloudlite.io';
Loading

0 comments on commit 6262e8b

Please sign in to comment.