diff --git a/app/app.android.scss b/app/app.android.scss
index ef3308722..100db4cdc 100644
--- a/app/app.android.scss
+++ b/app/app.android.scss
@@ -3,6 +3,16 @@ checkbox {
margin-right: 0;
}
+// the primary button is a 40 tall pill
+button[variant='contained'] {
+ height: 40;
+}
+
+.sheetHeaderTitle {
+ font-size: 22;
+ margin-left: 8;
+}
+
// a tonal chip: the surface has no glass here
.cardChip {
background-color: var(--colorPrimaryContainer);
@@ -17,3 +27,15 @@ checkbox {
border-radius: 30;
border-width: 1;
}
+
+// a field: 56 tall and 4 around
+.formRow {
+ height: 64;
+}
+
+// the outline takes the accent while the field has the focus
+textfield[variant='outline'] {
+ floating-color: var(--colorPrimary);
+ stroke-color: var(--colorPrimary);
+ stroke-inactive-color: var(--colorOutline);
+}
diff --git a/app/app.ios.scss b/app/app.ios.scss
index 4f7d17469..b4a3a3270 100644
--- a/app/app.ios.scss
+++ b/app/app.ios.scss
@@ -75,6 +75,18 @@ textfield[variant='none'] {
font-weight: 700;
}
+// the primary button is a 44 tall capsule
+button[variant='prominentGlass'],
+button[variant='contained'] {
+ height: 44;
+}
+
+.sheetHeaderTitle {
+ font-size: 17;
+ font-weight: bold;
+ text-align: center;
+}
+
// capsule text fields: the system fill, 12% gray in light and 24% in dark
textfield[variant='outline'],
textview[variant='outline'] {
@@ -94,3 +106,14 @@ textview[variant='outline'] {
min-height: 84;
padding: 12 16;
}
+
+// a field: 48 tall and 4 around
+.formRow {
+ height: 56;
+}
+
+textfield[variant='outline']:focused,
+textview[variant='outline']:focused {
+ border-color: var(--colorPrimary);
+ border-width: 1.5;
+}
diff --git a/app/components/common/SheetHeader.svelte b/app/components/common/SheetHeader.svelte
new file mode 100644
index 000000000..948a64f5f
--- /dev/null
+++ b/app/components/common/SheetHeader.svelte
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/app/components/list/CardsList.svelte b/app/components/list/CardsList.svelte
index 38a4faf7a..d1fa6ec22 100644
--- a/app/components/list/CardsList.svelte
+++ b/app/components/list/CardsList.svelte
@@ -20,7 +20,8 @@
DEFAULT_NB_COLUMNS_LANDSCAPE,
SETTINGS_CARD_ALWAYS_SHOW_NAME,
SETTINGS_NB_COLUMNS,
- SETTINGS_NB_COLUMNS_LANDSCAPE
+ SETTINGS_NB_COLUMNS_LANDSCAPE,
+ SHEET_SOFT_INPUT_MODE
} from '~/utils/constants';
import { appIcon } from '~/utils/appIcons';
import { documentHasPKPassData } from '~/utils/pkpass';
@@ -82,6 +83,7 @@
const result = await showBottomSheet({
parent: this,
view: CreateCard,
+ windowSoftInputMode: SHEET_SOFT_INPUT_MODE,
ignoreTopSafeArea: true
});
DEV_LOG && console.log('CreateCard', result);
diff --git a/app/components/view/CardEditSheet.svelte b/app/components/view/CardEditSheet.svelte
index 3717c63b9..0f473c7b9 100644
--- a/app/components/view/CardEditSheet.svelte
+++ b/app/components/view/CardEditSheet.svelte
@@ -2,6 +2,7 @@
import { lc } from '@nativescript-community/l';
import { Template } from '@nativescript-community/svelte-native/components';
import { TextField } from '@nativescript-community/ui-textfield';
+ import SheetHeader from '~/components/common/SheetHeader.svelte';
import { showBottomSheet } from '@nativescript-community/ui-bottomsheet/svelte';
import { showError } from '@shared/utils/showError';
import dayjs from 'dayjs';
@@ -9,6 +10,7 @@
import { qrcodeService } from '~/services/qrcode';
import { shortcutService } from '~/services/shortcuts';
import { appIcon } from '~/utils/appIcons';
+ import { SHEET_SOFT_INPUT_MODE } from '~/utils/constants';
import { pickColor } from '~/utils/ui';
import { colors } from '~/variables';
import ListItemAutoSize from '@shared/components/ListItemAutoSize.svelte';
@@ -108,6 +110,7 @@
parent: rootView,
skipCollapsedState: true,
view: ExtraFieldPicker,
+ windowSoftInputMode: SHEET_SOFT_INPUT_MODE,
props: { editing: !!field, ...(field?.extra || {}) }
});
if (!result) {
@@ -166,11 +169,7 @@
-
- close(false)} />
-
-
-
+ close(false)} onDone={save} title={lc('edit')} />
(name = e.value)} />
@@ -190,13 +189,13 @@
onCodeText(item.code, e.value, e.object)} />
- removeCode(item.code)} />
+ removeCode(item.code)} />
editField(item.field)}>
- removeField(item.field)} />
+ removeField(item.field)} />
diff --git a/app/components/view/CardView.svelte b/app/components/view/CardView.svelte
index 48473706e..446f256e4 100644
--- a/app/components/view/CardView.svelte
+++ b/app/components/view/CardView.svelte
@@ -57,7 +57,8 @@
EVENT_DOCUMENT_UPDATED,
QRCODE_RESIZE_THRESHOLD,
SETTINGS_DOCUMENT_NAME_FORMAT,
- SETTINGS_FORCE_WHITE_BACKGROUND_QRCODE
+ SETTINGS_FORCE_WHITE_BACKGROUND_QRCODE,
+ SHEET_SOFT_INPUT_MODE
} from '~/utils/constants';
import { appIcon } from '~/utils/appIcons';
import { optionsToMenuItems } from '~/utils/appMenu';
@@ -943,6 +944,7 @@
const saved = await showBottomSheet({
parent: page,
view: CardEditSheet,
+ windowSoftInputMode: SHEET_SOFT_INPUT_MODE,
detents: [{ fraction: 0.65 }, 'large'],
grabber: true,
props: { document }
diff --git a/app/components/widgets/CreateCard.svelte b/app/components/widgets/CreateCard.svelte
index 52b96c6bc..9d5470921 100644
--- a/app/components/widgets/CreateCard.svelte
+++ b/app/components/widgets/CreateCard.svelte
@@ -5,6 +5,8 @@
import { FORMATS, getBarcodeFallbackString, qrcodeService } from '~/services/qrcode';
import { pickColor, showPopoverMenu } from '~/utils/ui';
import { colors } from '~/variables';
+ import { focusState } from '~/utils/svelte/actions';
+ import SheetHeader from '../common/SheetHeader.svelte';
import SvgView from '../common/SVGView.svelte';
@@ -21,6 +23,10 @@
let validCode = true;
const tMargin = '4 0 4 0';
+ function close() {
+ rootView.nativeView.bindingContext.closeCallback();
+ }
+
async function add() {
try {
if (!name || !color) {
@@ -80,26 +86,36 @@
}
-
-
-
-
-
-
- (name = e.value)} />
-
- selectBarcodeFormat(e)} />
-
-
-
- 0} row={5} text={lc('add')} variant="text" on:tap={add} />
+
+ 0} doneText={lc('add')} onCancel={close} onDone={add} title={lc('create')} />
+
+ (name = e.value)} />
+
+ selectBarcodeFormat(e)}
+ />
+
+
+
+
+
+
+
diff --git a/app/components/widgets/ExtraFieldPicker.svelte b/app/components/widgets/ExtraFieldPicker.svelte
index 5a5a77021..637d835b3 100644
--- a/app/components/widgets/ExtraFieldPicker.svelte
+++ b/app/components/widgets/ExtraFieldPicker.svelte
@@ -4,14 +4,16 @@
import { showError } from '@shared/utils/showError';
import dayjs from 'dayjs';
import { formatDate } from '~/helpers/locale';
+ import SheetHeader from '~/components/common/SheetHeader.svelte';
+ import { focusState } from '~/utils/svelte/actions';
import { ExtraFieldType } from '~/models/OCRDocument';
import { pickDate, showPopoverMenu } from '~/utils/ui';
import { colors } from '~/variables';
-
-
-
- (currentName = e.value)} />
-
-
- selectType(e)} />
-
- (currentValue = e.value)}
- on:tap={(e) => selectDate(e)}
- />
-
-
+
+
+
+
+ (currentName = e.value)} />
+
+
+ selectType(e)} />
+ (currentValue = e.value)}
+ on:tap={(e) => selectDate(e)}
+ />
+
diff --git a/app/utils/constants.ts b/app/utils/constants.ts
index 81afe1a02..3a79f0715 100644
--- a/app/utils/constants.ts
+++ b/app/utils/constants.ts
@@ -174,3 +174,6 @@ export const DOCUMENT_DATA_FILENAME = 'data.json';
export const DELETED_DOCUMENTS_DATA_FILENAME = 'deleted_documents.json';
export const DELETED_FOLDERS_DATA_FILENAME = 'deleted_folders.json';
export const VALID_MARKER_FILENAME = '.valid';
+
+// SOFT_INPUT_ADJUST_RESIZE: a sheet with fields moves up with the keyboard
+export const SHEET_SOFT_INPUT_MODE = __ANDROID__ ? 16 : undefined;
diff --git a/app/utils/svelte/actions.ts b/app/utils/svelte/actions.ts
new file mode 100644
index 000000000..6bf49cb62
--- /dev/null
+++ b/app/utils/svelte/actions.ts
@@ -0,0 +1,16 @@
+import type { NativeViewElementNode } from '@nativescript-community/svelte-native/dom';
+import type { TextBase } from '@nativescript/core';
+
+/** css has no `:focus`: the field gets the `focused` pseudo class while it has the focus */
+export function focusState(node: NativeViewElementNode) {
+ const onFocus = () => node.nativeView.addPseudoClass('focused');
+ const onBlur = () => node.nativeView.deletePseudoClass('focused');
+ node.addEventListener('focus', onFocus);
+ node.addEventListener('blur', onBlur);
+ return {
+ destroy() {
+ node.removeEventListener('focus', onFocus);
+ node.removeEventListener('blur', onBlur);
+ }
+ };
+}