T
TanStack3y ago
vicious-gold

How to wrap <Link /> in a styled component and sync the active state? And get typesafety

@Tanner Linsley saw somone asked you this here as well https://discord.com/channels/719702312431386674/1007702008448426065/1128108663819747490 I tried this implementation below. Not sure if this is the best way of doing this but not sure how to get type safety of the routes and apply active/inactive styling with the button wrapping the Link any suggestions?
import { Link } from '@tanstack/react-router'

import { Button } from '../ui'

export type NavElementProps = {
name: string
icon: React.ReactNode
route: string
}

export const NavElement: React.FC<NavElementProps> = ({
name,
route,
icon,
}) => {
return (
<Button variant={'outline'}>
{icon}
<Link
params={{}}
search={{}}
to={route}
activeProps={{}}
inactiveProps={{}}
>
{name}
</Link>
</Button>
)
}
import { Link } from '@tanstack/react-router'

import { Button } from '../ui'

export type NavElementProps = {
name: string
icon: React.ReactNode
route: string
}

export const NavElement: React.FC<NavElementProps> = ({
name,
route,
icon,
}) => {
return (
<Button variant={'outline'}>
{icon}
<Link
params={{}}
search={{}}
to={route}
activeProps={{}}
inactiveProps={{}}
>
{name}
</Link>
</Button>
)
}
No description
5 Replies
vicious-gold
vicious-goldOP3y ago
interface NavBarProps {
onMenuClick: () => void
avatarUrl: string
settingsOnClick: () => void
navElement: NavElementProps[]
}
const navigation: NavElementProps[] = [
{
name: 'Contacts',
icon: <Contact2 className='mr-2' />,
route: '/contacts',
},
{
name: 'Companies',
icon: <Castle className='mr-2' />,
route: '/companies',
},
]

export const NavBar = ({ onMenuClick, settingsOnClick }: NavBarProps) => {
const handleSelect = (value: string, label: string) => {
console.log('Selected Value:', value)
console.log('Selected Label:', label)
}

return (
...

<div className='flex flex-row justify-end gap-2 bg-red-200 '>
{/* Links */}
<div className='hidden sm:ml-6 sm:block'>
<div
data-testid='!!navbar-element-link'
className='flex space-x-4'
>
{navigation.map(item => (
<NavElement
key={item.name}
name={item.name}
icon={item.icon}
route={item.route}
/>
))}
</div>
</div>
interface NavBarProps {
onMenuClick: () => void
avatarUrl: string
settingsOnClick: () => void
navElement: NavElementProps[]
}
const navigation: NavElementProps[] = [
{
name: 'Contacts',
icon: <Contact2 className='mr-2' />,
route: '/contacts',
},
{
name: 'Companies',
icon: <Castle className='mr-2' />,
route: '/companies',
},
]

export const NavBar = ({ onMenuClick, settingsOnClick }: NavBarProps) => {
const handleSelect = (value: string, label: string) => {
console.log('Selected Value:', value)
console.log('Selected Label:', label)
}

return (
...

<div className='flex flex-row justify-end gap-2 bg-red-200 '>
{/* Links */}
<div className='hidden sm:ml-6 sm:block'>
<div
data-testid='!!navbar-element-link'
className='flex space-x-4'
>
{navigation.map(item => (
<NavElement
key={item.name}
name={item.name}
icon={item.icon}
route={item.route}
/>
))}
</div>
</div>
This is the navbar
vicious-gold
vicious-goldOP3y ago
thanks ! hmm weird. my navbar is in a ui lib in a mono repo. When i export the type out of apps/web it doesn't share the config , but does from within the app/web package
No description
No description
equal-jade
equal-jade3y ago
🤷🏻 sorry no idea about that
vicious-gold
vicious-goldOP3y ago
I figured this out, needed to use aschild prop in my button

Did you find this page helpful?