Categorias
AMP Accelerated mobile pages

Convertendo uma aplicação AMP em uma PWA

Agora chegou o momento de conectar os meus dois assuntos favoritos, Progressive Web Apps(PWA) e AMP. Se você ainda não sabe o que é uma PWA podemos definir conjunto de tecnologias que nos permitem criar aplicações web com recursos que antes só possíveis em aplicações nativas se quiser saber mais sobre PWA tenho um curso dedicado em meu canal.

As PWA possui uma série de diferentes API que podem ser aplicadas a diferentes soluções, mas para o caso de nossa aplicação AMP vamos abordar dois items:

  1. Tonar nossa aplicação instalável
  2. Adicionar suporte a versão offline.

Criando um web app manifest para nossa PWA

Primeiro passo vamos criar um web app manifest arquivo json que permite que dispositivos que reconheçam que nossa aplicação pode se instalável. Para isso vamos adicionar em nosso projeto um arquivo chamado manifest.json e nele vamos adicionar o seguinte código:

{
  "short_name": "Caipirinha",
  "name": "How to prepare the best caipirinha",
  "icons": [
    {
      "src": "./images/capi_icon_192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "./images/capi_icon_512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/index.html",
  "background_color": "#00d1c3",
  "display": "standalone",
  "scope": "/",
  "theme_color": "#00d1c3"
 }

O código acima descreve as informações que iremos exibir para o usuário quando ele instalar nossa aplicação, que são elas:

  • short_name: o nome que sera exibido na tela inicial do nosso usuário.
  • icons: com uma lista de ícones que iremos exibir em diferentes plataformas.
  • start_url: o endereço nossa aplicação irá carregar quando acessada através do ícone na tela inicial do usuário.
  • background_color: a cor do background da splash screen do nosso app.
  • display: o modo em que nossa PWA será exibida
  • theme_color: as cor do tema da nossa aplicação, por exemplo, barra de controle.

Depois que criarmos nosso arquivo manifest.json temos adicionar uma referência dentro da tag head de nosso index.html ao arquivo de configuração, como podemos ver no código abaixo:

<link rel="manifest" href="/manifest.json">

Adicionando suporte a versão off-line

Agora que já definimos como nosso app será instalado é hora de adicionar a versão off-line de nossa aplicação para isso vamos trabalhar com service workers.

Service Worker um script que é executando por nosso browser em background, separado de nosso DOM onde funciona como proxy acompanhando as requisições no nosso app.

Caso queira saber mais sobre o assunto confira o post sobre service worker.

Mas com esse recurso conseguimos controlar quando nosso app faz requisições a rede e definir estratégias de cache e suporte a versão offline utilizando em conjunto com a cache API.

Atualmente existem bibliotecas que facilitam a implementação desses recursos, por exemplo, Workbox onde também tenho um post mais detalhado sobre o assunto aqui.

Mas AMP vai um passo além do Workbox e abstrai uma série de passos na configuração de um service worker para implantação de estratégias de cache e versão off-line. Isso tudo utilizando AMP Service Worker ele armazena automaticamente os scripts e os documentos de nossa aplicação.

Como criar um service worker com AMP?

Passo 1 – criar o arquivo que irá importar o AMP Service Worker e incializa-lo, para isso vamos criar um arquivo JavaScript chamado sw.js e adicionar os seguinte código:

importScripts('https://cdn.ampproject.org/sw/amp-sw.js');
AMP_SW.init();

Passo 2 – Incluímos o script que irá instalar o AMP Service Worker próximos as scripts que você já carrega em sua aplicação AMP.

<script async custom-element="amp-install-serviceworker" src="https://cdn.ampproject.org/v0/amp-install-serviceworker-0.1.js"></script>

Passo 3 – Adicionamos dentro do corpo da nossa página HTML o componente amp-install-servieworker:

<amp-install-serviceworker src="/sw.js"
           data-iframe-src="install-sw.html"
           layout="nodisplay">
</amp-install-serviceworker>

O componente amp-install-serviceworker irá registrar um service worker definido na propriedade src, dois pontos importante sobre o service worker:

  • Precisa estar na pasta raiz da aplicação
  • Precisa ser servido via HTTPS.

A segunda propriedade é o data-iframe-src é um atributo opicional que será responsável por verificar se o browser possui suporte a service worker e instalar-lo em caso possua.

Passo 4 – o último passo vamos criar o arquivo definida pela propriedade data-iframe-src:

<!doctype html>
<title>installing service worker</title>
<script type='text/javascript'>
 if('serviceWorker' in navigator) {
   navigator.serviceWorker.register('./sw.js');
 };
</script>

Com esse 4 passos temos nossa primeira versao offline, o AMP Service Worker nos permite definir estratégias de cache para arquivos especificos. Caso queira saber mais sobre estrategias de cache eu escrevi um post aqui.

Vou criar mais um post de como modificar estratégias de cache e exibir uma página específica parar quando os usuários estiverem off-line.

Categorias
AMP Accelerated mobile pages

Trabalhando com light-box para imagens com AMP: amp-image-lightbox

No post anterior vimos como implementar um light-box com o componente amp-lightbox e nesse post vamos ver como implementar light-box para imagens, assim iremos trabalhar com o componente amp-image-lightbox. Ele possui algumas particularidades comparado ao componente amp-lightbox mas o comportamento será bem parecido.

amp-image-lightbox

O componente amp-image-lightbox habilita um lightbox específico para images, quando acionado a image será exibida em destaque. Para trabalhar como o componente precisamos primeiramente carregar o script:

<script async custom-element="amp-image-lightbox" src="https://cdn.ampproject.org/v0/amp-image-lightbox-0.1.js"></script>

Em seguida adicionamos em nossa aplicação seguinte o código:

<amp-image-lightbox id="lightbox-caipirinha" layout="nodisplay"></amp-image-lightbox>
<amp-img
  on="tap:lightbox-caipirinha"
  role="button"
  tabindex="0"
  src="caipirinha.jpg"
  width="200"
  height="100"
></amp-img>

O amp-img possui um evento de tap que irá referenciar o light-box que queremos exibir e nesse caso o amp-image-lightbox com id “lightbox-caipirinha” será o nosso alvo, assim como amp-lightbox ele possui o layout “nodisplay” e com o código acima o resultado será o seguinte:

light-box quando acionado

O componente amp-image-lightbox já vem com estilização do background interações, por exemplo, zoom, panorâmica, e ações para fechar o lightbox quando o usuário clicar fora da imagem ou precionar ESC.

Diferente do amp-lightbox o amp-image-light pode ser utilizado por múltiplas images, assim podemos ter duas images fazendo referência ao mesmo light-box. Como no código a seguir:

<amp-image-lightbox id="lightbox-caipirinha" layout="nodisplay"></amp-image-lightbox>

<amp-img
  on="tap:lightbox-caipirinha"
  role="button"
  tabindex="0"
  src="caipirinha1.jpg"
  width="200"
  height="100"
></amp-img>

<amp-img
  on="tap:lightbox-caipirinha"
  role="button"
  tabindex="0"
  src="caipirinha2.jpg"
  width="200"
  height="100"
></amp-img>

Legendas

Um recurso opcional é a inclusão de legendas no light-box, para isso precisamos incluir uma tag “figure” e como filha uma tag “figcaption” ou adicionar uma descrição com aria através da propriedade “aria-describedby” essas serão as duas opções que veremos no código a seguir:

Com tag figure

<amp-image-lightbox id="lightbox-caipirinha" layout="nodisplay"></amp-image-lightbox>

<!-- Captions via figcaption -->
<figure>
  <amp-img
    on="tap:lightbox-caipirinha"
    role="button"
    tabindex="0"
    src="caipirinha.jpg"
    layout="responsive"
    width="300"
    height="246"
  ></amp-img>
  <figcaption>Learn how to prepare the best Caipirinha</figcaption>
</figure>

Resultado do light-box com legenda

Com ARIA

<amp-image-lightbox id="lightbox-caipirinha" layout="nodisplay"></amp-image-lightbox>

<!-- Captions via figcaption -->
<div>
  <amp-img
    on="tap:lightbox-caipirinha"
    role="button"
    tabindex="0"
    src="caipirinha.jpg"
    aria-describedby="image-description"
    layout="responsive"
    width="300"
    height="246"
  ></amp-img>
  <div id="image-description">Caipirinha from Brazil</div>
</div>

Em ambas situações o resultado visual será o mesmo, com a legenda no canto inferior.

Atributos

Os atributos no componente amp-image-lightbox é um pouco diferente do amp-lightbox não temos opções de animação mas temos a seguintes propriedades:

  • layout(obrigatório): deve ser nodisplay
  • id (obrigatório): necessário para ser referenciado pelo elemento que ira disparar a ação de exibir
  • data-close-button-aria-label(opcional): Uma legenda usada pelo ARIA que podemos incluir em nosso botão fechar.

Se quiser saber mais sobre am-lightbox eu publiquei um post falando sobre o componente. Para acompanhar o curso de AMP assine meu canal no YouTube. Qualquer dúvida deixe um comentário e até o proximo post.

Categorias
AMP Accelerated mobile pages

Criando light-box com AMP: amp-lightbox

Nesse post vamos ver como implementar um light-box em nossa aplicação AMP, light-box é um dos recursos mais usados desde a popularização do JavaScript. Na maioria das vezes usado para focar a exibição de elementos gráficos ou mensagens. A plataforma amp disponibiliza três componentes para exibiãção de light-box amp-lightbox, amp-image-lightbox e amp-lightbox-gallery.

Cada um desses componentes possui uma aplicação específica, Para esse tutorial iremos abordar o componente amp-lightbox.

amp-lightbox

Esse componente quando utilizado seu elemento filho será exibido em uma modal quando acionado através de um evento de clique. Com isso temos que ter um segundo elemento para ativa-lo, um botão poderá ser uma alternativa. O componente possui alguns comportamentos já pre definidos, por exemplo, quando o usuário pressionar a tecla “esc” o light-box será fechado. Um alternativa é incluir um elemento com a ação close no light-box.

O componente amp-lightbox é um componente extended assim precisamos carregar o script relacionado:

<script async custom-element="amp-lightbox" src="https://cdn.ampproject.org/v0/amp-lightbox-0.1.js"></script>

Com essa introdução vamos criar o nosso primeiro exemplo, baseado no projeto the best caipirinha, vamos utilizar o light-box para trazer mais informações sobre os items da nossa receita, por exemplo, descrição sobre cana de açúcar com isso temos o seguinte código:

<button on="tap:sugarcane-wiki">sugarcane</button>

<amp-lightbox id="sugarcane-wiki" layout="nodisplay">
                <p>
                  Sugarcane, or sugar cane, or simply cane, are several species of tall perennial true grasses of the genus Saccharum...
                </p>
</amp-lightbox>

Apenas com o botão e o componente amp-lighbox temos nosso light box somente com a funcionalidade como podemos ver na imagem abaixo:

Agora é hora de adicionar a parte visual, para isso precisamos adicionar o estilo para o nosso elementos com isso vamos criar classes para estilizar nossos elementos em nosso CSS e aciona-los em nosso elementos HTML:

CSS

.lightbox {
        align-items: center;
        background: rgba(0, 0, 0, 0.8);
        box-sizing: border-box;
        display: flex;
        flex-direction: column;
        justify-content: center;
        height: 100%;
        width: 100%;
        position: absolute;
        padding: 2em;
      }

      .lightbox_p {
        color: #fff;
        font-size: 1.5em;
        font-weight: 500;
      }

HMTL

<amp-lightbox id="sugarcane-wiki" layout="nodisplay">
              <div class="lightbox">
                <p class="lightbox_p">
                  Sugarcane, or sugar cane, or simply cane, are several species of tall perennial true grasses of the genus Saccharum....
                </p>
                <p class="lightbox_p">source: wikipedia</p>
              </div>
            </amp-lightbox>

Adicionando o estilo temos o seguinte resultado:

Apenas adicionando o botão para abrir o light-box, para fechar precisamos pressionar a tecla “esc” mas isso pode não ser intuitivo para os nossos usuários com isso vamos adicionar um botão fechar dentro de nosso light-box.

<amp-lightbox id="sugarcane-wiki" layout="nodisplay">
              <div class="lightbox">
                <p class="lightbox_p">
                  Sugarcane, or sugar cane, or simply cane, are several species of tall perennial true grasses of the genus Saccharum....
                </p>
                <p class="lightbox_p">source: wikipedia</p>
                <button class="lightbox_close" on="tap:sugarcane-wiki.close">close</button>
              </div>
            </amp-lightbox>

Adicionamos um botão com a ação de close sobre o light-box, falando em ações o componente amp-lightbox aceita duas ações open e close. Por padrão ele aciona a ação de open por isso que no botão para abrir o light-box não especificamos a ação. Agora para realizar a estilização do nosso botão vamos adicioar o seguinte CSS:

.lightbox_close {
        position: absolute;
        right: 32px;
        top: 32px;
        width: 32px;
        height: 32px;
        opacity: 0.7;
        text-indent: -999px;
        overflow: hidden;
        border: none;
        background: transparent;
      }

      .lightbox_close:hover {
        opacity: 1;
      }

      .lightbox_close::before,
      .lightbox_close::after {
        background-color: #fff;
        content: '';
        position: absolute;
        left: 16px;
        top: 0;
        height: 33px;
        width: 3px;
      }

      .lightbox_close::before {
        transform: rotate(45deg);
      }

      .lightbox_close::after {
        transform: rotate(-45deg);
      }

E o resultado será o seguinte:

com CSS criamos o botão de fechar o texto é escondido para ser ligo apenas por leitores de tela

Outro opção que poderíamos incluir se o usuário fechasse o light-box clicando no background com isso adicionamos o evento de clique no elemento com o class “lightbox”:

<amp-lightbox id="sugarcane-wiki" layout="nodisplay">
              <div class="lightbox"
                on="tap:sugarcane-wiki.close"
                role="button"
                tabindex="0">
                <p class="lightbox_p">
                  Sugarcane, or sugar cane, or simply cane, are several species of tall perennial true grasses of the genus Saccharum...
                </p>
                <p class="lightbox_p">source: wikipedia</p>
              </div>
              <button class="lightbox_close" on="tap:sugarcane-wiki.close">close</button>
            </amp-lightbox>

No código acima adicionei o evento de tap no elemento lightbox também adicionei duas propriedades por questões de acessibilidade “role” e “tabindex” para tornar a div clicável e não interferir na ordem lógica dos elementos para leitores de tela.

Atributos

Então vimos alguns exemplos práticos com light-box agora vamos ver alguns atributos:

  • animate-in (opcional): define o estilo de animação de abertura do light-box. Por default sua aparição vai ser feita por fade-in. Mas temos disponíveis: fade-in, fly-in-bottom e fly-in-top.
  • close-button (obrigatório para AMP ads): renderiza um botão no to do lightbox. Ele é somente válido e obrigatório para AMP ads.
  • id (obrigatório): valor único para identificar o lightbox.
  • layout (obrigatório): deve ser definido como nodisplay.
  • scrollable (opcional): Quando este atributo é definido o conteúdo do light-box pode ter rolagem horizontal habilitada quando necessário.

O tipos de animações com animate-in eu vou deixar para mostrar em uma vídeo aula no meu canal, mas caso queira saber mais sobre AMP confira a página com outros tutoriais aqui.

Em breve estarei adicionando mais posts sobre os componentes amp, qualquer dúvida deixe um comentário e até o próximo vídeo.

Categorias
Geral

Utilizando Dark Mode em sua aplicações web

Nesse post vamos ver como implementar Dark mode em nossas aplicações web, lançado em sistemas operacionais tanto Mobile quanto para Desktop agora podemos controlar a estilização do nosso conteúdo de acordo com a preferência do usuário. Falando um pouco dessa trajetória no inicio da computação por questões de limitação utilizávamos “dark mode” com os famosos monitores de tela preta como o texto verde.

Com a evolução das telas tivemos uma mudança dos sistemas operacionais para representar elementos reais como documentos e images. Com o passar dos anos a comunidade de desenvolvimento passou a utilizar IDEs para codificação em dark, e agora nos últimos anos Dark Mode passou a ser uma opção para sistema operacionais mobile.

Preferências e vantagens

Particularmente por uma longa exposição durante o dia a diversas telas, no trabalho, celular e em casa. Eu utilizo modo como uma forma de descanso mas estudos realizados pelo time do android mostram que dark mode permite uma economia de até 60% em algumas aplicações, por exemplo, o Youtube app em dark mode.

Mas a web não fica para trás, nas últimas versões dos browsers passaram a reconhecer quando o usuário utiliza o modo, Conseguimos através de media queries monitorar a preferência do usuário.

Media Query CSS

@media (prefers-color-scheme: dark) { ... }

@media (prefers-color-scheme: light) { ... }

@media (prefers-color-scheme: no-preference) { ... }

Com essas três media queries conseguimos captar 3 estados: dark, light, no-preference. Assim conseguimos alterar propriedades quando o usuário utiliza um modo especifico, por exemplo:

body {
  color: #000;
  background-color: #fff;
}

@media (prefers-color-scheme: dark) { 
  body {
     color: #fff;
     background-color: #000;
  }
}

Habilitando Dark mode

No MacOS definimos através de configurações > preferencias gerais:

Alterando para Dark Mode Mac OS

Para iOS vamos em Configurações > Tela e Brilho

Como definir dark mode no iOS

Essa é uma maneira que podemos modificar toda a configuração do sistema operacional. Mas quando estamos desenvolvendo ficar trocando todas as configurações do sistema operacional pode se tornar inconveniente. Nas novas versões do Chrome 79 podemos simular essa mudança como o Chrome DevTools. Para isso vamos no seguinte painel.

Com o DeTools aberto clicamos no menu mais opções(três pontos) e habilitamos a opção renderização(rendering), Lá na propriedade “Emulate CSS media feature prefers-color-scheme” conseguimos simular light mode e dark mode.

Tela do devtools do Chrome

Agora que sabemos como simular e qual media query utilizamos, vamos aplicar o código ao projeto utilizado no curso de PWA. Atualmente o tema principal utilizar um background preto com fontes branca, agora vamos criar uma tema light com as cores invertidas:

Resultado final Light vs Dark mode

Controlando as cores com variáveis CSS

Para isso vamos fazer algumas modificações. Atualmente o projeto utiliza SASS, vou levar em consideração o modo light como o modo padrão e para esse exercício vou utilizar as variáveis para CSS para modifica-las quando usuário muda o modo:

//cores com variáveis CSS
:root {
  --primary-color: #fff;
  --secondary-color: #000;
  --ternary-color: #bae2fd;
  --gray-color: #333;
}

@media (prefers-color-scheme: dark) {
  :root {
    --primary-color: #000;
    --secondary-color: #fff;
  }
}

No código acima á parte de nossa solução, temos as variáveis sendo modificadas quando o usuário muda entre modos, assim não precisamos modificar todos os seletores do nosso CSS apenas as variáveis.

Quando testamos nossa aplicação em Dark Mode deparamos com a seguinte situação:

SVGs e images precisa de ajustes

Para esse caso temos duas correções os icones das redes sociais estão como “embedados” em nosso HTML conseguimos controlar a propriedade fill do nosso SVGs para isso adicionamos o seguinte código:

.social__icon {
    width: 25px;
    height: 25px;
    fill: var(--secondary-color);
}

a:hover .social__icon {
    fill: var(--primary-color);
}

Para a logo principal, por conta de ser uma image preto e branco conseguimos inverter sua cor através de filtros CSS:

@media (prefers-color-scheme: dark) {
  .header__picture {
    filter: invert(1);
  }
}

Assim temos o fix para os dois items, lembrando que no caso da imagem funcionou por que eu utilizo uma image monocromática e temos o seguinte resultado:

Observações

Implementações do dark mode pode ser mais complexa que no exemplo acima, por conta da paleta de cores restritas temos uma simples implementação, caso de uma paleta mais complexa preste atenção nos níveis de contraste.

Em caso mais complexos o ideal é dividir o CSS e carregar o estilo para mode preterido pelo usuário, adicionando as seguintes tags em nosso html:

<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)">
<link rel="stylesheet" href="/light.css" media="(prefers-color-scheme: no-preference), (prefers-color-scheme: light)">
<!-- Estilo principal -->
<link rel="stylesheet" href="/style.css">

No caso acima temos um estilo geral style.css e dark.css para os usuários que preferem dark mode e light.css para os usuários sem seleção ou light mode. Assim os usuários em dark mode so carregam o css relacionado.

Para browser antigos

Caso o browser não suporte prefers-color-scheme conseguimos adicionar um fallback em nosso código:

<script>
  // Se `prefers-color-scheme` não for suportado pelo browser, o fall back será light mode.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
        'beforeend',
        '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">'
    );
  }
</script>

Após a inclusão da media query a validação do stylelint acusou a media query como desconhecida, isso por conta da versão do style lint caso passe o mesmo problema atualize o stylelint para versão 10 ou superior e a validação passará a reconhecer a media query

Falso alert de validação das versões antigas do stylelint

Suporte

Atualmente Novembro de 2019 o suporte para a media query prefers-color-scheme é de 74% dos browser do mercado:

Edge, firefox, chrome, safari, opera, iOS safari suas ultimas versões suportam dark mode.

O código completo você encontra em meu github: https://github.com/fellyph/pwa-tutorial/tree/video/dark_mode_20_final

A base desse tutorial vem do projeto utilizado no curso de PWA que estou rodando no Youtube: https://blog.fellyph.com.br/curso-online-progressive-web-apps/

Qualquer dúvida deixe um comentário e até o próximo post.

Esse post foi baseado no artigo “Hello darkness, my old friend” do @tomayac: https://web.dev/prefers-color-scheme/

Categorias
AMP Accelerated mobile pages

Criando menu acordeão com AMP: amp-accordion

Veja a aula do curso como implementar um menu sanfona

Um dos componentes mais populares do AMP é o amp-accordion, o componente de accordion(acordeão) ou sanfona como também é conhecido permite o usuários comprimir e expandir determinadas sessões. Ele é útil também em dispositivos móveis para reduzir a quantidade de scroll de uma sessão. Neste post iremos entrar em alguns detalhes desse componente.

Comportamento

Cada filho imediato do componente para ser considerado um accordion session precisa estar dentro de uma tag section.

  • amp-accordion pode conter uma ou mais elementos <section>
  • Cada <section> deve conter exatamente dois filhos.
  • O primeiro filho vai representar o header o ideal ele utilizar as tags h1, h2, h3, …, h6 e header.
  • Clique ou tap no header vai expandir ou comprimir o elemento responsável pelo conteúdo.
  • Os estados de expandir e comprimir é preservado por cada elemento.

Eventos e ações

Accordion component dispara dois eventos:

  • expand: quando o elemento section referente ao conteúdo muda do estado recolhido para o estado expandido.
  • collapse: quando a elemento section referente ao conteúdo muda do estado expandido para o estado recolhido.

Já quando falamos de ações temos as seguintes ações disponíveis: toggle, collapse e expand. Agora temos uma introdução sobre o componente vamos para um exemplo prático primeiro precisamos chamar o script responsável.

<script async custom-element="amp-accordion" src="https://cdn.ampproject.org/v0/amp-accordion-0.1.js"></script>

Nosso markup ficará da seguinte forma:

<amp-accordion expand-single-section>
              <section id="step1" expanded>
                <h3 class="recipe__step__title">1. Gather the ingredients.</h3>
                <p>
                  Lorem, ipsum dolor sit amet consectetur adipisicing elit.
                  Perspiciatis explicabo vero, facere, dolorem quia eligendi solut.
                </p>
              </section>
              <section id="step2">
                <h3 class="recipe__step__title">
                  2. Cut half of a lime into small wedges.
                </h3>
                <p>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic,
                  ipsam repellat? Animi excepturi nostrum ducimus minus natus nobis.
                </p>
              </section>
</amp-accordion>

E resultado será o seguinte:

No markup acima não coloquei as 6 sections mas o código é só uma repetição do primeiro bloco. Mas o importante nesse print são dois pontos primeiro as propriedades:

  • expand-single-section: com ela determinamos somente um sessão do acordeão será aberta por vez.
  • expanded: determina se a sessão iniciará expandida.

Segundo o componente já possui um estilo, caso queira personalizar esse estilo podemos adicionar qualquer class nos elementos que fazem parte do acordeão:

<amp-accordion expand-single-section>
              <section id="step1" expanded>
                <h3 class="recipe__step__title">1. Gather the ingredients.</h3>
                <p>
                  Lorem, ipsum dolor sit amet consectetur adipisicing elit.
                  Perspiciatis explicabo vero, facere, dolorem quia eligendi soluta
                  expedita maxime animi, quos deleniti exercitationem quae impedit
                  recusandae nobis laborum hic? Sed, dolor.
                </p>
              </section>
              <section id="step2">
                <h3 class="recipe__step__title">
                  2. Cut half of a lime into small wedges.
                </h3>
                <p>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit. Hic,
                  ipsam repellat? Animi excepturi nostrum ducimus minus natus nobis
                  porro, facere, ipsa id repudiandae illum tenetur nulla vel et
                  molestias fugit.
                </p>
              </section>
</amp-accordion>

css:

.recipe__step__title {
        background: var(--secondary-color);
        padding: 0.5em;
        border-top: transparent;
        border-left: transparent;
        border-right: transparent;
        border-bottom: 3px solid var(--primary-color);
        color: var(--header-color);
        text-align: left;
      }

Com isso temos o resultado:

O exemplo acima é somente para exibir como o podemos alterar o cabeçalho, por exemplo, alterando o h3 conseguimos personalizar o header da nossa sessão.

Para mais tutorias sobre amp confira a página de categoria: https://blog.fellyph.com.br/category/amp/

Para acompanhar o curso online assine o canal:

Link da playlist: https://www.youtube.com/watch?v=Ku9-Hnqjjb4&list=PLmIA3VZysEqQxsVcZ7u2ZHOnh78eIOKON