@boostdev/design-system-react-native 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to `@boostdev/design-system-react-native` are documented here.
4
+ ## [0.2.1] - 2026-06-11
5
+ ### Fixed
6
+ - Fix(form): prevent iOS text clipping in single-line inputs
7
+
8
+ Remove explicit lineHeight from the TextInput style in FormInput,
9
+ NumberInput, and Combobox. On iOS, an explicit lineHeight on a
10
+ single-line TextInput clips descenders and ascenders at the line box
11
+ boundary. The minHeight: 44 token satisfies touch-target requirements
12
+ without needing lineHeight. Textarea (multiline) is unaffected.
13
+
14
+ Test contract pinned: FormInput spec asserts lineHeight resolves to
15
+ "normal" and minHeight >= 44pt via getComputedStyle. ([`c3055e4`](https://gitlab.com/b00stdev/boostdev-design-system-react-native/-/commit/c3055e464fd0b8891fec1f0eb616b8357390ec50))
16
+
4
17
  ## [0.2.0] - 2026-06-10
5
18
  ### Added
6
19
  - Feat: rename Drawer to SideSheet, optional @react-navigation/native peer, nav theme docs, git-cliff ([`42e165d`](https://gitlab.com/b00stdev/boostdev-design-system-react-native/-/commit/42e165d6df397876df8b721122259af640eeaa98))
package/dist/index.cjs CHANGED
@@ -2693,7 +2693,8 @@ var styles33 = import_react_native37.StyleSheet.create({
2693
2693
  input: {
2694
2694
  fontFamily: import_native.font.family.body,
2695
2695
  fontSize: import_native.font.size.body,
2696
- lineHeight: lineHeight.body,
2696
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
2697
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
2697
2698
  paddingVertical: import_native.spacing.xs,
2698
2699
  paddingHorizontal: import_native.spacing.s,
2699
2700
  borderWidth: 1,
@@ -2944,7 +2945,8 @@ var styles35 = import_react_native39.StyleSheet.create({
2944
2945
  input: {
2945
2946
  fontFamily: import_native.font.family.body,
2946
2947
  fontSize: import_native.font.size.body,
2947
- lineHeight: lineHeight.body,
2948
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
2949
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
2948
2950
  paddingHorizontal: import_native.spacing.s,
2949
2951
  paddingVertical: import_native.spacing.xs,
2950
2952
  borderWidth: 1,
@@ -3504,7 +3506,8 @@ var styles39 = import_react_native43.StyleSheet.create({
3504
3506
  flex: 1,
3505
3507
  fontFamily: import_native.font.family.body,
3506
3508
  fontSize: import_native.font.size.body,
3507
- lineHeight: lineHeight.body,
3509
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
3510
+ // lineHeight is set explicitly. minHeight: STEPPER_SIZE (44) covers the touch target.
3508
3511
  textAlign: "center",
3509
3512
  paddingHorizontal: import_native.spacing.xs,
3510
3513
  paddingVertical: import_native.spacing.xs,
package/dist/index.js CHANGED
@@ -2646,7 +2646,8 @@ var styles33 = StyleSheet33.create({
2646
2646
  input: {
2647
2647
  fontFamily: font.family.body,
2648
2648
  fontSize: font.size.body,
2649
- lineHeight: lineHeight.body,
2649
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
2650
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
2650
2651
  paddingVertical: spacing.xs,
2651
2652
  paddingHorizontal: spacing.s,
2652
2653
  borderWidth: 1,
@@ -2901,7 +2902,8 @@ var styles35 = StyleSheet35.create({
2901
2902
  input: {
2902
2903
  fontFamily: font.family.body,
2903
2904
  fontSize: font.size.body,
2904
- lineHeight: lineHeight.body,
2905
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
2906
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
2905
2907
  paddingHorizontal: spacing.s,
2906
2908
  paddingVertical: spacing.xs,
2907
2909
  borderWidth: 1,
@@ -3483,7 +3485,8 @@ var styles39 = StyleSheet39.create({
3483
3485
  flex: 1,
3484
3486
  fontFamily: font.family.body,
3485
3487
  fontSize: font.size.body,
3486
- lineHeight: lineHeight.body,
3488
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
3489
+ // lineHeight is set explicitly. minHeight: STEPPER_SIZE (44) covers the touch target.
3487
3490
  textAlign: "center",
3488
3491
  paddingHorizontal: spacing.xs,
3489
3492
  paddingVertical: spacing.xs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@boostdev/design-system-react-native",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "BoostDev React Native component library: accessible, token-driven components built on @boostdev/design-system-foundation",
5
5
  "keywords": [
6
6
  "react-native",
@@ -9,7 +9,7 @@ import {
9
9
  StyleProp,
10
10
  ViewStyle,
11
11
  } from 'react-native';
12
- import { spacing, font, border, lineHeight } from '../../../../native/tokens';
12
+ import { spacing, font, border, lineHeight } from '../../../../native/tokens'; // lineHeight used for optionText (Text, not TextInput)
13
13
  import { useTheme } from '../../../../native/ThemeContext';
14
14
  import { Label } from '../atoms/Label';
15
15
  import { Message } from '../atoms/Message';
@@ -45,7 +45,8 @@ const styles = StyleSheet.create({
45
45
  input: {
46
46
  fontFamily: font.family.body,
47
47
  fontSize: font.size.body,
48
- lineHeight: lineHeight.body,
48
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
49
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
49
50
  paddingVertical: spacing.xs,
50
51
  paddingHorizontal: spacing.s,
51
52
  borderWidth: 1,
@@ -48,4 +48,34 @@ describe('FormInput (native)', () => {
48
48
  const inputs = container.querySelectorAll('input, [style*="opacity"]');
49
49
  expect(inputs.length).toBeGreaterThan(0);
50
50
  });
51
+
52
+ /**
53
+ * Style-contract invariant: single-line TextInput must NOT have lineHeight set.
54
+ *
55
+ * On iOS, an explicit lineHeight on a single-line TextInput causes the text to
56
+ * render vertically clipped — descenders and ascenders are cut off at the line box
57
+ * boundary. The minHeight: 44 token satisfies the touch-target requirement without
58
+ * needing lineHeight. This test pins that invariant so it can't silently regress.
59
+ *
60
+ * react-native-web applies token-based styles as atomic CSS classes. getComputedStyle
61
+ * resolves those classes in jsdom and returns "normal" when lineHeight is absent.
62
+ */
63
+ it('does not set lineHeight on the TextInput (iOS clipping prevention)', () => {
64
+ renderWithTheme(<FormInput label="Email" name="email" value="bjorn@boonen.eu" />);
65
+ const input = screen.getByDisplayValue('bjorn@boonen.eu');
66
+ // "normal" means no explicit lineHeight was applied; a numeric value means it was.
67
+ expect(getComputedStyle(input).lineHeight).toBe('normal');
68
+ });
69
+
70
+ /**
71
+ * Touch-target invariant: single-line input must meet the 44pt minimum touch target.
72
+ * This is the replacement constraint that makes lineHeight safe to omit.
73
+ */
74
+ it('has minHeight of at least 44pt on the TextInput', () => {
75
+ renderWithTheme(<FormInput label="Email" name="email" />);
76
+ const input = screen.getByRole('textbox');
77
+ // getComputedStyle resolves the atomic CSS class to a pixel value.
78
+ const minHeightPx = parseFloat(getComputedStyle(input).minHeight);
79
+ expect(minHeightPx).toBeGreaterThanOrEqual(44);
80
+ });
51
81
  });
@@ -7,7 +7,7 @@ import {
7
7
  StyleProp,
8
8
  ViewStyle,
9
9
  } from 'react-native';
10
- import { spacing, font, border, lineHeight } from '../../../../native/tokens';
10
+ import { spacing, font, border } from '../../../../native/tokens';
11
11
  import { useTheme } from '../../../../native/ThemeContext';
12
12
  import { Label } from '../atoms/Label';
13
13
  import { Message } from '../atoms/Message';
@@ -47,7 +47,8 @@ const styles = StyleSheet.create({
47
47
  input: {
48
48
  fontFamily: font.family.body,
49
49
  fontSize: font.size.body,
50
- lineHeight: lineHeight.body,
50
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
51
+ // lineHeight is set explicitly. minHeight: 44 satisfies the touch-target requirement.
51
52
  paddingHorizontal: spacing.s,
52
53
  paddingVertical: spacing.xs,
53
54
  borderWidth: 1,
@@ -8,7 +8,7 @@ import {
8
8
  StyleProp,
9
9
  ViewStyle,
10
10
  } from 'react-native';
11
- import { spacing, font, border, lineHeight } from '../../../../native/tokens';
11
+ import { spacing, font, border } from '../../../../native/tokens';
12
12
  import { useTheme } from '../../../../native/ThemeContext';
13
13
  import { Label } from '../atoms/Label';
14
14
  import { Message } from '../atoms/Message';
@@ -64,7 +64,8 @@ const styles = StyleSheet.create({
64
64
  flex: 1,
65
65
  fontFamily: font.family.body,
66
66
  fontSize: font.size.body,
67
- lineHeight: lineHeight.body,
67
+ // No lineHeight on single-line TextInput: iOS clips descenders/ascenders when
68
+ // lineHeight is set explicitly. minHeight: STEPPER_SIZE (44) covers the touch target.
68
69
  textAlign: 'center',
69
70
  paddingHorizontal: spacing.xs,
70
71
  paddingVertical: spacing.xs,