Modais
5 modais ativos no app — anatomy, tokens reais e diferenças entre variantes.
CityPickerModal
Bottom sheet de busca de cidades e aeroportos para o formulário de voo. Slide-up em 220ms, arrastar > 80px fecha. Background #000, tem drag handle.
Bottom sheet · #000 bg · drag handle
| Propriedade | Valor |
|---|---|
sheet.bg | #000000 (colors.background) |
sheet.borderTopRadius | radius.lg (16px) |
sheet.maxHeight | 90% |
sheet.paddingH | spacing.md (16px) |
sheet.paddingBottom | 56px (spacing.xl + 24) |
handle | 40×4px, rgba(255,255,255,0.3) |
searchWrap.bg | white10 (rgba(255,255,255,0.10)) |
searchWrap.borderRadius | radius.sm (8px) |
searchWrap.minHeight | 48px |
cityName.fontSize | 16px, Medium |
cityDetail.fontSize | 13px, white60 |
cityRow.borderBottom | 1px rgba(255,255,255,0.08) |
animation.open | translateY 48→0, 220ms |
swipe.close | dy > 80 ou vy > 1.0 |
ViatorDestinationPickerModal
Bottom sheet de destinos para passeios Viator. Background mais escuro #0A0D11, search pill (borderRadius 100), altura fixa 85%, sem drag handle, border dinâmica (white60 → #4494FC). Seções "Recentes" e "Destinos populares". Debounce 320ms.
Bottom sheet · #0A0D11 bg · pill search · sem handle
| Propriedade | Valor | Nota |
|---|---|---|
sheet.bg | #0A0D11 | Diferente do CityPickerModal (#000) |
sheet.height | 85% | Fixo — não maxHeight |
drag handle | nenhum | Diferente do CityPickerModal |
closeBtn | 36×36, borderRadius 18 | bg white10 |
searchWrap.height | 54px (inputHeight) | |
searchWrap.borderRadius | 100 (pill) | Diferente do CityPickerModal (8px) |
searchWrap.bg | transparent | Diferente do CityPickerModal (white10) |
searchWrap.border | white60 → #4494FC (dinâmico) | |
iconWrap | 40×40, borderRadius 8, white10 | Ausente no CityPickerModal |
cityName.fontFamily | Semibold | Medium no CityPickerModal |
cityDetail.fontSize | 14px | 13px no CityPickerModal |
recentes | AsyncStorage, max 6 | embarko:viator-recent-destinations:v1 |
debounce | 320ms |
AirlinePickerModal
Modal full-screen — não é bottom sheet. animationType="slide"cobre a tela toda. Busca local em ALL_AIRLINES, sem API, sem debounce. Logos via images.kiwi.com. autoFocus: true.
Full-screen · animationType "slide" · #000 bg
| Propriedade | Valor | Nota |
|---|---|---|
animationType | "slide" | Full-screen, não bottom sheet |
overlay.bg | #000 (colors.background) | |
overlay.paddingTop | insets.top | SafeAreaInsets |
closeBtn | 40×40, borderRadius 20 | Maior que ViatorPicker (36×36) |
searchWrap.height | 54px (inputHeight) | |
searchWrap.borderRadius | radius.sm (8px) | |
searchWrap.bg | white10 | |
searchWrap.border | 1px rgba(255,255,255,0.10) | |
logoWrap | 40×40, borderRadius 20 (círculo) | |
logo.url | images.kiwi.com/airlines/64/{CODE}.png | |
rowName.fontSize | 16px, Medium | |
rowCode.fontSize | 14px, white60 | |
busca | filtro local em ALL_AIRLINES | Sem API, sem debounce |
SaveToFavoritesModal
Bottom sheet com dois modos: list (grid de listas existentes) e create (criar nova lista). Animação spring (damping 50, stiffness 350). Após salvar, toast azul com "Salvo em {cidade}".
components/SaveToFavoritesModal.tsxMode: list
Mode: create
Toast (3.5s auto-dismiss)
| Propriedade | Valor | Nota |
|---|---|---|
sheet.bg | #111318 | Mais claro que o app |
sheet.maxHeight | 92% | |
closeBtn | 36×36, borderRadius 18 | bg white10 |
animation.open | spring, damping 50, stiffness 350 | |
folderImage.borderRadius | 16px | |
folderName.fontSize | 20px, Semibold | |
nameInput.height | 52px | |
nameInput.border | 1px rgba(255,255,255,0.6) | |
createBtn.bg | #4494FC | |
createBtn.disabled | opacity 0.45 | Quando input vazio |
toast.bg | #4494FC | |
toast.autoDismiss | 3500ms |
DateRangeModal
Seletor de datas de ida e volta com calendário, quick chips (Hoje / Amanhã) e footer com Limpar + Concluído. Background #000, height 90%.
Bottom sheet · #000 bg · height 90%
| Propriedade | Valor | Nota |
|---|---|---|
sheet.bg | #000 (colors.background) | Igual ao CityPickerModal |
sheet.height | 90% | |
header.height | 52px | |
header.borderBottom | 1px rgba(255,255,255,0.08) | |
quickChip.height | 44px | |
quickChip.radius | 12px | |
calendar.height | 410px | react-native-calendars |
doneBtn.height | 50px | |
doneBtn.borderRadius | 999 (pill) | |
doneBtn.bg | #4494FC | |
clearText | white60, textDecorationLine underline |
| Propriedade | CityPickerModal | ViatorDestinationPickerModal |
|---|---|---|
sheet.bg | #000000 | #0A0D11 |
sheet.height | maxHeight 90% | height 85% (fixo) |
| drag handle | sim | não |
| closeBtn | não tem | 36×36, borderRadius 18 |
searchWrap.radius | radius.sm (8px) | 100 (pill) |
searchWrap.bg | white10 | transparent |
searchWrap.border | nenhuma | white60 → #4494FC |
cityName.fontFamily | Medium | Semibold |
cityRow.gap | spacing.sm (8px) | 12px |
| iconWrap | não tem | 40×40, borderRadius 8 |
| Recentes | não tem | AsyncStorage, max 6 |
| Populares | não tem | lista fixa |