mirror of
https://github.com/stablyai/orca.git
synced 2026-10-19 16:03:26 +00:00
* feat(mobile): add explicit keyboard dismiss control to terminal command dock Add a fixed Hide control at the left of the terminal command dock accessory bar whenever the software keyboard is open (keyboardHeight > 0). Tapping it clears any pending live-input focus timer, blurs the live and buffered command inputs, and dismisses the keyboard without sending bytes, switching input mode, or clearing typed text. The dismiss behavior lives in a dedicated, unit-tested terminal-keyboard-dismiss module rather than the customizable accessory-key path, so the escape hatch cannot be hidden by user shortcut customization. Available on every platform where the IME covers the app (iOS and Android). * review: harden keyboard dismiss control per adversarial review - document the load-bearing clear-before-blur order in dismissTerminalKeyboard - cover the both-handles-missing case in unit tests (5/5) - move the #5106 first-tap comment onto the accessory ScrollView and add a why-comment for the fixed Hide control - add accessibilityRole=button and hitSlop to the Hide control for a larger, semantically-correct touch target * fix(mobile): harden hide button visibility and scroll layout * refactor(mobile): use stacked keyboard+chevron glyph for dismiss control Replace the icon+'Hide' text with the iOS-native dismiss glyph (keyboard with a chevron-down beneath it). Narrower in the accessory row, removes the icon/word redundancy, and reads as distinct from the >> input-mode toggle. Accessibility label/hint/role unchanged. * fix(mobile): align keyboard dismiss accessory height * test(mobile): align vitest transform with Vite 8 --------- Co-authored-by: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Co-authored-by: Jinwoo-H <jinwoo0825@gmail.com>
223 lines
4.9 KiB
TypeScript
223 lines
4.9 KiB
TypeScript
import { StyleSheet } from 'react-native'
|
|
|
|
import { colors, spacing, radii, typography } from '../../../../src/theme/mobile-theme'
|
|
|
|
export const mobileSessionCommandInputStyles = StyleSheet.create({
|
|
createWarningBanner: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-start',
|
|
gap: spacing.sm,
|
|
backgroundColor: colors.bgPanel,
|
|
borderBottomWidth: StyleSheet.hairlineWidth,
|
|
borderBottomColor: colors.borderSubtle,
|
|
paddingHorizontal: spacing.md,
|
|
paddingVertical: spacing.sm
|
|
},
|
|
createWarningText: {
|
|
flex: 1,
|
|
color: colors.textPrimary,
|
|
fontSize: 12,
|
|
lineHeight: 16
|
|
},
|
|
createWarningDismiss: {
|
|
width: 24,
|
|
height: 24,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginTop: -4
|
|
},
|
|
emptyState: {
|
|
flex: 1,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
padding: spacing.xl
|
|
},
|
|
emptyText: {
|
|
color: colors.textSecondary,
|
|
fontSize: typography.bodySize,
|
|
marginBottom: spacing.lg
|
|
},
|
|
createError: {
|
|
color: colors.statusRed,
|
|
fontSize: 13,
|
|
marginBottom: spacing.sm
|
|
},
|
|
emptyActions: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
justifyContent: 'center',
|
|
gap: spacing.sm
|
|
},
|
|
createButton: {
|
|
backgroundColor: colors.bgRaised,
|
|
borderWidth: 1,
|
|
borderColor: colors.borderSubtle,
|
|
paddingHorizontal: spacing.xl,
|
|
paddingVertical: spacing.sm + 2,
|
|
borderRadius: radii.button
|
|
},
|
|
createButtonDisabled: {
|
|
opacity: 0.5
|
|
},
|
|
createButtonText: {
|
|
color: colors.textPrimary,
|
|
fontSize: typography.bodySize,
|
|
fontWeight: '600'
|
|
},
|
|
commandDock: {
|
|
zIndex: 20
|
|
},
|
|
accessoryBar: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
borderTopWidth: 1,
|
|
borderTopColor: colors.borderSubtle,
|
|
backgroundColor: colors.bgPanel
|
|
},
|
|
accessoryScroll: {
|
|
flex: 1,
|
|
minWidth: 0
|
|
},
|
|
accessoryContent: {
|
|
paddingHorizontal: spacing.sm,
|
|
paddingVertical: spacing.xs,
|
|
gap: spacing.xs
|
|
},
|
|
accessoryKey: {
|
|
backgroundColor: colors.bgRaised,
|
|
paddingHorizontal: spacing.sm + 2,
|
|
paddingVertical: spacing.xs,
|
|
borderRadius: radii.button,
|
|
minWidth: 36,
|
|
alignItems: 'center'
|
|
},
|
|
accessoryKeyPressed: {
|
|
backgroundColor: colors.borderSubtle
|
|
},
|
|
accessoryKeyActive: {
|
|
backgroundColor: colors.textPrimary
|
|
},
|
|
customAccessoryKey: {
|
|
borderWidth: 1,
|
|
borderColor: colors.borderSubtle
|
|
},
|
|
accessoryKeyDisabled: {
|
|
opacity: 0.35
|
|
},
|
|
accessoryKeyText: {
|
|
color: colors.textSecondary,
|
|
fontSize: 12,
|
|
fontFamily: typography.monoFamily
|
|
},
|
|
accessoryKeyTextActive: {
|
|
color: colors.bgBase,
|
|
fontWeight: '700'
|
|
},
|
|
accessoryKeyTextDisabled: {
|
|
color: colors.textMuted
|
|
},
|
|
keyboardDismissKey: {
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginLeft: spacing.sm,
|
|
marginVertical: spacing.xs,
|
|
backgroundColor: colors.bgRaised,
|
|
paddingHorizontal: spacing.sm + 2,
|
|
paddingVertical: 0,
|
|
borderRadius: radii.button,
|
|
minWidth: 36,
|
|
height: 28
|
|
},
|
|
keyboardDismissGlyph: {
|
|
alignItems: 'center',
|
|
height: 18,
|
|
justifyContent: 'flex-start',
|
|
position: 'relative',
|
|
width: 18
|
|
},
|
|
keyboardDismissChevron: {
|
|
bottom: -2,
|
|
position: 'absolute'
|
|
},
|
|
inputBar: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
minHeight: 46,
|
|
paddingVertical: spacing.xs + 2,
|
|
paddingHorizontal: spacing.md,
|
|
borderTopWidth: 1,
|
|
borderTopColor: colors.borderSubtle,
|
|
backgroundColor: colors.bgPanel
|
|
},
|
|
textInput: {
|
|
flex: 1,
|
|
height: 34,
|
|
backgroundColor: colors.bgRaised,
|
|
color: colors.textPrimary,
|
|
borderRadius: radii.input,
|
|
paddingHorizontal: spacing.md,
|
|
paddingVertical: 0,
|
|
fontSize: 14,
|
|
fontFamily: typography.monoFamily,
|
|
marginRight: spacing.sm
|
|
},
|
|
liveInputBar: {
|
|
gap: spacing.sm
|
|
},
|
|
|
|
liveInputFocusTarget: {
|
|
flex: 1,
|
|
minHeight: 34,
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
gap: spacing.sm,
|
|
backgroundColor: colors.bgRaised,
|
|
borderWidth: 1,
|
|
borderColor: colors.borderSubtle,
|
|
borderRadius: radii.input,
|
|
paddingHorizontal: spacing.sm + 2
|
|
},
|
|
|
|
liveInputFocusTargetPressed: {
|
|
backgroundColor: colors.borderSubtle
|
|
},
|
|
|
|
liveInputFocusTargetDisabled: {
|
|
opacity: 0.45
|
|
},
|
|
|
|
liveInputCapture: {
|
|
position: 'absolute',
|
|
opacity: 0,
|
|
width: 1,
|
|
height: 1,
|
|
color: colors.textPrimary
|
|
},
|
|
sendButton: {
|
|
backgroundColor: colors.bgRaised,
|
|
width: 34,
|
|
height: 34,
|
|
borderRadius: 17,
|
|
alignItems: 'center',
|
|
justifyContent: 'center'
|
|
},
|
|
dictationButton: {
|
|
backgroundColor: colors.bgRaised,
|
|
width: 34,
|
|
height: 34,
|
|
borderRadius: 17,
|
|
borderWidth: 1,
|
|
borderColor: 'transparent',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
marginRight: spacing.sm
|
|
},
|
|
dictationButtonActive: {
|
|
backgroundColor: colors.bgPanel,
|
|
borderColor: colors.textSecondary
|
|
},
|
|
sendButtonDisabled: {
|
|
opacity: 0.35
|
|
}
|
|
})
|