@multidots/sanity-plugin-tab-block
v1.0.7
Published
A Sanity Studio plugin that lets you create tabbed content blocks with customizable styles, layouts and rich text editing capabilities.
Downloads
36
Readme
@multidots/sanity-plugin-tab-block
A comprehensive tab block plugin for Sanity Studio that provides dynamic, customizable tab interfaces with rich content support.
Features
🎯 Core Functionality
- Multiple Tabs: Support for multiple tabs per block with validation
- Rich Content: Portable Text support with headings, lists, links, and formatting
- Flexible Layouts: Horizontal and vertical tab orientations with intelligent mobile adaptation
- Responsive Design: Comprehensive responsive behavior across all device sizes
- Full ARIA Compliance: Complete
role,aria-selected,aria-controls,aria-labelledby, andtablistattributes
🎨 Customization Options
- Layout Control: Choose between horizontal and vertical tab arrangements
- Advanced Alignment Settings: Independent control over title, tab titles, content, and vertical alignment
- Comprehensive Color Theming: Full color customization for all visual elements
- Block title color
- Tab title colors (active/inactive/hover states)
- Tab background colors (active/inactive states)
- Content text and background colors
- Tab hover colors
Installation
npm install @multidots/sanity-plugin-tab-blockQuick Start
1. Add the Plugin to Your Sanity Config
import {defineConfig} from 'sanity'
import {tabBlockPlugin} from '@multidots/sanity-plugin-tab-block'
export default defineConfig({
// ... other config
plugins: [
tabBlockPlugin(),
// ... other plugins
],
})2. Add to Your Schema
// In your document schema
export default defineType({
name: 'page',
title: 'Page',
type: 'document',
fields: [
defineField({
name: "tabBlock",
type: "tabBlock",
}),
],
})3. Render in Your Frontend
Update GROQ Queries to Include Tab Block
export const getPageQuery = defineQuery(`
*[_type == 'page' && slug.current == $slug][0]{
_id,
_type,
name,
slug,
tabBlock,
}
}`);Create a Component Wrapper
For a clean and maintainable frontend implementation, create a dedicated component wrapper first, then use it in your pages. This approach provides better code organization and reusability.
First, create a Tab.tsx component in your components directory:
'use client'
import { TabBlock as TabBlockComponent, TabBlockData } from "@multidots/sanity-plugin-tab-block"
import { PortableText } from 'next-sanity'
type TabProps = {
tab: TabBlockData
}
const Tab = ({ tab }: TabProps) => {
return (
<TabBlockComponent
tab={tab}
PortableText={(props: any) => <PortableText {...props} />}
/>
)
}
export default TabRender in Your Page Example
Use in Your Page Component
import { TabBlockData } from '@multidots/sanity-plugin-tab-block';
import Tab from '@/components/Tab'
// Add code to get the page data
export default async function Page({ params }: RouteProps) {
const { data: page } = await getPage(params);
return (
<>
{page?.tabBlock && (
<Tab tab={page?.tabBlock as TabBlockData} />
)}
</>
) ;
}
Configuration Options
Schema Fields
| Field | Type | Description | Group |
|-------|------|-------------|-------|
| title | string | Optional title for the entire tab block | - |
| tabs | array | Array of tab objects (1-10 tabs) | Tabs & Content |
| layout | string | 'horizontal' or 'vertical' | Layout & Alignment |
| titleAlignment | string | 'left', 'center', or 'right' | Layout & Alignment |
| tabTitleAlignment | string | 'left', 'center', or 'right' | Layout & Alignment |
| tabTitleVerticalAlignment | string | 'start', 'center', or 'end' (vertical layout only) | Layout & Alignment |
| tabContentAlignment | string | 'left', 'center', or 'right' | Layout & Alignment |
Color Customization
| Color Field | Description | Usage |
|-------------|-------------|-------|
| titleColor | Main block title color | Applied to the main title text |
| tabTitleColor | Inactive tab title color | Default color for tab buttons |
| tabTitleHoverColor | Tab title hover background color | Background color when hovering over tabs |
| activeTabTitleColor | Active tab title color | Text color for the currently active tab |
| tabBackgroundColor | Tab button background color | Default background for tab buttons |
| activeTabBackgroundColor | Active tab background color | Background color for the active tab |
| tabContentColor | Tab content text color | Text color within tab content areas |
| tabContentBackgroundColor | Tab content area background color | Background color for the content area |
Tab Object Structure
Each tab in the tabs array contains:
{
tabTitle: string // Tab button text (required, 1-50 characters)
content: PortableText[] // Rich text content (required)
}Content Features
Supported Rich Text Elements
- Headings: H1, H2, H3, H4
- Text Formatting: Bold, italic, underline
- Lists: Bulleted and numbered lists
- Blockquotes: Quote styling
Link Configuration
Links support:
- HTTP/HTTPS URLs
- Email addresses (
mailto:) - Phone numbers (
tel:)
Component Props
TabBlock Component
interface TabBlockProps {
tab: TabBlockData // The tab block data from Sanity
PortableText?: React.ComponentType<{value: unknown}> // Portable Text renderer
className?: string // Additional CSS classes
}TabBlockData Interface
interface TabBlockData {
title?: string
tabs?: Array<{
tabTitle?: string
content?: unknown[]
_type?: string
_key?: string
}>
layout?: 'horizontal' | 'vertical'
titleAlignment?: 'left' | 'center' | 'right'
tabTitleAlignment?: 'left' | 'center' | 'right'
tabTitleVerticalAlignment?: 'start' | 'center' | 'end'
tabContentAlignment?: 'left' | 'center' | 'right'
// Color properties
titleColor?: {hex: string}
tabTitleColor?: {hex: string}
tabTitleHoverColor?: {hex: string}
activeTabTitleColor?: {hex: string}
tabBackgroundColor?: {hex: string}
activeTabBackgroundColor?: {hex: string}
tabContentColor?: {hex: string}
tabContentBackgroundColor?: {hex: string}
}Styling and Customization
Responsive Design
The component automatically adapts to different screen sizes:
- Desktop & Tablet: Maintains chosen layout (horizontal/vertical)
- Mobile: Vertical tabs convert to horizontal scrollable navigation
Custom Styling
You can override styles by:
- Passing a
classNameprop to the component - Using CSS specificity to override built-in styles
- Customizing colors through the Sanity interface
- Targeting specific responsive breakpoints
CSS Classes
The component generates these CSS classes:
.tab-block- Main container.tab-block-title- Block title.tab-container- Tab layout container (.horizontalor.vertical).tab-nav- Tab navigation container.tab-nav-item- Individual tab buttons (.activefor current tab).tab-content- Content area.tab-panel- Individual content panels (.hiddenfor inactive panels)
Screenshots
Backend Settings:
https://share.cleanshot.com/vyGd88Rybns7g2vwmxZW

Frontend Horizontal View:
https://share.cleanshot.com/3x4DB3JYSZCFyhBR8MK0

Frontend Vertical View:
https://share.cleanshot.com/0Q5yBP3KTlszMFMST5Ft

Development
Testing in Sanity Studio
See Testing a plugin in Sanity Studio for instructions on how to run this plugin with hotreload in your studio.
Examples
Advanced Configuration
// Full customization with all available options
{
_type: 'tabBlock',
title: 'Service Information',
layout: 'vertical',
titleAlignment: 'center',
tabTitleAlignment: 'left',
tabTitleVerticalAlignment: 'start',
tabContentAlignment: 'left',
titleColor: {hex: '#2D3748'},
tabTitleColor: {hex: '#4A5568'},
tabTitleHoverColor: {hex: '#F7FAFC'},
activeTabTitleColor: {hex: '#3182CE'},
tabBackgroundColor: {hex: 'transparent'},
activeTabBackgroundColor: {hex: '#EBF8FF'},
tabContentColor: {hex: '#2D3748'},
tabContentBackgroundColor: {hex: '#F7FAFC'},
tabs: [
{
tabTitle: 'Overview',
content: [
{
_type: 'block',
children: [{text: 'Comprehensive service overview...'}]
}
]
},
{
tabTitle: 'Features',
content: [
{
_type: 'block',
children: [{text: 'Key features and benefits...'}]
}
]
}
]
}Troubleshooting
Common Issues
Issue: Tabs not rendering properly
- Solution: Ensure you're passing the
PortableTextcomponent prop
Issue: Styles not applying
- Solution: Check that color values are in the correct
{hex: string}format
Issue: Content not displaying
- Solution: Verify that tab content is properly structured Portable Text
Performance Tips
- Tab Limits: Keep tabs to 10 or fewer for optimal performance and user experience
- Content Optimization: Use lazy loading for heavy content in tabs
- Mobile Considerations: Consider tab content length and title length for mobile users
- Color Usage: Use the built-in color customization rather than custom CSS for better performance
- Responsive Testing: Test on various devices to ensure optimal responsive behavior
License
MIT © Multidots
