← Todos os Posts

Liquid Glass no SwiftUI: três padrões de quem lançou o Return no iOS 26

O Liquid Glass da Apple é uma API SwiftUI de uma linha: .glassEffect().1 O Return, meu timer de meditação, usa isso nove vezes entre iOS, macOS e tvOS.2 Um desses usos aplica o modificador a um Shape personalizado que transforma os próprios números do timer em liquid glass, glifo por glifo.

Return no iPhone — os próprios números do timer são renderizados como Liquid Glass via um Shape personalizado (abordado no Padrão 1 abaixo); o seletor de duração é um HUD em Liquid Glass

A pergunta interessante é o que acontece quando você vai além da única linha. As Human Interface Guidelines da Apple definem uma regra estrita de camadas: o Liquid Glass pertence à camada funcional (controles, navegação, UI transitória) e nunca à camada de conteúdo.3 A maioria dos nove usos do Return são aplicações clássicas da camada funcional: seletores, botões, faixas de controle, selos de estado pausado. Os usos interessantes são os três que dobram as regras sem quebrá-las.

Este ensaio percorre três padrões que lancei, as regras que eles respeitam, as armadilhas que me pegaram e a superfície de API que deliberadamente não usei.

As Human Interface Guidelines da Apple definem o Liquid Glass por meio de três variantes de material. A variante regular adapta sua aparência ao que estiver embaixo dela (exemplo à esquerda, escuro; exemplo à direita, claro); a variante clear deixa o detalhe subjacente transparecer com muito menos filtragem:3

Variante regular do Liquid Glass sobre um fundo escuro — referência das HIG da Apple

Variante regular do Liquid Glass sobre um fundo claro — referência das HIG da Apple

Variante clear do Liquid Glass — referência das HIG da Apple, mostrando como a variante clear deixa o detalhe visual do conteúdo subjacente transparecer

Imagens de referência da página de Materials das HIG da Apple.3 Ambas as variantes são o que .glassEffect() produz no SwiftUI; a escolha entre elas é um único argumento do modificador.

TL;DR

  • O iOS 26 entrega o Liquid Glass como .glassEffect(_:in:). A variante padrão é .regular e o shape padrão é Capsule.1
  • O Return usa três padrões que vão além da única linha: glass sobre um Shape personalizado (texto do timer via Core Text glyph paths), o padrão de espelho (reflexo embaixo via cópia invertida e mascarada) e overlays de HUD na camada funcional.
  • A regra das HIG da Apple: Liquid Glass para a camada funcional, materiais padrão para a camada de conteúdo.3
  • Deliberadamente não usei GlassEffectContainer. A API de morphing não tem caso de uso no Return (nenhum elemento glass se transforma em outro), e não fiz benchmark da diferença de desempenho de renderização; este é um trade-off não medido, não uma recomendação.1
  • Armadilhas: glass sobre um fundo plano fica com cara de plano; a renderização de dígitos sem tremedeira precisa de células de largura fixa; o HStack do tvOS ignora o valor de ambiente de direção de layout; o reduce-motion precisa ser respeitado na animação de morph.

Para padrões de UI adjacentes da Apple, leia o mergulho profundo no protocolo de layout do SwiftUI, o sistema tipográfico SF Pro e o vocabulário de Symbol Effects.

A API de uma linha e a regra de camadas

A Apple entrega o Liquid Glass com uma superfície pequena, apresentada como um pilar de design importante na WWDC 2025:113

Text("Hello, World!")
    .font(.title)
    .padding()
    .glassEffect()                              // default: .regular variant, Capsule shape

Text("Hello, World!")
    .glassEffect(in: .rect(cornerRadius: 16))   // custom shape

Text("Hello, World!")
    .glassEffect(.regular.tint(.orange).interactive())  // tint + touch reactivity

Três botões de ajuste: variante (.regular ou .clear), shape (qualquer Shape) e uma cadeia de GlassEffectStyle (tint, interactive). Essa é toda a API para uma única view. A renderização de múltiplas views é tratada por um GlassEffectContainer separado, ao qual chegarei.

A HIG é mais apertada que a API. As Human Interface Guidelines da Apple definem duas camadas em toda interface a partir do iOS 26:3

  1. A camada de conteúdo: o documento, a lista, a foto ou a mídia que a pessoa está consumindo. Use materiais padrão aqui (os já existentes .regularMaterial, .thinMaterial, etc.).
  2. A camada funcional: controles, navegação, tab bars, sidebars, overlays transitórios. Use Liquid Glass aqui.

A instrução específica da Apple: “Don’t use Liquid Glass in the content layer. Liquid Glass works best when it provides a clear distinction between interactive elements and content, and including it in the content layer can result in unnecessary complexity and a confusing visual hierarchy.”3

A regra parece restritiva até você mapeá-la em um app real. O Return é um timer de meditação. Sua camada de conteúdo é a imagem de respiração e o vídeo em loop que roda atrás de tudo. Sua camada funcional é o seletor de duração, a pilha de botões iniciar/pausar/parar, a linha secundária de botões de configurações e (no tvOS) o selo de estado pausado. Oito dos nove usos de glass do Return são aplicações clássicas da camada funcional: três variantes do seletor de duração para os caminhos de código de iOS e macOS, o botão iniciar/pausar, o botão parar, a linha de botões de configurações, o indicador de pausa do tvOS e mais um overlay de controle transitório.4

O nono é o caso-limite deliberado (Liquid Glass nos próprios números do timer), que a próxima seção percorre.

Padrão 1: glass sobre um Shape personalizado

Os números do timer no Return não são texto desenhado sobre um fundo de glass. O glass é o texto. .glassEffect(.clear, in:) aceita qualquer Shape,9 e um Shape é um protocolo que produz um Path.10 Então o truque é: converter a string do timer em um path de glifos usando Core Text,11 e então passar esse path-como-Shape para .glassEffect.56

import SwiftUI
@preconcurrency import CoreText

struct GlassTextShape: Shape {
    let text: String
    let font: CTFont

    func path(in rect: CGRect) -> Path {
        guard !text.isEmpty else { return Path() }
        let combinedPath = CGMutablePath()

        let attrString = NSAttributedString(string: text, attributes: [.font: font])
        let line = CTLineCreateWithAttributedString(attrString)
        guard let runs = CTLineGetGlyphRuns(line) as? [CTRun], !runs.isEmpty else {
            return Path()
        }

        for run in runs {
            let glyphCount = CTRunGetGlyphCount(run)
            guard glyphCount > 0 else { continue }
            var glyphs = [CGGlyph](repeating: 0, count: glyphCount)
            var positions = [CGPoint](repeating: .zero, count: glyphCount)
            let range = CFRange(location: 0, length: glyphCount)
            CTRunGetGlyphs(run, range, &glyphs)
            CTRunGetPositions(run, range, &positions)

            for i in 0..<glyphCount {
                guard let glyphPath = CTFontCreatePathForGlyph(font, glyphs[i], nil) else { continue }
                let transform = CGAffineTransform(translationX: positions[i].x, y: positions[i].y)
                combinedPath.addPath(glyphPath, transform: transform)
            }
        }

        // Core Text y-axis is flipped vs SwiftUI; flip then re-bound and center.
        var swiftPath = Path(combinedPath).applying(CGAffineTransform(scaleX: 1, y: -1))
        let flippedBounds = swiftPath.boundingRect
        let offsetX = rect.midX - flippedBounds.midX
        let offsetY = rect.midY - flippedBounds.midY
        return swiftPath.applying(CGAffineTransform(translationX: offsetX, y: offsetY))
    }
}

Código de produção real de Return/Return/GlassTextShape.swift.5 A função path(in:) usa Core Text para diagramar a string, percorre cada CTRun, extrai o CGPath de cada glifo e os une em um único CGMutablePath. Os dois passos não óbvios vêm depois da união: o sistema de coordenadas do Core Text coloca a origem no canto inferior esquerdo, enquanto o Path do SwiftUI a coloca no canto superior esquerdo, então o path precisa ser invertido via CGAffineTransform(scaleX: 1, y: -1). Depois, o boundingRect do path invertido tem valores de y negativos, então uma translação o recentraliza dentro do rect que o SwiftUI entrega ao Shape. Pule qualquer uma das transformações e os glifos serão renderizados de cabeça para baixo ou fora da tela.

Então a aplicação é uma única linha:

Rectangle()
    .fill(.clear)
    .glassEffect(.clear, in: textShape)
    .frame(width: cellWidth, height: cellHeight)

O Rectangle clear é um placeholder de área de toque; o visual de verdade é qualquer shape que textShape produzir. Com um shape de glyph-path, o material Liquid Glass preenche apenas os contornos dos glifos. O resultado: cada dígito do timer é uma forma de liquid glass separada, refratando qualquer animação que rode atrás dele.6

A nuance da HIG. A regra declarada da Apple é Liquid Glass para a camada funcional, materiais padrão para a camada de conteúdo, com uma exceção explícita: controles interativos transitórios na camada de conteúdo (sliders, toggles) podem receber Liquid Glass quando ativados.3 Os números do timer no Return são exibição de estado, não um controle: eles se atualizam uma vez por segundo a partir de Timer.publish(every: 1, ...) e não têm gesto de toque (o botão iniciar/pausar abaixo deles é o que alterna o estado). Então colocar Liquid Glass neles é um caso-limite deliberado, mais próximo de “controle interativo transitório” por intenção do que por interatividade literal, já que os números são o ponto focal visual que os usuários acompanham a sessão inteira. Estou dobrando a regra, não a quebrando. Um revisor que ler a HIG de forma estrita poderia argumentar que isso deveria ser material padrão; eu argumento que o timer é uma superfície de controle de tempo decorrido da mesma família que um indicador de progresso. Os docs da Apple não julgam o caso diretamente.

Por que Shape personalizado em vez de Text + background. Text renderizado acima de um fundo de glass é percebido como texto sobre glass. Text renderizado como o próprio glass é percebido como uma categoria visual diferente. O usuário percebe os números como primeiro plano funcional, especificamente como um elemento transitório que existe para ser olhado através, não para.

Padrão 2: o padrão de espelho

O Return mostra um reflexo do timer embaixo dele, desaparecendo gradualmente. Código de produção real:6

Return no Mac — o seletor de duração como um overlay de HUD em Liquid Glass, com o tratamento de glass no texto do timer visível acima

VStack(spacing: 0) {
    GlassTimerText(text: displayTime, fontSize: fontSize)
        .accessibilityLabel("Time remaining: \(accessibleDescription)")

    if showReflection {
        GlassTimerText(text: displayTime, fontSize: fontSize)
            .scaleEffect(x: 1, y: -1)
            .mask(
                LinearGradient(
                    stops: [
                        .init(color: .white.opacity(0.2), location: 0),
                        .init(color: .clear, location: 0.6)
                    ],
                    startPoint: .top,
                    endPoint: .bottom
                )
            )
            .offset(y: -8)
            .accessibilityHidden(true)
    }
}

Três transformações compõem o espelho, todas primitivas padrão do SwiftUI:14

  1. scaleEffect(x: 1, y: -1) inverte a segunda cópia de cabeça para baixo.
  2. .mask(LinearGradient(...)) faz o reflexo desaparecer de 20% de opacidade no topo até totalmente transparente a 60% para baixo.
  3. .offset(y: -8) puxa o reflexo 8 pontos para cima para que ele encoste no original em vez de deixar uma emenda visível.

O modificador .accessibilityHidden(true) no reflexo é estrutural. O VoiceOver não deve anunciar o tempo espelhado duas vezes; o accessibilityLabel e o accessibilityAddTraits(.updatesFrequently) do original já estão anexados à instância principal de GlassTimerText acima, e o reflexo é puramente decorativo.

Por que isso funciona especificamente com Liquid Glass. O reflexo herda o material glass de GlassTimerText. Qualquer fundo sobre o qual o original esteja (um gradiente de círculo de respiração, um vídeo, uma cena tingida) refrata através de ambas as cópias. O espelho não precisa de nenhum código específico de glass; o material glass cuida da refração de graça. O efeito inteiro são três modificadores e um gradiente.

O custo de acessibilidade. Usuários com reduce-motion ainda veem o espelho, mas a animação do material glass entre as atualizações de tempo é suprimida em outros pontos via @Environment(\.accessibilityReduceMotion).7 O reflexo em si é estático; só o morph entre as transições de dígitos é animado.

Padrão 3: overlays de HUD em glass para controles transitórios

Os oito usos restantes de glass no Return são aplicações clássicas da camada funcional.4 Cada um segue o mesmo padrão:

Return no Apple Watch — Liquid Glass na camada funcional em uma tela de tamanho pequeno

durationPicker
    .frame(height: 50)
    .frame(maxWidth: 320)
    .glassEffect()
    .padding(.horizontal, 20)
    .transition(.opacity.combined(with: .scale(scale: 0.95)))

O .transition(.opacity.combined(with: .scale(scale: 0.95))) é a parte estrutural. Liquid Glass em controles transitórios só fica certo quando os controles transitam. Um HUD de glass estático que fica permanentemente na tela é percebido como chrome. Um HUD de glass que entra com fade e scale quando o usuário toca e sai quando ele desvia o olhar é percebido como uma superfície de controle momentânea.

Os docs da Apple sobre glassEffect apontam isso implicitamente: o modificador “captures the content to send to the container to render” e “react[s] to touch and pointer interactions in real time.”1 Os ganchos de animação não estão na API, mas o pipeline de renderização presume que os elementos glass se movem. Elementos glass estáticos perdem essa affordance.

O Return usa o padrão para o seletor de duração (sobe quando o usuário toca), o botão de alternância iniciar/pausar (sempre visível, mas escala ao ser pressionado), o botão parar (visível só no meio da sessão), a linha de botões de configurações (uma faixa de controle horizontal abaixo do seletor de duração) e o selo de estado pausado do tvOS (visível só quando uma sessão está pausada na Apple TV). Todos os cinco contextos respeitam a regra da camada funcional da HIG.3

Referência da Apple no tvOS: overlays de Liquid Glass flutuando acima de um fundo de vídeo, deixando a mídia subjacente transparecer — o caso de uso canônico de UI a 3 metros de distância

Referência das HIG da Apple: overlays de Liquid Glass no tvOS ficam acima da camada de mídia, deixando-a transparecer.3 A implementação do Return no tvOS segue o mesmo modelo: os controles flutuam acima do fundo de fogo/floresta/água em loop.

Uma nota sobre toolbar vinda dos labs. Um painel do SwiftUI Group Lab da WWDC 2026 afinou como isso se desenrola em toolbars. Colocar conteúdo não-glass em uma toolbar — o exemplo era uma foto de perfil — pede sharedBackgroundVisibility(.hidden) para que o item largue seu fundo de glass compartilhado e mostre a foto diretamente.15 O painel sinalizou um refinamento: uma API mais nova remove apenas a margem de conteúdo de um botão de toolbar, onde antes ocultar o fundo era a única alavanca e ela removia o fundo e a margem juntos. Para os botões de toolbar em si, o painel direcionou para o estilo de botão prominent (glassProminent) e buttonBorderShape em vez de partir para .glassEffect diretamente em um botão. A posição subjacente da HIG é a mesma regra de camadas em que este post se apoia: o Liquid Glass pertence ao chrome, não à área de conteúdo, porque uma superfície de glass sem conteúdo rolando por baixo dela não tem nada a refratar.153

A questão do GlassEffectContainer

A Apple recomenda GlassEffectContainer sempre que um app usa .glassEffect() em múltiplas views, por dois motivos: melhor desempenho de renderização (os efeitos glass são agrupados em lote) e a capacidade de transformar (morph) shapes um no outro durante transições.1

Eu não o usei. O raciocínio é específico da aplicação, não uma refutação da orientação da Apple. O Return tem nove views glass, nenhuma das quais precisa se transformar em outra.46 O seletor de duração nunca anima até virar o botão iniciar. O texto do timer nunca anima até virar a linha de botões de configurações. Cada elemento glass é independente. A API de morphing não teria caso de uso para disparar, e as regras de espaçamento do container restringiriam layouts que hoje não precisam de coordenação.

O argumento do desempenho de renderização eu não consigo refutar totalmente sem medição. Os docs da Apple alertam que “demais” efeitos glass fora de um container podem degradar o desempenho.1 As nove views do Return nunca compartilham a tela ao mesmo tempo (o seletor de duração só aparece no estado de menu, o botão parar só quando pausado no meio da sessão). Em qualquer frame dado, conto três ou quatro elementos glass visíveis, o que tem sido suave em todos os dispositivos que testei entre iOS, iPadOS, macOS, watchOS e tvOS, mas não rodei um trace no Instruments comparando o que está envolto em container contra o que é só modificador. Então o enquadramento honesto: o Return pula o GlassEffectContainer com base em uma experiência de usuário observada como boa, não em uma equivalência de desempenho medida.

A regra que tirei disso: GlassEffectContainer é para apps em que múltiplos elementos glass estão visíveis e animando simultaneamente. O exemplo da Apple é a renderização de um conjunto de símbolos com glassEffectUnion(id:namespace:): quatro símbolos de clima que fluidamente se fundem e se separam como uma única unidade.1 Esse é um caso de uso clássico. Se um recurso futuro do Return precisar que elementos glass se transformem ou compartilhem as regras de espaçamento de um container, o container é a ferramenta certa para adicionar então. Para o app de hoje, ainda não cheguei a esse caso.

As armadilhas que me pegaram

Três bugs reais de produção:

Tremedeira dos dígitos de glass. O SF Pro Rounded tem dígitos de largura variável na renderização proporcional. À medida que o timer fazia a contagem regressiva, a string exibida mudava de comprimento, e o HStack ao redor refluía a cada segundo, fazendo o timer inteiro tremer. A correção: células de largura fixa para cada caractere. Cada dígito recebe um cellWidth de fontSize * 0.6, cada dois-pontos recebe fontSize * 0.3, e o HStack vira um grid estável.6

HStack(spacing: 0) {
    ForEach(Array(text.enumerated()), id: \.offset) { _, char in
        let isColon = char == ":"
        let cellWidth = isColon ? colonCellWidth : digitCellWidth
        GlassDigitCell(character: String(char), font: ctFont,
                       cellWidth: cellWidth, cellHeight: cellHeight)
    }
}

As células não são padrão da Apple; são uma solução alternativa para a renderização de largura proporcional em tamanhos de fonte fixos e pequenos. O SF Pro Rounded da Apple com .monospacedDigit() resolveria o mesmo problema em Text, mas o modificador não está disponível em um renderizador de glass baseado em Shape personalizado. O layout de células fixas é o substituto.

Override de direção de layout no tvOS. O mesmo GlassTimerText rodava em iOS, iPadOS, macOS e tvOS. No tvOS especificamente, o HStack ficava espelhado sob um ambiente de idioma da direita para a esquerda mesmo que a versão de iOS respeitasse o override no ambiente. A correção: fixar a direção de layout tanto pelo valor de ambiente quanto pelo modificador explícito flipsForRightToLeftLayoutDirection(false), aplicado diretamente ao HStack de células de dígitos (o VStack pai aplica o override de ambiente separadamente, para que a cópia do reflexo o herde):6

HStack(spacing: 0) { ... }
    .flipsForRightToLeftLayoutDirection(false)
    .environment(\.layoutDirection, .leftToRight)

O motivo: o HStack do tvOS parece ignorar o override no nível de ambiente em algumas versões, e flipsForRightToLeftLayoutDirection(false) é o contrato explícito de não-espelhar, que é respeitado de forma mais confiável.12 Cinto e suspensórios.

Reduce-motion no morph dos dígitos. O Liquid Glass anima transições de morph entre strings exibidas por padrão. Usuários com accessibilityReduceMotion ativado viam o morph como uma piscada. A correção:6

.animation(reduceMotion ? nil : .easeInOut(duration: 0.15), value: displayTime)

O modificador de animação lê @Environment(\.accessibilityReduceMotion) e desativa a transição inteira quando o reduce-motion está ligado. A orientação de acessibilidade da Apple é explícita: qualquer animação decorativa precisa respeitar a preferência de movimento do usuário.7

Quando não usar Liquid Glass

A recusa faz parte do design.

Não coloque Liquid Glass na camada de conteúdo. A HIG da Apple é explícita, e ignorar a regra produz uma hierarquia confusa: o usuário não consegue distinguir o que é interativo e o que é conteúdo.3 Se um efeito glass está decorando uma linha de lista ou um card de foto, o design está brigando com a plataforma.

Não use glass sobre um fundo plano. O Liquid Glass refrata o que está atrás dele. Se “o que está atrás dele” for uma única cor sólida, a refração não tem nada para curvar, e o resultado é percebido como um retângulo tingido e plano. Ou coloque glass sobre conteúdo variado (um gradiente, uma imagem, um vídeo) ou simplesmente não use glass. A tela do timer do Return roda imagens de capa baseadas em tema e vídeo em loop como fundo através do VideoBackgroundView,4 justamente para que os elementos glass acima dele sempre tenham textura a refratar.

Tenha cautela com glass sobre conteúdo de alta frequência. A renderização do material glass é limitada pela GPU, e a animação de morph padrão entre mudanças de shape do glass é ela mesma uma animação. Um timer que se atualiza uma vez por segundo está bem nos meus testes; uma waveform ou um visualizador de áudio a 60 Hz não está comprovado e provavelmente briga com a animação de morph. Não fiz benchmark do limite superior; trate isto como uma heurística, não como um limiar medido. Os docs da Apple não publicam um.

Não lance glass sem testar o reduce-motion. Toda animação de glass deve ser condicionada a accessibilityReduceMotion.7 O morph padrão entre shapes de glass é um efeito cinético, não apenas um fade.

O que o Liquid Glass significa para apps que lançam no iOS 26+

A tese é pequena. O Liquid Glass é uma API de uma linha apenas quando o app já respeita a regra de camadas da HIG. Um app SwiftUI que coloca controles na camada funcional e conteúdo na camada de conteúdo pode adotar o Liquid Glass com modificadores .glassEffect() e parecer nativo por padrão.

Apps que misturam as duas camadas (controles dentro de linhas de lista, barras de navegação tratadas como conteúdo, chrome decorativo em cards de foto) adotarão o Liquid Glass e parecerão errados. O material está correto; a arquitetura embaixo dele não.

O padrão de Shape personalizado (Padrão 1) estende a regra de forma limpa. Qualquer coisa que seja funcionalmente um controle pode receber Liquid Glass, mesmo que não pareça um “controle” no sentido convencional. Um timer é um controle, um medidor de nível é um controle, um indicador de progresso é um controle. Liquid Glass em cada um deles está dentro da especificação.

Combine este post com meus textos anteriores sobre entregar a camada de dados do mesmo app através de App Intents e através de um servidor MCP. A camada visual é a terceira superfície da mesma pilha: entidades tipadas para a IA do sistema, formato de arquivo para agentes cross-LLM e Liquid Glass para o humano no dispositivo.8

FAQ

Posso usar .glassEffect() em plataformas que não sejam iOS 26?

O modificador .glassEffect() é iOS 26+, iPadOS 26+, macOS 26+, watchOS 26+, tvOS 26+, visionOS 26+. Plataformas anteriores ao 26 têm .background(.regularMaterial) e similares, que produzem efeitos de vidro fosco, mas não a nova refração do Liquid Glass.1

O GlassEffectContainer muda o visual?

Elementos glass envoltos em container podem mesclar seus shapes quando suas regras de espaçamento causam sobreposição. Sem um container, cada .glassEffect() é independente. Para apps em que os elementos glass devem se fundir fluidamente durante a animação, o GlassEffectContainer é a ferramenta certa. Para apps em que cada elemento glass permanece distinto, um container é custo extra.1

Por que não usar Text diretamente com .foregroundStyle(.thinMaterial)?

thinMaterial é um material padrão, não Liquid Glass. O visual é um overlay de vidro fosco, não o efeito refrativo de glass-com-curvatura-de-luz do Liquid Glass.3 Para texto que deva parecer especificamente o novo material, .glassEffect(.clear, in: customShape) é o caminho suportado.

Como capturo um screenshot de Liquid Glass para marketing?

Os efeitos glass são renderizados pela GPU em tempo de execução, então os screenshots são tirados do simulador ou do dispositivo com o efeito já aplicado. As imagens oficiais de referência de Liquid Glass da Apple vêm das páginas de documentação das HIG e das sessões da WWDC 2025.3

O GlassTextShape funciona para texto arbitrário ou só para dígitos?

Qualquer string que o Core Text consiga diagramar funciona. O Return o usa para dígitos e um dois-pontos, mas o mesmo Shape funciona para letras, símbolos, emoji (com a fonte certa) ou strings mistas. O desempenho é limitado pela contagem de glifos; um parágrafo longo renderizado como glass seria caro, mas um timer de seis caracteres é trivial.


Três padrões, uma regra e uma API que deliberadamente pulei. O Liquid Glass é a terceira superfície de um app no iOS 26+, posicionada por cima de entidades tipadas e formatos de arquivo compartilhados. A API de uma linha é real. A regra da HIG embaixo dela é o que faz a única linha funcionar.

Referências


  1. Apple Developer, “Applying Liquid Glass to custom views”. Documentation for the glassEffect(_:in:) modifier, GlassEffectContainer, glassEffectUnion(id:namespace:), glassEffectID(_:in:), and GlassEffectTransition. Default variant .regular, default shape Capsule

  2. Author’s Return, a meditation-timer app published on the App Store on April 21, 2026, available for iPhone, iPad, Mac, Apple Watch, and Apple TV. Uses SwiftUI, SwiftData, and HealthKit on iOS 26+ / macOS 26+. 

  3. Apple Developer, “Materials” Human Interface Guidelines. Defines the functional vs content layer rule for Liquid Glass: “Don’t use Liquid Glass in the content layer.” Lists the regular and clear variants and their intended uses. 

  4. Production code in Return/Return/ContentView.swift (seven .glassEffect() call sites), Return/Return/GlassTimerText.swift (one call site on GlassDigitCell), and Return/ReturnTV/TVContentView.swift (one call site on the tvOS “Paused” indicator). Total nine. Plus Return/Return/VideoBackgroundView.swift, which renders the theme-based cover imagery and looped video that the glass elements refract through. 

  5. Production code in Return/Return/GlassTextShape.swift. The Shape-conforming wrapper around Core Text. Created November 26, 2025, included in shipped App Store v1.0. 

  6. Production code in Return/Return/GlassTimerText.swift. GlassDigitCell, GlassTimerText, and GlassTimerDisplay views. Implements fixed-width cell layout, the mirror reflection, and reduce-motion gating. 

  7. Apple Developer, “accessibilityReduceMotion” environment value. Apps must honor the user’s motion preference; default morph animations on Liquid Glass should be gated on the value. 

  8. Author’s analysis in App Intents Are Apple’s New API to Your App and Two Agent Ecosystems, One Shopping List. The three-surface model: App Intents for Apple Intelligence, MCP for cross-LLM agents, Liquid Glass for the human at the device. 

  9. Apple Developer, “glassEffect(_:in:isEnabled:)” on View. The in: parameter accepts any Shape-conforming type. The default shape is Capsule

  10. Apple Developer, “Shape” protocol. A Shape is any type that produces a Path for a given rectangle. Custom shapes can wrap arbitrary CGPath data. 

  11. Apple Developer, “Core Text Programming Guide” and CTLineCreateWithAttributedString. Core Text is the lower-level text engine used to lay out attributed strings into glyph runs and extract per-glyph paths. 

  12. Apple Developer, “flipsForRightToLeftLayoutDirection(_:)”. Explicitly overrides RTL mirroring on a View regardless of the surrounding \.layoutDirection environment value. 

  13. Apple, “WWDC 2025 Highlights” via Apple Newsroom. Liquid Glass announced as the unifying design material across iOS 26, iPadOS 26, macOS 26, watchOS 26, tvOS 26, and visionOS 26. Sessions: “Meet Liquid Glass” (WWDC 2025), “Build a SwiftUI app with Liquid Glass”

  14. Apple Developer, “LinearGradient”, “scaleEffect(x:y:anchor:)”, “mask(_:)”. Standard SwiftUI primitives, all available since iOS 13. 

  15. Apple, WWDC 2026 SwiftUI Group Lab (session 2). Paraphrased from a locally transcribed recording of the WWDC 2026 SwiftUI Group Lab (session 2); Apple publishes no official captions for the labs. Source for hiding a toolbar item’s shared glass background to show non-glass content (a profile photo), the newer API that removes only a toolbar button’s content margin rather than the background and margin together, the preference for the prominent glass button style and buttonBorderShape over .glassEffect on a button, and the chrome-not-content layering rationale. The supporting symbols are documented at sharedBackgroundVisibility(_:) on CustomizableToolbarContent, which takes a Visibility value such as .hidden, and buttonBorderShape(_:); glassProminent is the prominent Liquid Glass PrimitiveButtonStyle. The specific content-margin API named in the lab could not be confirmed against Apple’s published documentation, so it is described by behavior rather than asserted by symbol. 

Artigos relacionados

HealthKit + SwiftUI no iOS 26: autorização, tipos de amostra e padrões multiplataforma a partir do envio de dois apps

Padrões reais de produção do Water (rastreamento de água, HKQuantitySample) e do Return (sessões mindful, HKCategorySamp…

16 min de leitura

Internos do @Observable: A macro, o registrar e o que o ObservableObject errou

O @Observable substitui o modelo de transmissão do ObservableObject por rastreamento de acesso por propriedade. A expans…

10 min de leitura

Gosto é infraestrutura

À medida que agentes geram mais do que vai para produção, o teto de qualidade é definido por quão bem você codifica julg…

6 min de leitura