Schema UI é um projeto que fornece um 'schema' de configuração flexível e altamente personalizável para componentes customizados no VTEX IO. Utilizando React JSON Schema Form, este repositório facilita a criação de interfaces dinâmicas e adaptáveis dentro do ecossistema VTEX.
✅ Definição clara de types para cada propriedade
✅ Uso de widgets personalizados para melhorar a experiência de edição
✅ Implementação de dependencies e oneOf para configurações condicionais
✅ Suporte a uploads, seleções, datas, arrays e muito mais
- Clone o repositório:
git clone https://github.com/gblcintra/schema-ui.git
cd schema-ui- Instale as dependências:
yarn installnomeação de componentes na interface (store\interfaces.json)
"schema-ui": {
"component": "SchemaUi"
}...
{
"store.home": {
"title": "Home",
"blocks": [
"account.schema-ui:schema-ui",
...
]
},
...
}- Adicione o aplicativo Login às dependências do seu tema no arquivo
manifest.json:
"dependencies": {
+ "account.schema-ui": "0.x"
}O SchemaUi suporta diferentes widgets para renderização dinâmica de campos. Alguns dos principais incluem:
| Widget | Tipo | Descrição |
|---|---|---|
ui:widget: textarea |
string |
Caixa de texto multilinhas. |
ui:widget: color |
string |
Campo para seleção de cores. |
ui:widget: password |
string |
Input de senha com máscara. |
ui:widget: date |
string |
Campo de seleção de data. |
ui:widget: datetime |
string |
Campo de seleção de data e hora. |
ui:widget: range |
number |
Slider de seleção de números. |
ui:widget: image-uploader |
string |
Upload de imagens. |
ui:widget: select |
string |
Caixa de seleção suspensa. |
ui:widget: radio |
string |
Botões de opção (radio buttons). |
ui:field |
({ schema }: any) => {} |
Permite a criação de componentes personalizados para exibir um campo específico. |
ui:placeholder |
string |
Define um texto de exemplo dentro do campo de entrada para orientar o usuário. |
ui:inputType |
string |
Define o tipo de entrada de um campo de texto, como password, email, tel, etc. |
ui:help |
string |
Adiciona uma dica abaixo do campo para fornecer mais contexto ao usuário. |
ui:options |
object |
Permite configurações adicionais para widgets específicos. |
ui:disabled |
boolean |
Desabilita um campo para impedir que ele seja editado pelo usuário. |
ui:readonly |
boolean |
Deixa o campo somente leitura, permitindo que os usuários vejam o conteúdo, mas não façam alterações. |
classNames |
boolean |
Permite adicionar classes CSS personalizadas aos campos para melhor estilização. |
A configuração do schema proporciona flexibilidade através da utilização de vários tipos de dados para configurar elementos da IU. Estes tipos de dados podem ser utilizados para estilizar e definir o comportamento de diferentes componentes, quer se trate de introdução de texto, imagens, datas, cores ou menus pendentes de seleção.
| Type | Descrição |
|---|---|
String |
Usado para campos de texto, URL, imagem ou data. |
Boolean |
Uma opção de alternância simples para ativar/desativar recursos. |
Object |
Define objetos aninhados e suas propriedades. |
Array |
Usado para repetir grupos de itens, como imagens, formulários ou vários campos. |
| Propriedade | Tipo | Descrição |
|---|---|---|
titleItem |
string |
Define o título do bloco exibido. |
activeItem |
boolean |
Determina se o componente deve ser exibido. |
textProps |
object |
Propriedades relacionadas a campos de texto. |
dataProps |
object |
Propriedades relacionadas a seleção de datas. |
selectProps |
object |
Propriedades relacionadas a seleções e listas suspensas. |
colorProps |
object |
Configuração de cores para o componente. |
arrayItem |
array |
Lista de itens dentro de um array. |
Campo Null
| Propriedade | Tipo | Descrição |
|---|---|---|
fieldNull |
null |
Texto de exibição, pode ser utilizado para explicações. |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
fieldNull: {
title: "Texto com type Null",
type: "null",
description: "Campos nulos como este são ótimos para adicionar informações extras",
widget: {
'ui:field': ({ schema }: any) => {
return <h4 className="ma0 f5 near-black">{schema?.description}</h4>;
},
},
},
}
}Campos de texto
| Propriedade | Tipo | Descrição |
|---|---|---|
titleItem |
string |
Texto de exibição. |
passwordItem |
string |
Campo de senha. |
descriptionItem |
string |
Campo de textarea para descrição. |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
titleItem: {
type: 'string',
title: 'Título PlaceHolder',
description: 'Insira o texto que será exibido no botão.',
minLength: 10,
widget: {
'ui:widget': 'text',
'ui:placeholder': 'Ex.: Teste',
},
},
passwordItem: {
type: 'string',
title: 'Senha',
widget: {
'ui:inputType': 'password',
"ui:help": "Dica: Faça com que seja forte!"
},
},
descriptionItem: {
type: "string",
title: "Bio",
widget: {
"ui:widget": "textarea",
"ui:options": {
"rows": 5
}
}
},
}
}Campos de data
| Propriedade | Tipo | Descrição |
|---|---|---|
dataItem |
string |
Data no formato YYYY-MM-DD. |
dataTimeItem |
string |
Data e hora no formato ISO 8601. |
altDatetime |
string |
Data e hora com opções alternativas. |
altDate |
string |
Data alternativa com formato configurável. |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
dataItem: {
type: 'string',
title: 'Data',
format: 'date',
widget: {
'ui:widget': 'date',
},
},
dataTimeItem: {
type: 'string',
title: 'Data Time',
format: 'date-time',
widget: {
'ui:widget': 'datetime',
},
},
altDatetime: {
type: "string",
format: "date-time",
widget: {
"ui:widget": "alt-datetime",
"ui:options": {
"yearsRange": [
2023,
2030
],
"format": "MDY"
},
},
},
altDate: {
type: "string",
format: "date",
widget: {
"ui:widget": "alt-date",
"ui:options": {
"yearsRange": [
2023,
2030
],
"format": "MDY"
},
},
},
}
}O esquema também suporta a divisão de propriedades em grupos específicos utilizando categorias como textProps, dataProps, selectProps, colorProps e restrictProps para organizar e melhorar a interface do utilizador.
| Propriedade | Tipo | Descrição |
|---|---|---|
selectItem |
string |
Seleção de cor com valores predefinidos. |
colorItem |
string |
Cor do título (exemplo: #ff0000). |
toogleItem |
boolean |
Ativador. |
radioItem |
string |
Seleção de opção com valores predefinidos com opção radio. |
reference |
string |
Referência a uma definição global (enum). |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
definitions: {
largeEnum: {
enum: [
"option #0",
"option #1",
"option #2",
"option #3",
"option #4",
"option #5",
]
},
},
properties: {
selectItem: {
title: 'Seleção de Cor',
type: 'string',
default: '#000',
enumNames: ['Preto', 'Branco'],
enum: ['#000', '#fff'],
description: 'Por default a cor vem "Preto"',
widget: {
'ui:widget': 'select'
}
},
colorItem: {
title: 'Cor do titulo',
type: 'string',
widget: {
'ui:widget': 'color',
},
default: '#666',
description: 'Selecione a cor do texto principal do bloco',
},
toggleItem: {
title: 'Ativar Item',
type: 'boolean',
default: true,
},
radioItem: {
title: 'Escolha uma opção radio',
type: 'string',
enum: ['Opção 1', 'Opção 2', 'Opção 3'],
widget: {
'ui:widget': 'radio'
}
},
reference: {
type: 'string',
title: 'Seleção usando definitions como referencia',
$ref: "#/definitions/largeEnum"
},
}
}Restringir campos (ocultos, desativados ou só de leitura)
| Propriedade | Tipo | Descrição |
|---|---|---|
secret |
string |
Texto de exibição invisível no site editor. |
disabledItem |
string |
Texto de não editável no site editor. |
readonlyItem |
string |
Texto de exibição somente leitura no site editor. |
readonlyItem2 |
string |
Texto de exibição somente leitura no site editor. |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
secret: {
type: "string",
default: "Invisivel string.",
widget: {
"ui:widget": "hidden"
},
},
disabledItem: {
type: 'string',
title: 'Campo Desabilitado',
widget: {
'ui:disabled': true,
},
default: 'desabilitado',
},
readonlyItem: {
type: 'string',
title: 'Campo somente Leitura',
widget: {
'ui:readonly': true,
},
default: 'somenteLeitura',
},
readonlyItem2: {
type: 'string',
title: 'Campo somente Leitura 2',
readOnly: true,
default: 'somenteLeitura2',
},
}
}Campo de cadastro de itens utilizando array
| Propriedade | Tipo | Descrição |
|---|---|---|
title |
string |
Texto de exibição com placeholder |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
arrayItem: {
type: 'array',
title: "Array de Itens",
maxItems: 5, // máximo de itens que podem ser cadastrado em um array
widget: {
classNames: 'bg-washed-yellow ba b--light-gray ph3 mb3',
'ui:options': {
addable: true, // False ele Impede de adicionar Itens
removable: false, // false ele Impede de apagar o item
}
},
items: {
type: 'object',
title: "Item Array",
widget: {
classNames: 'bg-washed-yellow ba b--light-gray ph3 mb3'
},
properties: {
__editorItemTitle: {
title: 'Identificação do Item',
default: 'Item',
description: 'Max 15 caracteres',
type: 'string',
},
title: {
type: 'string',
title: 'Titulo Teste',
widget: {
'ui:placeholder': 'Ex.: Teste',
},
description: '**Preenchimento Obrigatório**',
},
},
},
},
}
}Campo de upload de Imagens
| Propriedade | Tipo | Descrição |
|---|---|---|
uploadItem |
string |
Carregamento de imagem |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
uploadItem: {
type: 'string',
title: 'Upload de Imagem',
widget: {
'ui:widget': 'image-uploader',
classNames: 'bg-white-30 ba b--light-gray ph3 mb3',
},
},
}
}Campo de upload de arquivos
| Propriedade | Tipo | Descrição |
|---|---|---|
uploadFile |
string |
Carregamento de arquivos |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
uploadFile: {
type: 'string',
title: 'Envie um arquivo',
widget: {
'ui:widget': 'file'
}
},
}
}Certas configurações podem ser mostradas condicionalmente com base no estado de outros campos. Por exemplo, um campo showMoreConfig revelará campos adicionais como numberItem quando ativado.
| Propriedade | Tipo | Descrição |
|---|---|---|
numberItem |
number |
Numero de exibição |
numberIntegerItem |
integer |
Numero de exibição com seletor tipo barra range |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
showMoreConfig: {
title: 'Mostrar mais Configurações com dependencies',
type: 'boolean',
enum: [true, false],
widget: {
classNames: 'bg-black-30 ba b--light-gray ph3 mb3',
},
},
},
dependencies: {
showMoreConfig: {
oneOf: [
{
properties: {
showMoreConfig: {
enum: [true],
title: 'Mostrar mais Configurações',
type: 'boolean',
widget: {
classNames: 'bg-danger--faded ba b--light-gray ph3 mb3',
}
},
numberItem: {
title: 'Campo de Numero',
type: 'number',
default: 8,
description: 'Esse campo é apenas para números'
},
numberIntegerItem: {
title: 'Campo de Numero Inteiro Com Range',
type: 'integer',
default: 10,
minimum: 10,
maximum: 100,
multipleOf: 10,
widget: {
"ui:widget": "range",
}
},
},
},
],
},
},
} type OnChange = (val: any) => void
type RegisteredComponent<P = any> = ComponentType<P> & {
SchemaField?: {
defaultProps?: {
autoFocus?: boolean
disabled?: boolean
registry?: Registry
readonly?: boolean
uiSchema?: {
'ui:widget'?: string
}
formData?: string
name?: string
onChange?: OnChange
}
}
}
interface Registry {
[key: string]: RegisteredComponent
}O widgetCustomUploadImage é um widget customizado que encapsula o image-uploader padrão do Site Editor, permitindo:
- Controle total sobre a renderização
- Customização de layout
- Encapsulamento de lógica adicional
- Reutilização estruturada via
registryEle utiliza oSchemaFieldinterno do rjsf-team no projeto react-jsonschema-form para manter compatibilidade total com o ecossistema do schema.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomUploadImage |
string |
Campo de upload de imagem utilizando widget customizado |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomUploadImage: {
type: 'string',
title: 'Widget Upload Customizado',
widget: {
'ui:widget': ({
schema,
value,
onChange,
registry,
}: { schema: any, value: any, onChange: OnChange, registry: Registry }) => {
const SchemaField = registry.fields.SchemaField as RegisteredComponent
return (
<div className="custom-widget">
<SchemaField
name="imageChoice"
schema={{
type: 'string',
title: schema.title,
}}
uiSchema={{
'ui:widget': 'image-uploader',
}}
formData={value || ''}
registry={registry}
onChange={(url: string) => onChange(url)}
/>
</div>
)
}
},
}
}
}- O widget intercepta as props padrão do RJSF:
schemavalueonChangeregistry
- Recupera o
SchemaFieldviaregistry.fields. - Renderiza internamente um campo padrão do tipo
string. - Injeta o widget
image-uploader. - Repassa o valor para o formulário via
onChange.
Use widgetCustomUploadImage quando precisar:
- Adicionar layout customizado ao upload
- Incluir validações adicionais
- Adicionar preview customizado
- Encapsular regras de negócio
- Criar múltiplos comportamentos reaproveitáveis
| image-uploader padrão | widgetCustomUploadImage |
|---|---|
| Uso direto | Uso encapsulado |
| Sem lógica adicional | Permite lógica custom |
| Layout padrão | Layout customizável |
O widgetCustomText é um widget customizado que encapsula o text padrão do Site Editor, permitindo:
- Controle total sobre a renderização
- Customização de layout
- Uso dinâmico de
descriptioncomo placeholder - Encapsulamento de lógica adicional
- Reutilização estruturada via
registry
Ele utiliza o SchemaField interno do rjsf-team no projeto react-jsonschema-form para manter compatibilidade total com o ecossistema do schema.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomText |
string |
Campo de texto utilizando widget customizado |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomText: {
type: 'string',
title: 'Widget Texto Customizado',
description: 'Esse é um exemplo de widget customizado para um campo de texto.',
widget: {
'ui:widget': ({
schema,
value,
onChange,
registry,
}: { schema: any, value: any, onChange: OnChange, registry: Registry }) => {
const SchemaField = registry.fields.SchemaField as RegisteredComponent
return (
<div className="custom-widget">
<SchemaField
name="textChoice"
schema={{
type: 'string',
title: schema.title,
}}
uiSchema={{
'ui:widget': 'text',
'ui:placeholder': schema.description,
}}
formData={value || ''}
registry={registry}
onChange={(value: string) => onChange(value)}
/>
</div>
)
}
},
}
}- O widget intercepta as props padrão do RJSF:
schemavalueonChangeregistry
- Recupera o
SchemaFieldviaregistry.fields. - Renderiza internamente um campo padrão do tipo
string. - Injeta o widget
text. - Define dinamicamente o
placeholderutilizandoschema.description. - Repassa o valor para o formulário via
onChange.
Use widgetCustomText quando precisar:
- Controlar dinamicamente o placeholder
- Adicionar layout customizado ao input
- Incluir validações adicionais
- Adicionar preview customizado
- Encapsular regras de negócio
- Criar múltiplos comportamentos reaproveitáveis
| text padrão | widgetCustomText |
|---|---|
| Uso direto | Uso encapsulado |
| Placeholder fixo via uiSchema | Placeholder dinâmico via schema |
| Sem lógica adicional | Permite lógica custom |
| Layout padrão | Layout customizável |
O widgetCustomSelect é um widget customizado que encapsula o select padrão do Site Editor, permitindo:
- Carregamento dinâmico de opções via API
- Cache em memória para evitar múltiplas requisições
- Controle total da renderização
- Encapsulamento de lógica assíncrona
- Reutilização estruturada via
registry
Ele utiliza o SchemaField interno do rjsf-team no projeto react-jsonschema-form para manter compatibilidade total com o ecossistema do schema.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomSelect |
string |
Campo select com opções carregadas dinamicamente via API |
let cachedNames: string[] | null = null
let isFetching: boolean = false
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomSelect: {
type: 'string',
title: 'Widget Select Customizado',
widget: {
'ui:widget': ({
schema,
value,
onChange,
registry
}: { schema: any, value: any, onChange: OnChange, registry: Registry }) => {
const SchemaField = registry.fields.SchemaField as RegisteredComponent
if (!cachedNames && !isFetching) {
isFetching = true
fetch('/api/catalog_system/pub/category/tree/2')
.then(res => res.json())
.then((data: any[]) => {
cachedNames = data.map(i => i.name).slice(0, 5)
isFetching = false
// força re-render do RJSF
onChange(value)
})
.catch((err) => {
cachedNames = []
isFetching = false
})
}
const options =
cachedNames === null
? ['Carregando...']
: (cachedNames as string[]).length
? cachedNames
: ['Sem opções']
return (
<div className="custom-widget">
<SchemaField
name="selectChoice"
schema={{
type: 'string',
title: schema.title,
enum: options
}}
uiSchema={{
'ui:widget': 'select',
}}
formData={value || ''}
registry={registry}
onChange={(option: string) => onChange(option)}
/>
</div>
)
},
},
},
}- O widget intercepta as props padrão do RJSF:
schemavalueonChangeregistry
- Utiliza variáveis externas (
cachedNameseisFetching) para:
- Evitar múltiplas requisições simultâneas
- Manter cache em memória
- Melhorar performance
- Realiza requisição para:
/api/catalog_system/pub/category/tree/2
- Mapeia os nomes retornados e limita os resultados (ex:
slice(0, 5)). - Atualiza o enum dinamicamente no
SchemaField. - Força re-render via
onChangeapós carregamento.
| Estado | Resultado no Select |
|---|---|
| null | "Carregando..." |
| Array vazio | "Sem opções" |
| Array populado | Lista dinâmica |
Use widgetCustomSelect quando precisar:
- Popular selects via API externa
- Trabalhar com dados dinâmicos do VTEX
- Evitar múltiplas requisições desnecessárias
- Criar comportamento inteligente com cache
- Encapsular lógica assíncrona dentro do schema
| select padrão | widgetCustomSelect |
|---|---|
| Enum fixo | Enum dinâmico |
| Sem fetch | Com fetch API |
| Sem cache | Cache em memória |
| Render simples | Render inteligente |
O widgetCustomRange encapsula um input type="range" dentro do Schema, permitindo:
- Controle visual em tempo real do valor selecionado
- Experiência interativa estilo slider
- Customização total da UI
- Integração direta com o ciclo de vida do RJSF
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomRange |
number |
Campo range customizado com slider interativo |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomRange: {
type: 'number',
title: 'Widget Range Customizado',
widget: {
'ui:widget': ({
value,
onChange,
}: { value: any, onChange: OnChange }) => {
return (
<div className="custom-widget">
<span className="db mb2">Valor: {value || 0}</span>
<input
type="range"
className="w-100"
min="0"
max="100"
value={value || 0}
onChange={(e) => onChange(Number(e.target.value))}
/>
<div className="flex justify-between">
<span>0</span>
<span>50</span>
<span>100</span>
</div>
</div>
)
}
},
}
}- Recebe
valueeonChangedo RJSF. - Renderiza um
input type="range"controlado. - Converte
string→numberantes de propagar. - Exibe o valor atual acima do slider.
| Estado | Resultado |
|---|---|
undefined |
Assume 0 |
| Número válido | Atualiza slider dinamicamente |
- Ajuste de volume, porcentagem ou intensidade
- Configurações numéricas graduais
- UX mais intuitiva que
input number
| Range padrão | widgetCustomRange |
|---|---|
| Sem preview visual | Exibe valor em tempo real |
| Estilização limitada | Total controle de UI |
| Sem marcações | Marcações personalizadas |
Sistema de avaliação por estrelas (1 a 5).
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomRating |
number |
Campo de avaliação por estrelas (1–5) |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomRating: {
type: 'number',
title: 'Widget Rating Customizado',
widget: {
'ui:widget': ({
value,
onChange,
}: { value: any, onChange: OnChange }) => {
const stars = [1, 2, 3, 4, 5]
return (
<div className="custom-widget">
<div className="flex justify-center">
{stars.map(star => (
<span
key={star}
className={`f2 pointer ${value >= star ? 'yellow' : 'gray'}`}
onClick={() => onChange(star)}
>
★
</span>
))}
</div>
</div>
)
}
},
}
}- Define um array fixo
[1–5]. - Compara
value >= starpara aplicar estilo ativo. - Atualiza o valor ao clicar.
- Mantém compatibilidade com tipo
number.
| Estado | Resultado |
|---|---|
undefined |
Nenhuma estrela ativa |
| 1–5 | Estrelas preenchidas até o valor |
- Avaliação de produto
- Feedback interno
- Sistema de ranking
| Select padrão | widgetCustomRating |
|---|---|
| Lista textual | Interface visual |
| UX simples | Experiência interativa |
| Menos intuitivo | Feedback imediato |
Seletor visual de cores.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomColorPicker |
string |
Campo seletor visual de cores |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomColorPicker: {
type: 'string',
title: 'Widget Color Picker Customizado',
widget: {
'ui:widget': ({
value,
onChange,
}: { value: any, onChange: OnChange }) => {
const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff']
return (
<div className="custom-widget">
<div className="flex justify-between">
{colors.map(color => (
<div
key={color}
className={`w2 h2 pointer mr2 ${value === color ? 'ba b--black' : ''}`}
style={{ backgroundColor: color }}
onClick={() => onChange(color)}
/>
))}
</div>
</div>
)
}
},
}
}- Define array fixo de cores.
- Aplica borda na cor selecionada.
- Retorna valor hexadecimal (
string).
| Estado | Resultado |
|---|---|
undefined |
Nenhuma cor ativa |
| Hex válido | Cor marcada |
- Configuração de tema
- Escolha de cor principal
- Personalização visual
| Select padrão | widgetCustomColorPicker |
|---|---|
| Texto | Representação visual |
| Não intuitivo para cores | Visual imediato |
| UX básica | UX moderna |
Campo de texto multilinha customizado.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomTextArea |
string |
Campo de texto multilinha custom |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomTextArea: {
type: 'string',
title: 'Widget TextArea Customizado',
widget: {
'ui:widget': ({
schema,
value,
onChange,
}: { schema: any, value: any, onChange: OnChange }) => {
return (
<div className="custom-widget">
<textarea
className="w-100 pa2"
placeholder={schema.description}
value={value || ''}
onChange={(e) => onChange(e.target.value)}
/>
</div>
)
}
},
}
}- Recebe
schema.descriptioncomo placeholder. - Controla valor via
onChange. - Trabalha como campo controlado React.
| Estado | Resultado |
|---|---|
undefined |
Campo vazio |
| String preenchida | Atualização dinâmica |
- Descrições longas
- Observações
- Campos narrativos
| Textarea padrão | widgetCustomTextArea |
|---|---|
| Sem customização | Total controle de layout |
| Placeholder fixo | Dinâmico via schema |
Checkbox customizado.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomCheckbox |
boolean |
Campo boolean customizado |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomCheckbox: {
type: 'boolean',
title: 'Widget Checkbox Customizado',
widget: {
'ui:widget': ({
schema,
value,
onChange,
}: { schema: any, value: any, onChange: OnChange }) => {
return (
<div className="custom-widget">
<label className="flex items-center">
<input
type="checkbox"
checked={value || false}
onChange={(e) => onChange(e.target.checked)}
/>
<span className="ml2">{schema.title}</span>
</label>
</div>
)
}
},
}
}- Trabalha com tipo
boolean. - Usa
checked={value || false}. - Propaga
e.target.checked.
| Estado | Resultado |
|---|---|
false |
Desmarcado |
true |
Marcado |
- Flags de ativação
- Habilitar/desabilitar recursos
| Checkbox padrão | widgetCustomCheckbox |
|---|---|
| Layout simples | Layout customizado |
| Sem controle visual extra | Integração estilizada |
Grupo de radio buttons customizado.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomRadio |
string |
Campo de seleção única via radio |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomRadio: {
type: 'string',
title: 'Widget Radio Customizado',
enum: ['Opção A', 'Opção B', 'Opção C'],
widget: {
'ui:widget': ({
schema,
value,
onChange,
}: { schema: any, value: any, onChange: OnChange }) => {
return (
<div className="custom-widget">
{schema.enum.map((option: string) => (
<label key={option} className="flex items-center mb2">
<input
type="radio"
name={schema.title}
value={option}
checked={value === option}
onChange={() => onChange(option)}
/>
<span className="ml2">{option}</span>
</label>
))}
</div>
)
}
},
}
}- Itera sobre
schema.enum. - Compara
value === option. - Atualiza via
onChange(option).
| Estado | Resultado |
|---|---|
undefined |
Nenhuma opção selecionada |
| String válida | Radio ativo |
- Escolhas exclusivas
- Modos de operação
| Radio padrão | widgetCustomRadio |
|---|---|
| Render automático | Controle manual |
| Estilização limitada | Total customização |
Seleção múltipla via checkboxes.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomMultiSelect |
array |
Campo de seleção múltipla custom |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomMultiSelect: {
type: 'array',
title: 'Widget MultiSelect Customizado',
items: {
type: 'string',
enum: ['Opção 1', 'Opção 2', 'Opção 3', 'Opção 4', 'Opção 5'],
},
widget: {
'ui:widget': ({
schema,
value,
onChange,
}: { schema: any, value: any, onChange: OnChange }) => {
const options = schema.items.enum || []
return (
<div className="custom-widget">
{options.map((option: string) => (
<label key={option} className="flex items-center mb2">
<input
type="checkbox"
value={option}
checked={value?.includes(option)}
onChange={(e) => {
if (e.target.checked) {
onChange([...(value || []), option])
} else {
onChange(value.filter((v: string) => v !== option))
}
}}
/>
<span className="ml2">{option}</span>
</label>
))}
</div>
)
}
},
}
}- Trabalha com
type: array. - Adiciona/remover via spread operator.
- Controla estado via
value?.includes.
| Estado | Resultado |
|---|---|
[] |
Nenhuma opção |
| Array populado | Múltiplas opções ativas |
- Tags
- Categorias múltiplas
- Features habilitáveis simultaneamente
| Select multiple padrão | widgetCustomMultiSelect |
|---|---|
| Dropdown fechado | Visual direto |
| UX menos clara | Controle explícito |
| Difícil visualização total | Todas opções visíveis |
O widgetCustomWithCustomLogic demonstra como implementar lógica condicional personalizada dentro do próprio widget, alterando dinamicamente o conteúdo exibido com base no valor do campo.
Esse padrão permite encapsular comportamento inteligente diretamente no ui:widget, sem depender de lógica externa no componente principal.
| Propriedade | Tipo | Descrição |
|---|---|---|
widgetCustomWithCustomLogic |
string |
Campo de texto com renderização condicional baseada no valor digitado |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
widgetCustomWithCustomLogic: {
type: 'string',
title: 'Widget Custom Widget com Lógica Customizada',
description: 'Esse é um exemplo de widget customizado usando ui:widget que implementa lógica personalizada para exibir diferentes conteúdos com base no valor do input.',
widget: {
'ui:widget': ({ schema, value, onChange }: { schema: any, value: any, onChange: OnChange }) => {
return (
<div className="custom-widget">
<p className="mb2">{schema.description}</p>
<input
type="text"
className="w-100 pa2 mb3"
placeholder="Digite 'mostrar' para ver o conteúdo secreto"
value={value || ''}
onChange={(e) => onChange(e.target.value)}
/>
{value === 'mostrar' ? (
<div className="pa3 bg-green white">
Conteúdo Secreto Revelado!
</div>
) : (
<div className="pa3 bg-red white">
Digite 'mostrar' para revelar o conteúdo secreto.
</div>
)}
</div>
);
},
},
}
}- Recebe
schema,valueeonChangedo RJSF. - Exibe
schema.descriptiondinamicamente. - Controla o input como componente controlado (
value || ''). - Executa renderização condicional baseada em:
value === 'mostrar'
- Alterna entre dois blocos visuais com estilos distintos.
- Toda a lógica permanece encapsulada dentro do
ui:widget.
| Estado do Valor | Resultado Renderizado |
|---|---|
undefined |
Exibe bloco vermelho |
String diferente de 'mostrar' |
Exibe instrução para revelar conteúdo |
'mostrar' |
Exibe conteúdo secreto |
Use widgetCustomWithCustomLogic quando precisar:
- Aplicar regras condicionais dentro do próprio widget
- Exibir conteúdo dinâmico com base em input
- Criar experiências interativas no Site Editor
- Encapsular microcomportamentos sem poluir o componente principal
- Implementar validações ou revelações progressivas
| Text padrão | widgetCustomWithCustomLogic |
|---|---|
| Apenas input | Input + renderização condicional |
| Sem lógica visual | Lógica encapsulada no widget |
| Render estático | Render dinâmico |
| Sem feedback contextual | Feedback visual imediato |
Utiliza as classes do Tachyons para estilizar o bloco do site editor e deixa com a aparência mais agradável.
| Propriedade | Tipo | Descrição |
|---|---|---|
classNames |
string |
Classe Tachyons |
SchemaUi.schema = {
title: 'Configuração do schema',
type: 'object',
properties: {
classeItem: {
type: 'string',
title: 'Teste de Classe',
widget: {
+ classNames: 'bg-white-30 ba b--light-gray ph3 mb3',
},
},
}
}<SchemaUi
titleItem="Configuração Avançada"
activeItem={true}
textProps={{
titleItem: "Texto de Exemplo",
passwordItem: "segredo123",
descriptionItem: "Este é um campo de textarea."
}}
selectProps={{
selectItem: "#000",
reference: "option #2"
}}
colorProps={{
colorItem: "#ff0000"
}}
dataProps={{
dataItem: "2025-02-21",
dataTimeItem: "2025-02-21T15:00:00"
}}
/>📖 Documentação Para mais detalhes sobre a estrutura do schema, consulte a documentação oficial do rjsf.
Gabriel Cintra 💻 📖 🚧 🧑🏫 |
Sinta-se à vontade para contribuir com melhorias! Basta abrir uma issue ou pull request no repositório.
- Faça um fork do repositório.
- Crie uma branch para a sua feature (
git checkout -b feature/MinhaFeature). - Commit suas mudanças (
git commit -am 'Adiciona nova funcionalidade'). - Envie a branch para o repositório remoto (
git push origin feature/MinhaFeature). - Abra um Pull Request no GitHub.
Se você encontrou algum bug ou tem uma sugestão, abra uma issue ou um pull request!
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!






















