mobile-design 0.1.1 → 0.1.3
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/COMPONENTS.md +3053 -1625
- package/README.md +115 -265
- package/examples/navigation-stack.tsx +132 -0
- package/package.json +8 -2
- package/src/components/fab.tsx +9 -10
- package/src/components/text-field.tsx +16 -5
package/src/components/fab.tsx
CHANGED
|
@@ -539,7 +539,8 @@ function MenuItem({
|
|
|
539
539
|
const { fontScale } = useWindowDimensions();
|
|
540
540
|
const colors = roleColors(theme, variant);
|
|
541
541
|
const disabled = Boolean(item.disabled || (item.items && !item.items.length));
|
|
542
|
-
const
|
|
542
|
+
const iconSpace = item.icon ? 32 : 0;
|
|
543
|
+
const [labelWidth, setLabelWidth] = useState<number | null>(null);
|
|
543
544
|
const [height, setHeight] = useState(56);
|
|
544
545
|
const [focused, setFocused] = useState(false);
|
|
545
546
|
const [hovered, setHovered] = useState(false);
|
|
@@ -568,7 +569,9 @@ function MenuItem({
|
|
|
568
569
|
},
|
|
569
570
|
[alpha, widthFraction]
|
|
570
571
|
);
|
|
571
|
-
|
|
572
|
+
// Keep the icon space live even before native text layout reports a new measurement.
|
|
573
|
+
const measuredWidth = labelWidth === null ? 56 : labelWidth + 49 + iconSpace;
|
|
574
|
+
const naturalWidth = Math.max(56, Math.min(maxWidth, measuredWidth));
|
|
572
575
|
const geometry = useAnimatedStyle(() => ({ width: naturalWidth * Math.max(0, widthFraction.get()) }));
|
|
573
576
|
const fade = useAnimatedStyle(() => ({ opacity: Math.max(0, Math.min(1, alpha.get())) }));
|
|
574
577
|
const contentOffset = useAnimatedStyle(() => {
|
|
@@ -661,19 +664,19 @@ function MenuItem({
|
|
|
661
664
|
</Animated.View>
|
|
662
665
|
</AnimatedSurface>
|
|
663
666
|
<View
|
|
664
|
-
key={JSON.stringify([item.label, fontScale, maxWidth, theme.fonts.titleMedium])}
|
|
667
|
+
key={JSON.stringify([item.label, fontScale, maxWidth, iconSpace, theme.fonts.titleMedium])}
|
|
665
668
|
pointerEvents="none"
|
|
666
669
|
accessibilityElementsHidden
|
|
667
670
|
importantForAccessibility="no-hide-descendants"
|
|
668
671
|
{...(Platform.OS === 'web' ? { 'aria-hidden': true } : {})}
|
|
669
|
-
style={[styles.measure, { maxWidth: Math.max(1, maxWidth - 48 -
|
|
672
|
+
style={[styles.measure, { maxWidth: Math.max(1, maxWidth - 48 - iconSpace) }]}
|
|
670
673
|
>
|
|
671
674
|
<Text
|
|
672
675
|
variant="titleMedium"
|
|
673
676
|
onLayout={
|
|
674
677
|
Platform.OS === 'web'
|
|
675
678
|
? (event) => {
|
|
676
|
-
|
|
679
|
+
setLabelWidth(Math.ceil(event.nativeEvent.layout.width));
|
|
677
680
|
setHeight(Math.max(56, Math.ceil(event.nativeEvent.layout.height) + 16));
|
|
678
681
|
}
|
|
679
682
|
: undefined
|
|
@@ -681,11 +684,7 @@ function MenuItem({
|
|
|
681
684
|
onTextLayout={
|
|
682
685
|
Platform.OS !== 'web'
|
|
683
686
|
? (event) => {
|
|
684
|
-
|
|
685
|
-
Math.ceil(Math.max(0, ...event.nativeEvent.lines.map((line) => line.width))) +
|
|
686
|
-
49 +
|
|
687
|
-
(item.icon ? 32 : 0)
|
|
688
|
-
);
|
|
687
|
+
setLabelWidth(Math.ceil(Math.max(0, ...event.nativeEvent.lines.map((line) => line.width))));
|
|
689
688
|
setHeight(
|
|
690
689
|
Math.max(56, Math.ceil(event.nativeEvent.lines.reduce((sum, line) => sum + line.height, 0)) + 16)
|
|
691
690
|
);
|
|
@@ -41,6 +41,8 @@ export interface TextFieldProps extends Omit<TextInputProps, 'style' | 'value' |
|
|
|
41
41
|
value: string;
|
|
42
42
|
onChangeText: (value: string) => void;
|
|
43
43
|
variant?: 'filled' | 'outlined';
|
|
44
|
+
/** Compact starts at 48 dp. Both sizes grow with text scaling and multiline content. */
|
|
45
|
+
size?: 'standard' | 'compact';
|
|
44
46
|
label?: string;
|
|
45
47
|
disabled?: boolean;
|
|
46
48
|
readOnly?: boolean;
|
|
@@ -83,6 +85,7 @@ export const TextField = forwardRef<TextFieldHandle, TextFieldProps>(function Te
|
|
|
83
85
|
value,
|
|
84
86
|
onChangeText,
|
|
85
87
|
variant = 'filled',
|
|
88
|
+
size = 'standard',
|
|
86
89
|
label,
|
|
87
90
|
disabled = false,
|
|
88
91
|
readOnly = false,
|
|
@@ -209,7 +212,15 @@ export const TextField = forwardRef<TextFieldHandle, TextFieldProps>(function Te
|
|
|
209
212
|
) : null);
|
|
210
213
|
const labelStart = leadingContent ? 52 : 16;
|
|
211
214
|
const lineHeight = 24 * fontScale;
|
|
212
|
-
const
|
|
215
|
+
const compact = size === 'compact';
|
|
216
|
+
const verticalPadding = compact ? 12 : 16;
|
|
217
|
+
const filledLabelPadding = verticalPadding - 8;
|
|
218
|
+
const hasFilledLabel = Boolean(label) && !outlined;
|
|
219
|
+
const paddingTop = hasFilledLabel ? filledLabelPadding + 16 * fontScale : verticalPadding;
|
|
220
|
+
const paddingBottom = hasFilledLabel ? filledLabelPadding : verticalPadding;
|
|
221
|
+
const minimumHeight = Math.max(compact ? 48 : 56, paddingTop + lineHeight + paddingBottom);
|
|
222
|
+
const labelTop = outlined ? verticalPadding : filledLabelPadding + 8 * fontScale;
|
|
223
|
+
const labelTravel = outlined ? labelTop + 8 * fontScale : 8 * fontScale;
|
|
213
224
|
|
|
214
225
|
// RNW reports scrollHeight including the previous minimum height. Measure the
|
|
215
226
|
// natural textarea synchronously, restoring its style before the next paint,
|
|
@@ -315,7 +326,7 @@ export const TextField = forwardRef<TextFieldHandle, TextFieldProps>(function Te
|
|
|
315
326
|
left: direction === 'rtl' ? undefined : labelStart + (outlined ? (16 - labelStart) * progress.get() - 4 : 0),
|
|
316
327
|
right: direction === 'rtl' ? labelStart + (outlined ? (16 - labelStart) * progress.get() - 4 : 0) : undefined,
|
|
317
328
|
backgroundColor: outlined && progress.get() > 0.001 ? fieldColor : 'transparent',
|
|
318
|
-
transform: [{ translateY:
|
|
329
|
+
transform: [{ translateY: -labelTravel * progress.get() }],
|
|
319
330
|
}));
|
|
320
331
|
const focusInput = () => {
|
|
321
332
|
// Read-only fields remain focusable for selecting and copying text.
|
|
@@ -391,8 +402,8 @@ export const TextField = forwardRef<TextFieldHandle, TextFieldProps>(function Te
|
|
|
391
402
|
flexDirection: direction === 'rtl' ? 'row-reverse' : 'row',
|
|
392
403
|
paddingLeft: (direction === 'rtl' ? trailingContent : leadingContent) ? 4 : 16,
|
|
393
404
|
paddingRight: (direction === 'rtl' ? leadingContent : trailingContent) ? 4 : 16,
|
|
394
|
-
paddingTop
|
|
395
|
-
paddingBottom
|
|
405
|
+
paddingTop,
|
|
406
|
+
paddingBottom,
|
|
396
407
|
},
|
|
397
408
|
]}
|
|
398
409
|
>
|
|
@@ -537,7 +548,7 @@ export const TextField = forwardRef<TextFieldHandle, TextFieldProps>(function Te
|
|
|
537
548
|
style={[
|
|
538
549
|
styles.label,
|
|
539
550
|
{
|
|
540
|
-
top:
|
|
551
|
+
top: labelTop,
|
|
541
552
|
paddingHorizontal: outlined ? 4 : 0,
|
|
542
553
|
maxWidth: trailingContent ? '70%' : '85%',
|
|
543
554
|
},
|