wip navigation example
This commit is contained in:
parent
2fac626e46
commit
097dae4f2a
|
|
@ -70,6 +70,11 @@ export const IndexPage = () => (
|
||||||
<h2>Buttons</h2>
|
<h2>Buttons</h2>
|
||||||
<p>Button component with intent, size, and disabled variants</p>
|
<p>Button component with intent, size, and disabled variants</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
<a href="/navigation" class="example-card">
|
||||||
|
<h2>Navigation</h2>
|
||||||
|
<p>Navigation patterns including tabs, pills, vertical nav, and breadcrumbs</p>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
||||||
335
examples/navigation.tsx
Normal file
335
examples/navigation.tsx
Normal file
|
|
@ -0,0 +1,335 @@
|
||||||
|
import { define } from '../src'
|
||||||
|
import { Layout, ExampleSection } from './helpers'
|
||||||
|
|
||||||
|
const Tabs = define('Tabs', {
|
||||||
|
layout: {
|
||||||
|
display: 'flex',
|
||||||
|
gap: 0,
|
||||||
|
},
|
||||||
|
look: {
|
||||||
|
borderBottom: '2px solid #e5e7eb',
|
||||||
|
},
|
||||||
|
|
||||||
|
parts: {
|
||||||
|
Tab: {
|
||||||
|
base: 'button',
|
||||||
|
layout: {
|
||||||
|
padding: '12px 24px',
|
||||||
|
position: 'relative',
|
||||||
|
marginBottom: -2,
|
||||||
|
},
|
||||||
|
look: {
|
||||||
|
background: 'transparent',
|
||||||
|
border: 'none',
|
||||||
|
borderBottom: '2px solid transparent',
|
||||||
|
color: '#6b7280',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.2s ease',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
color: '#111827',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
active: {
|
||||||
|
parts: {
|
||||||
|
Tab: {
|
||||||
|
look: {
|
||||||
|
color: '#3b82f6',
|
||||||
|
borderBottom: '2px solid #3b82f6',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render({ props, parts: { Root, Tab } }) {
|
||||||
|
return (
|
||||||
|
<Root>
|
||||||
|
{props.items?.map((item: any) => (
|
||||||
|
<Tab
|
||||||
|
key={item.id}
|
||||||
|
active={item.active}
|
||||||
|
onClick={() => console.log('Tab clicked:', item.label)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Tab>
|
||||||
|
))}
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const Pills = define('Pills', {
|
||||||
|
layout: {
|
||||||
|
display: 'flex',
|
||||||
|
gap: 8,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
|
||||||
|
parts: {
|
||||||
|
Pill: {
|
||||||
|
base: 'button',
|
||||||
|
layout: {
|
||||||
|
padding: '8px 16px',
|
||||||
|
},
|
||||||
|
look: {
|
||||||
|
background: '#f3f4f6',
|
||||||
|
border: 'none',
|
||||||
|
borderRadius: 20,
|
||||||
|
color: '#6b7280',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.2s ease',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
background: '#e5e7eb',
|
||||||
|
color: '#111827',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
active: {
|
||||||
|
parts: {
|
||||||
|
Pill: {
|
||||||
|
look: {
|
||||||
|
background: '#3b82f6',
|
||||||
|
color: 'white',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
background: '#2563eb',
|
||||||
|
color: 'white',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render({ props, parts: { Root, Pill } }) {
|
||||||
|
return (
|
||||||
|
<Root>
|
||||||
|
{props.items?.map((item: any) => (
|
||||||
|
<Pill
|
||||||
|
key={item.id}
|
||||||
|
active={item.active}
|
||||||
|
onclick={() => console.log('Pill clicked:', item.label)}
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Pill>
|
||||||
|
))}
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const VerticalNav = define('VerticalNav', {
|
||||||
|
layout: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
gap: 4,
|
||||||
|
width: 240,
|
||||||
|
},
|
||||||
|
|
||||||
|
parts: {
|
||||||
|
NavItem: {
|
||||||
|
base: 'a',
|
||||||
|
layout: {
|
||||||
|
padding: '12px 16px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 12,
|
||||||
|
},
|
||||||
|
look: {
|
||||||
|
background: 'transparent',
|
||||||
|
borderRadius: 8,
|
||||||
|
color: '#6b7280',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
textDecoration: 'none',
|
||||||
|
cursor: 'pointer',
|
||||||
|
transition: 'all 0.2s ease',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
background: '#f3f4f6',
|
||||||
|
color: '#111827',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Icon: {
|
||||||
|
layout: {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
look: {
|
||||||
|
fontSize: 18,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
variants: {
|
||||||
|
active: {
|
||||||
|
parts: {
|
||||||
|
NavItem: {
|
||||||
|
look: {
|
||||||
|
background: '#eff6ff',
|
||||||
|
color: '#3b82f6',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
background: '#dbeafe',
|
||||||
|
color: '#2563eb',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render({ props, parts: { Root, NavItem, Icon } }) {
|
||||||
|
return (
|
||||||
|
<Root>
|
||||||
|
{props.items?.map((item: any) => (
|
||||||
|
<NavItem
|
||||||
|
key={item.id}
|
||||||
|
active={item.active}
|
||||||
|
href={item.href || '#'}
|
||||||
|
>
|
||||||
|
{item.icon && <Icon>{item.icon}</Icon>}
|
||||||
|
{item.label}
|
||||||
|
</NavItem>
|
||||||
|
))}
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const Breadcrumbs = define('Breadcrumbs', {
|
||||||
|
layout: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
gap: 8,
|
||||||
|
flexWrap: 'wrap',
|
||||||
|
},
|
||||||
|
|
||||||
|
parts: {
|
||||||
|
Item: {
|
||||||
|
base: 'a',
|
||||||
|
look: {
|
||||||
|
color: '#6b7280',
|
||||||
|
fontSize: 14,
|
||||||
|
textDecoration: 'none',
|
||||||
|
transition: 'color 0.2s ease',
|
||||||
|
},
|
||||||
|
states: {
|
||||||
|
':hover': {
|
||||||
|
look: {
|
||||||
|
color: '#3b82f6',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Separator: {
|
||||||
|
look: {
|
||||||
|
color: '#d1d5db',
|
||||||
|
fontSize: 14,
|
||||||
|
userSelect: 'none',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Current: {
|
||||||
|
look: {
|
||||||
|
color: '#111827',
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: 500,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render({ props, parts: { Root, Item, Separator, Current } }) {
|
||||||
|
return (
|
||||||
|
<Root>
|
||||||
|
{props.items?.map((item: any, index: number) => (
|
||||||
|
<>
|
||||||
|
{index === props.items.length - 1 ? (
|
||||||
|
<Current key={item.id}>{item.label}</Current>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<Item key={item.id} href={item.href || '#'}>
|
||||||
|
{item.label}
|
||||||
|
</Item>
|
||||||
|
<Separator>/</Separator>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const NavigationExamplesPage = () => (
|
||||||
|
<Layout title="Forge Navigation Examples">
|
||||||
|
<ExampleSection title="Tabs">
|
||||||
|
<Tabs items={[
|
||||||
|
{ id: 1, label: 'Overview', active: true },
|
||||||
|
{ id: 2, label: 'Analytics', active: false },
|
||||||
|
{ id: 3, label: 'Reports', active: false },
|
||||||
|
{ id: 4, label: 'Settings', active: false },
|
||||||
|
]} />
|
||||||
|
</ExampleSection>
|
||||||
|
|
||||||
|
<ExampleSection title="Pills">
|
||||||
|
<Pills items={[
|
||||||
|
{ id: 1, label: 'All', active: true },
|
||||||
|
{ id: 2, label: 'Active', active: false },
|
||||||
|
{ id: 3, label: 'Pending', active: false },
|
||||||
|
{ id: 4, label: 'Archived', active: false },
|
||||||
|
]} />
|
||||||
|
</ExampleSection>
|
||||||
|
|
||||||
|
<ExampleSection title="Vertical Navigation">
|
||||||
|
<VerticalNav items={[
|
||||||
|
{ id: 1, label: 'Dashboard', icon: '📊', active: true, href: '#' },
|
||||||
|
{ id: 2, label: 'Projects', icon: '📁', active: false, href: '#' },
|
||||||
|
{ id: 3, label: 'Team', icon: '👥', active: false, href: '#' },
|
||||||
|
{ id: 4, label: 'Calendar', icon: '📅', active: false, href: '#' },
|
||||||
|
{ id: 5, label: 'Documents', icon: '📄', active: false, href: '#' },
|
||||||
|
{ id: 6, label: 'Settings', icon: '⚙️', active: false, href: '#' },
|
||||||
|
]} />
|
||||||
|
</ExampleSection>
|
||||||
|
|
||||||
|
<ExampleSection title="Breadcrumbs">
|
||||||
|
<Breadcrumbs items={[
|
||||||
|
{ id: 1, label: 'Home', href: '#' },
|
||||||
|
{ id: 2, label: 'Projects', href: '#' },
|
||||||
|
{ id: 3, label: 'Website Redesign', href: '#' },
|
||||||
|
{ id: 4, label: 'Design Assets' },
|
||||||
|
]} />
|
||||||
|
</ExampleSection>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
16
server.tsx
16
server.tsx
|
|
@ -2,21 +2,31 @@ import { Hono } from 'hono'
|
||||||
import { IndexPage } from './examples/index'
|
import { IndexPage } from './examples/index'
|
||||||
import { ProfileExamplesPage } from './examples/profile'
|
import { ProfileExamplesPage } from './examples/profile'
|
||||||
import { ButtonExamplesPage } from './examples/button'
|
import { ButtonExamplesPage } from './examples/button'
|
||||||
|
import { NavigationExamplesPage } from './examples/navigation'
|
||||||
|
import { styles, stylesToCSS } from './src'
|
||||||
|
|
||||||
const app = new Hono()
|
const app = new Hono()
|
||||||
|
|
||||||
app.get('/', (c) => {
|
app.get('/', c => {
|
||||||
return c.html(<IndexPage />)
|
return c.html(<IndexPage />)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/profile', (c) => {
|
app.get('/profile', c => {
|
||||||
return c.html(<ProfileExamplesPage />)
|
return c.html(<ProfileExamplesPage />)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('/buttons', (c) => {
|
app.get('/buttons', c => {
|
||||||
return c.html(<ButtonExamplesPage />)
|
return c.html(<ButtonExamplesPage />)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
app.get('/navigation', c => {
|
||||||
|
return c.html(<NavigationExamplesPage />)
|
||||||
|
})
|
||||||
|
|
||||||
|
app.get('/styles', c => {
|
||||||
|
return c.text(stylesToCSS(styles))
|
||||||
|
})
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
port: 3300,
|
port: 3300,
|
||||||
fetch: app.fetch,
|
fetch: app.fetch,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user