Tematização de iframe
Chastify envia informações de tema para extensões de iframe para que sua interface de usuário corresponda à página de bloqueio onde está incorporada.
Não presuma que o usuário esteja usando um tema escuro. Sua extensão pode ser aberta em temas claros, escuros, personalizados, translúcidos e de alto contraste.
A opção padrão mais segura é tratar o payload ui do iframe como a fonte de referência para a cor de fundo da página, cor do texto e cor da borda, e então derivar seus próprios painéis e ícones legíveis a partir do ui.isDark.
Carga útil do tema
Quando Chastify abre seu iframe, ele anexa uma carga útil JSON codificada em URI a location.hash.
A carga útil inclui ui:
{
"bridge": {
"v": 1,
"nonce": "request-nonce",
"parentOrigin": "https://chastify.net"
},
"sessionId": "extension-session-id",
"lockId": "lock-id",
"ui": {
"isDark": true,
"bg": "rgb(10, 10, 10)",
"text": "#e5e7eb",
"border": "#27272a"
}
}
Significados dos campos:
ui.isDark: indica se a página principal está usando um tema escuro no momento.ui.bg: fundo da página/superfície do host. Pode ser uma cor ou um fundo CSS complexo.ui.text: cor primária legível do texto.ui.border: cor da borda que corresponde ao tema principal.
ui.bg pode ser uma string CSS completa para a cor de fundo, não apenas um código hexadecimal. Use-o como um valor CSS background, e não como um valor que você analisa manualmente.
Analise o hash
type ChastifyThemePayload = {
ui?: {
isDark?: boolean;
bg?: string;
text?: string;
border?: string;
};
};
export function parseHashPayload(): ChastifyThemePayload | null {
const raw = window.location.hash.startsWith("#")
? window.location.hash.slice(1)
: window.location.hash;
if (!raw) return null;
try {
return JSON.parse(decodeURIComponent(raw));
} catch {
return null;
}
}
Variáveis CSS mínimas
Converter a carga útil em variáveis CSS uma única vez na inicialização:
const payload = parseHashPayload();
const ui = payload?.ui ?? {};
const isDark = ui.isDark !== false;
document.documentElement.style.setProperty("--chastify-bg", ui.bg || (isDark ? "#040711" : "#f8fafc"));
document.documentElement.style.setProperty("--chastify-text", ui.text || (isDark ? "#e5e7eb" : "#0f172a"));
document.documentElement.style.setProperty("--chastify-border", ui.border || (isDark ? "#27272a" : "#e2e8f0"));
document.documentElement.dataset.themeMode = isDark ? "dark" : "light";
Utilize essas variáveis no shell do seu aplicativo:
html,
body,
#root {
min-height: 100%;
margin: 0;
}
body {
background: var(--chastify-bg);
color: var(--chastify-text);
}
.panel {
border: 1px solid var(--chastify-border);
}
Exemplo de React
import { useMemo } from "react";
function getTheme(payload: any) {
const ui = payload?.ui ?? {};
const isDark = ui.isDark !== false;
return {
isDark,
pageStyle: {
background: ui.bg || (isDark ? "#040711" : "#f8fafc"),
color: ui.text || (isDark ? "#e5e7eb" : "#0f172a"),
} satisfies React.CSSProperties,
panelClass: isDark
? "border-white/10 bg-black/35 text-slate-100"
: "border-slate-200 bg-white/85 text-slate-950 shadow-sm",
mutedClass: isDark ? "text-slate-400" : "text-slate-600",
badgeClass: isDark
? "bg-sky-400/15 text-sky-200"
: "bg-sky-50 text-sky-900 ring-1 ring-sky-200",
};
}
export function ExtensionApp({ payload }: { payload: any }) {
const theme = useMemo(() => getTheme(payload), [payload]);
return (
<main style={theme.pageStyle} className="min-h-screen p-4">
<section className={`rounded-2xl border p-4 ${theme.panelClass}`}>
<h1 className="text-xl font-bold">My Extension</h1>
<p className={`mt-2 text-sm ${theme.mutedClass}`}>
This text stays readable on light and dark Chastify themes.
</p>
<span className={`mt-3 inline-flex rounded-full px-3 py-1 text-xs font-semibold ${theme.badgeClass}`}>
Connected
</span>
</section>
</main>
);
}
Padrão de vento de cauda
Se você usa Tailwind, crie um branch a partir de ui.isDark para cada superfície que contém texto.
const isDarkTheme = payload?.ui?.isDark !== false;
const panelClass = isDarkTheme
? "border-white/10 bg-black/30 text-slate-100"
: "border-slate-200 bg-white/85 text-slate-950 shadow-sm";
const successClass = isDarkTheme
? "border-emerald-300/20 bg-emerald-400/10 text-emerald-100"
: "border-emerald-500/25 bg-emerald-50 text-emerald-950";
const errorClass = isDarkTheme
? "border-rose-300/20 bg-rose-400/10 text-rose-100"
: "border-rose-500/25 bg-rose-50 text-rose-950";
Utilize as classes escolhidas onde o texto será renderizado:
<div className={`rounded-xl border px-3 py-2 text-sm ${result.ok ? successClass : errorClass}`}>
<div className="font-semibold">{result.title}</div>
<div className="mt-1 opacity-85">{result.message}</div>
</div>
Atualizações de temas ao vivo
O servidor pai pode enviar atualizações de tema em tempo real enquanto seu iframe estiver aberto:
type UiUpdateMessage = {
type: "chastify:ext:ui";
v: 1;
nonce: string;
ui: {
isDark?: boolean;
bg?: string;
text?: string;
border?: string;
};
};
Ouça essa mensagem e verifique o nonce:
const nonce = payload.bridge.nonce;
const parentOrigin = payload.bridge.parentOrigin;
window.addEventListener("message", (event) => {
if (event.origin !== parentOrigin) return;
const msg = event.data as Partial<UiUpdateMessage>;
if (msg.type !== "chastify:ext:ui" || msg.v !== 1) return;
if (msg.nonce !== nonce) return;
applyTheme(msg.ui);
});
Erros comuns
- Codificação fixa de
text-whiteoutext-*-100(em tom claro) nos cartões, sem uma alternativa de tema claro. - Estilizar o fundo da página, mas esquecer de cartões aninhados, emblemas, anéis de progresso e feeds de resultados.
- Tratando
ui.bgcomo uma cor hexadecimal simples. Pode ser um gradiente ou uma string de fundo CSS normalizada pelo navegador. - Ao usar controles de formulário nativos sem definir a cor de fundo e a cor do texto, as opções de seleção podem ficar ilegíveis em temas escuros.
- Supondo que seja necessário recarregar o iframe para que as alterações de tema ocorram, fique atento ao código
chastify:ext:uise desejar receber atualizações em tempo real.
Os dados do tema são apenas dados de apresentação. Não os utilize para autorização, decisões de confiança, lógica de desbloqueio, recompensas, punições ou identidade de sessão no servidor.
Lista de verificação
Antes de publicar sua extensão iframe:
- Tema de teste de luz.
- Testar o tema escuro.
- Teste um tema personalizado, se disponível.
- Verifique se todos os cartões, botões, crachás, controles de formulário, indicadores de progresso e mensagens de resultado têm contraste legível.
- Verifique se o texto ainda cabe na tela do celular.
- Verifique se o iframe se redimensiona automaticamente após alterações no tema ou no conteúdo.
A seguir: Início rápido do iframe ou Exemplos de API.