There are two ways to create custom fields with Tina:
component
propertyA field Component
is React component that accepts three props:
field
: The field definition for the current field.input
: The data and callbacks necessary to make an input.meta
: Metadata about the field in the form. (e.g. dirty
, valid
)Checkout the react-final-form docs for a more detailed description of the input
and meta
props.
A field plugin is a JavaScript object with three properties:
name
: A string used to identify the component. This is the name that is set in a field definition. This name must be unique; if multiple plugins are registered with the same name, only the last will be used.Component
: The component that will used in the form. The exact nature of this component depends on which form builder is being used.validate
: An optional function that will be used to validate the field's data.Interface
interface FieldPlugin {
__type: 'field'
name: string
Component: React.FC<any>
type?: string
validate?(
value: any,
allValues: any,
meta: any,
field: Field
): string | object | undefined
parse?: (value: any, name: string, field: Field) => any
format?: (value: any, name: string, field: Field) => any
defaultValue?: any
}
The optional validate
function can be utilized to configure field validation.
Arguments
value
: The field's current valueallValues
: The current state of the entire formmeta
: The form metadata for this fieldfield
: The field's configurationimport { MapPicker, validateMap } from 'cms-field-my-map-picker'
let cms = new CMS()
cms.fields.add({
name: 'map',
Component: MapPicker,
validate: validateMap,
})
Here is an example of a simple text field plugin. The Component
renders the label, the input, and the errors for the field.
import { CMS } from '@tinacms/core'
let cms = new CMS()
cms.fields.add({
name: 'text',
Component({ input, meta, field }) {
return (
<div>
<label htmFor={input.name}>{field.label || field.name}</label>
<div>{field.description}</div>
<input type="email" {...input} />
<div class="field-error">{meta.error}</div>
</div>
)
},
validate(email, allValues, meta, field) {
let isValidEmail = /.*@.*\..*/.test(email)
if (!isValidEmail) return 'Invalid email address'
},
})
If you want to style the custom field to fit in with the rest of the Tina sidebar, you'll need to access Tina theme styles from @tinacms/styles
.
If the Tina theme has been customized, the Theme
values will be a combination of the customized styles and those set by DefaultTheme
. The theme will fallback to all default values if no customization is set.
To utilize these Theme
values, helper functions have been created.
The helpers will only work when using
styled-components
to style custom fields. If using another CSS-in-JS framework, use theDefaultTheme
object directly.
Color | Default Value |
---|---|
primary(value?: "light" | "medium" | "dark") | "medium" |
grey(value?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9) | 0 |
error(value?: "light" | "medium" | "dark") | "medium" |
Font | Default Value |
---|---|
size(value?: 0 | 1 | 2 | 3 | 4 | 5 | 6) | 0 |
weight(value?: "regular" | "bold") | "regular" |
Misc | Default | Notes |
---|---|---|
radius(size?: "small" | "big") | "big" | For border-radius |
padding(size?: "small" | "big") | "big" | |
shadow(size?: "small" | "big") | "big" | For box-shadow |
timing(length: "medium" | "short" | "long") | length req. | For transition |
/*
** Example: Helper functions used
** within a styled component that will
** render in a custom field
*/
// 1. Import the helpers
import { padding, color, radius, font } from '@tinacms/styles'
import styled from 'styled-components'
// 2. Use the helpers in your styled components
const Label = styled.h3`
color: ___CSS_0___;
font-size: ___CSS_1___;
font-weight: ___CSS_2___;
border-radius: ___CSS_3___;
border: 1px solid ___CSS_4___;
transition: color linear ease ___CSS_5___;
padding: ___CSS_6___;
`
You can also access the DefaultTheme
directly without using the helpers. This is helpful when you want to utilize Tina Theme styles outside of styled-components
or if you just prefer working with the theme values directly, without helpers.
Although it's called
DefaultTheme
, note that if you pass custom values to the sidebar,DefaultTheme
provides the overridden values instead of the true Tina defaults.
/*
** Example: Using `DefaultTheme`
** directly with a CSS-in-JS,
** framework `styled-jsx`
*/
// 1. Import `DefaultTheme`
import { DefaultTheme } from '@tinacms/styles'
//2. Use `DefaultTheme` values in your styles
;<style jsx>{`
label {
color: ${DefaultTheme.color.primary.medium};
}
`}</style>