Focus Grid
Grid of items that can be focused; supports dimming unfocused items and showing description only on focus.
Loading block…
Implementation
npx shadcn@latest add @flx/focus-gridVariations
The block supports two props that change behavior: dimUnfocused (dim non-focused items) and descriptionOnFocus (show description only on focused item). Below are defaults and usage per variation.
Default
Loading block…
import { FocusGrid, type FocusGridProps } from './focus-grid'
export function FocusGridExample() {
const values = {
title: 'Our process',
description: 'From idea to launch—click each phase to see how we work.',
dimUnfocused: false,
descriptionOnFocus: true,
items: [
{
image:
'https://images.unsplash.com/photo-1523275335684-37898b6baf30?q=80&w=1099&auto=format&fit=crop',
title: 'Discovery',
description:
'We start by understanding your goals, your users, and the constraints you face.',
defaultFocus: true,
},
{
image:
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=1170&auto=format&fit=crop',
title: 'Design',
description:
'Clean interfaces and clear flows that people love to use every day.',
},
{
image:
'https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?q=80&w=1131&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Build',
description:
'Solid, accessible code that scales with your product and your team.',
},
{
image:
'https://images.unsplash.com/photo-1713623069173-3afa89926882?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Test',
description:
'We validate everything with real users before launch, so nothing is left to chance.',
},
{
image:
'https://images.unsplash.com/photo-1625245488600-f03fef636a3c?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Launch',
description:
'Go live with confidence, with support and iteration when you need it.',
},
],
} satisfies FocusGridProps
return (
<FocusGrid
title={values.title}
description={values.description}
dimUnfocused={values.dimUnfocused}
descriptionOnFocus={values.descriptionOnFocus}
items={values.items}
/>
)
}
Focused items are dimmed
When dimUnfocused is true, unfocused items are dimmed while another item is focused.
Loading block…
focus-grid-dim-unfocused.tsx
import { FocusGrid, type FocusGridProps } from '../focus-grid'
export function FocusGridDimUnfocused() {
const values = {
title: 'Our process',
description: 'From idea to launch—click each phase to see how we work.',
dimUnfocused: true,
descriptionOnFocus: true,
items: [
{
image:
'https://images.unsplash.com/photo-1523275335684-37898b6baf30?q=80&w=1099&auto=format&fit=crop',
title: 'Discovery',
description:
'We start by understanding your goals, your users, and the constraints you face.',
defaultFocus: true,
},
{
image:
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=1170&auto=format&fit=crop',
title: 'Design',
description:
'Clean interfaces and clear flows that people love to use every day.',
},
{
image:
'https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?q=80&w=1131&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Build',
description:
'Solid, accessible code that scales with your product and your team.',
},
{
image:
'https://images.unsplash.com/photo-1713623069173-3afa89926882?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Test',
description:
'We validate everything with real users before launch, so nothing is left to chance.',
},
{
image:
'https://images.unsplash.com/photo-1625245488600-f03fef636a3c?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Launch',
description:
'Go live with confidence, with support and iteration when you need it.',
},
],
} satisfies FocusGridProps
return (
<FocusGrid
title={values.title}
description={values.description}
dimUnfocused={values.dimUnfocused}
descriptionOnFocus={values.descriptionOnFocus}
items={values.items}
/>
)
}
Always show descriptions
When descriptionOnFocus is false, the description is always shown for all items.
Loading block…
focus-grid-description-always.tsx
import { FocusGrid, type FocusGridProps } from '../focus-grid'
export function FocusGridDescriptionAlways() {
const values = {
title: 'Our process',
description: 'From idea to launch—click each phase to see how we work.',
dimUnfocused: false,
descriptionOnFocus: false,
items: [
{
image:
'https://images.unsplash.com/photo-1523275335684-37898b6baf30?q=80&w=1099&auto=format&fit=crop',
title: 'Discovery',
description:
'We start by understanding your goals, your users, and the constraints you face.',
defaultFocus: true,
},
{
image:
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=1170&auto=format&fit=crop',
title: 'Design',
description:
'Clean interfaces and clear flows that people love to use every day.',
},
{
image:
'https://images.unsplash.com/photo-1587563871167-1ee9c731aefb?q=80&w=1131&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Build',
description:
'Solid, accessible code that scales with your product and your team.',
},
{
image:
'https://images.unsplash.com/photo-1713623069173-3afa89926882?q=80&w=1170&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Test',
description:
'We validate everything with real users before launch, so nothing is left to chance.',
},
{
image:
'https://images.unsplash.com/photo-1625245488600-f03fef636a3c?q=80&w=1074&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
title: 'Launch',
description:
'Go live with confidence, with support and iteration when you need it.',
},
],
} satisfies FocusGridProps
return (
<FocusGrid
title={values.title}
description={values.description}
dimUnfocused={values.dimUnfocused}
descriptionOnFocus={values.descriptionOnFocus}
items={values.items}
/>
)
}
Use fewer items for a cleaner, minimalist layout. The grid adjusts item widths to fit the content.
Loading block…
focus-grid-minimalist.tsx
import { FocusGrid, type FocusGridProps } from '../focus-grid'
export function FocusGridMinimalist() {
const values = {
title: 'Our process',
description: 'From idea to launch—click each phase to see how we work.',
dimUnfocused: false,
descriptionOnFocus: true,
items: [
{
image:
'https://images.unsplash.com/photo-1523275335684-37898b6baf30?q=80&w=1099&auto=format&fit=crop',
title: 'Discovery',
description:
'We start by understanding your goals, your users, and the constraints you face.',
defaultFocus: true,
},
{
image:
'https://images.unsplash.com/photo-1505740420928-5e560c06d30e?q=80&w=1170&auto=format&fit=crop',
title: 'Design',
description:
'Clean interfaces and clear flows that people love to use every day.',
},
],
} satisfies FocusGridProps
return (
<FocusGrid
title={values.title}
description={values.description}
dimUnfocused={values.dimUnfocused}
descriptionOnFocus={values.descriptionOnFocus}
items={values.items}
/>
)
}