The template repository for the Store Framework course on Learning Lab.
danvitoriano / store-framework Goto Github PK
View Code? Open in Web Editor NEWHome Page: https://lab.github.com/vtex-trainings/store-framework
Home Page: https://lab.github.com/vtex-trainings/store-framework
Dando uma rápida olhada na sua loja atual, você conseguirá perceber que todos os componentes possuem estilos parecidos, mesmo que nenhuma customização tenha sido feita por você.
Todos eles, incluindo o Info Card recém configurado, compartilham valores pré-estabelecidos para fonte, cor de fundo, cor principal, formato dos botões, etc.
Isso se deve ao style.json
, arquivo responsável por declarar valores genéricos de customização para toda loja do Store Framework.
Para criar uma identidade própria para os componentes da sua loja, você pode sobrescrever esses valores por meio de customizações de CSS.
Analisando a recipe para customizações de loja por CSS, percebemos que alguns passos serão necessários para aplicar o estilo próprio desejado por você, como:
Criar um novo arquivo dentro da pasta CSS
com o nome vtex.{AppName}.css
Usar o CSS Handle do componente que será customizado dentro deste arquivo seguindo o formato abaixo:
.{CSSHandle} {
{PropriedadeDeCSS}: {ValorDesejado};
{PropriedadeDeCSS}: {ValorDesejado};
}
Na falta de CSS Handles, aplicar CSS Selectors permitidos, como é o caso do :global(vtex-{componentName})
.
Para aplicar CSS em um bloco específico e não a todos os blocos daquele tipo, usa-se o recurso de blockClass, que aparece ao lado dos handles de css ao inspecionar seu código. As blockClass devem ser declaradas como uma prop no bloco em questão, e então referenciado no arquivo de estilo como mostrado abaixo:
.{CSSHandle}--{blockClass} {
{PropriedadeDeCSS}: {ValorDesejado};
{PropriedadeDeCSS}: {ValorDesejado};
}
Para descobrir os CSS Handles de um componente, como o Info Card, basta acessar a sessão Customization
da sua documentação.
De acordo com a descrição dos CSS Handles e com a recipe customizações de loja por CSS, conseguimos implementar um exemplo de Info Card customizado, alterando seu título e as configurações do botão call to action ao adicionar o código a seguir no arquivo vtex.store-components.css
dentro de /styles/css
:
.infoCardHeadline {
font-family: serif;
font-size: 2.25rem;
font-weight: normal;
color: gray;
border: 2px solid black;
padding: 24px;
}
.infoCardCallActionContainer :global(.vtex-button) {
color: white;
background-color: gray;
border: transparent;
}
.infoCardCallActionContainer :global(.vtex-button):hover {
color: gray;
background-color: blue;
border: transparent;
}
Você pode conferir o efeito das mudanças feitas por você executando o comando vtex link
.
Em seguida, vamos adicionar um estilo específico para o infocard Vintage. Para começar, adicione a prop blockClass
no info-card#button-right
como mostrado abaixo:
"info-card#button-right": {
"props": {
"isFullModeStyle": false,
"textPosition": "right",
"imageUrl": "https://appliancetheme.vteximg.com.br/arquivos/cozinha-rosa-min.png",
"headline": "Vintage Pink",
"subhead": "Give your kitchen a boho style adding vintage apparels.<br>Available until January 2020.",
"callToActionMode": "button",
"callToActionText": "Explore",
"callToActionUrl": "/sale/d",
"textAlignment": "center",
"blockClass": "vintage" // <------------
}
}
E então declare uma background-color
para este infocard específico no seu arquivo de css:
.infoCardContainer--vintage {
background-color: #EDCFD1
}
Observe o efeito atingido linkando sua app.
vtex.store-components.css
, copie o código acima para usá-lo no arquivo CSS do seu tema, seguindo a recipe sobre customizações de loja por CSS;max-width
) de de todos os infocards para 1260px
, a margin para 0 auto
e o padding para 0
.black
;bold
);white
.vintage
, aplique um novo block class chamado metal
no infocard info-card#button-left
e aplique a cor de fundo #e1e1e1
nele.Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Neste passo, iremos aprender como criar um componente que é comumente visto como pouco relevante, mas que é fundamental para dar uma boa experiência ao usuário: o footer.
Poucos usuários chegam a scrollar até o footer. Porém, essa parcela que chega pode estar procurando informações que usualmente são abrigadas neste bloco, como links para mídias sociais e meios de pagamento aceitos pela loja. Ele também pode abrigar páginas customizadas que direcionam ao site de vagas da empresa, suporte ao cliente e menus de categorias.
FOTO Footer
O bloco do Footer, assim como o do header, é responsivo. Isso significa que ele pode ser configurado para se adaptar a diferentes dispositivos, como desktop e mobile.
Abaixo, podemos conferir um exemplo de implementação do Footer para desktop:
{
"footer": {
"blocks": ["footer-layout.desktop"]
},
"footer-layout.desktop": {
"children": [
"flex-layout.row#footer-1-desktop"
]
}
}
Agora, vamos configurar um footer para a página inicial da sua loja, levando em consideração o código exemplo apresentado acima para desktop e mobile.
Não implementaremos o menu nessa atividade, pois ele já foi visto no contexto do Header. Iremos cobrir os casos de meios de pagamento aceitos e redes sociais da loja.
No arquivo footer.jsonc
, copie o código acima para usá-lo no seu tema;
Declare o seguinte bloco em seguida:
"flex-layout.row#footer-1-desktop": {
"children": [
"flex-layout.col#footer-left-desktop",
"flex-layout.col#footer-right-desktop"
],
"props": {
"blockClass": "footer-row",
"paddingTop": 7,
"paddingBottom": 7
}
}
Com base no bloco acima, construa o flex-layout.col#footer-left-desktop
com a seguinte children: accepted-payment-methods
;
Agora construa o bloco accepted-payment-methods
com os seguintes meios de pagamento: MasterCard
, Visa
e Diners Club
. Só para mostrar um pouco mais de conhecimento, descubra também como mostrar os meios de pagamento em cores nesta documentação;
No próximo passo iremos usar o bloco social-networks
para mostrar as redes sociais da nossa loja. Veja na documentação como fazer isso. E implemente como children do bloco flex-layout.col#footer-right-desktop
. Nós queremos mostrar Facebook
, Instagram
e Twitter
.
Agora, faça os logos das redes sociais aparecerem com cores, como a documentação do footer menciona.
ℹ️ Lembre-se de acessar a documentação do Footer caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Uma loja precisa de uma boa home page para manter a atenção do usuário, aumentando o tempo de sessão e, portanto, aumentando as chances de conversão. Para que isso seja possível, vários elementos podem ser usados, como: banners promocionais, prateleiras de destaque, conteúdos institucionais.
Criaremos o próximo bloco na home page usando um Call to Action. No Store Framework, temos um bloco que serve para esse propósito chamado Info Card.
Com o Info Card, é possível criar imagens com links e botões (no topo ou na lateral do bloco) que direcionem o fluxo do usuário (Call to Action).
Olhando a documentação é possível ver que:
isFullModeStyle
define se o Call to Action (CTA) deve estar acima do banner;textPosition
definirá a posição do texto;textAlignment
definirá o alinhamento do texto;imageUrl
definirá qual imagem será usada como banner;headline
determinará qual o texto que será usado de título;callToActionMode
possibilitará a escolha do CTA como sendo um link ou um botão;callToActionText
definirá o texto do CTA;callToActionUrl
determinará o link ao qual será redirecionado;Ficamos, assim, com as seguintes props:
{
"store.home": {
"blocks": [
"rich-text",
"info-card"
]
},
"rich-text": {
"props": {
"text": "*Hello, World!*",
"textPosition": "RIGHT"
}
},
"info-card": {
"props": {
"isFullModeStyle": false,
"textPosition": "right",
"imageUrl": "https://appliancetheme.vteximg.com.br/arquivos/cozinha-rosa-min.png",
"headline": "Vintage Pink",
"subhead": "Give your kitchen a boho style adding vintage apparels.<br>Available until January 2020.",
"callToActionMode": "button",
"callToActionText": "Explore",
"callToActionUrl": "/sale/d",
"textAlignment": "center"
}
}
}
Pode ser que você tenha se perguntado:
"E se eu quiser ter dois Info Cards com aparências diferentes?"
Isso é possível através da instanciação de blocos.
Todos os blocos têm nomes preestabelecidos, mas você pode criar instâncias deles e definir aparências diferentes para um mesmo tipo de bloco. Para fazer isso, basta colocar um #
com um nome arbitrário e que faça sentido depois da definição de cada bloco, por exemplo:
{
"store.home": {
"blocks": [
"rich-text",
"info-card#button-right"
]
},
...
"info-card#button-right": {
"props": {
"isFullModeStyle": false,
"textPosition": "right",
"imageUrl": "https://appliancetheme.vteximg.com.br/arquivos/cozinha-rosa-min.png",
"headline": "Vintage Pink",
"subhead": "Give your kitchen a boho style adding vintage apparels.<br>Available until January 2020.",
"callToActionMode": "button",
"callToActionText": "Explore",
"callToActionUrl": "/sale/d",
"textAlignment": "center"
}
}
}
ATENÇÃO: Durante o curso serão vistos vários
...
, essa parte não deve ser copiada e representa o progresso de steps anteriores
A partir do código acima, no arquivo home.jsonc
, crie o info-card#button-left
logo abaixo do infocard info-card#button-right
. Este novo infocard deve possuir:
Shining chrome
Go to Collection
no lugar do botaohttps://appliancetheme.vteximg.com.br/arquivos/cozinha-cinza-min.png
Give your kitchen a cool style adding warm metallic finishes.<br>Available until January 2020.
textPosition
).O resultado esperado é semelhante ao apresentado na imagem abaixo:
ℹ️ Lembre-se de acessar a documentação do Info Card caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
O Slider Layout, como o Flex Layout, é uma forma flexível de criar um novo bloco a partir de outros blocos usando children
. Ele permite que sejam criados sliders de outros blocos, como info-card
s e até mesmo flex-layout
s por exemplo.
Vamos utilizar o Slider Layout para tornar um conjunto de info-cards em um slider.
Analisando a documentação, vemos que você pode utilizar qualquer array de blocos como children
, assim como no Flex Layout.
Abaixo, segue um exemplo de implementação de um slider-layout com dois info-card
:
"slider-layout#home": {
"children": ["info-card#1", "info-card#2"],
"props": {
"autoplay": {
"timeout": 5000,
"stopOnHover": false
}
}
},
"info-card#1": {
"props": {
"imageUrl": "https://images.unsplash.com/photo-1524185962737-ea7c028a12cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
"isFullModeStyle": true,
"headline": "Black Friday",
"callToActionText": "Subscribe",
"textPosition": "center"
}
},
"info-card#2": {
"props": {
"imageUrl": "https://images.unsplash.com/photo-1524185962737-ea7c028a12cd?ixlib=rb-1.2.1&auto=format&fit=crop&w=1350&q=80",
"isFullModeStyle": true,
"headline": "Black Friday",
"callToActionText": "Subscribe",
"textPosition": "center"
}
}
Nesta atividade, vamos criar um slider de marcas para o nosso site:
No arquivo home.jsonc
, declare o bloco slider-layout#home
ao template store.home
.
Crie um arquivo chamado slider-layout.jsonc
dentro da pasta /store/blocks
;
Neste arquivo, baseando-se no código acima, substitua os info-card
declarados como children de slider-layout#home
e adicione 6 componentes de imagem image
como children. Utilize o formato image#brand1
, image#brand2
(...) image#brand6
para declarar os componentes;
Declare uma prop src
específica para cada image#brand
definido. Utilize as URLs abaixo para cada uma delas:
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square1.png
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square2.png
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square3.png
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square4.png
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square5.png
https://appliancetheme.vteximg.com.br/arquivos/flatflat-brand-logo-square6.png
Por fim, você deve utilizar a propriedade de autoplay
no bloco slider-layout#home
. Faça com que o slide aconteça automaticamente a cada 7 segundos e que ele pare quando o usuário passar o mouse em cima do slide.
ℹ️ Lembre-se de acessar a documentação do Slider Layout e Image caso tenha alguma dúvida durante a atividade.
Com o Header já configurado e implementado, vamos agora adicionar nele o Menu.
A configuração do Menu é um passo importante na construção do tema, pois é ele o bloco é responsável pela navegação do usuário na sua loja.
Por conta da sua função e relevância, o Menu possui uma estrutura hierárquica complexa, envolvendo Menu Items, Submenus e, a partir desse último, qualquer bloco do Store Framework (como outros Menus e Menu Items).
Abaixo, você pode conferir uma imagem exemplificando a estrutura do bloco Menu na prática:
Se comparada com as de alguns blocos, a configuração do Menu pode parecer mais difícil por conta da sua estrutura de menus, itens de menu e submenus.
Mas o Menu não necessariamente precisa ser configurado seguindo esse cenário mais complexo.
Abaixo, podemos conferir um exemplo de implementação básica do bloco, contendo apenas 3 Menu Items:
{
"[email protected]:menu#categories": {
"children": [
"menu-item#major-appliances",
"menu-item#small-appliances",
"menu-item#electronics"
],
"props":{
"orientation": "horizontal"
}
}
},
Nesta atividade, entenderemos melhor sobre a configuração do Menu e a hierarquia existente dentro dele a partir da construção de Menu Items e Submenus.
No arquivo header.jsonc
, adicione header-row#menu
como o último item na lista de children do bloco header-layout.desktop
(configurado na [atividade anterior]) para que o Menu possa ser renderizado pelo Header da loja;
Copie e cole o código abaixo para declarar o bloco header-row#menu
:
"header-row#menu": {
"children": [
"header-spacer",
"[email protected]:menu#categories",
"header-spacer"
]
},
Também precisamos nos preocupar com Menu no layout de outros dispositivos, como mobile. Por isso, adicione drawer
como a primeira de children do bloco header-row#main-mobile
;
Cole o código abaixo no arquivo menu.jsonc
para renderizar horizontalmente os 3 itens do seu Menu principal:
{
"[email protected]:menu#categories": {
"children": [
"menu-item#major-appliances",
"menu-item#small-appliances",
"menu-item#electronics"
],
"props":{
"orientation": "horizontal"
}
},
Como vimos na introdução, um Menu Item pode permitir a configuração de um Submenu dentro dele que, por sua vez, pode ter consigo outro Menu com Menu Items. Crie então o Submenu de Major Appliance, ainda no arquivo menu.jsonc
, de acordo com o exemplo abaixo:
"[email protected]:submenu#major":{
"children":[
"[email protected]:menu#major"
]
},
Seguindo o formato estabelecido pelo bloco [email protected]:menu#categories
, construa o Menu secundário de Major Appliances declarado no último passo no arquivo menu.jsonc
. Você deve definir vertical
como valor da prop orientation
e configurar os seguintes Menu Items na lista de children do bloco: menu-item#refrigerators
, menu-item#ovens
e menu-item#washers
;
Crie também o Submenu de Small Appliances:
"[email protected]:submenu#small":{
"children":[
"[email protected]:menu#small"
]
},
Construa agora o Menu secundário de Small Appliances no arquivo menu.jsonc
. Assim como feito para Major Appliance, você deve definir vertical
como valor da prop orientation
e configurar os seguintes Menu Items na lista de children do bloco: menu-item#mixers
, menu-item#toasters
e menu-item#coffee
;
Com base nos passos anteriores, faça o mesmo para Eletronics: crie o seu Submenu ([email protected]:submenu#electronics
) e Menu secundário. Depois, construa esse último com o mesmo valor de prop (vertical
) e configure o os seguintes Menu Items na lista de children do bloco: menu-item#cameras
, menu-item#laptops
e menu-item#tvs
.
ℹ️ Lembre-se de acessar a documentação do Menu caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
No step anterior, você pôde aprender um pouco mais sobre como criar um template customizado. É muito comum que, em cenários de promoção e datas comemorativas, seja necessário criar landing pages especiais.
Vimos que a busca infere o que precisa pelo contexto que está inclusa. Numa página customizada, no entanto, o contexto não existe e é preciso que se defina qual a query deve ser realizada para inferir os resultados. Tudo isso é possível através do search-result-layout.customQuery
.
A query schema é uma das props do search result custom query com ela é possível controlar a busca que a nossa landing page deverá fazer. Para saber todas as possibilidades da query schema, veja sua documentação aqui.
Defina uma rota nova (store.custom#landing
) no arquivo routes.json
;
"store.custom#landing": {
"path": "/landing"
}
Crie um novo arquivo na pasta de blocos chamado search-landing.jsonc
;
Crie um novo template custom store.custom#landing
;
Defina o bloco image
como um dos blocos desse template. Este bloco deve possuir props minWidth
de 100% e uma imagem a sua escolha.
Faça o mesmo com o search-result-layout.customQuery
:
{
"store.custom#landing": {
"blocks": [
"image#landingbanner",
"search-result-layout.customQuery"
]
}
}
Defina o bloco search-result-layout.customQuery
com prop de querySchema que:
ft
.Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Para o vídeo de setup do Mac, clique aqui
Antes de começar a botar a mão na massa e aprender mais sobre o Store Framework do VTEX IO, algumas configurações básicas precisam ser feitas por você, como:
Confira abaixo o passo a passo para cada uma dessas configurações:
Instale o Git no seu computador acessando o link abaixo e selecionando o software usado pelo seu computador (Windows, MAC ou Linux):
O Toolbelt é a ferramenta de linha de comando do VTEX IO. É ele quem permite a realização de qualquer atividade na plataforma, como criar um novo workspace de desenvolvimento, fazer login em uma conta VTEX, desenvolver novas apps, gerenciar as já existentes, etc.
Uma vez que o Toolbelt é quem estabelece a comunicação entre o desenvolvedor e a plataforma, você precisará dele para conseguir realizar todas as atividades propostas durante o curso do Store Framework.
npm i -g vtex
no seu terminal se você estiver trabalhando de um Windows e yarn global add vtex
no MAC;Você pode executar o comando vtex-v
(Windows) ou vtex
(MAC) para confirmar se a instalação do Toolbelt ocorreu como esperado.
Com a instalação concluída, o seu próximo passo deve ser logar em uma conta VTEX.
Execute o comando vtex login contaVTEX
no seu terminal, substituindo contaVTEX
pelo nome real da conta em que você deseja trabalhar. Por exemplo, vtex login appliancetheme
.
Uma vez logado, execute o comando vtex whoami
para confirmar em qual conta e workspace você está.
Workspaces nada mais são do que espaços de trabalho. Na plataforma do VTEX IO, as contas possuem três tipos principais de workspaces: master, de produção e desenvolvimento.
O próximo passo irá fazer com que um workspace de desenvolvimento seja criado para você, permitindo que as configurações feitas nas atividades do curso não alterem a versão final pública da loja.
vtex use nome-do-workspace
, substituindo nome-do-workspace
pelo nome desejado. Por exemplo, vtex use devworkspace
.Depois que seu workspace foi criado, você conseguirá acessá-lo a partir do link https://{workspace}--{conta}.myvtex.com
, substituindo {workspace}
e {conta}
pelo workspace criado anteriormente e pelo nome da conta, respectivamente. Por exemplo, https://devworkspace--appliancetheme.myvtex.com
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Com todas as configurações básicas concluídas, você está pronto pra começar o curso!
Além do css, que já foi aprendido anteriormente, o Store Framework oferece um outro tipo de customização de design, provida a partir do style.json
.
Todos os blocos do Store Framework se alavancam das mesmas definições semânticas de estilo, definidas usando o Tachyons. Na prática, isso significa que ao invés de precisar mudar todos os fundos de botões para usar a cor que se interessa, é necessário apenas redefinir a cor que um background
de uma action-primary
tem.
Customizações através do style.json
tendem a ter um impacto muito maior que através de css, pois, em geral, mantém a identidade visual da loja ao longo de todas as páginas sendo necessárias poucas mudanças. Por esse motivo, sempre que possível, essa ferramenta deve ser usada, evitando assim overhead de css desnecessário.
style.json
O styles/configs/style.json
pode ser confuso em primeiro momento, por conter todas as definições de estilo que todos os blocos visuais do Store Framework usam. No entanto, um bom fluxo para identificar que estilos mudar, é através da inspeção de elementos no browser.
Por exemplo, clique com o botão direito em cima de qualquer botão da loja aperte em inspecionar.
Observando a barra lateral no Chrome que abriu é possível ver uma série de definições, uma delas é a de cor do background do botão (#0f3e99):
Além dela, se você inspecionar no momento em que estiver somente passando o mouse em cima do botão, descobrirá a cor de hover (#072c75):
Se fizermos uma busca pelas ocorrências de ambas as cores no style.json
, as cores que descobrimos são, respectivamente, as usadas para action-primary
em hover-background
e background
, por exemplo. Isso nos dá uma ideia melhor de onde poderemos achar outras ocorrências dessa mesma definição.
Para descobrir definições semânticas de texto e quais campos são editáveis, o processo é o mesmo do anterior, podemos buscar atributos como tamanho da fonte, peso, família.
Em um cabeçalho nível 1, por exemplo, ao inspecionar descobrimos que seu tamanho foi definido como 3 rem.
style.json
, substitua todas as ocorrências das cores que encontramos, trocando:Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
No último passo aprendemos como fazer uma página de produto simples com seus itens mínimos, mas sabemos que o que fizemos está longe de ser uma página de produto ideal, colocaremos outros elementos que vemos com frequência nas páginas de produto de várias lojas.
Na nossa documentação é possível encontrar mais 30 blocos relacionados a produto. No começo do curso falamos sobre Shelf e seus blocos relacionados, além de na última seção termos visto outros 4 blocos. Neste passo veremos mais 4:
É importante que ao fim do curso, você tome um tempo para explorar nossos componentes, bem como as possibilidades de customização que se tem com estes.
Evolua a página de produto adicionando os outros 4 blocos listados acima da seguinte forma no arquivo product.jsonc
:
Defina um breadcrumb
logo no início antes da linha principal do produto;
"store.product": {
"children": [
"breadcrumb",
"flex-layout.row#main"
]
}
Defina o product-identifier.product
logo abaixo do product-name
;
Crie uma linha logo abaixo do preço com o sku-selector
e o product-quantity
como children;
{
...
"children": [
"product-price",
"flex-layout.row#qty-sku"
]
},
"flex-layout.row#qty-sku": {
"children": [
"sku-selector",
"product-quantity"
]
},
...
}
Defina shipping-simulator
logo abaixo da linha com o SKU Selector e o Product Quantity
ℹ️ Lembre-se de acessar a documentação do Breadcrumb, Product Identifier, Product Quantity e SKU Selector caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
A página inicial de um e-commerce é sempre o primeiro contato do cliente com a marca. Por isso, é comum que o lojista queira estabelecer uma comunicação direta com os seus usuários nesse momento estratégico da navegação.
No Store Framework, existem alguns componentes que atendem a esse cenário, como o Info Card visto nos passos anteriores e o Rich Text.
Como vimos no terceiro passo, o Rich Text é responsável por transformar textos em elementos HTML, com a grande vantagem de ler em Markdown. Isso dá ao componente a flexibilidade de aceitar diferentes estruturas de texto, permitindo ao lojista construir sua comunicação de forma mais clara e direta.
Assim como a sua funcionalidade, a configuração do Rich Text também é simples.
Da mesma forma que o "Hello, world!" foi feito, podemos montar um exemplo de implementação do bloco usando texto escrito em markdown. Por exemplo:
"rich-text": {
"props": {
"text": "# Your Coffee, Your Way \n ### New Coffee Makers Collection",
"textPosition": "CENTER",
"textAlignment": "CENTER"
}
},
Como falado anteriormente, o uso de Markdown permite flexibilidade ao componente. Mas, por outro lado, também pode fazer com que a sua renderização sofra alterações de acordo com o dispositivo usado pelo usuário.
Por exemplo: a frase acima ( # Your Coffee, Your Way \n ### New Coffee Makers Collection
) pode usar um markdown adequado para desktop, mas não necessariamente para mobile (cujo tamanho de tela é menor).
Para resolver esse cenário e tornar o componente mais adaptável a outros dispositivos, devemos usar o Responsive Layout.
Primeiramente devemos delcarar os blocos dentro do template store.home
:
"responsive-layout.desktop#desktop", "responsive-layout.mobile#mobile"
Em seguida devemos declarar esses blocos da seguinte forma:
...
"responsive-layout.desktop#desktop": {
"children": ["rich-text#desktop"]
},
"responsive-layout.mobile#mobile": {
"children": ["rich-text#mobile"]
},
"rich-text#desktop": {
"props": {
"text": "# Your Coffee, Your Way \n ### New Coffee Makers Collection",
"textPosition": "CENTER",
"textAlignment": "CENTER"
}
},
"rich-text#mobile": {
"props": {
"text": "# Your Coffee, Your Way \n ### New Coffee Makers Collection",
"textPosition": "CENTER",
"textAlignment": "CENTER"
}
}
Ao interpretar o código acima, perceba como duas configurações de Rich Text são construídas a partir do uso de responsive-layout.desktop#desktop
e responsive-layout.mobile#mobile
.
Nessa atividade, vamos brincar um pouco com o markdown do Rich Text e aprender a usá-lo com o componente Image. Tudo isso usando o Responsive Layout, é claro!
Adicione o código proposto acima no arquivo home.jsonc
e declare os blocos de responsive-layout
no template store.home
;
No rich-text#mobile
, altere o markdown da primeira frase para h3
e da segunda para h4
;
Adicione image#desktop
como children de responsive-layout.desktop#desktop
. Faça o mesmo com image#mobile
em responsive-layout.mobile#mobile
;
Declare os seguintes blocos de Image:
"image#desktop": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/arquivos/Responsive-Image-Desktop.jpg?q=1",
"link": {
"url": "/small-appliances/coffee-makers"
} ,
"alt": "Coffee Makers Collection"
}
},
"image#mobile": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/arquivos/Responsive-Image-Mobile.jpg?q=1",
"link": {
"url": "/small-appliances/coffee-makers"
} ,
"alt": "Coffee Makers Collection"
}
},
Analisando as props do componente Image, defina a largura máxima das duas imagens como 100%
.
ℹ️ Lembre-se de acessar a documentação do Responsive Layout caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Terminamos de implementar nossa página de produto e seguiremos para a página de busca. Ambas são muito similares no aspecto de terem blocos que são únicos desse contexto. Exploraremos esse bloco de forma desordenada nesse step, somente para entender seus comportamentos e seguiremos para melhorar o layout no próximo passo.
A store.search
, como os outros templates, também pode ser flexível. Para construir um layout único, é preciso usar um bloco chamado search-result-layout
.
{
"store.search": {
"blocks": ["search-result-layout"]
}
}
O search-result-layout
, por sua vez, deve receber três outros blocos:
search-result-layout.desktop
search-result-layout.mobile
search-not-found-layout
Como você já deve ter percebido, os dois primeiros definem qual layout será exibido no desktop e no mobile, respectivamente, e o terceiro define o layout da página de resultados não encontrados.
{
"store.search": {
"blocks": ["search-result-layout"]
},
"search-result-layout": {
"blocks": [
"search-result-layout.desktop",
"search-result-layout.mobile",
"search-not-found-layout"
]
}
}
No curso, focaremos na implementação do layout de desktop
A documentação de Search Result oferece uma boa referência dos blocos que podem ser usados no contexto de busca. Nesse step focaremos em tentar exibir os principais:
breadcrumb.search
);search-title.v2
);total-products.v2
);order-by.v2
);search-fetch-more
);search-fetch-previous
);filter-navigator.v3
);search-content
)Apesar de serem muitos, todos esses blocos são relativamente simples e funcionam muito bem sem muita necessidade de configurar suas props
.
Copie o código acima no arquivo search.jsonc
e defina uma search-result-layout.desktop
que tenha como filhos, nesta ordem:
breadcrumb.search
;search-title.v2
;total-products.v2
;order-by.v2
;search-fetch-previous
;search-content
;filter-navigator.v3
;search-fetch-more
.ℹ️ Lembre-se de acessar a documentação de Search Result caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Terminada a página inicial da nossa loja, começamos um novo template da loja: a página de produto. Páginas de produto são provavelmente o template que mais possuem blocos diferentes, o que as torna extremamente customizáveis e flexíveis.
Vamos então construir uma página de produto mínima, em que tenhamos somente o essencial:
A maioria dos blocos de produto, diferentemente dos de conteúdo, possuem um contexto ao qual estão inseridos. Tudo isso faz com que esses blocos sejam um pouco "plug-n-play": colocar um product-images
na página de produto, automaticamente redenrizará as imagens do produto da página, da mesma forma se faz com o preço e o nome.
Nada disso quer dizer, no entanto, que esses blocos são pouco customizáveis, conforme veremos adiante.
Construa uma página de produto usando os blocos product-images
, product-price
, product-name
e buy-button
no arquivo product.jsonc
declarado dentro da pasta store/blocks
. Esperamos que na estrutura tenhamos:
Uma linha na store.product
;
{
"store.product": {
"children": [
"flex-layout.row#main"
]
}
}
Dentro da linha devem haver duas colunas;
"flex-layout.row#main": {
"props": {
"marginTop": 6
},
"children": [
"flex-layout.col#left",
"flex-layout.col#right"
]
}
Dentro da coluna da esquerda deve haver um product-images
;
"flex-layout.col#left": {
"children": [
"product-images"
]
}
Dentro da coluna da direita deve haver o product-name
, product-price
e o buy-button
;
Além disso, queremos que:
verticalAlign
e preventVerticalStretch
na documentação de Flex Layout Column)product-price
mostre o total de economia e o preço de listagem (showSavings
e showListPrice
)ℹ️ Lembre-se de acessar a documentação do product-images
, product-price
, product-name
e buy-button
caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Antes de começarmos a colocar as mãos na massa vamos passar por alguns conceitos importantes que serão recorrentemente referenciados daqui pra frente.
O Store Framework é uma ferramenta commerce low-code de construção de frentes de loja únicas e customizadas.
O fluxo de construção se dá pela customização de um tema, que pode ser trabalhado em diferentes workspaces sem que o ambiente de produção seja impactado.
Um tema é, essencialmente, um arranjo de blocos e suas posições. Nele são definidas todas as customizações, posições e estilos de cada um dos blocos que o compõem. Também é possível declarar novas páginas em um tema que, futuramente, podem representar páginas institucionais ou landing pages promocionais (dia das mães, black friday, cyber monday). O resultado final de um tema e o conteúdo que o compõe é a frente de uma loja.
Os blocos são a abstração mínima no Store Framework. Eles declaram pequenas peças que compõem o layout de uma loja. Por mais que pareçam simples, os blocos tem alto poder de customização, fazendo com que design complexos sejam possíveis de ser alcançados. Há quatro níveis de customização para blocos:
Ambientes de trabalho protegidos que representam uma cópia bem próxima do está montado em produção, possibilitando a evolução de temas sem que nada na loja seja afetado.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Neste passo, aprenderemos a configurar o primeiro componente de toda loja: o Header.
O Header tem um papel muito importante na página inicial da loja, pois ele é o responsável por abrigar outros blocos essenciais para a navegação do usuário, como a barra de busca e o menu.
O bloco do Header é responsivo, ou seja, ele pode ser configurado para se adaptar a diferentes dispositivos, como desktop e mobile.
Abaixo, podemos conferir um exemplo de implementação:
{
"header": {
"blocks": [
"header-layout.desktop",
"header-layout.mobile"
]
},
"header.full": {
"blocks": [
"header-layout.desktop",
"header-layout.mobile"
]
},
"header-layout.desktop": {
"children": [
"header-row#notification",
"header-row#main"
]
},
"header-layout.mobile": {
"children": [
"header-row#notification",
"header-row#main-mobile",
"header-row#search"
]
},
}
Agora, vamos configurar do zero um Header para a página inicial da sua loja, com barra de notificação e busca, logo, carrinho e login. O Menu não será configurado nesse momento, pois trabalharemos com ele mais a fundo na próxima atividade.
Para a implementação do Header com todos esses blocos, levaremos em consideração o código exemplo apresentado acima. Assim, será possível construir um Header responsivo, adaptável para usuários de desktop e mobile.
Diferentemente do comportamento de outros blocos, o Header não precisa ser declarado dentro um template do seu tema, pois de toda forma ele será renderizado em todas as páginas da loja. Neste exercício, vamos declarar os blocos do header
no arquivo header.jsonc
, que deve ser criado na pasta store/blocks
.
Declare o seguinte bloco em seguida:
"header-row#notification": {
"children": [
"header-spacer",
"rich-text#header",
"header-spacer"
]
},
Com base no bloco acima, construa o header-row#main
com as seguintes children: logo
, header-spacer
, search-bar
, minicart
e login
;
Ainda no bloco header-row#main
, declare as props inverted
, sticky
e fullWidth
com os valores true
, true
e false
, respectivamente;
Copie e cole o código abaixo para configurar o bloco header para mobile, da mesma forma que fizemos para o desktop anteriormente:
"header-row#main-mobile": {
"children": [
"logo",
"header-spacer",
"minicart",
"login"
],
"props": {
"sticky": true,
"inverted":true
}
},
"header-row#search": {
"children": [
"search-bar"
],
"props": {
"sticky": true
}
},
Declare o bloco responsável por definir o login e o logo da loja, usando o código apresentado abaixo. Eles serão usados pelo Header dos dois dispositivos;
"login":{
"props": {
"showIconProfile": true,
"iconLabel": "Login"
}
},
"logo":{
"props": {
"url": "https://appliancetheme.vteximg.com.br/assets/vtex.file-manager-graphql/images/flatflat___6081e50402943bcb11bc45a8e613aa72.png"
}
},
Por último, precisamos declarar o componente principal da linha do Header de notificação ("header-row#notification"
): o Rich Text;
"rich-text#header": {
"props": {
"text": "**Free Shipping on orders over $50**",
"textPosition": "CENTER"
}
}
Seguindo a recipe sobre customizar ícones de loja, substitua o ícone padrão usado na barra de busca e no carrinho pelos exemplificados abaixo.
Novo ícone da barra de busca:
<path fill="currentColor" d="M4,13H1c-0.552,0-1-0.448-1-1v0c0-0.552,0.448-1,1-1h3V13z"></path> <path fill="currentColor" d="M15,3H1C0.448,3,0,2.552,0,2v0c0-0.552,0.448-1,1-1h14c0.552,0,1,0.448,1,1v0C16,2.552,15.552,3,15,3z"></path> <path fill="currentColor" d="M4,8H1C0.448,8,0,7.552,0,7v0c0-0.552,0.448-1,1-1h3V8z"></path> <path fill="currentColor" d="M15.707,13.293l-2.274-2.274C13.785,10.424,14,9.74,14,9c0-2.206-1.794-4-4-4S6,6.794,6,9 s1.794,4,4,4c0.74,0,1.424-0.215,2.019-0.567l2.274,2.274L15.707,13.293z M10,11c-1.103,0-2-0.897-2-2s0.897-2,2-2s2,0.897,2,2 S11.103,11,10,11z"></path>
Novo ícone do carrinho:
<path fill="currentColor" d="M15,6h-1.4l-2.7-5.4C10.6,0.1,10-0.1,9.6,0.1C9.1,0.4,8.9,1,9.1,1.4L11.4,6H4.6l2.3-4.6 c0.2-0.5,0-1.1-0.4-1.3C6-0.1,5.4,0.1,5.1,0.6L2.4,6H1c-1.1,0-1.1,1-0.9,1.4l3,8C3.2,15.7,3.6,16,4,16h8c0.4,0,0.8-0.3,0.9-0.6l3-8 C16.1,7,16,6,15,6z"></path>
Ao concluir o passo 8, os novos ícones de barra de busca e carrinho devem estar renderizados na sua loja da seguinte forma:
ℹ️ Lembre-se de acessar a documentação do Header caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
O próximo bloco que vamos utilizar é a Shelf, a nossa prateleira para uma coleção de produtos. Nessa sessão vamos aprender a renderizar e configurar essa prateleira na home da nossa loja.
Analisando a documentação da Shelf, vemos que é possível configurar qual coleção de produtos queremos mostrar através das props category
, specificationFilters
ou collection
, de acordo com os produtos cadastrados no catálogo.
As demais props são para configuração na maneira com que os items são mostrados. É importante notar que o componente shelf
sempre pede que block do tipo product-summary
faça parte da sua composição. Veja a documentação do bloco product-summary para entender mais sobre seu funcionamento
Abaixo, temos o exemplo da implementação de uma Shelf:
{
"store.home": {
"blocks": [
...
"shelf"
]
},
...
"shelf": {
"blocks": ["product-summary.shelf"],
"props": {
"category": 1,
"orderBy": "OrderByTopSaleDESC",
"paginationDotsVisibility": "desktopOnly",
"productList": {
"maxItems": 10,
"itemsPerPage": 5,
"minItemsPerPage": 1,
"scroll": "BY_PAGE",
"arrows": true,
"titleText": "Top sellers"
}
}
},
"product-summary.shelf": {
"children": [
"product-summary-image",
"product-summary-add-to-list-button",
"product-summary-name",
"product-rating-inline",
"product-summary-space",
"product-summary-price",
"product-identifier.summary",
"product-summary-buy-button"
]
}
}
home.jsonc
, declare um componente shelf
no template store.home
shelf.jsonc
shelf.jsonc
, defina o bloco shelf
com todas as props propostas no exemplo acima8
4
Obs.: É importante notar que o bloco product-summary.shelf
já está declarado dentro do arquivo default.jsonc
. Por este motivo, não foi necessário declará-lo nesta atividade.
ℹ️ Lembre-se de acessar a documentação da Shelf caso tenha alguma dúvida durante a atividade.
O resultado final esperado deve ser semelhante a este:
Caso esteja usando uma conta VTEX própria, verifique se a categoria 1
está ativa e funcional no ambiente que está usando.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
O Tab Layout é um paradigma de estruturação de layouts criado no Store Framework para permitir a construção de layouts com abas ou guias.
Neste paradigma, temos dois containers: o tab-list
e o tab-content
. Em cada um destes containers, temos os itens que os compõem. Dentro do tab-list
, temos os tab-list.item
. Já no tab-content
, temos os tab-content.item
.
Abaixo, veremos um exemplo de implementação de um tab layout.
Primeiro, é necessário declarar o block tab-layout
no template desejado:
{
"store.custom#about-us": {
"blocks": [
...
"tab-layout"
]
}
}
Depois, é necessário declarar um tab-list
e um tab-content
como children do tab-layout
:
...
"tab-layout": {
"children": [
"tab-list",
"tab-content"
]
}
Com isso, temos esses dois containers como componentes do nosso tab-layout
. O próximo passo é declarar os tab-list.item
e tab-content.item
como children do tab-list
e do tab-content
, respectivamente:
...
"tab-list": {
"children": [
"tab-list.item#1",
"tab-list.item#2"
]
}
...
"tab-content": {
"children": [
"tab-content.item#1",
"tab-content.item#2"
]
}
Na próxima etapa, temos declarar que as propriedades dos tab-list.item
. O código abaixo gera uma interface de tabs como a desta imagem:
A propriedade tabId
é muito importante, pois ela é a chave que conecta o botão de um tab-list.item
com um tab-content.item
.
...
"tab-list.item#1": {
"props": {
"tabId": "majorAppliances",
"label": "Major Appliances",
"defaultActiveTab": true
}
},
"tab-list.item#2": {
"props": {
"tabId": "electronics",
"label": "Electronics"
}
}
A seguir, vamos declarar as children e as props dos tab-content.item
.
No array de children, é possível incluir diversos blocks como rich-text
, info-card
, image
, flex-layout
e etc.
Na prop tabId
, é necessário incluir os mesmos ids declarados nos tab-list.item
para que o link entre a aba e o conteúdo funcione.
...
"tab-content.item#1": {
"children": [
"rich-text#1"
],
"props": {
"tabId": "majorAppliances"
}
},
"tab-content.item#2": {
"children": [
"rich-text#2"
],
"props": {
"tabId": "electronics"
}
}
Por fim, você deve declarar as propriedades do seu conteúdo. No nosso exemplo, colocamos apenas um rich-text
em cada tab-content.item
:
"rich-text#1": {
"props": {
"text": "Texto para Major Appliances",
"textPosition": "CENTER",
"font": "t-heading-3"
}
},
"rich-text#2": {
"props": {
"text": "Texto para Electronics",
"textPosition": "CENTER",
"font": "t-heading-3"
}
}
Nesta atividade, vamos criar a estrutura simples de um tab layout, conforme imagem abaixo. Mais tarde, vamos incluir algum conteúdo para estilizar nossa página customizada.
No arquivo about-us.jsonc
criado anteriormente, adicione um tab-layout#home
ao template store.custom#about-us
;
Declare o bloco tab-layout#home
e adicione como seus children um tab-list#home
e um tab-content#home
;
Declare um tab-list#home
e adicione como seus children um tab-list.item#home1
e um tab-list.item#home2
;
Declare as props do tab-list.item#home1
de maneira que a interface exiba o texto "Major Appliances". (Dica: não se esqueça que incluir nas props um tabId
= "majorAppliances"
e a propriedade defaultActiveTab
= true
);
Declare as props do tab-list.item#home2
de maneira que a interface exiba o texto "Electronics". (Dica: não se esqueça que incluir nas props um tabId
= "electronics"
);
Agora, vamos para a parte o conteúdo. Declare um tab-content#home
no seu tema e adicione os children tab-content.item#home1
e tab-content.item#home2
;
Em cada tab-content.item
, declare apenas um rich-text
como children (por exemplo, rich-text#home1
e rich-text#home2
);
Depois, inclua uma prop tabId
em cada tab-content.item
de maneira que aconteça o link entre o tab-list
criado anteriormente e tab-content
;
Por fim, adicione os rich-text
e declare suas props conforme o código abaixo:
"rich-text#home1": {
"props": {
"text": "Área do conteúdo da tab-list.item com tabId = majorAppliances",
"textPosition": "CENTER",
"font": "t-heading-3"
}
},
"rich-text#home2": {
"props": {
"text": "Área do conteúdo da tab-list.item com tabId = electronics",
"textPosition": "CENTER",
"font": "t-heading-3"
}
}
ℹ️ Lembre-se de acessar a documentação Tab Layout e do Rich Text caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Lojas são compostas por várias páginas diferentes, cada uma com layout e conteúdo específicos. Ao criar uma loja do zero no VTEX IO, algumas páginas padrão com URLs predefinidas já são disponibilizadas para você. Abaixo, vemos uma lista com algumas dessas páginas padrão:
store.home
�(Home page)store.product
(Product page)store.search
(Search Results page)store.account
(Client Account page)store.login
(Login page)store.orderplaced
(Order Placed page)Mas é possível que você queira criar uma landing page customizada. Nesse caso, você deve criar uma nova URL e um conteúdo específico para exibir aos usuários que acessarem essa rota.
São necessários poucos passos para se criar uma landing page customizada:
Um template define o layout da página. Portanto, se você deseja criar uma página personalizada, também precisará criar um novo template no seu tema.
Vamos supor que você queira criar uma página simples com informações sobre a sua loja. Dentro da pasta blocks
, você pode criar um arquivo que contenha o seguinte código, declarando um novo template para uma página customizada,
{
"store.custom#{templatename}": {
"blocks": [
]
}
}
onde {templateName}
deve ser substituído pelo nome identificador do template.
A seguir, você deve preencher o código com os componentes necessários para montar o layout. Abaixo, vemos um exemplo dessa implementação:
{
"store.custom#{templatename}": {
"blocks": [
"flex-layout.row#about-us"
]
},
"flex-layout.row#about-us": {
"children": [
"image#about-us",
"flex-layout.col#text-about-us"
]
},
"flex-layout.col#text-about-us": {
"children": [
"rich-text#about-title",
"rich-text#about-content"
],
"props": {
"preventVerticalStretch": true
}
},
"rich-text#about-title": {
"props": {
"text":
"# Sobre a FlatFlat"
}
},
"rich-text#about-content": {
"props": {
"text":
" FlatFlat é uma loja de eletro eletrônicos com muita tradição na fabricação de itens modernos e vintage. Nosso objetivo é criar eletrodomésticos que tornem as casas dos nossos clientes interessantes, independente do estilo. Com apenas 2 meses de história, já somos a loja com os produtos mais bonitos de toda a VTEX. Estamos construindo o nosso site nesse momento com o intuito de dar ao nosso cliente uma experiência memorável com a nossa marca!"
}
},
"image#about-us": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/arquivos/cozinha-about-us.png",
"maxHeight": "600px"
}
}
}
Agora que um novo template com o layout da página foi definido no código do tema da loja, a próxima etapa é definir o caminho (path) da página que acessará este layout.
Devemos criar um arquivo routes.json
dentro da pasta store
do seu tema. Após isto, insira o código abaixo,
{
"store.custom#about-us": {
"path": "/{URL}"
}
}
onde {URL}
é o nome do caminho desejado
Vamos criar uma página com informações sobre a sua loja conforme o exemplo abaixo:
blocks
, crie um arquivo about-us.jsonc
;store.custom#about-us
neste arquivo;flex-layout.row
, utilize o código do exemplo dado acima para completar o layout da página;store
, crie um arquivo routes.json
;/about-us
;{workspace}--appliancetheme.myvtex.com/about-us
para ver sua nova landing page.Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Começamos nossa jornada pelo clássico "Hello, World!". Para criar algo do tipo, precisamos conhecer os blocos do Store Framework e usar um que nos possibilite a criação de textos. Este bloco se chama Rich Text.
O Rich Text é somente um das dezenas de blocos disponíveis no Store Framework. É um bloco que parece simples, mas que possibilita uma série de customizações para criar textos. Para começar, todo texto escrito no Rich Text suporta linguagem Markdown, isso faz com que a estilização do texto seja muito mais fácil.
Olhando a documentação do bloco é possível encontrar a especificação técnica. Uma das seções presentes é a de Blocks API nela é vista toda a lista de propriedades (props) que o Rich Text possui. As propriedades são o principal ponto de customização de um bloco, são elas que garantem que um mesmo bloco possa ter visual e comportamento completamente diferente, dependendo de como for configurado.
Vamos então começar a personalizar a home page. No seu tema é possível encontrar um arquivo chamado home.jsonc
na pasta /store/blocks
. Neste arquivo é determinada a organização dos blocos que se deseja usar. A linguagem para composição do layout é simples e baseada em JSON.
No home.jsonc
se ver um bloco que é padrão em todos os temas: store.home
. Este bloco determina os blocos filhos que estarão expostos na home page.
{
"store.home": {
"blocks": []
}
...
}
Vamos então usar o Rich Text em seu corpo:
{
"store.home": {
"blocks": [
"rich-text"
]
}
...
}
Dessa forma, o store.home
agora sabe que precisará renderizar um Rich Text. Todavia, ainda não especificamos qual o visual desse Rich Text. Para isso, precisamos fazer uma definição de bloco.
A definição de blocos deve ser sempre feita fora de qualquer outro bloco, no nível da raiz do arquivo JSON.
{
"store.home": {
"blocks": [
"rich-text" <----- Aqui o bloco está sendo usado dentro de outro
]
},
"rich-text": { <----- Aqui está na raiz
}
}
Na definição é possível determinar o comportamento e visual de um bloco. Para tal devem ser usados pontos de customização, começaremos usando as props
do Rich Text:
{
"store.home": {
"blocks": [
"rich-text"
]
},
"rich-text": {
"props": {
}
}
}
Observe novamente a documentação do Rich Text e vamos, então, definir as props que usaremos para customizá-lo.
Queremos fazer um simples "Hello, World!", olhando nas props vemos uma que se chama: text
(Text written in markdown language to be displayed). Essa é, então, a prop que determinará qual o texto que será exibido.
Incluindo essa prop temos, então:
{
"store.home": {
"blocks": [
"rich-text"
]
},
"rich-text": {
"props": {
"text": "Hello, World!"
}
}
}
Olhando a documentação do Markdown vemos que para deixar itálico basta colocar *
antes e depois do texto:
{
"store.home": {
"blocks": [
"rich-text"
]
},
"rich-text": {
"props": {
"text": "*Hello, World!*"
}
}
}
Para posicioná-lo ao centro, podemos adicionar a prop textPosition
e atribuir a ela o valor CENTER
:
{
"store.home": {
"blocks": [
"rich-text"
]
},
"rich-text": {
"props": {
"text": "*Hello, World!*",
"textPosition": "CENTER"
}
}
}
Defina um Rich Text na sua home e crie um texto "Hello, World!" em negrito e posicionado à direita.
ℹ️ Lembre-se de acessar a documentação do Rich Text caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Neste passo vamos terminar de montar a nossa página de produto. Aprenderemos como empilhar blocos usando o Stack Layout, como sugerir produtos similares e como customizar melhor o SKU Selector para produtos com imagem de SKU.
Para testar este step, utilize a url do produto /3-colors-retro-stand-mixer/p
.
O stack-layout
é um tipo layout que possibilita que blocos possam ser empilhados sobre outros. É muito útil quando se deseja colocar algum badge em cima de uma imagem ou produto. Também é útil para compor textos compostos sobre imagens (usando um rich-text
e uma image
).
(Na imagem, uma shelf empilhada sobre um carrossel 👆)
Neste passo, usaremos o stack-layout
para colocar a marca sobre as imagens de produto.
Evolua a página de produto adicionando os passos abaixo ao arquivo product.jsonc
:
Declare um shelf.relatedProducts
abaixo da linha principal de produto
"store.product": {
"children": [
"breadcrumb",
"flex-layout.row#main",
"shelf.relatedProducts"
]
}
/3-colors-retro-stand-mixer/p
.
Troque product-images
na coluna da esquerda por uma declaração de stack-layout
;
"flex-layout.col#left": {
"children": [
"stack-layout#brand"
]
}
Defina o stack-layout
e coloque como filhos o product-images
e product-brand
;
"stack-layout#brand": {
"children": [
"product-images",
"product-brand"
]
}
Consulte a documentação para mudar a forma que o product-brand
é exibido. Você deve fazer o logo aparecer com altura de 30 e incluir a prop displayMode: "logo"
.
Consulte a documentação para fazer com que o sku-selector
:
ℹ️ Lembre-se de acessar a documentação do Stack Layout caso tenha alguma dúvida durante a atividade.
ℹ️ Lembre-se de utilizar o produto /3-colors-retro-stand-mixer/p
para testar este passo.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Conforme já vimos, Markdown é uma linguagem de marcação amigável que pode ser convertida de maneira simples para HTML. Nesta lição, veremos como é possível utilizar esta linguagem em nosso bloco Rich Text para criar textos interessantes.
Para incluir textos no bloco de rich-text
, é necessário utilizar a prop text
:
"rich-text#home1": {
"props": {
"text": "Meu texto",
"textPosition": "LEFT",
"textAlignment": "LEFT"
}
A prop text
aceita o formato de markdown. Portanto, se você deseja escrever seu texto utilizando essa linguagem, seu código deve ficar semelhante a este:
```json
"rich-text#home1": {
"props": {
"text": "# Meu título h1 \n Escreva aqui um parágrafo \n ## Meu título h2 \n Escreva aqui seu segundo parágrafo \n Inclua aqui uma lista \n - Item 1 \n - Item 2 \n - Item3",
"textPosition": "LEFT",
"textAlignment": "LEFT"
}
DICA: Sempre utilize o comando \n
para pular linhas ao utilizar markdown na prop text
Outras propriedades do componente rich-text
podem ser encontrados na documentação oficial do Store Framework
Dentro do arquivo about-us.jsonc
, troque o texto da tab-list.item#home1
para que apareça um "Sobre" na primeira aba;
No conteúdo rich-text
associado a essa aba, utilize o texto abaixo:
# Nossa História \n ### Nascemos de uma hackathon interna da VTEX! \n Isso mesmo. A primeira Hackatheme (hackathon de temas de loja) da VTEX teve 3 finalistas. Um deles foi a FlatFlat, essa loja que vocês estão acessando agora. A FlatFlat foi criada pelos engenheiros Afonso Praça e Sávio Muniz, pelos designers Lucas Falcão e Augusto Barbosa, e pelo diretor de novos negócios Maurício Baum. Como a loja foi criada por profissionais com os mais diversos backgrounds, o resultado ficou óbvio: foram finalistas com o layout mais legal dentre os participantes.
Coloque o título e o subtítulo em negrito.
ℹ️ Lembre-se de acessar a documentação do Rich Text caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever no link a seguir:
https://github.com/danvitoriano/store-framework/issues/2
Como vimos no último passo, um Submenu aceita como children qualquer bloco do Store Framework.
A partir desse entendimento, podemos melhorar a configuração do Menu feita na atividade anterior, incrementando seu conteúdo com o uso do Flex Layout.
De acordo com o que foi praticado na atividade anterior e o que foi aprendido sobre Flex Layout, vamos aplicar o Flex Layout no Submenu de Major Appliance.
No arquivo menu.jsonc
, remova o block de código em que são definidos [email protected]:submenu#major
e seus filhos:
"[email protected]:submenu#major": {
"children":[ "[email protected]:menu#major" ]
},
"[email protected]:menu#major": {
"children": [
"menu-item#refrigerators",
"menu-item#ovens",
"menu-item#washers"
],
"props": {
"orientation": "vertical"
}
},
Crie o arquivo menu-flex.jsonc
file; flex-layout.row#major
estará na lista de children do bloco [email protected]:submenu#major
e será definido como:
{
...
"flex-layout.row#major": {
"children": [
"flex-layout.col#menu",
"flex-layout.col#img"
]
},
...
}
Agora temos que declarar os blocos definidos em flex-layout.row#major
. Para começar, declare o bloco flex-layout.col#menu
com [email protected]:menu#major
como children;
Faça o mesmo para o bloco flex-layout.col#img
, o declarando com image#menu
e rich-text#header
como children e as seguintes props:
...
"props":{
"paddingRight": 4,
"horizontalAlign": "right"
}
...
Por último, vamos declarar o image#menu
passado como children no último passo. Para isso, use o código abaixo:
...
"image#menu": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/arquivos/menu-washer.jpg",
"link": {
"url": "/small-appliances/coffee-makers"
},
"alt": "Coffee Makers Collection",
"maxWidth": "200px"
}
}
ℹ️ Lembre-se de acessar a documentação do Flex Layout e do Menu caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
Um Iframe é um elemento HTML que permite a incorporação de uma outra página HTML à atual. Dessa forma, a partir do bloco Iframe é possível embutir conteúdos de outras URLs para serem exibidos em nossa página. É importante lembrar que as URLs renderizadas pelo Iframe possuem um contexto próprio, tendo histórico de sessão e DOM independentes da sua página customizada.
ATENÇÃO: Iframes só são permitidos dentro de templates de custom pages.
O bloco iframe
tem propriedades bem simples:
src
: indica qual URL o iframe deve renderizarwidth
: largura do elemento iframe em pixelsheight
: altura do elemento iframeAbaixo, vemos um exemplo de implementação do bloco iframe
:
"store.custom#about-us": {
"blocks": [
"flex-layout.row#about-us",
"iframe"
]
},
"iframe": {
"props": {
"src": "http://someURL.com/resource",
"width": 100,
"height": 200
}
}
Vamos exibir um post de Instagram em nossa loja:
rich-text
e inclua um bloco iframe
;iframe
, exiba o conteúdo do link https://www.instagram.com/p/B973Qp8BacC/embed
num container de 800px de largura por 1000px de altura.ℹ️ Lembre-se de acessar a documentação do Iframe caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
No último step conhecemos a página de busca e seus principais componentes. Também aprendemos que o layout de search funciona como qualquer outro bloco tendo, portanto, toda a flexibilidade ao seu alcance. Nesse step criaremos algumas linhas e colunas para melhorar a aparência da busca criada.
No arquivo search.jsonc
, remova total-products.v2
e order-by.v2
do search-result-layout.desktop
.
Substitua ambos acima por uma linha de topo que inclua os blocos removidos:
...
"flex-layout.row#top": {
"children": [
"total-products.v2",
"order-by.v2"
]
}
...
Remova o search-content
e o filter-navigator.v3
do search-result-layout.desktop
e crie uma linha de resultados;
Na linha de resultado coloque outras duas colunas:
{
...
"search-result-layout.desktop": {
"children": [
"breadcrumb.search",
"search-title.v2",
"flex-layout.row#top",
"search-fetch-previous",
"flex-layout.row#results",
"search-fetch-more"
]
},
"flex-layout.row#results": {
"children": [
"flex-layout.col#filter",
"flex-layout.col#search"
]
},
...
}
Configure a prop width
da coluna filter
para 20%
.
Na coluna da esquerda inclua o filter-navigator.v3
novamente e, na da direita, inclua o search-content
Para finalizar, vamos usar o mesmo Resumo de Produto(product-summary
) que usamos na shelf para exibir os resultados de busca.
Defina seu search-content
com os blocos gallery
e not-found
:
{
...
"search-content": {
"blocks": ["gallery", "not-found"]
}
...
}
Use o product-summary.shelf
nas props da Gallery:
{
...
"search-content": {
"blocks": ["gallery", "not-found"]
},
"gallery": {
"blocks": ["product-summary.shelf"]
}
...
}
No blocoproduct-summary.shelf
que se encontra no arquivo default.jsonc
, inclua product-summary-sku-selector
acima de product-summary-buy-button
.
ℹ️ Lembre-se de acessar a documentação do Flex Layout caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
O Flex Layout é um paradigma de estruturação de layout criado no Store Framework para permitir a construção de layouts complexos. Esse paradigma usa o conceito de linhas e colunas para definir a estrutura e o posicionamento desejados dos blocos em uma determinada página.
Existem dois blocos de construção básicos de cada Flex Layout:
flex-layout.row
flex-layout.col
Se você já está familiarizado com o Flexbox utilizado no CSS, o Flex Layout deve ser simples de entender, já que o Flexbox está sendo utilizar "por debaixo dos panos" pelo flex-layout.row e flex-layout.col.
Com o Flex Layout é possível criar layouts personalizados, utilizando a estrutura de linhas e colunas do Flexbox.
Analisando a documentação do bloco, vemos que você pode utilizar qualquer array de blocos como children
do Flex Layout. Além disso, você deve sempre usar flex-layout.row
e flex-layout.col
, NUNCA flex-layout
de forma isolada.
Abaixo, temos um exemplo de flex layout composto de um flex-layout.row
com dois children: um info-card
e um rich-text
:
"flex-layout.row":{
"children": [
"info-card#rethink",
"rich-text#deletar"
]
},
"info-card#rethink": {
"props": {
"imageUrl": "https://appliancetheme.vteximg.com.br/arquivos/utensilios-cozinha-min.png",
"isFullModeStyle": true,
"headline": "Time to rethink your kitchen",
"callToActionText": "Discover",
"textPosition": "center"
}
},
"rich-text#deletar": {
"props": {
"text": "I'll be deleted soon"
}
}
Declare o flex-layout.row
dentro dos blocks
do template de store.home
e declare os blocos propostos acima no seu arquivo home.jsonc
Altere as children do flex-layout.row
, substituindo o bloco rich-text
por uma coluna flex-layout.col
.
Delete o bloco de rich-text
proposto acima do seu tema.
Declare o bloco flex-layout.col
no seu arquivo home.jsonc
com dois componentes de imagem como children: image#electronics
e image#major-appliance
, nesta ordem.
Defina os blocos image
com as seguintes props:
...
"image#electronics": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/assets/vtex.file-manager-graphql/images/electronics_banner___25d69b49f8224b369375e68513b4d593.png",
"maxWidth": "100%"
}
},
"image#major-appliance": {
"props": {
"src": "https://appliancetheme.vteximg.com.br/assets/vtex.file-manager-graphql/images/major_appliance_banner___bb10093866a127345ddfbcca3efa5022.png",
"maxWidth": "100%"
}
}
O resultado obtido deve ser semelhante a este:
ℹ️ Lembre-se de acessar a documentação do Flex Layout caso tenha alguma dúvida durante a atividade.
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
Se ainda tiver dúvida sobre como enviar sua resposta, você pode rever aqui.
É importante estabelecer que este não é um curso expositivo. O seu objetivo é ensinar os participantes sobre o Store Framework do VTEX IO a partir de atividades práticas. Por isso, para que se consiga avançar, é preciso que um pouco do seu tempo e dedicação sejam investidos.
No começo do curso você recebeu um repositório com código mínimo e queremos que, ao completar todas as tarefas, você o tenha transformado em uma loja completa e funcional.
O curso é divido em etapas. Ao começo de cada etapa, você receberá instruções iniciais, como você já recebeu nesse e no anterior. Você deve ler todo o conteúdo apresentado e receberá, ao fim, uma pequena atividade.
Para que suas respostas sejam enviadas, siga os seguintes passos:
git clone
https://github.com/danvitoriano/store-framework
Open
na notificação que abre no canto inferior direitostore-framework
;danvitoriano/store-framework
e clique em Install.Ao terminar de ler todo o conteúdo e fazer a atividade proposta, você deve enviar a sua resposta seguindo os passos abaixo:
Source Control
, no menu lateral do VSCode;+
na seção de CHANGES;✓
(Commit);+ Create new branch...
;Quando terminar de fazer todo o fluxo, nosso robô responderá se você conseguiu ou não acertar a resposta que esperávamos. Se sim, receberá uma resposta como:
Em seguida, você receberá uma outra resposta que indicará os próximos passos:
Se você é familiarizado com o git, todo esse fluxo equivale a criar uma branch com um nome predefinido, fazer commit das mudanças e dar push.
Ao longo do curso, é possível que você não consiga completar corretamente a atividade na primeira tentativa. Se isso acontecer, você receberá uma mensagem de feedback que indicará qual foi o por quê da falha:
Você pode submeter quantas respostas você quiser, basta refazer todo o processo explicado na seção anterior.
A qualquer momento do curso você pode acompanhar o seu progresso voltando na página inicial. Nela, serão indicados todos os steps, quais você já completou e um botão para você voltar para o step de onde parou:
A todo momento, abrindo o terminal do VSCode, você pode executar um vtex link
e acompanhar a evolução do seu projeto em https://{workspace}--{conta}.myvtex.com
. Certifique-se que visualmente a solução é equiparável com o que foi apresentado e que nenhum erro aconteceu no link.
Não crie issues e PRs durante o fluxo do curso, isso pode interferir no seu funcionament
Há algum problema com esse passo? Que tal nos enviar um feedback? 🙏
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.