517 lines
12 KiB
TypeScript
517 lines
12 KiB
TypeScript
import { define } from '../src'
|
|
import { ExampleSection } from './ssr/helpers'
|
|
|
|
const TabSwitcher = define('TabSwitcher', {
|
|
parts: {
|
|
Input: {
|
|
base: 'input',
|
|
display: 'none', // Hide radio inputs
|
|
},
|
|
TabBar: {
|
|
display: 'flex',
|
|
gap: 0,
|
|
borderBottom: '2px solid #e5e7eb',
|
|
marginBottom: 24,
|
|
},
|
|
TabLabel: {
|
|
base: 'label',
|
|
|
|
padding: '12px 24px',
|
|
position: 'relative',
|
|
marginBottom: -2,
|
|
background: 'transparent',
|
|
borderBottom: '2px solid transparent',
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
color: '#111827',
|
|
}
|
|
}
|
|
},
|
|
Content: {
|
|
display: 'none',
|
|
padding: 20,
|
|
background: '#f9fafb',
|
|
borderRadius: 8,
|
|
}
|
|
},
|
|
|
|
render({ props, parts: { Root, Input, TabBar, TabLabel, Content } }) {
|
|
return (
|
|
<Root>
|
|
{/* Hidden radio inputs */}
|
|
{props.tabs?.map((tab: any, index: number) => (
|
|
<Input
|
|
key={`input-${tab.id}`}
|
|
type="radio"
|
|
id={`tab-${props.name}-${tab.id}`}
|
|
name={props.name || 'tabs'}
|
|
checked={index === 0}
|
|
/>
|
|
))}
|
|
|
|
{/* Tab labels */}
|
|
<TabBar>
|
|
{props.tabs?.map((tab: any) => (
|
|
<TabLabel key={`label-${tab.id}`} for={`tab-${props.name}-${tab.id}`}>
|
|
{tab.label}
|
|
</TabLabel>
|
|
))}
|
|
</TabBar>
|
|
|
|
{/* Tab content panels */}
|
|
{props.tabs?.map((tab: any) => (
|
|
<Content key={`content-${tab.id}`} class={`content-${props.name}-${tab.id}`}>
|
|
{tab.content}
|
|
</Content>
|
|
))}
|
|
|
|
{/* CSS to show active tab and content */}
|
|
<style dangerouslySetInnerHTML={{
|
|
__html: props.tabs?.map((tab: any) => `
|
|
input#tab-${props.name}-${tab.id}:checked + .TabBar label[for="tab-${props.name}-${tab.id}"],
|
|
input#tab-${props.name}-${tab.id}:checked ~ .TabBar label[for="tab-${props.name}-${tab.id}"] {
|
|
color: #3b82f6 !important;
|
|
border-bottom: 2px solid #3b82f6 !important;
|
|
}
|
|
input#tab-${props.name}-${tab.id}:checked ~ .content-${props.name}-${tab.id} {
|
|
display: block !important;
|
|
}
|
|
`).join('\n')
|
|
}} />
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
const Pills = define('Pills', {
|
|
parts: {
|
|
Input: {
|
|
base: 'input',
|
|
display: 'none',
|
|
},
|
|
PillBar: {
|
|
display: 'flex',
|
|
gap: 8,
|
|
flexWrap: 'wrap',
|
|
},
|
|
PillLabel: {
|
|
base: 'label',
|
|
|
|
padding: '8px 16px',
|
|
background: '#f3f4f6',
|
|
border: 'none',
|
|
borderRadius: 20,
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
background: '#e5e7eb',
|
|
color: '#111827',
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render({ props, parts: { Root, Input, PillBar, PillLabel } }) {
|
|
return (
|
|
<Root>
|
|
{props.items?.map((item: any, index: number) => (
|
|
<Input
|
|
key={`input-${item.id}`}
|
|
type="radio"
|
|
id={`pill-${props.name}-${item.id}`}
|
|
name={props.name || 'pills'}
|
|
checked={index === 0}
|
|
/>
|
|
))}
|
|
|
|
<PillBar>
|
|
{props.items?.map((item: any) => (
|
|
<PillLabel key={`label-${item.id}`} for={`pill-${props.name}-${item.id}`}>
|
|
{item.label}
|
|
</PillLabel>
|
|
))}
|
|
</PillBar>
|
|
|
|
<style dangerouslySetInnerHTML={{
|
|
__html: props.items?.map((item: any) => `
|
|
input#pill-${props.name}-${item.id}:checked + .PillBar label[for="pill-${props.name}-${item.id}"],
|
|
input#pill-${props.name}-${item.id}:checked ~ .PillBar label[for="pill-${props.name}-${item.id}"] {
|
|
background: #3b82f6 !important;
|
|
color: white !important;
|
|
}
|
|
`).join('\n')
|
|
}} />
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
const VerticalNav = define('VerticalNav', {
|
|
parts: {
|
|
Input: {
|
|
base: 'input',
|
|
display: 'none',
|
|
},
|
|
NavBar: {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 4,
|
|
width: 240,
|
|
},
|
|
NavLabel: {
|
|
base: 'label',
|
|
|
|
padding: '12px 16px',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
|
|
background: 'transparent',
|
|
borderRadius: 8,
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
background: '#f3f4f6',
|
|
color: '#111827',
|
|
}
|
|
}
|
|
},
|
|
Icon: {
|
|
width: 20,
|
|
height: 20,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontSize: 18,
|
|
}
|
|
},
|
|
|
|
render({ props, parts: { Root, Input, NavBar, NavLabel, Icon } }) {
|
|
return (
|
|
<Root>
|
|
{props.items?.map((item: any, index: number) => (
|
|
<Input
|
|
key={`input-${item.id}`}
|
|
type="radio"
|
|
id={`nav-${props.name}-${item.id}`}
|
|
name={props.name || 'nav'}
|
|
checked={index === 0}
|
|
/>
|
|
))}
|
|
|
|
<NavBar>
|
|
{props.items?.map((item: any) => (
|
|
<NavLabel key={`label-${item.id}`} for={`nav-${props.name}-${item.id}`}>
|
|
{item.icon && <Icon>{item.icon}</Icon>}
|
|
{item.label}
|
|
</NavLabel>
|
|
))}
|
|
</NavBar>
|
|
|
|
<style dangerouslySetInnerHTML={{
|
|
__html: props.items?.map((item: any) => `
|
|
input#nav-${props.name}-${item.id}:checked + .NavBar label[for="nav-${props.name}-${item.id}"],
|
|
input#nav-${props.name}-${item.id}:checked ~ .NavBar label[for="nav-${props.name}-${item.id}"] {
|
|
background: #eff6ff !important;
|
|
color: #3b82f6 !important;
|
|
}
|
|
`).join('\n')
|
|
}} />
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
const Breadcrumbs = define('Breadcrumbs', {
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 8,
|
|
flexWrap: 'wrap',
|
|
|
|
parts: {
|
|
Item: {
|
|
base: 'a',
|
|
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
textDecoration: 'none',
|
|
transition: 'color 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
color: '#3b82f6',
|
|
}
|
|
}
|
|
},
|
|
Separator: {
|
|
color: '#d1d5db',
|
|
fontSize: 14,
|
|
userSelect: 'none',
|
|
},
|
|
Current: {
|
|
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>
|
|
)
|
|
}
|
|
})
|
|
|
|
const Tabs = define('Tabs', {
|
|
display: 'flex',
|
|
gap: 0,
|
|
borderBottom: '2px solid #e5e7eb',
|
|
|
|
parts: {
|
|
Tab: {
|
|
base: 'button',
|
|
padding: '12px 24px',
|
|
position: 'relative',
|
|
marginBottom: -2,
|
|
background: 'transparent',
|
|
border: 'none',
|
|
borderBottom: '2px solid transparent',
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
color: '#111827',
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
variants: {
|
|
active: {
|
|
parts: {
|
|
Tab: {
|
|
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}>
|
|
{item.label}
|
|
</Tab>
|
|
))}
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
const SimplePills = define('SimplePills', {
|
|
display: 'flex',
|
|
gap: 8,
|
|
flexWrap: 'wrap',
|
|
|
|
parts: {
|
|
Pill: {
|
|
base: 'button',
|
|
padding: '8px 16px',
|
|
background: '#f3f4f6',
|
|
border: 'none',
|
|
borderRadius: 20,
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
background: '#e5e7eb',
|
|
color: '#111827',
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
variants: {
|
|
active: {
|
|
parts: {
|
|
Pill: {
|
|
background: '#3b82f6',
|
|
color: 'white',
|
|
states: {
|
|
':hover': {
|
|
background: '#2563eb',
|
|
color: 'white',
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render({ props, parts: { Root, Pill } }) {
|
|
return (
|
|
<Root>
|
|
{props.items?.map((item: any) => (
|
|
<Pill key={item.id} active={item.active}>
|
|
{item.label}
|
|
</Pill>
|
|
))}
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
const SimpleVerticalNav = define('SimpleVerticalNav', {
|
|
display: 'flex',
|
|
flexDirection: 'column',
|
|
gap: 4,
|
|
width: 240,
|
|
|
|
parts: {
|
|
NavItem: {
|
|
base: 'button',
|
|
padding: '12px 16px',
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
gap: 12,
|
|
background: 'transparent',
|
|
border: 'none',
|
|
borderRadius: 8,
|
|
color: '#6b7280',
|
|
fontSize: 14,
|
|
fontWeight: 500,
|
|
textAlign: 'left',
|
|
cursor: 'pointer',
|
|
transition: 'all 0.2s ease',
|
|
|
|
states: {
|
|
':hover': {
|
|
background: '#f3f4f6',
|
|
color: '#111827',
|
|
}
|
|
}
|
|
},
|
|
Icon: {
|
|
width: 20,
|
|
height: 20,
|
|
display: 'flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
fontSize: 18,
|
|
}
|
|
},
|
|
|
|
variants: {
|
|
active: {
|
|
parts: {
|
|
NavItem: {
|
|
background: '#eff6ff',
|
|
color: '#3b82f6',
|
|
states: {
|
|
':hover': {
|
|
background: '#dbeafe',
|
|
color: '#2563eb',
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
render({ props, parts: { Root, NavItem, Icon } }) {
|
|
return (
|
|
<Root>
|
|
{props.items?.map((item: any) => (
|
|
<NavItem key={item.id} active={item.active}>
|
|
{item.icon && <Icon>{item.icon}</Icon>}
|
|
{item.label}
|
|
</NavItem>
|
|
))}
|
|
</Root>
|
|
)
|
|
}
|
|
})
|
|
|
|
export const NavigationExamplesContent = () => (
|
|
<>
|
|
<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">
|
|
<SimplePills 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">
|
|
<SimpleVerticalNav items={[
|
|
{ id: 1, label: 'Dashboard', icon: '📊', active: true },
|
|
{ id: 2, label: 'Projects', icon: '📁', active: false },
|
|
{ id: 3, label: 'Team', icon: '👥', active: false },
|
|
{ id: 4, label: 'Calendar', icon: '📅', active: false },
|
|
{ id: 5, label: 'Documents', icon: '📄', active: false },
|
|
{ id: 6, label: 'Settings', icon: '⚙️', active: false },
|
|
]} />
|
|
</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>
|
|
</>
|
|
)
|