Portable Text
Portable Text renders rich text content with embedded blocks. It follows the Portable Text π specification and allows for rich formatting and embedded content.
Schema Configuration
Sanity Schema
// In your feature descriptorimport { PortableTextDescriptor } from '@vyuh/sanity-schema-system';
export const myFeature = new FeatureDescriptor({ name: 'myFeature', title: 'My Feature',
contents: [ new PortableTextDescriptor({ // Optional: Define custom marks and blocks marks: [ // Custom marks ], blocks: [ // Custom blocks that can be embedded ], }), ],});
Content Structure
// Portable Text content object structureinterface PortableText { _type: 'vyuh.portableText'; blocks: { _type: 'block'; style: string; children: { _type: 'span'; text: string; marks?: string[]; }[]; markDefs?: { _key: string; _type: string; // Mark-specific properties }[]; }[];}
Portable Text can include embedded content blocks, links, and custom marks. Itβs perfect for blog posts, articles, and other rich text content.
Extensibility
Schema Descriptors
The PortableTextDescriptor
in the schema system provides the following extensibility points:
- annotations: Register custom marks (annotations) for text formatting
- blocks: Define custom block types that can be embedded within portable text
- styles: Define custom block styles beyond the default ones
// Schema-side descriptornew PortableTextDescriptor({ annotations: [highlightMark, tooltipMark], blocks: [codeBlock, { type: 'vyuh.card' }], styles: [{ title: 'Callout', value: 'callout' }]})
React Descriptors
In the React system, portable text content is configured using the PortableTextDescriptor:
// React-side registrationimport { PortableTextDescriptor } from '@vyuh/react-feature-system';import { ContentExtensionDescriptor } from '@vyuh/react-extension-content';import { FeatureDescriptor } from '@vyuh/react-core';
new FeatureDescriptor({ name: 'myFeature', extensions: [ new ContentExtensionDescriptor({ contents: [ new PortableTextDescriptor({ blockTypes: [ { type: 'codeBlock', component: CodeBlockComponent }, { type: 'vyuh.card', component: PortableTextConfig.shared.renderContentItem }, ], marks: [ { type: 'highlight', component: HighlightComponent }, ], blockStyles: [ { style: 'callout', component: CalloutComponent }, ], }), ], }), ],});