Sistema de componentes Tailwind · Novo recurso

Sistema de design Preline UI.

Um planejador de sessões nativo do Preline, com guias vinculadas, um plugin de entrada numérica com restrições, aliases de tema instalados, escalas reais do Tailwind e uma estimativa local de materiais que se atualiza conforme a sessão selecionada.

Guia OpenDesign9 capítulos31 entradas de referênciaGuia de aplicação original
01

Prévia da interface do sistema de design Preline UI

Compare três sessões criativas originais, altere o tamanho do grupo e salve uma estimativa local de materiais, claramente identificada como tal.

Planejador do sábado no estúdioAbrir exemplo completo
HSTabs e HSInputNumber do Preline 4.2.0 com Tailwind CSS 4.3.3 e o tema padrão do pacote. · Referência de implementação
02

Referência de design do sistema de design Preline UI

Preline npm 4.2.0 com Tailwind CSS 4.3.3; tema padrão do pacote instalado. O site de marketing e documentação pode exibir um aviso de uma versão mais recente, por isso o exemplo executável está explicitamente fixado. Os aliases do tema continuam sendo aliases; não há conversões hexadecimais presumidas.

Tema semântico claro padrão

Fonte
Nome / RegraValor / ConfiguraçãoUso
--backgroundvar(--color-white)Função de fundo padrão.
--foregroundvar(--color-gray-800)Função do texto principal.
--bordervar(--color-gray-200)Função compartilhada de borda.
--primaryvar(--color-primary-600)Aba ativa e ação principal.
--primary-foregroundvar(--color-white)Texto sobre a cor primária.
--primary-hovervar(--color-primary-700)Estado ao passar o cursor.
--primary-focusvar(--color-primary-700)Estado de foco.
--primary-activevar(--color-primary-700)Estado ativo.
--layervar(--color-white)Superfície do controle de quantidade.
--layer-linevar(--color-gray-200)Limite do controle de quantidade.
--layer-hovervar(--color-gray-50)Superfície ao passar o cursor.
--cardvar(--color-white)Cartões de sessão e grupo.
--card-linevar(--color-gray-200)Limite do cartão.
--muted-foreground-1var(--color-gray-500)Texto de apoio.

Escalas do Tailwind realmente usadas

Fonte
Nome / RegraValor / ConfiguraçãoUso
p-2 / gap-20.5remEstrutura do controle de quantidade e espaçamento entre abas.
px-3 / gap-30.75remPreenchimento das abas e espaçamento do controle numérico.
p-51.25remCartões e margem interna padrão da página.
sm:p-82rem from 640pxMargem interna da página no breakpoint pequeno.
mt-71.75remEspaço antes do planejador.
text-xs0.75rem / 1remRótulos de apoio.
text-sm0.875rem / 1.25remControles e texto explicativo.
text-lg1.125rem / 1.75remCabeçalho do grupo.
text-2xl1.5rem / 2remTítulo da sessão.
text-3xl1.875rem / 2.25remTítulo da página e total.
rounded-lg / rounded-xl0.5rem / 0.75remControles / cartões; valores padrão de border-radius do Tailwind.

Restrições do aplicativo original e dos plugins

Fonte
Nome / RegraValor / ConfiguraçãoUso
Group sizemin 1 / max 6 / step 1As opções de dados do HSInputNumber e as restrições de entrada de HTML correspondem.
Print studio allowance$12 per participantEstimativa fictícia de materiais.
Clay workshop allowance$18 per participantEstimativa fictícia de materiais.
Drawing walk allowance$5 per participantEstimativa fictícia de materiais.
LayoutFlexible session + 280px group card; stack at 760pxComposição original e responsiva.
Theme mappingbg-primary → --color-primary → --primaryA classe utilitária semântica do Tailwind é resolvida por meio do alias do Preline.
03

Guia completo do sistema de design Preline UI

Um guia prático para escolher, aplicar e avaliar este sistema em uma interface real.

DESIGN-preline-ui.md

Orientações completas, um ponto de partida para a implementação e links para o código-fonte.

Baixar o guia

Sistema de design Preline UI: o Preline combina marcação com utilitários e plugins de comportamento

O Preline combina marcação com utilitários e plugins de comportamento

O planejador usa dois plugins nativos do Preline: HSTabs seleciona um painel de sessão, e HSInputNumber gerencia controles de incremento e decremento com limites. As classes do Tailwind fornecem a maior parte do tratamento visual. A ilustração original da sessão e o cálculo do orçamento pertencem ao aplicativo, não a um componente fictício que faz tudo.

Com base neste guia de OpenDesign

Essa distinção é importante ao copiar o exemplo. Instalar apenas o pacote JavaScript não compila as classes utilitárias nem fornece a marcação do aplicativo. Da mesma forma, copiar o HTML sem inicializar os plugins deixa incompleto o comportamento das abas e dos controles numéricos. A integração completa abaixo apresenta cada parte explicitamente.

Consulte a especificação de apoio

Sistema de design Preline UI: acompanhe os aliases semânticos até suas funções na paleta

Acompanhe os aliases semânticos até suas funções na paleta

No tema claro padrão do pacote, --primary aponta para --color-primary-600, cuja escala primária subjacente é azul. A cor de primeiro plano primária é branca; hover, focus e active usam a função de setecentos. A aba selecionada e a ação Save compartilham essa família por meio de classes utilitárias semânticas.

Os cartões usam --card e --card-line, enquanto o campo de quantidade usa --layer e --layer-line. Manter essas funções separadas torna futuras alterações de tema mais previsíveis do que espalhar classes literais de branco e cinza por toda parte. A tabela mantém os aliases oficiais em vez de apresentar aproximações calculadas como tokens de origem.

Consulte a especificação de apoio

Sistema de design Preline UI: use a escala real do Tailwind e identifique as exceções originais

Use a escala real do Tailwind e identifique as exceções originais

O título da página e a estimativa usam text-3xl, o título da sessão usa text-2xl e o texto do formulário usa text-sm. O preenchimento p-5 do cartão equivale a 1.25rem com a unidade de espaçamento padrão. A margem interna maior sm:p-8 começa no breakpoint pequeno de 640px do Tailwind, enquanto a grade original passa a uma coluna em 760px.

A folha de estilos local usa system-ui e não carrega as fontes personalizadas opcionais indicadas no arquivo de tema do Preline. Em 280px, as abas quebram em duas linhas e o cartão do grupo passa a aparecer abaixo da sessão. São escolhas deliberadas de composição do aplicativo, não uma afirmação de que todos os layouts do Preline tenham essa geometria.

Consulte a especificação de apoio

Sistema de design Preline UI: mantenha os controles de abas e os painéis vinculados por IDs estáveis

Mantenha os controles de abas e os painéis vinculados por IDs estáveis

Cada aba tem um data-hs-tab que aponta para um painel único. O aria-controls da aba e o aria-labelledby do painel repetem essa relação para tecnologias assistivas. Exatamente uma aba inicial tem active e aria-selected=true, e os demais painéis começam ocultos. O HSTabs nativo atualiza esses estados conforme a navegação do usuário.

O estilo visual ativo usa hs-tab-active:bg-primary e hs-tab-active:text-primary-foreground. Essas variantes vêm de variants.css do Preline; sem essa importação, o estado selecionado pode ficar visualmente ambíguo, mesmo que o JavaScript altere as classes corretamente. O aplicativo observa as mudanças de seleção para atualizar o resumo ao lado.

  1. Selecione a oficina de argila e confirme o título, os materiais e a duração.
  2. Aumente o número de participantes de dois para três e confira a estimativa de $54.
  3. Salve o plano local e, em seguida, altere uma aba para limpar a confirmação anterior.

Consulte a especificação de apoio

Sistema de design Preline UI: as opções dos plugins e as restrições dos campos de entrada devem corresponder

As opções dos plugins e as restrições dos campos de entrada devem corresponder

O wrapper de quantidade define min como um, max como seis e step como um em data-hs-input-number. O campo numérico nativo repete essas restrições. Assim, tanto os botões do plugin quanto a validação do navegador usam o mesmo intervalo permitido, em vez de permitir que um número digitado contorne um limite definido apenas no manipulador do botão.

O resumo acompanha os eventos de entrada e alteração, além do callback de alteração do plugin. Uma entrada manual inválida substitui o total por um travessão e desativa o botão Salvar; o manipulador de salvamento também chama reportValidity antes de ler o valor. O limite de seis pessoas é uma restrição de planejamento de exemplo, não uma afirmação sobre disponibilidade real.

Consulte a especificação de apoio

Sistema de design Preline UI: calcule com base no painel ativo, não em rótulos desatualizados

Calcule com base no painel ativo, não em rótulos desatualizados

Cada painel armazena um nome de sessão, preço e duração estáveis como atributos de dados. A função de atualização lê o painel visível e multiplica o valor por pessoa pelo tamanho válido do grupo. Assim, Estúdio de serigrafia, Oficina de cerâmica e Caminhada de desenho são opções realmente distintas, em vez de abas que exibem o mesmo cartão provisório.

A estimativa exibida inclui apenas os materiais. As descrições originais explicam o que esse valor cobre, e a página informa explicitamente que ele não reserva uma vaga. Não há pagamento, consulta de estoque ou agenda externa por trás dos valores. Um fluxo de reservas real exigiria esses sistemas separados e validação no servidor.

Consulte a especificação de apoio

Sistema de design Preline UI: use a entrada manual exportada nesta versão do pacote

Use a entrada manual exportada nesta versão do pacote

O pacote 4.2.0 verificado disponibiliza as exportações nomeadas HSTabs e HSInputNumber em preline/non-auto. O exemplo as importa e chama seus métodos autoInit depois que a marcação existe. Apesar do nome, aqui autoInit é uma busca explícita iniciada pela aplicação, não um gancho implícito de carregamento da página para o pacote inteiro.

Durante a verificação, os caminhos .mjs individuais dos plugins não disponibilizaram uma classe padrão, e importações diretas desses caminhos podiam ser removidas devido aos metadados de efeitos colaterais do pacote. Usar a entrada manual exportada resolveu esse problema concreto de compilação. Por isso, a configuração mostra a importação funcional e versionada, em vez de uma importação genérica do plugin que não foi testada.

Consulte a especificação de apoio

Sistema de design Preline UI: faça a confirmação expirar quando o plano mudar

Faça a confirmação expirar quando o plano mudar

Salvar plano local grava uma frase de status com a sessão exata, a quantidade e o total dos materiais e, em seguida, desativa o botão. Qualquer alteração na quantidade ou na aba selecionada chama update, restaura a mensagem explicativa padrão e recalcula se é possível salvar. Uma frase de confirmação anterior não pode permanecer associada a um novo plano.

O teste local selecionou Oficina de cerâmica, aumentou a quantidade para três e verificou o status resultante de US$ 54. Também inspecionou a página renderizada em 280 px. Um total estático ou um botão que apenas muda o próprio rótulo não comprovaria que os dois plugins nativos e o estado da aplicação estão conectados.

  • Use uma região de status para exibir o resultado local com precisão.
  • Impeça que valores inválidos sejam incluídos no total calculado.
  • Mantenha IDs estáveis para as abas e os painéis ao adaptar a marcação.

Consulte a especificação de apoio

Sistema de design Preline UI: compile o tema, as variantes e a marcação-fonte real

Compile o tema, as variantes e a marcação real do código-fonte

A folha de estilos importa primeiro o Tailwind, depois as variantes do Preline e o tema padrão incluído no pacote. Os caminhos de origem explícitos incluem os arquivos locais HTML, da aplicação JavaScript e da distribuição do Preline, para que as classes utilitárias dependentes de estado estejam disponíveis no CSS gerado. A folha de estilos original do layout vem depois dessas importações.

A prévia independente incorpora o CSS compilado e o JavaScript empacotado e não faz nenhuma solicitação a CDN. Um projeto de produção pode servir os mesmos arquivos de saída separadamente. Mantenha os caminhos relativos à entrada real de CSS; o exemplo reproduzível abaixo coloca todos os arquivos-fonte na raiz do projeto para evitar dependências ocultas de um espaço de trabalho temporário.

Consulte a especificação de apoio

Sistema de design Preline UI: exemplos de componentes

Marcação semântica completa do planejador

IDs das abas, relações entre painéis, ganchos do input-number e uma região de status local explícita.

html
<main class="max-w-5xl mx-auto p-5 sm:p-8"><header><p class="text-xs font-semibold tracking-widest text-muted-foreground-1">STUDIO SATURDAY · SAMPLE PROGRAM</p><h1 class="text-3xl font-semibold tracking-tight mt-3">Choose a different kind of afternoon.</h1><p class="text-sm text-muted-foreground-1 leading-6 mt-3 max-w-2xl">Explore three creative sessions and calculate a sample materials budget for your group. This planner does not book a place.</p></header><div class="planner-grid mt-7"><section class="min-w-0"><nav class="flex flex-wrap gap-2 mb-5" role="tablist" aria-label="Creative sessions"><button type="button" id="tab-print" data-hs-tab="#panel-print" role="tab" aria-controls="panel-print" aria-selected="true" class="active hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Print studio</button><button type="button" id="tab-ceramics" data-hs-tab="#panel-ceramics" role="tab" aria-controls="panel-ceramics" aria-selected="false" class=" hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Clay workshop</button><button type="button" id="tab-drawing" data-hs-tab="#panel-drawing" role="tab" aria-controls="panel-drawing" aria-selected="false" class=" hs-tab-active:bg-primary hs-tab-active:text-primary-foreground py-2 px-3 text-sm rounded-lg border border-border text-foreground hover:bg-layer-hover focus-visible:outline-2 focus-visible:outline-primary">Drawing walk</button></nav><div id="panel-print" role="tabpanel" aria-labelledby="tab-print" class="" data-name="Print studio" data-price="12" data-duration="90 minutes"><div class="session-art print" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">09:30–11:00 · 90 minutes</p><h2 class="text-2xl mt-3 font-semibold">Ink, paper, repeat.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Make a two-color print from a simple cut-paper composition.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Cobalt ink</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Warm white stock</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Registration guide</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $12 per person</p></div></div><div id="panel-ceramics" role="tabpanel" aria-labelledby="tab-ceramics" class="hidden" data-name="Clay workshop" data-price="18" data-duration="120 minutes"><div class="session-art ceramics" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">13:00–15:00 · 120 minutes</p><h2 class="text-2xl mt-3 font-semibold">A shape held by hand.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Build a small pinch vessel and explore three surface textures.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Stoneware clay</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Wooden modeling tool</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Texture samples</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $18 per person</p></div></div><div id="panel-drawing" role="tabpanel" aria-labelledby="tab-drawing" class="hidden" data-name="Drawing walk" data-price="5" data-duration="60 minutes"><div class="session-art drawing" aria-hidden="true"><i></i><b></b><span></span></div><div class="p-5 bg-card rounded-b-xl border border-card-line border-t-0"><p class="text-xs text-muted-foreground-1 font-medium">16:00–17:00 · 60 minutes</p><h2 class="text-2xl mt-3 font-semibold">Notice the edges.</h2><p class="text-sm leading-6 mt-3 text-muted-foreground-1">Make a sequence of quick drawings along an original sample walking route.</p><h3 class="text-sm font-semibold mt-5">Materials included in the estimate</h3><ul class="mt-3 space-y-2 text-sm"><li class="flex gap-2"><span aria-hidden="true">↗</span>Pocket sketchbook</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Soft graphite pencil</li><li class="flex gap-2"><span aria-hidden="true">↗</span>Portable drawing board</li></ul><p class="mt-5 text-sm font-medium">Sample materials allowance: $5 per person</p></div></div></section><aside class="bg-card border border-card-line rounded-xl p-5 self-start"><h2 class="text-lg font-semibold">Your group</h2><label for="people" class="block text-sm mt-5 mb-2">Participants</label><div id="quantity" data-hs-input-number='{"min":1,"max":6,"step":1}' class="flex items-center gap-3 border border-layer-line rounded-lg p-2 bg-layer"><button type="button" data-hs-input-number-decrement aria-label="Decrease participants" class="size-9 shrink-0 rounded-md border border-border disabled:opacity-40">−</button><input id="people" type="number" value="2" min="1" max="6" step="1" data-hs-input-number-input class="w-full min-w-0 text-center bg-transparent"/><button type="button" data-hs-input-number-increment aria-label="Increase participants" class="size-9 shrink-0 rounded-md border border-border disabled:opacity-40">+</button></div><p class="text-xs text-muted-foreground-1 mt-2">1–6 participants · sample planning limit</p><dl class="mt-6 space-y-3 text-sm"><div><dt class="text-muted-foreground-1">Selected session</dt><dd id="selected-name" class="font-semibold mt-1"></dd></div><div><dt class="text-muted-foreground-1">Duration</dt><dd id="selected-duration" class="font-semibold mt-1"></dd></div><div class="pt-4 border-t border-border"><dt class="text-muted-foreground-1">Materials estimate</dt><dd id="total" class="text-3xl font-semibold mt-1"></dd></div></dl><button id="save" class="mt-6 w-full py-3 px-4 bg-primary text-primary-foreground rounded-lg font-medium text-sm hover:bg-primary-hover disabled:opacity-50" type="button">Save local plan</button><p id="feedback" role="status" class="text-xs leading-5 mt-3 text-muted-foreground-1">No booking or payment is created.</p></aside></div></main>

Referência de código

  • As três sessões e seus preços são dados de exemplo originais.
  • O campo de entrada nativo usa as mesmas restrições do plugin.

Inicialização completa do plugin e cálculo

Inicialização manual pela entrada non-auto exportada; a seleção e a quantidade alimentam um único resumo calculado.

javascript
import {HSTabs,HSInputNumber} from 'preline/non-auto';
HSTabs.autoInit();HSInputNumber.autoInit();
const quantity=document.querySelector('#people'),save=document.querySelector('#save'),feedback=document.querySelector('#feedback');
function selected(){return document.querySelector('[role=tabpanel]:not(.hidden)')}
function update(){const panel=selected(),count=Number(quantity.value);document.querySelector('#selected-name').textContent=panel.dataset.name;document.querySelector('#selected-duration').textContent=panel.dataset.duration;document.querySelector('#total').textContent=quantity.checkValidity()&&count>=1?'$'+count*Number(panel.dataset.price):'—';save.disabled=!quantity.checkValidity()||count<1;feedback.textContent='No booking or payment is created.'}
document.querySelectorAll('[data-hs-tab]').forEach(button=>button.addEventListener('click',()=>queueMicrotask(update)));
new MutationObserver(update).observe(document.querySelector('nav'),{subtree:true,attributes:true,attributeFilter:['aria-selected']});
quantity.addEventListener('input',update);quantity.addEventListener('change',update);
const instance=HSInputNumber.getInstance('#quantity');instance.on('change',update);
save.addEventListener('click',()=>{if(!quantity.reportValidity())return;const panel=selected();feedback.textContent=`Saved locally: ${panel.dataset.name}, ${quantity.value} people, $${Number(quantity.value)*Number(panel.dataset.price)} materials estimate.`;save.disabled=true});update();

Referência de código

  • Use as exportações nomeadas de preline/non-auto.
  • Os arquivos .mjs dos subcaminhos versionados do plugin não exportam uma classe padrão.
  • Os eventos de alteração do campo de entrada e os callbacks de alteração do plugin atualizam o resumo.

Composição responsiva original completa

Ilustrações decorativas de serigrafia, cerâmica e desenho ao redor dos plugins nativos de abas e de números.

css
html,body{margin:0;height:auto;min-height:0}body{background:#f7f8fb;font-family:ui-sans-serif,system-ui,sans-serif;color:var(--foreground)}button{cursor:pointer}button:disabled{cursor:default}.planner-grid{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:24px}.session-art{height:200px;position:relative;overflow:hidden;border-radius:12px 12px 0 0}.session-art i,.session-art b,.session-art span{display:block;position:absolute}.print{background:#e2e9f4}.print i{width:160px;height:140px;left:15%;top:45px;background:#2456a7;transform:rotate(-13deg)}.print b{width:150px;height:150px;right:14%;top:30px;background:#f0a979;border-radius:50%;mix-blend-mode:multiply}.print span{width:180px;height:8px;left:20%;top:160px;background:#f9f8ef;transform:rotate(-13deg)}.ceramics{background:#e8d9c8}.ceramics i{width:150px;height:100px;left:25%;top:65px;border-radius:15% 15% 50% 50%;background:#a87862}.ceramics b{width:150px;height:32px;border-radius:50%;left:25%;top:53px;background:#704a3d;box-shadow:inset 0 0 0 10px #bd8f78}.ceramics span{width:150px;height:12px;left:25%;top:171px;background:#c7b39e;border-radius:50%}.drawing{background:#e2e8de}.drawing i{width:160px;height:145px;left:23%;top:25px;background:#fffdf4;transform:rotate(8deg);border:1px solid #d6d8cb}.drawing b{height:90px;width:80px;left:33%;top:49px;border:2px solid #4d655b;transform:rotate(-18deg);border-radius:50% 50% 10% 10%}.drawing span{width:130px;height:7px;background:#ad754c;left:45%;top:145px;transform:rotate(-33deg)}@media(max-width:760px){.planner-grid{grid-template-columns:minmax(0,1fr)}.session-art{height:170px}}@media(max-width:360px){main{padding:14px!important}.session-art i,.session-art b,.session-art span{transform:scale(.8)}.session-art{height:150px}h1{font-size:26px!important}}

Referência de código

  • A arte é original CSS e está oculta para tecnologias assistivas.
  • Esta folha de estilos vem depois das importações do Tailwind e do Preline.
04

Sistema de design Preline UI: configuração do agente de IA

Ponto de partida para implementação

Preline 4.2.0 nativo, verificado. A marcação, a lógica e o CSS completos estão incluídos acima. Os caminhos de origem de input.css pressupõem que os quatro arquivos-fonte estejam na raiz do projeto.

bash
# Create an empty directory and run:
npm init -y
npm install [email protected] [email protected] @tailwindcss/[email protected] esbuild
# Save the complete examples above as body.html, app.js and style.css.
# Create input.css with exactly:
# @import "tailwindcss" source(none);
# @import "./node_modules/preline/variants.css";
# @import "./node_modules/preline/css/themes/theme.css";
# @source "./body.html";
# @source "./app.js";
# @source "./node_modules/preline/dist/*.js";
# @import "./style.css";
npx @tailwindcss/cli -i input.css -o bundle.css --minify
npx esbuild app.js --bundle --format=iife --outfile=bundle.js
# Assemble the actual root document without placeholder markup:
node -e 'const f=require("fs");f.writeFileSync("index.html",`<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Studio planner</title><link rel="stylesheet" href="bundle.css"></head><body>${f.readFileSync("body.html","utf8")}<script src="bundle.js"></script></body></html>`)'
# Serve this directory with your existing static server.

Um prompt para seu projeto

Prompt para agente de IA
Use o Preline 4.2.0 com as importações nomeadas HSTabs e HSInputNumber de preline/non-auto e inicialize explicitamente os dois plugins. Mantenha as três oficinas do Studio Saturday, o intervalo de quantidade de um a seis e o custo dos materiais da oficina selecionada. Calcule o total com base no painel ativo e na quantidade, invalide o plano salvo após qualquer alteração e valide o intervalo numérico antes de salvar localmente. Inclua a configuração de tema e variantes do Tailwind fornecida e o layout original. Não transforme o plano local do estúdio em uma confirmação de reserva ou pagamento.
05

Sistema de design Preline UI: fontes e escopo

Preline npm 4.2.0 nativo com Tailwind CSS 4.3.3. Descrições originais das sessões, ilustrações e valores fictícios para materiais. Salvar armazena apenas o estado local da página; não há reserva, pagamento ou mensagem externa.