@ledgerhq/lumen-ui-rnative 0.1.33 → 0.1.35
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/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/lib/Animations/Pulse/Pulse.js +17 -7
- package/dist/module/lib/Animations/Pulse/Pulse.js.map +1 -1
- package/dist/module/lib/Components/BaseTag/BaseTag.js +122 -0
- package/dist/module/lib/Components/BaseTag/BaseTag.js.map +1 -0
- package/dist/module/lib/Components/BaseTag/BaseTag.test.js +144 -0
- package/dist/module/lib/Components/BaseTag/BaseTag.test.js.map +1 -0
- package/dist/module/lib/Components/BaseTag/index.js +5 -0
- package/dist/module/lib/Components/BaseTag/index.js.map +1 -0
- package/dist/module/lib/Components/BaseTag/types.js +4 -0
- package/dist/module/lib/Components/BaseTag/types.js.map +1 -0
- package/dist/module/lib/Components/BottomSheet/BottomSheet.js +12 -7
- package/dist/module/lib/Components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheet.stories.js +220 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheet.stories.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheet.test.js +73 -0
- package/dist/module/lib/Components/BottomSheet/BottomSheet.test.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheetHeader.js +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheetHeader.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/CustomHandle.js +15 -2
- package/dist/module/lib/Components/BottomSheet/CustomHandle.js.map +1 -1
- package/dist/module/lib/Components/Card/Card.js.map +1 -1
- package/dist/module/lib/Components/ListItem/ListItem.js.map +1 -1
- package/dist/module/lib/Components/MediaImage/MediaImage.js +10 -2
- package/dist/module/lib/Components/MediaImage/MediaImage.js.map +1 -1
- package/dist/module/lib/Components/MediaTag/MediaTag.js +39 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.js.map +1 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.mdx +161 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.stories.js +122 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.stories.js.map +1 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.test.js +30 -0
- package/dist/module/lib/Components/MediaTag/MediaTag.test.js.map +1 -0
- package/dist/module/lib/Components/MediaTag/index.js +5 -0
- package/dist/module/lib/Components/MediaTag/index.js.map +1 -0
- package/dist/module/lib/Components/MediaTag/types.js +4 -0
- package/dist/module/lib/Components/MediaTag/types.js.map +1 -0
- package/dist/module/lib/Components/OptionList/OptionList.js +45 -4
- package/dist/module/lib/Components/OptionList/OptionList.js.map +1 -1
- package/dist/module/lib/Components/OptionList/OptionList.mdx +19 -0
- package/dist/module/lib/Components/OptionList/OptionList.stories.js +254 -1
- package/dist/module/lib/Components/OptionList/OptionList.stories.js.map +1 -1
- package/dist/module/lib/Components/OptionList/OptionList.test.js +136 -1
- package/dist/module/lib/Components/OptionList/OptionList.test.js.map +1 -1
- package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.js +39 -13
- package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.js.map +1 -1
- package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.test.js +117 -2
- package/dist/module/lib/Components/OptionList/useOptionList/useOptionListItems.test.js.map +1 -1
- package/dist/module/lib/Components/PageIndicator/PageIndicator.test.js.map +1 -1
- package/dist/module/lib/Components/Skeleton/Skeleton.js +10 -3
- package/dist/module/lib/Components/Skeleton/Skeleton.js.map +1 -1
- package/dist/module/lib/Components/TabBar/TabBar.js +7 -6
- package/dist/module/lib/Components/TabBar/TabBar.js.map +1 -1
- package/dist/module/lib/Components/Tag/Tag.js +10 -95
- package/dist/module/lib/Components/Tag/Tag.js.map +1 -1
- package/dist/module/lib/Components/Tag/Tag.mdx +1 -79
- package/dist/module/lib/Components/Tag/Tag.stories.js +8 -1
- package/dist/module/lib/Components/Tag/Tag.stories.js.map +1 -1
- package/dist/module/lib/Components/Tag/Tag.test.js +69 -0
- package/dist/module/lib/Components/Tag/Tag.test.js.map +1 -0
- package/dist/module/lib/Components/index.js +1 -0
- package/dist/module/lib/Components/index.js.map +1 -1
- package/dist/module/styles/lx/resolveStyle.js.map +1 -1
- package/dist/typescript/src/index.d.ts +1 -0
- package/dist/typescript/src/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/Animations/Pulse/Pulse.d.ts +1 -1
- package/dist/typescript/src/lib/Animations/Pulse/Pulse.d.ts.map +1 -1
- package/dist/typescript/src/lib/Animations/Pulse/types.d.ts +2 -1
- package/dist/typescript/src/lib/Animations/Pulse/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/BaseTag/BaseTag.d.ts +3 -0
- package/dist/typescript/src/lib/Components/BaseTag/BaseTag.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/BaseTag/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/BaseTag/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/BaseTag/types.d.ts +10 -0
- package/dist/typescript/src/lib/Components/BaseTag/types.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/BottomSheet/BottomSheet.d.ts +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/BottomSheet.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/CustomHandle.d.ts +5 -2
- package/dist/typescript/src/lib/Components/BottomSheet/CustomHandle.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/types.d.ts +16 -3
- package/dist/typescript/src/lib/Components/BottomSheet/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Card/Card.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/ListItem/ListItem.d.ts +3 -3
- package/dist/typescript/src/lib/Components/ListItem/ListItem.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/MediaImage/MediaImage.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/MediaTag/MediaTag.d.ts +26 -0
- package/dist/typescript/src/lib/Components/MediaTag/MediaTag.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/MediaTag/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/MediaTag/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/MediaTag/types.d.ts +10 -0
- package/dist/typescript/src/lib/Components/MediaTag/types.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/OptionList/OptionList.d.ts +3 -2
- package/dist/typescript/src/lib/Components/OptionList/OptionList.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/OptionList/types.d.ts +42 -5
- package/dist/typescript/src/lib/Components/OptionList/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/OptionList/useOptionList/useOptionListItems.d.ts +9 -1
- package/dist/typescript/src/lib/Components/OptionList/useOptionList/useOptionListItems.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Skeleton/Skeleton.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/TabBar/TabBar.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Tag/Tag.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Tag/Tag.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Tag/types.d.ts +1 -1
- package/dist/typescript/src/lib/Components/Tag/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/index.d.ts +1 -0
- package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/types/index.d.ts +3 -3
- package/dist/typescript/src/lib/types/index.d.ts.map +1 -1
- package/dist/typescript/src/styles/lx/resolveStyle.d.ts +3 -3
- package/dist/typescript/src/styles/lx/resolveStyle.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +1 -0
- package/src/lib/Animations/Pulse/Pulse.tsx +34 -29
- package/src/lib/Animations/Pulse/types.ts +2 -1
- package/src/lib/Components/BaseTag/BaseTag.test.tsx +137 -0
- package/src/lib/Components/BaseTag/BaseTag.tsx +152 -0
- package/src/lib/Components/BaseTag/index.ts +2 -0
- package/src/lib/Components/BaseTag/types.ts +11 -0
- package/src/lib/Components/BottomSheet/BottomSheet.stories.tsx +174 -1
- package/src/lib/Components/BottomSheet/BottomSheet.test.tsx +59 -0
- package/src/lib/Components/BottomSheet/BottomSheet.tsx +19 -7
- package/src/lib/Components/BottomSheet/BottomSheetHeader.tsx +1 -1
- package/src/lib/Components/BottomSheet/CustomHandle.tsx +26 -5
- package/src/lib/Components/BottomSheet/types.ts +24 -3
- package/src/lib/Components/Card/Card.tsx +3 -3
- package/src/lib/Components/ListItem/ListItem.tsx +3 -3
- package/src/lib/Components/MediaImage/MediaImage.tsx +10 -2
- package/src/lib/Components/MediaTag/MediaTag.mdx +161 -0
- package/src/lib/Components/MediaTag/MediaTag.stories.tsx +112 -0
- package/src/lib/Components/MediaTag/MediaTag.test.tsx +27 -0
- package/src/lib/Components/MediaTag/MediaTag.tsx +36 -0
- package/src/lib/Components/MediaTag/index.ts +2 -0
- package/src/lib/Components/MediaTag/types.ts +10 -0
- package/src/lib/Components/OptionList/OptionList.mdx +19 -0
- package/src/lib/Components/OptionList/OptionList.stories.tsx +254 -0
- package/src/lib/Components/OptionList/OptionList.test.tsx +143 -0
- package/src/lib/Components/OptionList/OptionList.tsx +49 -3
- package/src/lib/Components/OptionList/types.ts +46 -5
- package/src/lib/Components/OptionList/useOptionList/useOptionListItems.test.ts +124 -2
- package/src/lib/Components/OptionList/useOptionList/useOptionListItems.ts +53 -10
- package/src/lib/Components/PageIndicator/PageIndicator.test.tsx +2 -1
- package/src/lib/Components/Skeleton/Skeleton.tsx +9 -5
- package/src/lib/Components/TabBar/TabBar.tsx +3 -2
- package/src/lib/Components/Tag/Tag.mdx +1 -79
- package/src/lib/Components/Tag/Tag.stories.tsx +3 -0
- package/src/lib/Components/Tag/Tag.test.tsx +51 -0
- package/src/lib/Components/Tag/Tag.tsx +12 -119
- package/src/lib/Components/Tag/types.ts +2 -1
- package/src/lib/Components/index.ts +1 -0
- package/src/lib/types/index.ts +3 -3
- package/src/styles/lx/resolveStyle.ts +4 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BottomSheetVariables } from '@gorhom/bottom-sheet/lib/typescript/types';
|
|
2
|
-
import type { Ref } from 'react';
|
|
2
|
+
import type { ComponentRef, Ref } from 'react';
|
|
3
3
|
import { View } from 'react-native';
|
|
4
4
|
import { useStyleSheet } from '../../../styles';
|
|
5
5
|
|
|
@@ -12,13 +12,13 @@ const useStyles = () => {
|
|
|
12
12
|
alignItems: 'center',
|
|
13
13
|
justifyContent: 'center',
|
|
14
14
|
alignSelf: 'center',
|
|
15
|
-
backgroundColor:
|
|
15
|
+
backgroundColor: 'transparent',
|
|
16
16
|
},
|
|
17
17
|
handle: {
|
|
18
18
|
height: t.spacings.s4,
|
|
19
19
|
width: t.sizes.s36,
|
|
20
20
|
borderRadius: t.borderRadius.full,
|
|
21
|
-
backgroundColor: t.colors.bg.
|
|
21
|
+
backgroundColor: t.colors.bg.mutedTransparentPressed,
|
|
22
22
|
},
|
|
23
23
|
}),
|
|
24
24
|
[],
|
|
@@ -28,12 +28,33 @@ const useStyles = () => {
|
|
|
28
28
|
export const CustomHandle = ({
|
|
29
29
|
ref,
|
|
30
30
|
...props
|
|
31
|
-
}: BottomSheetVariables & { ref?: Ref<
|
|
31
|
+
}: BottomSheetVariables & { ref?: Ref<ComponentRef<typeof View>> }) => {
|
|
32
32
|
const styles = useStyles();
|
|
33
33
|
|
|
34
34
|
return (
|
|
35
|
-
<View
|
|
35
|
+
<View
|
|
36
|
+
{...props}
|
|
37
|
+
ref={ref}
|
|
38
|
+
style={styles.container}
|
|
39
|
+
testID='bottom-sheet-handle'
|
|
40
|
+
>
|
|
36
41
|
<View style={styles.handle} />
|
|
37
42
|
</View>
|
|
38
43
|
);
|
|
39
44
|
};
|
|
45
|
+
|
|
46
|
+
export const HiddenHandle = ({
|
|
47
|
+
ref,
|
|
48
|
+
...props
|
|
49
|
+
}: BottomSheetVariables & { ref?: Ref<ComponentRef<typeof View>> }) => {
|
|
50
|
+
const styles = useStyles();
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<View
|
|
54
|
+
{...props}
|
|
55
|
+
ref={ref}
|
|
56
|
+
style={styles.container}
|
|
57
|
+
testID='bottom-sheet-handle-hidden'
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
};
|
|
@@ -5,16 +5,23 @@ import type {
|
|
|
5
5
|
BottomSheetSectionList as GorhomBottomSheetSectionList,
|
|
6
6
|
BottomSheetScrollView as GorhomBottomSheetScrollView,
|
|
7
7
|
BottomSheetVirtualizedList as GorhomBottomSheetVirtualizedList,
|
|
8
|
+
BottomSheetBackgroundProps,
|
|
8
9
|
} from '@gorhom/bottom-sheet';
|
|
9
|
-
|
|
10
10
|
import type { Density } from '@ledgerhq/lumen-utils-shared';
|
|
11
|
-
import type {
|
|
11
|
+
import type {
|
|
12
|
+
ComponentRef,
|
|
13
|
+
FC,
|
|
14
|
+
PropsWithChildren,
|
|
15
|
+
ReactNode,
|
|
16
|
+
Ref,
|
|
17
|
+
} from 'react';
|
|
18
|
+
|
|
12
19
|
import type { StyledViewProps } from '../../../styles';
|
|
13
20
|
export type BottomSheetProps = PropsWithChildren & {
|
|
14
21
|
/**
|
|
15
22
|
* Ref to the bottom sheet component.
|
|
16
23
|
*/
|
|
17
|
-
ref?: Ref<
|
|
24
|
+
ref?: Ref<ComponentRef<typeof GorhomBottomSheetModal>>;
|
|
18
25
|
/**
|
|
19
26
|
* Used to locate this view in end-to-end tests.
|
|
20
27
|
*/
|
|
@@ -131,8 +138,22 @@ export type BottomSheetProps = PropsWithChildren & {
|
|
|
131
138
|
* @default true
|
|
132
139
|
*/
|
|
133
140
|
enableBlurKeyboardOnGesture?: boolean;
|
|
141
|
+
/**
|
|
142
|
+
* Custom background component rendered behind the sheet content and handle.
|
|
143
|
+
* Use to render gradients or other effects that should span the full sheet area,
|
|
144
|
+
* including the handle strip. When provided, the default sheet background is removed.
|
|
145
|
+
* @default undefined
|
|
146
|
+
*/
|
|
147
|
+
backgroundComponent?: FC<BottomSheetBackgroundProps> | null;
|
|
148
|
+
/**
|
|
149
|
+
* If true, the drag handle (grabber) at the top of the sheet is hidden.
|
|
150
|
+
* @default false
|
|
151
|
+
*/
|
|
152
|
+
hideHandle?: boolean;
|
|
134
153
|
};
|
|
135
154
|
|
|
155
|
+
export type { BottomSheetBackgroundProps };
|
|
156
|
+
|
|
136
157
|
export type BottomSheetHeaderProps = {
|
|
137
158
|
/**
|
|
138
159
|
* The density of the header.
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
DisabledProvider,
|
|
4
4
|
isTextChildren,
|
|
5
5
|
} from '@ledgerhq/lumen-utils-shared';
|
|
6
|
-
import type { ReactNode, Ref } from 'react';
|
|
6
|
+
import type { ComponentRef, ReactNode, Ref } from 'react';
|
|
7
7
|
import { useCallback, useEffect, useMemo } from 'react';
|
|
8
8
|
import type { LayoutChangeEvent, ViewStyle } from 'react-native';
|
|
9
9
|
import { StyleSheet, View } from 'react-native';
|
|
@@ -486,7 +486,7 @@ export const CardContentTitle = ({
|
|
|
486
486
|
if (isTextChildren(children)) {
|
|
487
487
|
return (
|
|
488
488
|
<Text
|
|
489
|
-
ref={ref as Ref<
|
|
489
|
+
ref={ref as Ref<ComponentRef<typeof Text>>}
|
|
490
490
|
lx={lx}
|
|
491
491
|
style={StyleSheet.flatten([styles.asText, style])}
|
|
492
492
|
numberOfLines={1}
|
|
@@ -553,7 +553,7 @@ export const CardContentDescription = ({
|
|
|
553
553
|
if (isTextChildren(children)) {
|
|
554
554
|
return (
|
|
555
555
|
<Text
|
|
556
|
-
ref={ref as Ref<
|
|
556
|
+
ref={ref as Ref<ComponentRef<typeof Text>>}
|
|
557
557
|
lx={lx}
|
|
558
558
|
style={StyleSheet.flatten([styles.asText, style])}
|
|
559
559
|
numberOfLines={1}
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
DisabledProvider,
|
|
5
5
|
useDisabledContext,
|
|
6
6
|
} from '@ledgerhq/lumen-utils-shared';
|
|
7
|
-
import type {
|
|
7
|
+
import type { ComponentRef, ReactNode, Ref } from 'react';
|
|
8
8
|
import type { ViewStyle } from 'react-native';
|
|
9
9
|
import { StyleSheet, View } from 'react-native';
|
|
10
10
|
import { useStyleSheet } from '../../../styles';
|
|
@@ -286,7 +286,7 @@ export const ListItemTitle = ({
|
|
|
286
286
|
style,
|
|
287
287
|
ref,
|
|
288
288
|
...props
|
|
289
|
-
}: ListItemTitleProps & { ref?: Ref<
|
|
289
|
+
}: ListItemTitleProps & { ref?: Ref<ComponentRef<typeof Text>> }) => {
|
|
290
290
|
const disabled = useDisabledContext({
|
|
291
291
|
consumerName: 'ListItemTitle',
|
|
292
292
|
contextRequired: true,
|
|
@@ -336,7 +336,7 @@ export const ListItemDescription = ({
|
|
|
336
336
|
style,
|
|
337
337
|
ref,
|
|
338
338
|
...props
|
|
339
|
-
}: ListItemDescriptionProps & { ref?: Ref<
|
|
339
|
+
}: ListItemDescriptionProps & { ref?: Ref<ComponentRef<typeof Text>> }) => {
|
|
340
340
|
const disabled = useDisabledContext({
|
|
341
341
|
consumerName: 'ListItemDescription',
|
|
342
342
|
contextRequired: true,
|
|
@@ -2,6 +2,7 @@ import { useEffect, useState } from 'react';
|
|
|
2
2
|
import { Image, StyleSheet } from 'react-native';
|
|
3
3
|
import { useStyleSheet } from '../../../styles';
|
|
4
4
|
import type { LumenStyleSheetTheme } from '../../../styles';
|
|
5
|
+
import { RuntimeConstants } from '../../utils';
|
|
5
6
|
import { Skeleton } from '../Skeleton';
|
|
6
7
|
import { Box, Text } from '../Utility';
|
|
7
8
|
import type { MediaImageProps, MediaImageSize, MediaImageShape } from './types';
|
|
@@ -65,6 +66,10 @@ const useStyles = ({
|
|
|
65
66
|
width: '100%',
|
|
66
67
|
height: '100%',
|
|
67
68
|
},
|
|
69
|
+
skeleton: {
|
|
70
|
+
width: '100%',
|
|
71
|
+
height: '100%',
|
|
72
|
+
},
|
|
68
73
|
};
|
|
69
74
|
},
|
|
70
75
|
[size, shape],
|
|
@@ -116,10 +121,13 @@ export const MediaImage = ({
|
|
|
116
121
|
accessibilityLabel={alt}
|
|
117
122
|
{...props}
|
|
118
123
|
>
|
|
119
|
-
{loading && <Skeleton style={
|
|
124
|
+
{loading && <Skeleton style={styles.skeleton} />}
|
|
120
125
|
{!loading && shouldFallback && fallback && (
|
|
121
126
|
<Text
|
|
122
|
-
style={{
|
|
127
|
+
style={{
|
|
128
|
+
fontSize: fontSizeMap[size],
|
|
129
|
+
...(RuntimeConstants.isIOS && { lineHeight: 0 }),
|
|
130
|
+
}}
|
|
123
131
|
lx={{ color: 'base' }}
|
|
124
132
|
accessible={false}
|
|
125
133
|
>
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as MediaTagStories from './MediaTag.stories';
|
|
3
|
+
import { CustomTabs, Tab } from '../../../../.storybook/components';
|
|
4
|
+
import { DoVsDontRow, DoBlockItem, DontBlockItem } from '../../../../.storybook/components/DoVsDont';
|
|
5
|
+
import CommonRulesDoAndDont from '../../../../.storybook/components/DoVsDont/CommonRulesDoAndDont.mdx';
|
|
6
|
+
import { Box } from '../Utility/Box';
|
|
7
|
+
|
|
8
|
+
<Meta title='Components/MediaTag' of={MediaTagStories} />
|
|
9
|
+
|
|
10
|
+
# MediaTag
|
|
11
|
+
|
|
12
|
+
<CustomTabs>
|
|
13
|
+
<Tab label="Overview">
|
|
14
|
+
|
|
15
|
+
## Introduction
|
|
16
|
+
|
|
17
|
+
MediaTag is a compact label used to categorize, classify, or highlight information alongside a required media element such as an image or crypto icon. Like [Tag](/docs/communication-tag--docs), it supports multiple appearances and sizes, but is designed for cases where the icon is richer than a Symbol.
|
|
18
|
+
|
|
19
|
+
> View in [Figma](https://www.figma.com/design/JxaLVMTWirCpU0rsbZ30k7/2.-Components-Library?node-id=16793-36383&m=dev).
|
|
20
|
+
|
|
21
|
+
## Anatomy
|
|
22
|
+
|
|
23
|
+
<Canvas of={MediaTagStories.Base} />
|
|
24
|
+
|
|
25
|
+
- **Label:** The text content of the tag.
|
|
26
|
+
- **Leading content:** A required media element (image, crypto icon, etc.) displayed before the label. Passed via the `leadingContent` prop.
|
|
27
|
+
|
|
28
|
+
## Properties
|
|
29
|
+
|
|
30
|
+
<Canvas of={MediaTagStories.Base} />
|
|
31
|
+
<Controls of={MediaTagStories.Base} />
|
|
32
|
+
|
|
33
|
+
### Appearance
|
|
34
|
+
|
|
35
|
+
<Canvas of={MediaTagStories.AppearanceShowcase} />
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
### Size
|
|
40
|
+
|
|
41
|
+
MediaTags come in two different sizes:
|
|
42
|
+
|
|
43
|
+
- **md** (default) — the `leadingContent` media should be rendered at **16px**.
|
|
44
|
+
- **sm** — the `leadingContent` media should be rendered at **12px**.
|
|
45
|
+
|
|
46
|
+
The MediaTag does not resize its `leadingContent`; consumers are responsible for passing a media element sized to match the tag's `size`.
|
|
47
|
+
|
|
48
|
+
<Canvas of={MediaTagStories.SizeShowcase} />
|
|
49
|
+
|
|
50
|
+
### Truncation
|
|
51
|
+
|
|
52
|
+
When a MediaTag's label exceeds the available space, the text is automatically truncated with an ellipsis.
|
|
53
|
+
|
|
54
|
+
<Canvas of={MediaTagStories.TruncateShowcase} />
|
|
55
|
+
|
|
56
|
+
### Accessibility
|
|
57
|
+
|
|
58
|
+
To be implemented:
|
|
59
|
+
|
|
60
|
+
- **Color contrast**
|
|
61
|
+
- **Text zoom**
|
|
62
|
+
- **Touch targets**
|
|
63
|
+
- **Screen reader support**
|
|
64
|
+
- **Semantic labeling**
|
|
65
|
+
|
|
66
|
+
</Tab>
|
|
67
|
+
<Tab label="Implementation">
|
|
68
|
+
|
|
69
|
+
## Setup
|
|
70
|
+
|
|
71
|
+
Install and set up the library with our [Setup Guide →](?path=/docs/getting-started-setup--docs).
|
|
72
|
+
|
|
73
|
+
### Basic Usage
|
|
74
|
+
|
|
75
|
+
Match the media element size to the MediaTag `size`: **16px** for `md`, **12px** for `sm`.
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { MediaTag, MediaImage } from '@ledgerhq/lumen-ui-rnative';
|
|
79
|
+
|
|
80
|
+
function MyComponent() {
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
{/* md → image size 16 */}
|
|
84
|
+
<MediaTag
|
|
85
|
+
size="md"
|
|
86
|
+
appearance="accent"
|
|
87
|
+
label="Ethereum"
|
|
88
|
+
leadingContent={
|
|
89
|
+
<MediaImage
|
|
90
|
+
src="https://crypto-icons.ledger.com/ETH.png"
|
|
91
|
+
alt="Ethereum"
|
|
92
|
+
size={16}
|
|
93
|
+
shape="square"
|
|
94
|
+
/>
|
|
95
|
+
}
|
|
96
|
+
/>
|
|
97
|
+
|
|
98
|
+
{/* sm → image size 12 */}
|
|
99
|
+
<MediaTag
|
|
100
|
+
size="sm"
|
|
101
|
+
appearance="accent"
|
|
102
|
+
label="Ethereum"
|
|
103
|
+
leadingContent={
|
|
104
|
+
<MediaImage
|
|
105
|
+
src="https://crypto-icons.ledger.com/ETH.png"
|
|
106
|
+
alt="Ethereum"
|
|
107
|
+
size={12}
|
|
108
|
+
shape="square"
|
|
109
|
+
/>
|
|
110
|
+
}
|
|
111
|
+
/>
|
|
112
|
+
</>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Custom Styling
|
|
118
|
+
|
|
119
|
+
While the component comes with predefined styles, you can extend them using the `lx` prop for layout adjustments:
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
<MediaTag
|
|
123
|
+
size="md"
|
|
124
|
+
appearance="accent"
|
|
125
|
+
label="Custom MediaTag"
|
|
126
|
+
leadingContent={myIcon}
|
|
127
|
+
lx={{ marginTop: 's4' }}
|
|
128
|
+
/>
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### With Crypto Icons
|
|
132
|
+
|
|
133
|
+
The MediaTag accepts any `ReactNode` as its `leadingContent`, including crypto icons. Use **16px** for `md` and **12px** for `sm`:
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import { MediaTag } from '@ledgerhq/lumen-ui-rnative';
|
|
137
|
+
import CryptoIcon from '@ledgerhq/crypto-icons/native';
|
|
138
|
+
|
|
139
|
+
function MyComponent() {
|
|
140
|
+
return (
|
|
141
|
+
<>
|
|
142
|
+
{/* md → leadingContent size 16 */}
|
|
143
|
+
<MediaTag
|
|
144
|
+
size="md"
|
|
145
|
+
label="Bitcoin"
|
|
146
|
+
leadingContent={<CryptoIcon ledgerId="bitcoin" ticker="BTC" size={16} />}
|
|
147
|
+
/>
|
|
148
|
+
|
|
149
|
+
{/* sm → leadingContent size 12 */}
|
|
150
|
+
<MediaTag
|
|
151
|
+
size="sm"
|
|
152
|
+
label="Bitcoin"
|
|
153
|
+
leadingContent={<CryptoIcon ledgerId="bitcoin" ticker="BTC" size={12} />}
|
|
154
|
+
/>
|
|
155
|
+
</>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
</Tab>
|
|
161
|
+
</CustomTabs>
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
|
|
2
|
+
import { MediaImage } from '../MediaImage';
|
|
3
|
+
import { Box } from '../Utility/Box';
|
|
4
|
+
import { MediaTag } from './MediaTag';
|
|
5
|
+
|
|
6
|
+
const ETH_ICON = (
|
|
7
|
+
<MediaImage
|
|
8
|
+
src='https://crypto-icons.ledger.com/ETH.png'
|
|
9
|
+
alt='Ethereum'
|
|
10
|
+
size={16}
|
|
11
|
+
shape='square'
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const meta: Meta<typeof MediaTag> = {
|
|
16
|
+
component: MediaTag,
|
|
17
|
+
title: 'Communication/MediaTag',
|
|
18
|
+
argTypes: {
|
|
19
|
+
appearance: {
|
|
20
|
+
control: 'select',
|
|
21
|
+
options: [
|
|
22
|
+
'base',
|
|
23
|
+
'gray',
|
|
24
|
+
'accent',
|
|
25
|
+
'accent-subtle',
|
|
26
|
+
'success',
|
|
27
|
+
'error',
|
|
28
|
+
'warning',
|
|
29
|
+
'white',
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
size: {
|
|
33
|
+
control: 'radio',
|
|
34
|
+
options: ['sm', 'md'],
|
|
35
|
+
},
|
|
36
|
+
label: {
|
|
37
|
+
control: 'text',
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
|
|
44
|
+
type Story = StoryObj<typeof MediaTag>;
|
|
45
|
+
|
|
46
|
+
export const Base: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
label: 'Ethereum',
|
|
49
|
+
appearance: 'accent',
|
|
50
|
+
size: 'md',
|
|
51
|
+
},
|
|
52
|
+
render: (args) => <MediaTag {...args} leadingContent={ETH_ICON} />,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export const AppearanceShowcase: Story = {
|
|
56
|
+
render: () => (
|
|
57
|
+
<Box lx={{ flexDirection: 'row', flexWrap: 'wrap', gap: 's4' }}>
|
|
58
|
+
<MediaTag appearance='base' label='Base' leadingContent={ETH_ICON} />
|
|
59
|
+
<MediaTag appearance='gray' label='Gray' leadingContent={ETH_ICON} />
|
|
60
|
+
<MediaTag appearance='accent' label='Accent' leadingContent={ETH_ICON} />
|
|
61
|
+
<MediaTag
|
|
62
|
+
appearance='accent-subtle'
|
|
63
|
+
label='Accent subtle'
|
|
64
|
+
leadingContent={ETH_ICON}
|
|
65
|
+
/>
|
|
66
|
+
<MediaTag
|
|
67
|
+
appearance='success'
|
|
68
|
+
label='Success'
|
|
69
|
+
leadingContent={ETH_ICON}
|
|
70
|
+
/>
|
|
71
|
+
<MediaTag appearance='error' label='Error' leadingContent={ETH_ICON} />
|
|
72
|
+
<MediaTag
|
|
73
|
+
appearance='warning'
|
|
74
|
+
label='Warning'
|
|
75
|
+
leadingContent={ETH_ICON}
|
|
76
|
+
/>
|
|
77
|
+
<MediaTag appearance='white' label='White' leadingContent={ETH_ICON} />
|
|
78
|
+
<MediaTag label='Disabled' leadingContent={ETH_ICON} disabled />
|
|
79
|
+
</Box>
|
|
80
|
+
),
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export const SizeShowcase: Story = {
|
|
84
|
+
render: () => (
|
|
85
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's4' }}>
|
|
86
|
+
<MediaTag size='md' label='Medium' leadingContent={ETH_ICON} />
|
|
87
|
+
<MediaTag
|
|
88
|
+
size='sm'
|
|
89
|
+
label='Small'
|
|
90
|
+
leadingContent={
|
|
91
|
+
<MediaImage
|
|
92
|
+
src='https://crypto-icons.ledger.com/ETH.png'
|
|
93
|
+
alt='Ethereum'
|
|
94
|
+
size={12}
|
|
95
|
+
shape='square'
|
|
96
|
+
/>
|
|
97
|
+
}
|
|
98
|
+
/>
|
|
99
|
+
</Box>
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const TruncateShowcase: Story = {
|
|
104
|
+
render: () => (
|
|
105
|
+
<Box lx={{ width: 's176' }}>
|
|
106
|
+
<MediaTag
|
|
107
|
+
label='Very long text that truncates'
|
|
108
|
+
leadingContent={ETH_ICON}
|
|
109
|
+
/>
|
|
110
|
+
</Box>
|
|
111
|
+
),
|
|
112
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
2
|
+
import { ledgerLiveThemes } from '@ledgerhq/lumen-design-core';
|
|
3
|
+
import { render, screen } from '@testing-library/react-native';
|
|
4
|
+
import { Text } from 'react-native';
|
|
5
|
+
import { ThemeProvider } from '../ThemeProvider/ThemeProvider';
|
|
6
|
+
import { MediaTag } from './MediaTag';
|
|
7
|
+
|
|
8
|
+
const renderWithProvider = (component: React.ReactElement) =>
|
|
9
|
+
render(
|
|
10
|
+
<ThemeProvider themes={ledgerLiveThemes} colorScheme='dark' locale='en'>
|
|
11
|
+
{component}
|
|
12
|
+
</ThemeProvider>,
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
describe('MediaTag Component', () => {
|
|
16
|
+
it('should render label and the provided ReactNode icon as-is', () => {
|
|
17
|
+
renderWithProvider(
|
|
18
|
+
<MediaTag
|
|
19
|
+
label='Bitcoin'
|
|
20
|
+
leadingContent={<Text testID='media-icon'>bitcoin-icon</Text>}
|
|
21
|
+
/>,
|
|
22
|
+
);
|
|
23
|
+
expect(screen.getByText('Bitcoin')).toBeTruthy();
|
|
24
|
+
expect(screen.getByTestId('media-icon')).toBeTruthy();
|
|
25
|
+
expect(screen.getByText('bitcoin-icon')).toBeTruthy();
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BaseTag } from '../BaseTag';
|
|
2
|
+
import type { MediaTagProps } from './types';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A compact label used to categorize, classify, or highlight information with a required media element (image, crypto icon, etc.).
|
|
6
|
+
*
|
|
7
|
+
* The appearance determines the color scheme used.
|
|
8
|
+
*
|
|
9
|
+
* @see {@link https://ldls.vercel.app/?path=/docs/communication-mediatag-overview--docs Storybook}
|
|
10
|
+
* @see {@link https://ldls.vercel.app/?path=/docs/communication-mediatag-implementation--docs#dos-and-donts Guidelines}
|
|
11
|
+
*
|
|
12
|
+
* @warning The `lx` prop should only be used for layout adjustments like margins or positioning.
|
|
13
|
+
* Do not use it to modify the tag's core appearance (colors, padding, etc). Use the `appearance` prop instead.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* import { MediaTag, MediaImage } from '@ledgerhq/lumen-ui-rnative';
|
|
17
|
+
*
|
|
18
|
+
* // MediaTag with image
|
|
19
|
+
* <MediaTag
|
|
20
|
+
* label='Ethereum'
|
|
21
|
+
* leadingContent={<MediaImage src='https://crypto-icons.ledger.com/ETH.png' alt='Ethereum' size={16} shape='square' />}
|
|
22
|
+
* />
|
|
23
|
+
*
|
|
24
|
+
* // Small MediaTag
|
|
25
|
+
* <MediaTag label='Bitcoin' size='sm' leadingContent={myIcon} />
|
|
26
|
+
*/
|
|
27
|
+
export const MediaTag = ({ leadingContent, ...props }: MediaTagProps) => {
|
|
28
|
+
return (
|
|
29
|
+
<BaseTag
|
|
30
|
+
{...props}
|
|
31
|
+
variant='media'
|
|
32
|
+
consumerName='MediaTag'
|
|
33
|
+
renderIcon={() => leadingContent}
|
|
34
|
+
/>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { TagProps } from '../Tag';
|
|
3
|
+
|
|
4
|
+
export type MediaTagProps = Omit<TagProps, 'icon'> & {
|
|
5
|
+
/**
|
|
6
|
+
* The media element rendered before the label (e.g. an image or a crypto icon).
|
|
7
|
+
* Should be sized to match the tag's `size`: 16px for `md`, 12px for `sm`.
|
|
8
|
+
*/
|
|
9
|
+
leadingContent: ReactNode;
|
|
10
|
+
};
|
|
@@ -36,6 +36,7 @@ It handles **selection state**, **automatic grouping** (via a `group` field on i
|
|
|
36
36
|
- **OptionListItemContentRow**: Horizontal row for placing elements side-by-side (e.g. title + tag)
|
|
37
37
|
- **OptionListItemText**: Styled title text
|
|
38
38
|
- **OptionListItemDescription**: Styled description text
|
|
39
|
+
- **OptionListSearch**: Search input that filters items by label (default) or via a custom `filter` function
|
|
39
40
|
|
|
40
41
|
## Properties
|
|
41
42
|
|
|
@@ -63,6 +64,24 @@ Combining grouping with rich item content:
|
|
|
63
64
|
|
|
64
65
|
<Canvas of={OptionListStories.GroupedWithContentRow} />
|
|
65
66
|
|
|
67
|
+
### Search
|
|
68
|
+
|
|
69
|
+
Drop `OptionListSearch` inside the list to enable case-insensitive filtering on item labels. Pair with `OptionListEmptyState` to handle no-match scenarios. Pass a custom `filter` to match against meta (or anything else), or `filter={null}` to disable filtering. Use `filteredItems` + `onSearchValueChange` for async/server-side search.
|
|
70
|
+
|
|
71
|
+
<Canvas of={OptionListStories.WithSearch} />
|
|
72
|
+
|
|
73
|
+
Search works within grouped items too. Empty groups are hidden automatically:
|
|
74
|
+
|
|
75
|
+
<Canvas of={OptionListStories.WithSearchAndGroups} />
|
|
76
|
+
|
|
77
|
+
Pass a custom `filter` to match against fields beyond the label. Here, the query also matches each item's ticker via `meta`:
|
|
78
|
+
|
|
79
|
+
<Canvas of={OptionListStories.WithCustomSearchFilter} />
|
|
80
|
+
|
|
81
|
+
Drive the search input from the outside with `searchValue` + `onSearchValueChange`. This is useful for syncing search state with other UI or kicking off async fetches:
|
|
82
|
+
|
|
83
|
+
<Canvas of={OptionListStories.WithControlledSearch} />
|
|
84
|
+
|
|
66
85
|
### Trigger showcase
|
|
67
86
|
|
|
68
87
|
OptionList can be opened from any trigger. `MediaButton` supports multiple appearances (`gray`, `transparent`, `no-background`), optional icons (`flat` / `rounded`), and disabled state:
|