Inputs
Todos os campos de entrada do app — 3 componentes com tokens reais, estados e código fonte.
SearchInput (pill)
Para onde você quer ir?
OriginDestination
Saindo de
Indo para
TripTypeSelector
Ida e volta
1
Inputs
Clique em cada input para simular o estado focused.
SearchInput (Pill)
Input principal de busca. Usado na home para destino e em outras buscas rápidas. Pill perfeito com 54px de altura, fundo white10 que clareia no estado focused.
Component/SearchInputVariants: Default, Focused — components/SearchInput.js
Para onde você quer ir?
DefaultParis
Focused / Com valor| Propriedade | Valor | Descrição |
|---|---|---|
height | inputHeight (54px) | Token compartilhado com outros inputs |
borderRadius | 100 | Pill perfeito |
backgroundColor | colors.white10 | rgba(255,255,255,0.10) |
borderWidth | 1 | |
borderColor | colors.white10 | Não muda no focused |
paddingHorizontal | spacing.md (16px) | |
gap | spacing.sm (8px) | Entre ícone e texto |
fontSize | 16 | |
fontFamily | Medium | General Sans Medium |
color (text) | colors.white (#FFFFFF) | |
color (placeholder) | colors.white60 | rgba(255,255,255,0.60) |
bg (focused) | rgba(255,255,255,0.18) | Border não muda |
iconSize | 20 | MaterialIcons, color white |
tsx
copy
import { SearchInput } from '@/components/SearchInput';
<SearchInput
icon="search"
placeholder="Para onde você quer ir?"
value={destination}
onPress={() => openDestinationPicker()}
/>
// StyleSheet interno — SearchInput.js:
// input: {
// flexDirection: 'row',
// alignItems: 'center',
// gap: spacing.sm, // 8
// height: inputHeight, // 54
// paddingHorizontal: spacing.md, // 16
// borderRadius: 100,
// backgroundColor: colors.white10,
// borderWidth: 1,
// borderColor: colors.white10,
// },
// inputFocused: {
// backgroundColor: 'rgba(255, 255, 255, 0.18)',
// },
// text: { flex: 1, fontSize: 16, color: colors.white, fontFamily: Medium },
// placeholder: { color: colors.white60 }OriginDestinationInput
Input duplo de origem e destino num único container pill. Altura total de 109px (2 × 54px + 1px separador). Botão de swap posicionado absolutamente à direita, com animação de rotação 180° via Reanimated.
Component/OriginDestinationInputVariants: Default, Origin focused, Dest focused — components/OriginDestinationInput.js
Saindo de
Indo para
São Paulo (GRU)
Indo para
| Propriedade | Valor | Descrição |
|---|---|---|
height (container) | rowHeight*2 + 1 (109px) | 2 rows + 1px separator |
borderRadius | radius.sm (8px) | |
backgroundColor | colors.white10 | rgba(255,255,255,0.10) |
borderWidth | 1 | |
borderColor | colors.white10 | |
rowHeight | 54px | Cada linha |
paddingHorizontal | spacing.md (16px) | |
gap | spacing.sm (8px) | Entre ícone e texto |
row focused bg | rgba(255,255,255,0.18) | Só a row ativa |
separator | 1px rgba(255,255,255,0.15) | |
swapButton size | 36×36px | borderRadius 18 |
swapButton bg | #000000 | Preto puro |
swapButton border | 1px rgba(255,255,255,0.3) | |
swapButton position | right: 16px, center Y | Posição absoluta |
tsx
copy
import { OriginDestinationInput } from '@/components/OriginDestinationInput';
<OriginDestinationInput
origin={origin} // { name, country, code } | null
destination={destination}
onOriginPress={() => openOriginPicker()}
onDestinationPress={() => openDestinationPicker()}
onSwapPress={() => swapOriginDestination()}
/>
// StyleSheet interno — OriginDestinationInput.js:
// container: {
// height: containerHeight, // rowHeight * 2 + 1 = 109
// borderRadius: 999,
// backgroundColor: colors.white10,
// borderWidth: 1,
// borderColor: colors.white10,
// overflow: 'hidden',
// },
// row: {
// flexDirection: 'row',
// alignItems: 'center',
// gap: spacing.sm, // 8
// paddingHorizontal: spacing.md, // 16
// height: rowHeight, // 54
// },
// rowFocused: { backgroundColor: 'rgba(255, 255, 255, 0.18)' },
// separator: { height: 1, backgroundColor: 'rgba(255, 255, 255, 0.15)' },
// swapButton: {
// position: 'absolute',
// right: spacing.md, // 16
// width: 36, height: 36,
// borderRadius: 18,
// backgroundColor: '#000000',
// borderWidth: 1,
// borderColor: 'rgba(255, 255, 255, 0.3)',
// }TripTypeSelector
Seletor duplo de tipo de viagem e número de passageiros. Container retangular comradius.sm (8px), dividido em dois segmentos com divider vertical. Cada segmento tem estado focused independente.
Component/TripTypeSelectorVariants: Default, Segment focused — components/TripTypeSelector.js
Ida e volta
1
Só ida
2
| Propriedade | Valor | Descrição |
|---|---|---|
height | inputHeight (54px) | |
borderRadius | radius.sm (8px) | Quadrado, não pill |
backgroundColor | colors.white10 | rgba(255,255,255,0.10) |
borderWidth | 1 | |
borderColor | colors.white10 | |
segment paddingLeft | spacing.md (16px) | |
segment paddingRight | spacing.sm (8px) | |
gap | spacing.sm (8px) | Entre elementos do segmento |
divider | 1px rgba(255,255,255,0.2) | Entre os dois segmentos |
fontSize | 16 | fontFamily Medium |
segment focused bg | rgba(255,255,255,0.18) | Só o segmento ativo |
icon (chevron) | keyboard-arrow-down, 24 | MaterialIcons |
icon (person) | person-outline, 20 | MaterialIcons |
tsx
copy
import { TripTypeSelector } from '@/components/TripTypeSelector';
<TripTypeSelector
tripType="ida e volta" // ou "só ida"
passengers={1}
onTripTypePress={() => openTripTypePicker()}
onPassengersPress={() => openPassengersPicker()}
/>
// StyleSheet interno — TripTypeSelector.js:
// container: {
// flexDirection: 'row',
// height: inputHeight, // 54
// borderRadius: radius.sm, // 8
// backgroundColor: colors.white10,
// borderWidth: 1,
// borderColor: colors.white10,
// overflow: 'hidden',
// },
// segment: {
// flex: 1,
// flexDirection: 'row',
// alignItems: 'center',
// gap: spacing.sm, // 8
// paddingLeft: spacing.md, // 16
// paddingRight: spacing.sm, // 8
// },
// segmentRight: {
// borderLeftWidth: 1,
// borderLeftColor: 'rgba(255, 255, 255, 0.2)',
// },
// segmentFocused: { backgroundColor: 'rgba(255, 255, 255, 0.18)' },
// text: { fontSize: 16, color: colors.white, fontFamily: Medium }