Add top nav bar
Signed-off-by: Charles de Dreuille <charles.dedreuille@gmail.com>
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
import type { Metadata } from 'next';
|
||||
import { Sidebar } from '../components/Sidebar';
|
||||
import { Toolbar } from '@/components/Toolbar';
|
||||
import { Providers } from './providers';
|
||||
|
||||
import styles from './page.module.css';
|
||||
import { Providers } from './providers';
|
||||
|
||||
import './globals.css';
|
||||
import '/public/core.css';
|
||||
@@ -19,10 +20,6 @@ export default function RootLayout({
|
||||
}: Readonly<{
|
||||
children: React.ReactNode;
|
||||
}>) {
|
||||
// const cookieStore = await cookies();
|
||||
// const theme = cookieStore.get('theme')?.value || 'light';
|
||||
// const themeName = cookieStore.get('theme-name')?.value || 'default';
|
||||
|
||||
return (
|
||||
<html
|
||||
lang="en"
|
||||
@@ -34,7 +31,10 @@ export default function RootLayout({
|
||||
<Providers>
|
||||
<div className={styles.global}>
|
||||
<Sidebar />
|
||||
<div className={styles.container}>{children}</div>
|
||||
<div className={styles.container}>
|
||||
<Toolbar />
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</Providers>
|
||||
</body>
|
||||
|
||||
@@ -13,22 +13,15 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.logoContainer {
|
||||
padding-left: 6px;
|
||||
padding-top: 32px;
|
||||
}
|
||||
|
||||
.logo path {
|
||||
fill: var(--canon-text-primary);
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import styles from './Sidebar.module.css';
|
||||
import { TabsVersion, TabsPages, TabsTheme } from './tabs';
|
||||
import { Docs } from './docs';
|
||||
import { Playground } from './playground';
|
||||
import Link from 'next/link';
|
||||
@@ -7,7 +6,7 @@ import Link from 'next/link';
|
||||
export const Sidebar = () => {
|
||||
return (
|
||||
<div className={styles.sidebar}>
|
||||
<div className={styles.content}>
|
||||
<div className={styles.logoContainer}>
|
||||
<Link href="/">
|
||||
<svg
|
||||
width="89"
|
||||
@@ -20,15 +19,10 @@ export const Sidebar = () => {
|
||||
<path d="M14.037 16.729a4.237 4.237 0 0 0 4.234-4.24 4.237 4.237 0 0 0-4.234-4.242 4.237 4.237 0 0 0-4.234 4.241 4.237 4.237 0 0 0 4.234 4.24Z" />
|
||||
</svg>
|
||||
</Link>
|
||||
<div className={styles.actions}>
|
||||
<TabsVersion />
|
||||
<TabsTheme />
|
||||
</div>
|
||||
<TabsPages />
|
||||
<div className={styles.menu}>
|
||||
<Docs />
|
||||
<Playground />
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.menu}>
|
||||
<Docs />
|
||||
<Playground />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import Link from 'next/link';
|
||||
import { TabsVersion, TabsTheme } from './tabs';
|
||||
import styles from './styles.module.css';
|
||||
import { Nav } from './nav';
|
||||
|
||||
export const Toolbar = () => {
|
||||
return (
|
||||
<div className={styles.toolbar}>
|
||||
<div>
|
||||
<Nav />
|
||||
</div>
|
||||
<div className={styles.actions}>
|
||||
<TabsVersion />
|
||||
<TabsTheme />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,84 @@
|
||||
.tabs {
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.tabsTheme {
|
||||
width: 142px;
|
||||
border-radius: 0.375rem;
|
||||
background-color: var(--canon-surface-2);
|
||||
transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.list {
|
||||
display: flex;
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.tab {
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
background: none;
|
||||
appearance: none;
|
||||
color: var(--canon-text-secondary) !important;
|
||||
font-family: inherit;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
user-select: none;
|
||||
flex: 1;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
|
||||
&[data-selected] {
|
||||
color: var(--canon-text-primary) !important;
|
||||
|
||||
& p {
|
||||
color: var(--canon-text-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:hover {
|
||||
color: var(--canon-text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0.25rem 0;
|
||||
border-radius: 0.25rem;
|
||||
outline: 2px solid var(--canon-surface-1);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab p {
|
||||
color: var(--canon-text-secondary) !important;
|
||||
}
|
||||
|
||||
.indicator {
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
left: 0;
|
||||
bottom: -1px;
|
||||
translate: var(--active-tab-left) -50%;
|
||||
width: var(--active-tab-width);
|
||||
height: 1px;
|
||||
border-radius: 0.25rem;
|
||||
background-color: var(--canon-text-primary);
|
||||
transition-property: translate, width, background-color;
|
||||
transition-duration: 200ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
'use client';
|
||||
|
||||
import { Tabs } from '@base-ui-components/react/tabs';
|
||||
import { Text } from '../../../../packages/canon';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import styles from './nav.module.css';
|
||||
|
||||
export const Nav = () => {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
const onValueChange = (value: string) => {
|
||||
if (value === 'docs') {
|
||||
router.push('/');
|
||||
} else {
|
||||
router.push('/playground');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs.Root
|
||||
className={styles.tabs}
|
||||
value={pathname.includes('playground') ? 'playground' : 'docs'}
|
||||
onValueChange={onValueChange}
|
||||
>
|
||||
<Tabs.List className={styles.list}>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="docs"
|
||||
onClick={() => {
|
||||
router.push('/');
|
||||
}}
|
||||
>
|
||||
<Text variant="caption" weight="bold">
|
||||
Documentation
|
||||
</Text>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="playground"
|
||||
onClick={() => {
|
||||
router.push('/playground');
|
||||
}}
|
||||
>
|
||||
<Text variant="caption" weight="bold">
|
||||
Playground
|
||||
</Text>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Indicator className={styles.indicator} />
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
.toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
background-color: var(--canon-surface-1);
|
||||
border-bottom: 1px solid var(--canon-border-base);
|
||||
height: 60px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 var(--canon-spacing-md);
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--canon-spacing-md);
|
||||
}
|
||||
+2
-52
@@ -1,12 +1,9 @@
|
||||
'use client';
|
||||
|
||||
import styles from './Tabs.module.css';
|
||||
import { Tabs } from '@base-ui-components/react/tabs';
|
||||
import { Icon } from '../../../../packages/canon/src/components/Icon';
|
||||
import { Text } from '../../../../packages/canon/src/components/Text';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Icon, Text } from '../../../../packages/canon';
|
||||
import { usePlayground } from '@/utils/playground-context';
|
||||
import styles from './tabs.module.css';
|
||||
|
||||
export const TabsVersion = () => {
|
||||
const { selectedThemeName, setSelectedThemeName } = usePlayground();
|
||||
@@ -54,50 +51,3 @@ export const TabsTheme = () => {
|
||||
</Tabs.Root>
|
||||
);
|
||||
};
|
||||
|
||||
export const TabsPages = () => {
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
|
||||
const onValueChange = (value: string) => {
|
||||
if (value === 'docs') {
|
||||
router.push('/');
|
||||
} else {
|
||||
router.push('/playground');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Tabs.Root
|
||||
className={styles.tabs}
|
||||
value={pathname.includes('playground') ? 'playground' : 'docs'}
|
||||
onValueChange={onValueChange}
|
||||
>
|
||||
<Tabs.List className={styles.list}>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="docs"
|
||||
onClick={() => {
|
||||
router.push('/');
|
||||
}}
|
||||
>
|
||||
<Text variant="caption" weight="bold">
|
||||
Documentation
|
||||
</Text>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab
|
||||
className={styles.tab}
|
||||
value="playground"
|
||||
onClick={() => {
|
||||
router.push('/playground');
|
||||
}}
|
||||
>
|
||||
<Text variant="caption" weight="bold">
|
||||
Playground
|
||||
</Text>
|
||||
</Tabs.Tab>
|
||||
<Tabs.Indicator className={styles.indicator} />
|
||||
</Tabs.List>
|
||||
</Tabs.Root>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user