NeoGridBox Component
The NeoGridBox component allows you to create a responsive grid of boxes, each with an image, title, description, and link. You can customize the size, colors, and behavior of each box, and the grid will adjust automatically.
Installation
Include the NeoGridBox component in the VitePress installation and register it (globally or per scope, but globally is the most comfortable option).
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import NeoNeoGridBox from './components/NeoGridBox.vue'
export default {
extends: DefaultTheme,
enhanceApp({app}) {
app.component('NeoGridBox', NeoGridBox)
}
}Basic usage
The NeoGridBox component accepts an array of items via the :items prop. Each item can have several properties such as title, description, image, and link.
<NeoGridBox :items="[
{
title: 'Box 1',
description: 'This is the first box with an explanatory description.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information'
},
{
title: 'Box 2',
description: 'This is the second box with a different description.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details'
},
{
title: 'Box 3',
description: 'This is the third box with another description.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?height=512&color=%234a6cf7',
link: '#',
linkText: 'Get started'
}
]" />Customizing the grid layout
You can customize the number of columns and the space between the boxes:
<NeoGridBox
:columns="2"
gap="2rem"
:items="[
{
title: 'Box 1',
description: 'This box uses the default size.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information'
},
{
title: 'Box 2',
description: 'This box uses the default size.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details'
}
]"
/>Custom sizes
You can specify the size of each box using the size prop:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Large box',
description: 'This box occupies 2 columns and 1 row.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
size: { cols: 2, rows: 1 }
},
{
title: 'Small box',
description: 'This box uses the default size.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details'
},
{
title: 'Tall box',
description: 'This box occupies 1 column and 2 rows. It has more content to demonstrate how it expands vertically.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?height=512&color=%234a6cf7',
link: '#',
linkText: 'Get started',
size: { cols: 1, rows: 2 }
},
{
title: 'Regular box',
description: 'This box uses the default size.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information'
}
]"
/>Tall box
This box occupies 1 column and 2 rows. It has more content to demonstrate how it expands vertically.
Custom colors
You can customize the colors of each box or use the default VitePress colors:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Default background',
description: 'This box uses the default VitePress background color (--vp-c-bg-soft).',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information'
},
{
title: 'Custom background',
description: 'This box has a custom background color.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
backgroundColor: '#f0f8ff'
},
{
title: 'Custom title color',
description: 'This box has a custom title color.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?height=128&color=%234a6cf7',
link: '#',
linkText: 'Get started',
titleColor: '#e63946'
},
{
title: 'Custom text color',
description: 'This box has a custom text color for the description.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
textColor: '#2a9d8f'
},
{
title: 'Custom link color',
description: 'This box has a custom link color.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
linkColor: '#6a0dad'
},
{
title: 'All custom colors',
description: 'This box has all custom colors.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
backgroundColor: '#264653',
titleColor: '#e9c46a',
textColor: '#f4a261',
linkColor: '#e76f51'
}
]"
/>Default background
This box uses the default VitePress background color (--vp-c-bg-soft).
External URLs as images
You can now use external URLs as images for the boxes, allowing you to load SVGs or images from APIs or external CDNs:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Icon from external API',
description: 'This box loads an SVG icon from the Iconify API.',
image: 'https://api.iconify.design/bi/bell-fill.svg?height=16&color=%23ba3329',
link: '#',
linkText: 'More information'
},
{
title: 'Normal local image',
description: 'This box still uses a local image with a relative path.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details'
},
{
title: 'Another external icon',
description: 'Another example of an icon from Iconify with a different color.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
imageSize: 80
}
]"
/>Interactive features
You can customize the interactive behavior of each box:
<NeoGridBox
:columns="3"
:items="[
{
title: 'No hover effect',
description: 'This box has the hover effect disabled.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
disableHoverEffect: true
},
{
title: 'Background change on hover',
description: 'This box changes the background color when hovering.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
hoverBackgroundColor: '#e0f7fa'
},
{
title: 'Fully clickable box',
description: 'The entire box is clickable, not just the link.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
fullBoxClickable: true
},
{
title: 'Combined features',
description: 'This box changes the background on hover and is fully clickable.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
hoverBackgroundColor: '#fff8e1',
fullBoxClickable: true
}
]"
/>Fully clickable box
The entire box is clickable, not just the link.
Combined features
This box changes the background on hover and is fully clickable.
Text color change on hover
You can control whether the text color changes when hovering over fully clickable boxes:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Default behavior',
description: 'This box changes the text color on hover (default behavior).',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
fullBoxClickable: true
},
{
title: 'Custom hover text color',
description: 'This box uses a custom hover text color.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
fullBoxClickable: true,
hoverTextColor: '#e63946'
},
{
title: 'Color change disabled',
description: 'This box does not change the text color on hover.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
fullBoxClickable: true,
hoverTextColor: false
}
]"
/>Default behavior
This box changes the text color on hover (default behavior).
Custom hover text color
This box uses a custom hover text color.
Color change disabled
This box does not change the text color on hover.
Sizes and alignment of elements
You can customize the size and alignment of each element:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Custom image size',
description: 'This box has a larger image.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
imageSize: 100
},
{
title: 'Custom title size and alignment',
description: 'This box has a larger title aligned to the right.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
titleSize: 24,
titleAlign: 'right'
},
{
title: 'Custom description size and alignment',
description: 'This box has a larger description text aligned to the left.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
textSize: 18,
textAlign: 'left'
},
{
title: 'Custom link size and alignment',
description: 'This box has a larger link aligned to the center.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
linkSize: 18,
linkAlign: 'center'
},
{
title: 'Image aligned to the left',
description: 'This box has the image aligned to the left.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
imageAlign: 'left'
},
{
title: 'Image aligned to the right',
description: 'This box has the image aligned to the right.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
imageAlign: 'right'
}
]"
/>Custom description size and alignment
This box has a larger description text aligned to the left.
Optional elements
All elements are optional, so you can create boxes with only the elements you need:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Only image and title',
image: '/images/icon/firewall.png'
},
{
description: 'Only description',
},
{
title: 'Only title and link',
link: '#',
linkText: 'More information'
},
{
image: '/images/branding/icon/blue-transparent.svg',
description: 'Only image and description'
},
{
title: 'Title, description, and link',
description: 'No image in this box.',
link: '#',
linkText: 'View details'
}
]"
/>Only image and title
Only description
Only title and link
Only image and description
Vue components as icons
You can use Vue components as icons instead of images:
<script setup>
import { h } from 'vue'
// Example of creating a simple icon component
const DiscordIcon = () => h('svg', {
xmlns: 'http://www.w3.org/2000/svg',
width: '24',
height: '24',
viewBox: '0 0 24 24',
fill: 'currentColor',
style: { color: '#5865F2' }
}, [
h('path', { d: 'M19.27 5.33C17.94 4.71 16.5 4.26 15 4a.09.09 0 0 0-.07.03c-.18.33-.39.76-.53 1.09a16.09 16.09 0 0 0-4.8 0c-.14-.34-.35-.76-.54-1.09-.01-.02-.04-.03-.07-.03-1.5.26-2.93.71-4.27 1.33-.01 0-.02.01-.03.02-2.72 4.07-3.47 8.03-3.1 11.95 0 .02.01.04.03.05 1.8 1.32 3.53 2.12 5.24 2.65.03.01.06 0 .07-.02.4-.55.76-1.13 1.07-1.74.02-.04 0-.08-.04-.09-.57-.22-1.11-.48-1.64-.78-.04-.02-.04-.08-.01-.11.11-.08.22-.17.33-.25.02-.02.05-.02.07-.01 3.44 1.57 7.15 1.57 10.55 0 .02-.01.05-.01.07.01.11.09.22.17.33.26.04.03.04.09-.01.11-.52.31-1.07.56-1.64.78-.04.01-.05.06-.04.09.32.61.68 1.19 1.07 1.74.03.02.06.03.09.02 1.72-.53 3.45-1.33 5.25-2.65.02-.01.03-.03.03-.05.44-4.53-.73-8.46-3.1-11.95-.01-.01-.02-.02-.04-.02zM8.52 14.91c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.84 2.12-1.89 2.12zm6.97 0c-1.03 0-1.89-.95-1.89-2.12s.84-2.12 1.89-2.12c1.06 0 1.9.96 1.89 2.12 0 1.17-.83 2.12-1.89 2.12z' })
])
// Example of creating a mail icon component
const MailIcon = () => h('svg', {
xmlns: 'http://www.w3.org/2000/svg',
width: '24',
height: '24',
viewBox: '0 0 24 24',
fill: 'currentColor',
style: { color: '#0288D1' }
}, [
h('path', { d: 'M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z' })
])
</script>
<NeoGridBox
:columns="3"
:items="[
{
title: 'Discord Icon',
description: 'This box uses a Vue component for the Discord icon.',
component: DiscordIcon,
link: '#',
linkText: 'More information'
},
{
title: 'Mail Icon',
description: 'This box uses a Vue component for the Mail icon.',
component: MailIcon,
link: '#',
linkText: 'View details'
},
{
title: 'Custom icon size',
description: 'This box uses a Vue component with a custom size.',
component: DiscordIcon,
link: '#',
linkText: 'Get started',
imageSize: 48
}
]"
/>Link icons
You can add an icon to your links (either to the left or right of the link text). There are two ways to do this:
- Use a custom SVG by providing the SVG code in the
linkIconproperty - Set
linkIcontotrueto use the default arrow icon
By default, the icon appears to the right of the text, but you can change its position using the iconPosition property with values 'left' or 'right'.
<NeoGridBox
:columns="3"
:items="[
{
title: 'Default icon (right side)',
description: 'This box uses the default icon on the right side of the link.',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information',
linkIcon: true
},
{
title: 'Icon on the left side',
description: 'This box has the icon on the left side of the link.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
linkIcon: true,
iconPosition: 'left'
},
{
title: 'Custom SVG icon',
description: 'This box uses a custom SVG as the link icon.',
image: 'https://api.iconify.design/mdi/rocket-launch.svg?color=%234a6cf7',
link: '#',
linkText: 'Get started',
linkIcon: '<svg>...</svg>'
}
]"
/>Default icon (right side)
This box uses the default icon on the right side of the link.
Custom combinations
You can combine various properties to create unique designs:
<NeoGridBox
:columns="2"
gap="1.5rem"
:items="[
{
title: 'Complete design with customization',
description: 'This box combines multiple properties to create a unique design.',
image: '/images/branding/icon/blue-dark.svg',
link: '#',
linkText: 'Explore',
size: { cols: 1, rows: 2 },
backgroundColor: '#f8f9fa',
titleColor: '#1e88e5',
titleSize: 22,
titleAlign: 'center',
textSize: 16,
textAlign: 'justify',
linkColor: '#0d47a1',
linkSize: 16,
linkAlign: 'center',
imageSize: 80,
imageAlign: 'center',
hoverBackgroundColor: '#e3f2fd'
},
{
title: 'Clickable box with custom style',
description: 'This box is fully clickable and has custom hover effects.',
image: '/images/branding/icon/blue-light.svg',
link: '#',
linkText: 'Discover',
fullBoxClickable: true,
hoverBackgroundColor: '#e8f5e9',
hoverTextColor: '#2e7d32',
imageSize: 70,
titleAlign: 'center',
textAlign: 'center',
linkAlign: 'center'
},
{
title: 'Business design',
description: 'A more sober and professional style for corporate environments.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View solutions',
backgroundColor: '#ffffff',
titleColor: '#333333',
textColor: '#666666',
linkColor: '#1976d2',
imageAlign: 'left',
titleAlign: 'left',
textAlign: 'left',
hoverBackgroundColor: '#fafafa'
},
{
title: 'Product card style',
description: 'Design similar to a product card with hover effects.',
image: '/images/branding/icon/white-dark.svg',
link: '#',
linkText: 'Buy now',
fullBoxClickable: true,
backgroundColor: '#ffffff',
titleColor: '#212121',
textColor: '#757575',
linkColor: '#f44336',
titleAlign: 'center',
textAlign: 'center',
linkAlign: 'center',
hoverBackgroundColor: '#fafafa',
hoverTextColor: '#f44336'
}
]"
/>
## Custom combinations
You can combine various properties to create unique designs:
```vue:line-numbers {1}
<NeoGridBox
:columns="2"
gap="1.5rem"
:items="[
{
title: 'Complete design with customization',
description: 'This box combines multiple properties to create a unique design.',
image: '/images/branding/icon/blue-dark.svg',
link: '#',
linkText: 'Explore',
size: { cols: 1, rows: 2 },
backgroundColor: '#f8f9fa',
titleColor: '#1e88e5',
titleSize: 22,
titleAlign: 'center',
textSize: 16,
textAlign: 'justify',
linkColor: '#0d47a1',
linkSize: 16,
linkAlign: 'center',
imageSize: 80,
imageAlign: 'center',
hoverBackgroundColor: '#e3f2fd'
},
{
title: 'Clickable box with custom style',
description: 'This box is fully clickable and has custom hover effects.',
image: '/images/branding/icon/blue-light.svg',
link: '#',
linkText: 'Discover',
fullBoxClickable: true,
hoverBackgroundColor: '#e8f5e9',
hoverTextColor: '#2e7d32',
imageSize: 70,
titleAlign: 'center',
textAlign: 'center',
linkAlign: 'center'
},
{
title: 'Business design',
description: 'A more sober and professional style for corporate environments.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View solutions',
backgroundColor: '#ffffff',
titleColor: '#333333',
textColor: '#666666',
linkColor: '#1976d2',
imageAlign: 'left',
titleAlign: 'left',
textAlign: 'left',
hoverBackgroundColor: '#fafafa'
},
{
title: 'Product card style',
description: 'Design similar to a product card with hover effects.',
image: '/images/branding/icon/white-dark.svg',
link: '#',
linkText: 'Buy now',
fullBoxClickable: true,
backgroundColor: '#ffffff',
titleColor: '#212121',
textColor: '#757575',
linkColor: '#f44336',
titleAlign: 'center',
textAlign: 'center',
linkAlign: 'center',
hoverBackgroundColor: '#fafafa',
hoverTextColor: '#f44336'
}
]"
/>Complete design with customization
This box combines multiple properties to create a unique design.
Clickable box with custom style
This box is fully clickable and has custom hover effects.
Product card style
Design similar to a product card with hover effects.
Vertical alignment
By default, all boxes have their content vertically centered. You can disable this behavior for specific boxes by setting the alignVertically property to false:
<NeoGridBox
:columns="3"
:items="[
{
title: 'Default centered content',
description: 'This box has the content vertically centered (default behavior).',
image: '/images/icon/firewall.png',
link: '#',
linkText: 'More information'
},
{
title: 'Vertical centering disabled',
description: 'This box has the vertical centering disabled, so the content starts at the top.',
image: '/images/branding/icon/blue-transparent.svg',
link: '#',
linkText: 'View details',
alignVertically: false
}
]"
/>Default centered content
This box has the content vertically centered (default behavior).
Vertical centering disabled
This box has the vertical centering disabled, so the content starts at the top.
Component API
Props
| Prop | Type | Default value | Description |
|---|---|---|---|
| items | Array | (required) | Array of objects representing each box |
| columns | Number | 3 | Number of columns in the grid |
| gap | String | '1.5rem' | Space between grid elements |
Item properties
Each item in the items array can have the following properties. Every property that accepts text can also accept HTML being injected into it:
| Property | Type | Description |
|---|---|---|
| title | String | Box title |
| description | String | Description text |
| image | String | Path to the image |
| component | Component | Vue component to use as an icon instead of an image |
| link | String | URL for the link |
| linkText | String | Text for the link |
| linkIcon | String/Boolean | Custom SVG code for the link icon or true to use the default arrow icon |
| iconPosition | String | Position of the link icon. Can be 'left' or 'right' (default is 'right') |
| size | Object | Box size, e.g., { cols: 2, rows: 1 } |
| backgroundColor | String | Custom background color for the box |
| titleColor | String | Custom color for the title |
| textColor | String | Custom color for the description text |
| linkColor | String | Custom color for the link |
| disableHoverEffect | Boolean | Disables the hover effect (elevation and shadow) when set to true (default true) |
| hoverBackgroundColor | String | Changes the background color on hover to the specified color |
| fullBoxClickable | Boolean | Makes the entire box clickable, not just the link, when set to true |
| hoverTextColor | String/Boolean | Custom color for the text on hover when the box is fully clickable. Set to false to disable text color change on hover |
| imageSize | String/Number | Custom size for the image or icon. Can be a number (pixels) or a string (e.g., '50%') |
| imageAlign | String | Alignment of the image or icon. Can be 'left', 'center', or 'right' |
| titleSize | String/Number | Custom size for the title. Can be a number (pixels) or a string (e.g., '1.5rem') |
| titleAlign | String | Alignment of the title. Can be 'left', 'center', or 'right' |
| textSize | String/Number | Custom size for the description text. Can be a number (pixels) or a string (e.g., '1rem') |
| textAlign | String | Alignment of the description text. Can be 'left', 'center', or 'right' |
| linkSize | String/Number | Custom size for the link. Can be a number (pixels) or a string (e.g., '0.9rem') |
| linkAlign | String | Alignment of the link. Can be 'left', 'center', or 'right' |
| className | String | Additional CSS class name to be applied to the box |
| alignVertically | Boolean | Controls vertical alignment of the content. Set to false to disable vertical centering (default is true) |