Skip to content

Conversation

@guilhermepratac
Copy link
Contributor

@guilhermepratac guilhermepratac commented Sep 18, 2025

Pull Request

Ticket or Issue link

Description

Introduces a highly configurable BottomSheet component, offering flexible presentation options, gesture-based dismissal, and dynamic height adjustment.

Includes comprehensive configuration options for appearance and behavior and provides SwiftUI integration with a custom modifier, router, and navigation host.

Checklist

  • [] I have tested my changes creating a local version (More info in README file).
  • [] I have added tests that prove my solution is effective and works
  • [] New and existing unit tests pass locally with my changes.
  • [] Verify that you are merged with the latest in develop.
  • [] I have run swiftlint and fixed any possible issues of my code.
  • [] I have tested my changes with configuration changes such as rotation, no conection, framework error handling
  • [] I have tested the accessibility of the changes and added them to the screenshots.
  • [] I have added a tag to the pull request that contains the product this pull request is related to.

Screenshots or videos (if applies)

Simulator Screenshot - iPhone 16 - 2025-09-18 at 09 30 11

Introduces a highly configurable BottomSheet component, offering flexible presentation options, gesture-based dismissal, and dynamic height adjustment.

Includes comprehensive configuration options for appearance and behavior and provides SwiftUI integration with a custom modifier, router, and navigation host.

Enhances user experience with smooth transitions and interactive dismissal.
Refines the bottom sheet's behavior and appearance.
This includes setting an initial maximum height for content
and improving the height calculation within navigation controllers.
@guilhermepratac guilhermepratac self-assigned this Sep 18, 2025
Copy link

@icaldana icaldana left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@guilhermepratac

Resumo (TL;DR)

  • Compatibilidade de linguagem: o PR usa package access e marcações Sendable, o que implica Swift 5.9+; o repositório declara Swift 5.5+ → alinhar versão mínima ou trocar package por internal. ([GitHub][1])
  • Concorrência: vários tipos de configuração estão anotados como Sendable, porém carregam UIColor/CGColor (não-Sendable). Remover Sendable ou tornar @unchecked Sendable com justificativa. ([GitHub][1])
  • UI/Apresentação: garantir tudo que toca UIKit marcado com @MainActor (Presenter, TransitioningDelegate, PresentationController, HostingController).
  • Acessibilidade, adaptatividade e testes: adicionar rotas de VoiceOver e testes de gesto/altura.
  • Estilo e ACL: endurecer SwiftLint (explícito de ACL, file_length, type_body_length) e revisar public/package.

Bloqueadores

  1. Matriz de versões (Swift 5.5 vs. package)
    O código novo usa o nível de acesso package (Swift 5.9+). Já o README informa “Swift 5.5+”. Duas opções seguras:
  • Elevar a versão mínima para Swift 5.9 (README e Package.swift) e registrar no CHANGELOG como breaking de ambiente. ([GitHub][2])
  • Trocar packageinternal onde a intenção é ocultar no módulo, mantendo compatibilidade com 5.5.
    Trecho onde package aparece (ex.: BottomSheet+Configuration.swift). ([GitHub][1])
  1. Anotações Sendable em tipos com UIKit/CoreGraphics
    Configuration, PullBar.Appearance e GradientBackground estão Sendable, mas possuem UIColor/CGColor/CGPoint. Esses tipos não são garantidamente thread-safe. Sugestões:
  • Remover Sendable dos tipos puramente de UI ou
  • Usar @unchecked Sendable com docstring explicando a razão e restringir uso a @MainActor. ([GitHub][1])

Exemplo seguro:

@MainActor
package extension BottomSheet {
  // Remover Sendable de tipos que guardam UIKit/CoreGraphics:
  struct Configuration {
    // ...
  }

  enum PullBar {
    struct Appearance { /* ... */ }
    struct GradientBackground { /* ... */ }
  }
}
  1. Garantir @MainActor em componentes de apresentação
    Marcar como @MainActor classes/structs que orquestram UI:
  • BottomSheetPresenter, BottomSheetPresentationController, BottomSheetTransitioningDelegate, BaseHostingController.
    Isso previne chamadas acidentais de fora da main thread.
@MainActor
final class BottomSheetPresentationController: UIPresentationController { /* ... */ }

Qualidade da API e manutenção

  • ACL explícita: onde a intenção é API interna, use internal (ou package se adotarem Swift 5.9 oficialmente). Publique apenas o essencial.
  • final por padrão: classes que não precisam herança (e.g., controllers/handlers) marcadas como final para otimização e clareza.
  • Nomeação e consistência: propriedades como indicatorLineCornerRadius estão OK; mantenha padrão e docs breves nos inits (vocês já estão colocando bons comentários de parâmetro). ([GitHub][1])
  • Disponibilidade/OS: se houver APIs iOS 15/16+ (p.ex., esquinas contínuas), proteja com @available e caminhos alternativos.

Apresentação & Interações

  • Gestos x ScrollViews: como há core de transição e extensões para controladores, validar concorrência do pan com scroll interno (o histórico de commits sugere ajustes em scroll removível/pull bar). Considere exigir que o pan do sheet reconheça só quando o scroll está no topo.
  • Alturas & Safe Area: o arquivo UIView+CalculateHeight.swift deve calcular com systemLayoutSizeFitting e respeitar safe areas/teclado. Faça cache do resultado por traitCollection para evitar thrash.
  • Navegação embutida: há arquivos de “NavigationController/Style” — alinhe push/pop internos do sheet com um estilo previsível (ex.: animações consistentes e altura conservada entre telas).
  • iPad e compact/regular: ofereça largura máxima e centragem em regular.

Nota: houve commit “remove swizzled” — ótimo movimento; manter sem swizzling. ([GitHub][1])


Acessibilidade (faça agora)

  • Pull bar acessível: accessibilityLabel = "Arrastar para expandir ou fechar" + trait .updatesFrequently quando altura muda.
  • Modalidade: accessibilityViewIsModal = true quando apresentado; suporte ao gesto “escape” do VoiceOver para dismiss.
  • Dinamic Type/Contrast: valide cores do gradiente e indicador com contraste adequado; respeitar tamanhos grandes.

SwiftUI Interop

Com BaseHostingController e os modifiers/presenters SwiftUI:

  • Sincronize preferredContentSize com o tamanho do conteúdo SwiftUI quando a tela muda (rotation, Dynamic Type).
  • Exponha um ViewModifier público e minimalista (parece que já existe BottomSheetModifier/Presenter). Valide exemplos no sample app. ([GitHub][1])

Lint, formatação e CI

  • SwiftLint: ative regras como explicit_acl, file_length, type_body_length, cyclomatic_complexity, weak_delegate, redundant_type_annotation.
  • SwiftFormat: garanta trailing commas em multi-linhas para diffs mais limpos.
  • CI: inclua job que falhe em violações de lint e rode testes de snapshot (se houver) em diferentes trait collections.

Testes sugeridos

  • Unitários:

    • Defaults de Configuration (gradiente, altura do pull bar, etc.). ([GitHub][1])
    • Cálculo de altura (mocks de conteúdo com Auto Layout).
  • UI Tests:

    • Gestos: expandir, colapsar, dismiss interativo com scroll no topo/fundo.
    • Rotação e mudança de tamanho (iPad).
    • Acessibilidade (voz de escape, foco inicial no conteúdo do sheet).

Documentação & exemplos

  • Atualize o README para incluir exemplo rápido de apresentação do BottomSheet (UIKit e SwiftUI), parâmetros de configuração (incluindo GradientBackground com cores e locations). ([GitHub][2])

Mudanças concretas (exemplos rápidos)

A) Se mantiver Swift 5.5:
Trocar packageinternal e remover Sendable dos tipos de UI.

// Antes
package struct Configuration: Sendable { /* ... */ }

// Depois (Swift 5.5-5.8)
internal struct Configuration { /* ... */ }

B) Se migrar para Swift 5.9+:

  • README: “Swift 5.9+”; swift-tools-version: 5.9 no Package.swift.
  • Manter package, porém remover Sendable de tipos com UIKit/CoreGraphics (ou justificar @unchecked Sendable em um wrapper puro-dados separado do layer de UI).

@guilhermepratac guilhermepratac marked this pull request as draft September 23, 2025 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants