@ledgerhq/lumen-ui-rnative 0.1.19 → 0.1.21
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/lib/Components/AmountInput/AmountInput.js +2 -0
- package/dist/module/lib/Components/AmountInput/AmountInput.js.map +1 -1
- package/dist/module/lib/Components/Banner/Banner.js +13 -7
- package/dist/module/lib/Components/Banner/Banner.js.map +1 -1
- package/dist/module/lib/Components/BaseInput/BaseInput.js +7 -6
- package/dist/module/lib/Components/BaseInput/BaseInput.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheet.mdx +4 -4
- package/dist/module/lib/Components/BottomSheet/BottomSheet.stories.js +10 -10
- package/dist/module/lib/Components/BottomSheet/BottomSheet.stories.js.map +1 -1
- package/dist/module/lib/Components/BottomSheet/BottomSheetHeader.js +12 -12
- package/dist/module/lib/Components/BottomSheet/BottomSheetHeader.js.map +1 -1
- package/dist/module/lib/Components/Button/BaseButton.js +3 -1
- package/dist/module/lib/Components/Button/BaseButton.js.map +1 -1
- package/dist/module/lib/Components/Card/Card.js +3 -1
- package/dist/module/lib/Components/Card/Card.js.map +1 -1
- package/dist/module/lib/Components/DotSymbol/DotSymbol.js +141 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.js.map +1 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.mdx +54 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js +301 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.stories.js.map +1 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.test.js +134 -0
- package/dist/module/lib/Components/DotSymbol/DotSymbol.test.js.map +1 -0
- package/dist/module/lib/Components/DotSymbol/index.js +5 -0
- package/dist/module/lib/Components/DotSymbol/index.js.map +1 -0
- package/dist/module/lib/Components/DotSymbol/types.js +4 -0
- package/dist/module/lib/Components/DotSymbol/types.js.map +1 -0
- package/dist/module/lib/Components/ListItem/ListItem.js +2 -2
- package/dist/module/lib/Components/ListItem/ListItem.js.map +1 -1
- package/dist/module/lib/Components/MediaBanner/MediaBanner.js +1 -1
- package/dist/module/lib/Components/MediaBanner/MediaBanner.js.map +1 -1
- package/dist/module/lib/Components/MediaCard/MediaCard.js +1 -1
- package/dist/module/lib/Components/MediaCard/MediaCard.js.map +1 -1
- package/dist/module/lib/Components/MediaImage/MediaImage.js +1 -11
- package/dist/module/lib/Components/MediaImage/MediaImage.js.map +1 -1
- package/dist/module/lib/Components/MediaImage/index.js +1 -1
- package/dist/module/lib/Components/MediaImage/index.js.map +1 -1
- package/dist/module/lib/Components/NavBar/NavBar.js +27 -25
- package/dist/module/lib/Components/NavBar/NavBar.js.map +1 -1
- package/dist/module/lib/Components/NavBar/NavBar.mdx +7 -7
- package/dist/module/lib/Components/NavBar/NavBar.stories.js +6 -6
- package/dist/module/lib/Components/NavBar/NavBar.stories.js.map +1 -1
- package/dist/module/lib/Components/NavBar/NavBar.test.js +24 -24
- package/dist/module/lib/Components/NavBar/NavBar.test.js.map +1 -1
- package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js +1 -1
- package/dist/module/lib/Components/Select/GlobalSelectBottomSheet.js.map +1 -1
- package/dist/module/lib/Components/Select/Select.stories.js +1 -0
- package/dist/module/lib/Components/Select/Select.stories.js.map +1 -1
- package/dist/module/lib/Components/Spot/Spot.js +1 -0
- package/dist/module/lib/Components/Spot/Spot.js.map +1 -1
- package/dist/module/lib/Components/Stepper/Stepper.js +3 -0
- package/dist/module/lib/Components/Stepper/Stepper.js.map +1 -1
- package/dist/module/lib/Components/TabBar/TabBar.js +2 -2
- package/dist/module/lib/Components/TabBar/TabBar.js.map +1 -1
- package/dist/module/lib/Components/Tag/Tag.js +0 -2
- package/dist/module/lib/Components/Tag/Tag.js.map +1 -1
- package/dist/module/lib/Components/Tooltip/GlobalTooltipBottomSheet.js +1 -1
- package/dist/module/lib/Components/Tooltip/GlobalTooltipBottomSheet.js.map +1 -1
- package/dist/module/lib/Components/index.js +1 -0
- package/dist/module/lib/Components/index.js.map +1 -1
- package/dist/typescript/src/lib/Components/AmountInput/AmountInput.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Banner/Banner.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/BottomSheetHeader.d.ts +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/BottomSheetHeader.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/BottomSheet/types.d.ts +3 -2
- package/dist/typescript/src/lib/Components/BottomSheet/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Button/BaseButton.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Card/Card.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/DotSymbol/DotSymbol.d.ts +21 -0
- package/dist/typescript/src/lib/Components/DotSymbol/DotSymbol.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/DotSymbol/index.d.ts +3 -0
- package/dist/typescript/src/lib/Components/DotSymbol/index.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts +34 -0
- package/dist/typescript/src/lib/Components/DotSymbol/types.d.ts.map +1 -0
- package/dist/typescript/src/lib/Components/MediaImage/MediaImage.d.ts +1 -2
- package/dist/typescript/src/lib/Components/MediaImage/MediaImage.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/MediaImage/index.d.ts +1 -1
- package/dist/typescript/src/lib/Components/MediaImage/index.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/NavBar/NavBar.d.ts +1 -1
- package/dist/typescript/src/lib/Components/NavBar/NavBar.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/NavBar/types.d.ts +3 -3
- package/dist/typescript/src/lib/Components/NavBar/types.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Spot/Spot.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Stepper/Stepper.d.ts.map +1 -1
- package/dist/typescript/src/lib/Components/Tag/Tag.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/package.json +1 -1
- package/src/lib/Components/AmountInput/AmountInput.tsx +8 -2
- package/src/lib/Components/Banner/Banner.tsx +10 -4
- package/src/lib/Components/BaseInput/BaseInput.tsx +4 -3
- package/src/lib/Components/BottomSheet/BottomSheet.mdx +4 -4
- package/src/lib/Components/BottomSheet/BottomSheet.stories.tsx +10 -10
- package/src/lib/Components/BottomSheet/BottomSheetHeader.tsx +14 -14
- package/src/lib/Components/BottomSheet/types.ts +3 -2
- package/src/lib/Components/Button/BaseButton.tsx +4 -1
- package/src/lib/Components/Card/Card.tsx +2 -0
- package/src/lib/Components/DotSymbol/DotSymbol.mdx +54 -0
- package/src/lib/Components/DotSymbol/DotSymbol.stories.tsx +191 -0
- package/src/lib/Components/DotSymbol/DotSymbol.test.tsx +119 -0
- package/src/lib/Components/DotSymbol/DotSymbol.tsx +161 -0
- package/src/lib/Components/DotSymbol/index.ts +2 -0
- package/src/lib/Components/DotSymbol/types.ts +40 -0
- package/src/lib/Components/ListItem/ListItem.tsx +4 -4
- package/src/lib/Components/MediaBanner/MediaBanner.tsx +1 -1
- package/src/lib/Components/MediaCard/MediaCard.tsx +1 -1
- package/src/lib/Components/MediaImage/MediaImage.tsx +6 -17
- package/src/lib/Components/MediaImage/index.ts +1 -1
- package/src/lib/Components/NavBar/NavBar.mdx +7 -7
- package/src/lib/Components/NavBar/NavBar.stories.tsx +6 -6
- package/src/lib/Components/NavBar/NavBar.test.tsx +25 -25
- package/src/lib/Components/NavBar/NavBar.tsx +31 -29
- package/src/lib/Components/NavBar/types.ts +3 -4
- package/src/lib/Components/Select/GlobalSelectBottomSheet.tsx +1 -1
- package/src/lib/Components/Select/Select.stories.tsx +1 -0
- package/src/lib/Components/Spot/Spot.tsx +5 -1
- package/src/lib/Components/Stepper/Stepper.tsx +15 -3
- package/src/lib/Components/TabBar/TabBar.tsx +2 -2
- package/src/lib/Components/Tag/Tag.tsx +1 -3
- package/src/lib/Components/Tooltip/GlobalTooltipBottomSheet.tsx +1 -1
- package/src/lib/Components/index.ts +1 -0
|
@@ -129,7 +129,7 @@ export const Base: Story = {
|
|
|
129
129
|
<BottomSheetView>
|
|
130
130
|
<BottomSheetHeader
|
|
131
131
|
title='Title'
|
|
132
|
-
|
|
132
|
+
density='compact'
|
|
133
133
|
description='Description'
|
|
134
134
|
/>
|
|
135
135
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -179,7 +179,7 @@ export const TitleExpanded: Story = {
|
|
|
179
179
|
<BottomSheetView>
|
|
180
180
|
<BottomSheetHeader
|
|
181
181
|
title='Expanded title'
|
|
182
|
-
|
|
182
|
+
density='expanded'
|
|
183
183
|
description='Expanded description.'
|
|
184
184
|
/>
|
|
185
185
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -224,7 +224,7 @@ export const DynamicSizingWithoutSnapPoints: Story = {
|
|
|
224
224
|
<BottomSheetScrollView>
|
|
225
225
|
<BottomSheetHeader
|
|
226
226
|
title='Dynamic Sizing'
|
|
227
|
-
|
|
227
|
+
density='compact'
|
|
228
228
|
description='This bottom sheet adapts to its content height'
|
|
229
229
|
/>
|
|
230
230
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -266,7 +266,7 @@ export const DynamicSizingWithSnapPoints: Story = {
|
|
|
266
266
|
<BottomSheetScrollView>
|
|
267
267
|
<BottomSheetHeader
|
|
268
268
|
title='Dynamic Sizing'
|
|
269
|
-
|
|
269
|
+
density='compact'
|
|
270
270
|
description='This bottom sheet adapts to its content height and has snap points'
|
|
271
271
|
/>
|
|
272
272
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -311,7 +311,7 @@ export const PreventClose: Story = {
|
|
|
311
311
|
<BottomSheetView>
|
|
312
312
|
<BottomSheetHeader
|
|
313
313
|
title='Hidden Close Button'
|
|
314
|
-
|
|
314
|
+
density='compact'
|
|
315
315
|
description='This bottom sheet cannot be closed by dragging or button'
|
|
316
316
|
/>
|
|
317
317
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -355,7 +355,7 @@ export const ScrollView: Story = {
|
|
|
355
355
|
<BottomSheetScrollView>
|
|
356
356
|
<BottomSheetHeader
|
|
357
357
|
title='Scrollable Content'
|
|
358
|
-
|
|
358
|
+
density='compact'
|
|
359
359
|
description='This bottom sheet contains a scrollable view'
|
|
360
360
|
/>
|
|
361
361
|
<Box lx={{ flexDirection: 'column', gap: 's12' }}>
|
|
@@ -411,7 +411,7 @@ export const VirtualList: Story = {
|
|
|
411
411
|
<BottomSheetHeader
|
|
412
412
|
spacing
|
|
413
413
|
title='Virtual List'
|
|
414
|
-
|
|
414
|
+
density='compact'
|
|
415
415
|
description='This bottom sheet contains a virtualized list'
|
|
416
416
|
/>
|
|
417
417
|
<BottomSheetFlatList
|
|
@@ -491,7 +491,7 @@ export const StickyHeaderContent: Story = {
|
|
|
491
491
|
<BottomSheetHeader
|
|
492
492
|
spacing
|
|
493
493
|
title='BottomSheetFlatList'
|
|
494
|
-
|
|
494
|
+
density='compact'
|
|
495
495
|
description='The search input is rendered as a sticky list header'
|
|
496
496
|
/>
|
|
497
497
|
<BottomSheetFlatList
|
|
@@ -543,7 +543,7 @@ export const StickyHeaderContent: Story = {
|
|
|
543
543
|
<BottomSheetHeader
|
|
544
544
|
spacing
|
|
545
545
|
title='BottomSheetScrollView'
|
|
546
|
-
|
|
546
|
+
density='compact'
|
|
547
547
|
description='The search input is rendered as a sticky list header'
|
|
548
548
|
/>
|
|
549
549
|
{data.map((item) => (
|
|
@@ -613,7 +613,7 @@ export const VirtualizedList: Story = {
|
|
|
613
613
|
<BottomSheetHeader
|
|
614
614
|
spacing
|
|
615
615
|
title='Virtualized List'
|
|
616
|
-
|
|
616
|
+
density='compact'
|
|
617
617
|
description='This bottom sheet uses a VirtualizedList with custom getItem/getItemCount'
|
|
618
618
|
/>
|
|
619
619
|
<BottomSheetVirtualizedList
|
|
@@ -9,16 +9,16 @@ import { Box, Text } from '../Utility';
|
|
|
9
9
|
import { useBottomSheetContext } from './BottomSheet';
|
|
10
10
|
import { BottomSheetHeaderProps } from './types';
|
|
11
11
|
|
|
12
|
-
type
|
|
12
|
+
type DensityValue = NonNullable<BottomSheetHeaderProps['density']>;
|
|
13
13
|
|
|
14
14
|
const Z_INDEX_DIALOG_CONTENT = 1000;
|
|
15
15
|
|
|
16
16
|
const useStyles = ({
|
|
17
|
-
|
|
17
|
+
density,
|
|
18
18
|
spacing,
|
|
19
19
|
hidden,
|
|
20
20
|
}: {
|
|
21
|
-
|
|
21
|
+
density: DensityValue;
|
|
22
22
|
spacing: boolean;
|
|
23
23
|
hidden: boolean;
|
|
24
24
|
}) => {
|
|
@@ -42,7 +42,7 @@ const useStyles = ({
|
|
|
42
42
|
justifyContent: 'space-between',
|
|
43
43
|
gap: t.spacings.s16,
|
|
44
44
|
},
|
|
45
|
-
|
|
45
|
+
density === 'expanded' && {
|
|
46
46
|
marginBottom: t.spacings.s16,
|
|
47
47
|
},
|
|
48
48
|
hidden && {
|
|
@@ -53,7 +53,7 @@ const useStyles = ({
|
|
|
53
53
|
{
|
|
54
54
|
flex: 1,
|
|
55
55
|
},
|
|
56
|
-
|
|
56
|
+
density === 'expanded' && {
|
|
57
57
|
gap: t.spacings.s4,
|
|
58
58
|
flex: 0,
|
|
59
59
|
},
|
|
@@ -62,10 +62,10 @@ const useStyles = ({
|
|
|
62
62
|
{
|
|
63
63
|
color: t.colors.text.base,
|
|
64
64
|
},
|
|
65
|
-
|
|
65
|
+
density === 'expanded' && {
|
|
66
66
|
...t.typographies.heading3SemiBold,
|
|
67
67
|
},
|
|
68
|
-
|
|
68
|
+
density === 'compact' && {
|
|
69
69
|
textAlign: 'center',
|
|
70
70
|
...t.typographies.heading5SemiBold,
|
|
71
71
|
},
|
|
@@ -74,7 +74,7 @@ const useStyles = ({
|
|
|
74
74
|
t.typographies.body2,
|
|
75
75
|
{
|
|
76
76
|
color: t.colors.text.muted,
|
|
77
|
-
textAlign:
|
|
77
|
+
textAlign: density === 'compact' ? 'center' : 'left',
|
|
78
78
|
},
|
|
79
79
|
]),
|
|
80
80
|
iconPlaceholder: {
|
|
@@ -82,7 +82,7 @@ const useStyles = ({
|
|
|
82
82
|
height: t.sizes.s32,
|
|
83
83
|
},
|
|
84
84
|
}),
|
|
85
|
-
[
|
|
85
|
+
[density, spacing, hidden],
|
|
86
86
|
);
|
|
87
87
|
};
|
|
88
88
|
|
|
@@ -91,7 +91,7 @@ export const BottomSheetHeader = ({
|
|
|
91
91
|
style,
|
|
92
92
|
title,
|
|
93
93
|
description,
|
|
94
|
-
|
|
94
|
+
density = 'compact',
|
|
95
95
|
spacing = false,
|
|
96
96
|
...props
|
|
97
97
|
}: BottomSheetHeaderProps) => {
|
|
@@ -110,9 +110,9 @@ export const BottomSheetHeader = ({
|
|
|
110
110
|
const hasIcons = Boolean(onBack || !hideCloseButton);
|
|
111
111
|
|
|
112
112
|
const styles = useStyles({
|
|
113
|
-
|
|
113
|
+
density,
|
|
114
114
|
spacing,
|
|
115
|
-
hidden: !hasIcons &&
|
|
115
|
+
hidden: !hasIcons && density !== 'compact',
|
|
116
116
|
});
|
|
117
117
|
|
|
118
118
|
if (!title && !description && !onBack && hideCloseButton) {
|
|
@@ -154,7 +154,7 @@ export const BottomSheetHeader = ({
|
|
|
154
154
|
/>
|
|
155
155
|
)}
|
|
156
156
|
</Box>
|
|
157
|
-
{
|
|
157
|
+
{density === 'compact' && titleComponent}
|
|
158
158
|
<Box style={styles.iconPlaceholder}>
|
|
159
159
|
{!hideCloseButton && (
|
|
160
160
|
<IconButton
|
|
@@ -170,7 +170,7 @@ export const BottomSheetHeader = ({
|
|
|
170
170
|
)}
|
|
171
171
|
</Box>
|
|
172
172
|
</Box>
|
|
173
|
-
{
|
|
173
|
+
{density === 'expanded' && titleComponent}
|
|
174
174
|
</Box>
|
|
175
175
|
);
|
|
176
176
|
};
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
BottomSheetVirtualizedList as GorhomBottomSheetVirtualizedList,
|
|
8
8
|
} from '@gorhom/bottom-sheet';
|
|
9
9
|
|
|
10
|
+
import { Density } from '@ledgerhq/lumen-utils-shared';
|
|
10
11
|
import { PropsWithChildren, ReactNode, Ref } from 'react';
|
|
11
12
|
import { StyledViewProps } from '../../../styles';
|
|
12
13
|
export type BottomSheetProps = PropsWithChildren & {
|
|
@@ -134,10 +135,10 @@ export type BottomSheetProps = PropsWithChildren & {
|
|
|
134
135
|
|
|
135
136
|
export type BottomSheetHeaderProps = {
|
|
136
137
|
/**
|
|
137
|
-
* The
|
|
138
|
+
* The density of the header.
|
|
138
139
|
* @default 'compact'
|
|
139
140
|
*/
|
|
140
|
-
|
|
141
|
+
density?: Density;
|
|
141
142
|
/**
|
|
142
143
|
* The title of the header.
|
|
143
144
|
*/
|
|
@@ -35,6 +35,7 @@ const useStyles = ({
|
|
|
35
35
|
size,
|
|
36
36
|
disabled,
|
|
37
37
|
pressed,
|
|
38
|
+
hasIcon,
|
|
38
39
|
iconOnly,
|
|
39
40
|
isFull,
|
|
40
41
|
}: {
|
|
@@ -42,6 +43,7 @@ const useStyles = ({
|
|
|
42
43
|
size: Size;
|
|
43
44
|
disabled: boolean;
|
|
44
45
|
pressed: boolean;
|
|
46
|
+
hasIcon: boolean;
|
|
45
47
|
iconOnly: boolean;
|
|
46
48
|
isFull: boolean;
|
|
47
49
|
}) => {
|
|
@@ -121,7 +123,7 @@ const useStyles = ({
|
|
|
121
123
|
typography,
|
|
122
124
|
{
|
|
123
125
|
color: disabled ? t.colors.text.disabled : textColors[appearance],
|
|
124
|
-
textAlign: 'left',
|
|
126
|
+
textAlign: hasIcon ? 'left' : 'center',
|
|
125
127
|
},
|
|
126
128
|
]),
|
|
127
129
|
icon: {
|
|
@@ -212,6 +214,7 @@ const BaseButtonContent = ({
|
|
|
212
214
|
size,
|
|
213
215
|
disabled,
|
|
214
216
|
pressed,
|
|
217
|
+
hasIcon: !!IconProp,
|
|
215
218
|
iconOnly,
|
|
216
219
|
isFull,
|
|
217
220
|
});
|
|
@@ -472,6 +472,7 @@ export const CardContentTitle = ({
|
|
|
472
472
|
asText: StyleSheet.flatten([
|
|
473
473
|
t.typographies.body2SemiBold,
|
|
474
474
|
{
|
|
475
|
+
flexShrink: 1,
|
|
475
476
|
color: disabled ? t.colors.text.disabled : t.colors.text.base,
|
|
476
477
|
textAlign: align === 'right' ? 'right' : 'left',
|
|
477
478
|
},
|
|
@@ -538,6 +539,7 @@ export const CardContentDescription = ({
|
|
|
538
539
|
asText: StyleSheet.flatten([
|
|
539
540
|
t.typographies.body3,
|
|
540
541
|
{
|
|
542
|
+
flexShrink: 1,
|
|
541
543
|
color: disabled ? t.colors.text.disabled : t.colors.text.muted,
|
|
542
544
|
textAlign: align === 'right' ? 'right' : 'left',
|
|
543
545
|
},
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as DotSymbolStories from './DotSymbol.stories';
|
|
3
|
+
import { CustomTabs, Tab } from '../../../../.storybook/components';
|
|
4
|
+
|
|
5
|
+
<Meta title='Communication/DotSymbol' of={DotSymbolStories} />
|
|
6
|
+
|
|
7
|
+
<CustomTabs>
|
|
8
|
+
<Tab label="Overview">
|
|
9
|
+
# DotSymbol
|
|
10
|
+
|
|
11
|
+
## Introduction
|
|
12
|
+
|
|
13
|
+
DotSymbol positions a small image indicator at a configurable corner of a child element such as MediaImage or Spot. It is commonly used to show a network badge or secondary icon overlapping a primary symbol.
|
|
14
|
+
|
|
15
|
+
## Anatomy
|
|
16
|
+
|
|
17
|
+
<Canvas of={DotSymbolStories.Base} />
|
|
18
|
+
|
|
19
|
+
- **Wrapper**: Relative container that preserves the child's layout
|
|
20
|
+
- **Child**: The primary element (e.g. MediaImage, Spot)
|
|
21
|
+
- **Dot**: Absolutely-positioned image indicator with border and configurable shape
|
|
22
|
+
|
|
23
|
+
## Properties
|
|
24
|
+
|
|
25
|
+
### Overview
|
|
26
|
+
|
|
27
|
+
<Canvas of={DotSymbolStories.Base} />
|
|
28
|
+
<Controls of={DotSymbolStories.Base} />
|
|
29
|
+
|
|
30
|
+
### Pin
|
|
31
|
+
|
|
32
|
+
Four corner placements are available: `bottom-end` (default), `top-end`, `bottom-start`, and `top-start`.
|
|
33
|
+
|
|
34
|
+
<Canvas of={DotSymbolStories.PinShowcase} />
|
|
35
|
+
|
|
36
|
+
### Shapes
|
|
37
|
+
|
|
38
|
+
<Canvas of={DotSymbolStories.ShapeShowcase} />
|
|
39
|
+
|
|
40
|
+
- **circle** (default): Fully rounded dot
|
|
41
|
+
- **square**: Rounded corners that scale with size
|
|
42
|
+
|
|
43
|
+
### Sizes
|
|
44
|
+
|
|
45
|
+
The dot size is driven by the parent MediaImage or Spot size via the mapping helpers `mediaImageDotSizeMap` and `spotDotSizeMap`.
|
|
46
|
+
|
|
47
|
+
<Canvas of={DotSymbolStories.SizeShowcase} />
|
|
48
|
+
|
|
49
|
+
## Accessibility
|
|
50
|
+
|
|
51
|
+
- Always provide a meaningful `alt` prop on the DotSymbol so the indicator image is announced by screen readers.
|
|
52
|
+
- The child element should carry its own accessibility label independently.
|
|
53
|
+
</Tab>
|
|
54
|
+
</CustomTabs>
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
|
|
2
|
+
import { CoinAlert } from '../../Symbols';
|
|
3
|
+
import { MediaImage } from '../MediaImage';
|
|
4
|
+
import { Spot } from '../Spot';
|
|
5
|
+
import { Box } from '../Utility';
|
|
6
|
+
import { DotSymbol, mediaImageDotSizeMap } from './DotSymbol';
|
|
7
|
+
|
|
8
|
+
const meta = {
|
|
9
|
+
component: DotSymbol,
|
|
10
|
+
title: 'Communication/DotSymbol',
|
|
11
|
+
parameters: {
|
|
12
|
+
docs: {
|
|
13
|
+
source: {
|
|
14
|
+
language: 'tsx',
|
|
15
|
+
format: true,
|
|
16
|
+
type: 'code',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
} satisfies Meta<typeof DotSymbol>;
|
|
21
|
+
|
|
22
|
+
export default meta;
|
|
23
|
+
type Story = StoryObj<typeof meta>;
|
|
24
|
+
|
|
25
|
+
const parentSrc = 'https://crypto-icons.ledger.com/ADA.png';
|
|
26
|
+
const dotSrc = 'https://crypto-icons.ledger.com/BTC.png';
|
|
27
|
+
|
|
28
|
+
export const Base: Story = {
|
|
29
|
+
args: {
|
|
30
|
+
src: dotSrc,
|
|
31
|
+
alt: 'Ethereum network',
|
|
32
|
+
pin: 'bottom-end',
|
|
33
|
+
size: 20,
|
|
34
|
+
shape: 'circle',
|
|
35
|
+
children: <MediaImage src={parentSrc} alt='Cardano' shape='circle' />,
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export const PinShowcase: Story = {
|
|
40
|
+
args: { src: dotSrc, alt: 'Pin showcase' },
|
|
41
|
+
render: () => (
|
|
42
|
+
<Box lx={{ flexDirection: 'column', alignItems: 'center', gap: 's24' }}>
|
|
43
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's32' }}>
|
|
44
|
+
<DotSymbol src={dotSrc} pin='bottom-end'>
|
|
45
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
46
|
+
</DotSymbol>
|
|
47
|
+
<DotSymbol src={dotSrc} pin='top-end'>
|
|
48
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
49
|
+
</DotSymbol>
|
|
50
|
+
<DotSymbol src={dotSrc} pin='bottom-start'>
|
|
51
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
52
|
+
</DotSymbol>
|
|
53
|
+
<DotSymbol src={dotSrc} pin='top-start'>
|
|
54
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
55
|
+
</DotSymbol>
|
|
56
|
+
</Box>
|
|
57
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's32' }}>
|
|
58
|
+
<DotSymbol src={dotSrc} pin='bottom-end'>
|
|
59
|
+
<Spot appearance='icon' icon={CoinAlert} />
|
|
60
|
+
</DotSymbol>
|
|
61
|
+
<DotSymbol src={dotSrc} pin='top-end'>
|
|
62
|
+
<Spot appearance='icon' icon={CoinAlert} />
|
|
63
|
+
</DotSymbol>
|
|
64
|
+
<DotSymbol src={dotSrc} pin='bottom-start'>
|
|
65
|
+
<Spot appearance='icon' icon={CoinAlert} />
|
|
66
|
+
</DotSymbol>
|
|
67
|
+
<DotSymbol src={dotSrc} pin='top-start'>
|
|
68
|
+
<Spot appearance='icon' icon={CoinAlert} />
|
|
69
|
+
</DotSymbol>
|
|
70
|
+
</Box>
|
|
71
|
+
</Box>
|
|
72
|
+
),
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export const ShapeShowcase: Story = {
|
|
76
|
+
args: { src: dotSrc, alt: 'Shape showcase' },
|
|
77
|
+
render: () => (
|
|
78
|
+
<Box lx={{ flexDirection: 'column', alignItems: 'center', gap: 's48' }}>
|
|
79
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'center', gap: 's48' }}>
|
|
80
|
+
<DotSymbol shape='square' src={dotSrc} pin='bottom-end'>
|
|
81
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
82
|
+
</DotSymbol>
|
|
83
|
+
<DotSymbol shape='circle' src={dotSrc} pin='bottom-end'>
|
|
84
|
+
<MediaImage src={parentSrc} shape='circle' />
|
|
85
|
+
</DotSymbol>
|
|
86
|
+
</Box>
|
|
87
|
+
</Box>
|
|
88
|
+
),
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export const SizeShowcase: Story = {
|
|
92
|
+
args: { src: dotSrc, alt: 'Size showcase' },
|
|
93
|
+
render: () => (
|
|
94
|
+
<Box lx={{ flexDirection: 'column', gap: 's40' }}>
|
|
95
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'flex-end', gap: 's24' }}>
|
|
96
|
+
<DotSymbol
|
|
97
|
+
src={dotSrc}
|
|
98
|
+
size={mediaImageDotSizeMap[20]}
|
|
99
|
+
pin='bottom-end'
|
|
100
|
+
>
|
|
101
|
+
<MediaImage src={parentSrc} size={20} shape='circle' />
|
|
102
|
+
</DotSymbol>
|
|
103
|
+
<DotSymbol
|
|
104
|
+
src={dotSrc}
|
|
105
|
+
size={mediaImageDotSizeMap[24]}
|
|
106
|
+
pin='bottom-end'
|
|
107
|
+
>
|
|
108
|
+
<MediaImage src={parentSrc} size={24} shape='circle' />
|
|
109
|
+
</DotSymbol>
|
|
110
|
+
<DotSymbol
|
|
111
|
+
src={dotSrc}
|
|
112
|
+
size={mediaImageDotSizeMap[32]}
|
|
113
|
+
pin='bottom-end'
|
|
114
|
+
>
|
|
115
|
+
<MediaImage src={parentSrc} size={32} shape='circle' />
|
|
116
|
+
</DotSymbol>
|
|
117
|
+
<DotSymbol
|
|
118
|
+
src={dotSrc}
|
|
119
|
+
size={mediaImageDotSizeMap[40]}
|
|
120
|
+
pin='bottom-end'
|
|
121
|
+
>
|
|
122
|
+
<MediaImage src={parentSrc} size={40} shape='circle' />
|
|
123
|
+
</DotSymbol>
|
|
124
|
+
<DotSymbol
|
|
125
|
+
src={dotSrc}
|
|
126
|
+
size={mediaImageDotSizeMap[48]}
|
|
127
|
+
pin='bottom-end'
|
|
128
|
+
>
|
|
129
|
+
<MediaImage src={parentSrc} size={48} shape='circle' />
|
|
130
|
+
</DotSymbol>
|
|
131
|
+
<DotSymbol
|
|
132
|
+
src={dotSrc}
|
|
133
|
+
size={mediaImageDotSizeMap[56]}
|
|
134
|
+
pin='bottom-end'
|
|
135
|
+
>
|
|
136
|
+
<MediaImage src={parentSrc} size={56} shape='circle' />
|
|
137
|
+
</DotSymbol>
|
|
138
|
+
</Box>
|
|
139
|
+
<Box lx={{ flexDirection: 'row', alignItems: 'flex-end', gap: 's24' }}>
|
|
140
|
+
<DotSymbol
|
|
141
|
+
shape='square'
|
|
142
|
+
src={dotSrc}
|
|
143
|
+
size={mediaImageDotSizeMap[20]}
|
|
144
|
+
pin='bottom-end'
|
|
145
|
+
>
|
|
146
|
+
<MediaImage src={parentSrc} size={20} shape='circle' />
|
|
147
|
+
</DotSymbol>
|
|
148
|
+
<DotSymbol
|
|
149
|
+
shape='square'
|
|
150
|
+
src={dotSrc}
|
|
151
|
+
size={mediaImageDotSizeMap[24]}
|
|
152
|
+
pin='bottom-end'
|
|
153
|
+
>
|
|
154
|
+
<MediaImage src={parentSrc} size={24} shape='circle' />
|
|
155
|
+
</DotSymbol>
|
|
156
|
+
<DotSymbol
|
|
157
|
+
shape='square'
|
|
158
|
+
src={dotSrc}
|
|
159
|
+
size={mediaImageDotSizeMap[32]}
|
|
160
|
+
pin='bottom-end'
|
|
161
|
+
>
|
|
162
|
+
<MediaImage src={parentSrc} size={32} shape='circle' />
|
|
163
|
+
</DotSymbol>
|
|
164
|
+
<DotSymbol
|
|
165
|
+
shape='square'
|
|
166
|
+
src={dotSrc}
|
|
167
|
+
size={mediaImageDotSizeMap[40]}
|
|
168
|
+
pin='bottom-end'
|
|
169
|
+
>
|
|
170
|
+
<MediaImage src={parentSrc} size={40} shape='circle' />
|
|
171
|
+
</DotSymbol>
|
|
172
|
+
<DotSymbol
|
|
173
|
+
shape='square'
|
|
174
|
+
src={dotSrc}
|
|
175
|
+
size={mediaImageDotSizeMap[48]}
|
|
176
|
+
pin='bottom-end'
|
|
177
|
+
>
|
|
178
|
+
<MediaImage src={parentSrc} size={48} shape='circle' />
|
|
179
|
+
</DotSymbol>
|
|
180
|
+
<DotSymbol
|
|
181
|
+
shape='square'
|
|
182
|
+
src={dotSrc}
|
|
183
|
+
size={mediaImageDotSizeMap[56]}
|
|
184
|
+
pin='bottom-end'
|
|
185
|
+
>
|
|
186
|
+
<MediaImage src={parentSrc} size={56} shape='circle' />
|
|
187
|
+
</DotSymbol>
|
|
188
|
+
</Box>
|
|
189
|
+
</Box>
|
|
190
|
+
),
|
|
191
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { describe, it, expect } from '@jest/globals';
|
|
2
|
+
import { ledgerLiveThemes } from '@ledgerhq/lumen-design-core';
|
|
3
|
+
import { render, waitFor } from '@testing-library/react-native';
|
|
4
|
+
import { Text } from 'react-native';
|
|
5
|
+
import { ThemeProvider } from '../ThemeProvider/ThemeProvider';
|
|
6
|
+
import { DotSymbol } from './DotSymbol';
|
|
7
|
+
|
|
8
|
+
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
|
|
9
|
+
<ThemeProvider themes={ledgerLiveThemes} colorScheme='dark' locale='en'>
|
|
10
|
+
{children}
|
|
11
|
+
</ThemeProvider>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
describe('DotSymbol Component', () => {
|
|
15
|
+
const dotSrc = 'https://crypto-icons.ledger.com/BTC.png';
|
|
16
|
+
|
|
17
|
+
it('should render children and dot image', () => {
|
|
18
|
+
const { getByText, getByTestId } = render(
|
|
19
|
+
<TestWrapper>
|
|
20
|
+
<DotSymbol src={dotSrc} alt='Bitcoin'>
|
|
21
|
+
<Text>Child</Text>
|
|
22
|
+
</DotSymbol>
|
|
23
|
+
</TestWrapper>,
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
expect(getByText('Child')).toBeTruthy();
|
|
27
|
+
|
|
28
|
+
const img = getByTestId('dot-symbol-img');
|
|
29
|
+
expect(img.props.source).toEqual({ uri: dotSrc });
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('should render without children', () => {
|
|
33
|
+
const { getByTestId } = render(
|
|
34
|
+
<TestWrapper>
|
|
35
|
+
<DotSymbol src={dotSrc} />
|
|
36
|
+
</TestWrapper>,
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
expect(getByTestId('dot-symbol-img')).toBeTruthy();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('should render fallback when image fails to load', async () => {
|
|
43
|
+
const { getByTestId, queryByTestId, rerender } = render(
|
|
44
|
+
<TestWrapper>
|
|
45
|
+
<DotSymbol src='https://broken-link.com/404.png' />
|
|
46
|
+
</TestWrapper>,
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const img = getByTestId('dot-symbol-img');
|
|
50
|
+
img.props.onError();
|
|
51
|
+
|
|
52
|
+
rerender(
|
|
53
|
+
<TestWrapper>
|
|
54
|
+
<DotSymbol src='https://broken-link.com/404.png' />
|
|
55
|
+
</TestWrapper>,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
await waitFor(() => {
|
|
59
|
+
expect(queryByTestId('dot-symbol-img')).toBeNull();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it('should reset error state when src changes', async () => {
|
|
64
|
+
const { getByTestId, rerender } = render(
|
|
65
|
+
<TestWrapper>
|
|
66
|
+
<DotSymbol src='https://broken-link.com/404.png' />
|
|
67
|
+
</TestWrapper>,
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const img = getByTestId('dot-symbol-img');
|
|
71
|
+
img.props.onError();
|
|
72
|
+
|
|
73
|
+
rerender(
|
|
74
|
+
<TestWrapper>
|
|
75
|
+
<DotSymbol src={dotSrc} />
|
|
76
|
+
</TestWrapper>,
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
await waitFor(() => {
|
|
80
|
+
const newImg = getByTestId('dot-symbol-img');
|
|
81
|
+
expect(newImg.props.source).toEqual({ uri: dotSrc });
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should set accessibility label from alt prop', () => {
|
|
86
|
+
const { getByLabelText } = render(
|
|
87
|
+
<TestWrapper>
|
|
88
|
+
<DotSymbol src={dotSrc} alt='Bitcoin network' />
|
|
89
|
+
</TestWrapper>,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
expect(getByLabelText('Bitcoin network')).toBeTruthy();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('should apply custom styles', () => {
|
|
96
|
+
const { getByTestId } = render(
|
|
97
|
+
<TestWrapper>
|
|
98
|
+
<DotSymbol testID='ds' src={dotSrc} style={{ marginTop: 10 }} />
|
|
99
|
+
</TestWrapper>,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const root = getByTestId('ds');
|
|
103
|
+
expect(root.props.style.marginTop).toBe(10);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('should pass additional props', () => {
|
|
107
|
+
const { getByTestId } = render(
|
|
108
|
+
<TestWrapper>
|
|
109
|
+
<DotSymbol testID='custom-dot' src={dotSrc} />
|
|
110
|
+
</TestWrapper>,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(getByTestId('custom-dot')).toBeTruthy();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should have correct displayName', () => {
|
|
117
|
+
expect(DotSymbol.displayName).toBe('DotSymbol');
|
|
118
|
+
});
|
|
119
|
+
});
|