Tina's "click to edit" feature allows editors to select the HTML element they want to click on the page in order to see the corresponding field in the sidebar.
We can implement this with the data-tina-field
API.
[data-tina-field]
must be applied to HTML elements, not React components like TinaMarkdown.
The object which holds the field you're accessing.
The property from the object which you're accessing, omitting this will return the object field's metadata.
All properties marked as REQUIRED must be specified for the field to work properly.
Note: Theobject
property only needs to contain the nearest ancestor of the field you're trying to access.
// components/blocks/heroimport { tinaField } from 'tinacms/dist/react';export const HeroComponent = (props) => {return (<div><h4 data-tina-field={tinaField(props, 'heading')}>{props.heading}</h4><p data-tina-field={tinaField(props, 'message')}>{props.message}</p><ul data-tina-field={tinaField(props, 'links')}>{props.links.map((link) => (<li><a data-tina-field={tinaField(link)} href={link.url}>{link.label}</a></li>))}</ul></div>);};
React components can't take arbitrary HTML attributes like data-tina-field
. To work around this, define a prop (e.g. tinaField) and pass it down to an HTML element inside the component:
const Section = ({ children, tinaField }) => {return <section data-tina-field={tinaField}>{children}</section>;};<Section tinaField={tinaField(data, 'body')}><TinaMarkdown content={data.body} /></Section>
When using TinaMarkdown
with custom components, the props
object passed into each component already includes the _content_source
metadata. This metadata is automatically injected in edit mode via Tina's useTina
hook.
To make a component editable, all you need to do is pass the props
object directly into the tinaField
helper:
<div data-tina-field={tinaField(props)}><MyComponent {...props} /></div>
This links to the template component inside of TinaCMS, but does not target a specific field.
If you want to target a specific field inside the component. For example, only the format
property instead of the whole block. Use the second argument to tinaField
to specify the field name:
<div data-tina-field={tinaField(props, 'format')}>Format: {props.format}</div>
This gives Tina a more precise mapping to the field, based on the template definition defined in your collection.
Here's a slightly more advanced example showing how the tinaField
can be used to expose fields within rich text content, even inside custom components:
import { useTina, tinaField } from 'tinacms/dist/react';import { TinaMarkdown } from 'tinacms/dist/rich-text';export default function Post(props) {const { data } = useTina({query: props.query,variables: props.variables,data: props.data,});return (<div data-tina-field={tinaField(data.post, 'body')}><TinaMarkdowncontent={data.post.body}components={{DateTime: (props) => {return (<div data-tina-field={tinaField(props)}><TestComp {...props} /></div>);},}}/><code><pre>{JSON.stringify(data.post, null, 2)}</pre></code></div>);}const TestComp = (props) => {return (<><div data-tina-field={tinaField(props, 'format')}>Date Time Format: {props.format}</div><div data-tina-field={tinaField(props, 'stringTest')}><TinaMarkdown content={props.stringTest} /></div></>);};
This way editors can click any nested field inside custom components and go straight to that templates field.
When Tina is in edit mode, it enhances the data with metadata for each editable field. For example, a rich text template field like might look like:
{"type": "root","children": [{"type": "DateTime","format": "MMM yyyy","stringTest": "...","_content_source": { // metadata"queryId": "6rix9","path": ["post","body","children",0]}}]}
The tinaField
helper reads this _content_source
metadata to construct the correct path for the editor UI to connect the field with the form.
When edit mode is active, Tina automatically applies outlines to any [data-tina-field]
element.
You can override these styles if needed:
.__tina-quick-editing-enabled [data-tina-field] {outline: 2px dashed rgba(254, 34, 56, 0.5);}.__tina-quick-editing-enabled [data-tina-field]:hover {outline: 2px dashed rgba(254, 34, 56, 1);}