@ledgerhq/lumen-ui-rnative 0.1.12 → 0.1.14

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.
Files changed (56) hide show
  1. package/dist/module/lib/Components/MediaBanner/MediaBanner.js +158 -0
  2. package/dist/module/lib/Components/MediaBanner/MediaBanner.js.map +1 -0
  3. package/dist/module/lib/Components/MediaBanner/MediaBanner.mdx +150 -0
  4. package/dist/module/lib/Components/MediaBanner/MediaBanner.stories.js +135 -0
  5. package/dist/module/lib/Components/MediaBanner/MediaBanner.stories.js.map +1 -0
  6. package/dist/module/lib/Components/MediaBanner/MediaBanner.test.js +83 -0
  7. package/dist/module/lib/Components/MediaBanner/MediaBanner.test.js.map +1 -0
  8. package/dist/module/lib/Components/MediaBanner/index.js +5 -0
  9. package/dist/module/lib/Components/MediaBanner/index.js.map +1 -0
  10. package/dist/module/lib/Components/MediaBanner/types.js +4 -0
  11. package/dist/module/lib/Components/MediaBanner/types.js.map +1 -0
  12. package/dist/module/lib/Components/Tag/Tag.js +1 -0
  13. package/dist/module/lib/Components/Tag/Tag.js.map +1 -1
  14. package/dist/module/lib/Components/Tag/Tag.mdx +6 -0
  15. package/dist/module/lib/Components/Tag/Tag.stories.js +10 -0
  16. package/dist/module/lib/Components/Tag/Tag.stories.js.map +1 -1
  17. package/dist/module/lib/Components/index.js +1 -0
  18. package/dist/module/lib/Components/index.js.map +1 -1
  19. package/dist/module/lib/Symbols/Icons/Csv.js +1 -1
  20. package/dist/module/lib/Symbols/Icons/Csv.js.map +1 -1
  21. package/dist/module/lib/Symbols/Icons/TriangleDown.js +47 -0
  22. package/dist/module/lib/Symbols/Icons/TriangleDown.js.map +1 -0
  23. package/dist/module/lib/Symbols/Icons/TriangleUp.js +47 -0
  24. package/dist/module/lib/Symbols/Icons/TriangleUp.js.map +1 -0
  25. package/dist/module/lib/Symbols/index.js +2 -0
  26. package/dist/module/lib/Symbols/index.js.map +1 -1
  27. package/dist/typescript/src/lib/Components/MediaBanner/MediaBanner.d.ts +16 -0
  28. package/dist/typescript/src/lib/Components/MediaBanner/MediaBanner.d.ts.map +1 -0
  29. package/dist/typescript/src/lib/Components/MediaBanner/index.d.ts +3 -0
  30. package/dist/typescript/src/lib/Components/MediaBanner/index.d.ts.map +1 -0
  31. package/dist/typescript/src/lib/Components/MediaBanner/types.d.ts +42 -0
  32. package/dist/typescript/src/lib/Components/MediaBanner/types.d.ts.map +1 -0
  33. package/dist/typescript/src/lib/Components/Tag/Tag.d.ts.map +1 -1
  34. package/dist/typescript/src/lib/Components/index.d.ts +1 -0
  35. package/dist/typescript/src/lib/Components/index.d.ts.map +1 -1
  36. package/dist/typescript/src/lib/Symbols/Icons/TriangleDown.d.ts +35 -0
  37. package/dist/typescript/src/lib/Symbols/Icons/TriangleDown.d.ts.map +1 -0
  38. package/dist/typescript/src/lib/Symbols/Icons/TriangleUp.d.ts +35 -0
  39. package/dist/typescript/src/lib/Symbols/Icons/TriangleUp.d.ts.map +1 -0
  40. package/dist/typescript/src/lib/Symbols/index.d.ts +2 -0
  41. package/dist/typescript/src/lib/Symbols/index.d.ts.map +1 -1
  42. package/package.json +2 -2
  43. package/src/lib/Components/MediaBanner/MediaBanner.mdx +150 -0
  44. package/src/lib/Components/MediaBanner/MediaBanner.stories.tsx +143 -0
  45. package/src/lib/Components/MediaBanner/MediaBanner.test.tsx +77 -0
  46. package/src/lib/Components/MediaBanner/MediaBanner.tsx +172 -0
  47. package/src/lib/Components/MediaBanner/index.ts +2 -0
  48. package/src/lib/Components/MediaBanner/types.ts +44 -0
  49. package/src/lib/Components/Tag/Tag.mdx +6 -0
  50. package/src/lib/Components/Tag/Tag.stories.tsx +8 -0
  51. package/src/lib/Components/Tag/Tag.tsx +3 -1
  52. package/src/lib/Components/index.ts +1 -0
  53. package/src/lib/Symbols/Icons/Csv.tsx +1 -1
  54. package/src/lib/Symbols/Icons/TriangleDown.tsx +42 -0
  55. package/src/lib/Symbols/Icons/TriangleUp.tsx +42 -0
  56. package/src/lib/Symbols/index.ts +2 -0
@@ -0,0 +1,143 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
2
+ import { useState } from 'react';
3
+ import { Button } from '../Button';
4
+ import { Box } from '../Utility';
5
+ import {
6
+ MediaBanner,
7
+ MediaBannerDescription,
8
+ MediaBannerTitle,
9
+ } from './MediaBanner';
10
+
11
+ const IMAGE_URL =
12
+ 'https://images.unsplash.com/photo-1663741954108-d15d514529ef';
13
+
14
+ const meta: Meta<typeof MediaBanner> = {
15
+ component: MediaBanner,
16
+ title: 'Communication/MediaBanner',
17
+ subcomponents: {
18
+ MediaBannerTitle,
19
+ MediaBannerDescription,
20
+ },
21
+ parameters: {
22
+ docs: {
23
+ source: {
24
+ language: 'tsx',
25
+ format: true,
26
+ type: 'code',
27
+ },
28
+ },
29
+ },
30
+ argTypes: {
31
+ imageUrl: {
32
+ control: 'text',
33
+ description: 'URL of the background image',
34
+ },
35
+ onClose: {
36
+ control: 'select',
37
+ description: 'Close action callback',
38
+ options: ['With Close', 'None'],
39
+ mapping: {
40
+ 'With Close': () => {
41
+ console.log('Close clicked');
42
+ },
43
+ None: undefined,
44
+ },
45
+ },
46
+ },
47
+ };
48
+
49
+ export default meta;
50
+ type Story = StoryObj<typeof MediaBanner>;
51
+
52
+ export const Base: Story = {
53
+ args: {
54
+ imageUrl: IMAGE_URL,
55
+ },
56
+ render: (args) => (
57
+ <Box lx={{ width: 's400' }}>
58
+ <MediaBanner {...args}>
59
+ <MediaBannerTitle>Firmware Update</MediaBannerTitle>
60
+ <MediaBannerDescription>Keep your Nano updated!</MediaBannerDescription>
61
+ </MediaBanner>
62
+ </Box>
63
+ ),
64
+ parameters: {
65
+ docs: {
66
+ source: {
67
+ code: `
68
+ <MediaBanner imageUrl="https://images.unsplash.com/photo-1663741954108-d15d514529ef">
69
+ <MediaBannerTitle>Firmware Update</MediaBannerTitle>
70
+ <MediaBannerDescription>
71
+ Keep your Nano updated!
72
+ </MediaBannerDescription>
73
+ </MediaBanner>
74
+ `,
75
+ },
76
+ },
77
+ },
78
+ };
79
+
80
+ export const Truncation: Story = {
81
+ render: () => (
82
+ <Box lx={{ width: 's400' }}>
83
+ <MediaBanner imageUrl={IMAGE_URL} onClose={() => console.log('close')}>
84
+ <MediaBannerTitle>
85
+ Earn Up to 12% APY With Staking Now And Much More Rewards Awaiting You
86
+ </MediaBannerTitle>
87
+ <MediaBannerDescription>
88
+ Put your idle crypto to work. Start staking SOL, ETH, ATOM and more
89
+ directly from Ledger Live. Maximize your returns with our secure
90
+ staking solutions.
91
+ </MediaBannerDescription>
92
+ </MediaBanner>
93
+ </Box>
94
+ ),
95
+ };
96
+
97
+ export const WithBrokenImage: Story = {
98
+ render: () => (
99
+ <Box lx={{ width: 's400' }}>
100
+ <MediaBanner
101
+ imageUrl='https://broken-url.invalid/image.jpg'
102
+ onClose={() => console.log('close')}
103
+ >
104
+ <MediaBannerTitle>Sorry!</MediaBannerTitle>
105
+ <MediaBannerDescription>
106
+ The image failed to load so the banner decided to gracefully hide it.
107
+ </MediaBannerDescription>
108
+ </MediaBanner>
109
+ </Box>
110
+ ),
111
+ };
112
+
113
+ export const WithClose: Story = {
114
+ render: () => {
115
+ const [visible, setVisible] = useState(true);
116
+
117
+ if (!visible) {
118
+ return (
119
+ <Button
120
+ appearance='transparent'
121
+ size='sm'
122
+ onPress={() => setVisible(true)}
123
+ >
124
+ Show banner
125
+ </Button>
126
+ );
127
+ }
128
+
129
+ return (
130
+ <Box lx={{ width: 's400' }}>
131
+ <MediaBanner imageUrl={IMAGE_URL} onClose={() => setVisible(false)}>
132
+ <MediaBannerTitle>
133
+ Earn Up to 12% APY With Staking Now!
134
+ </MediaBannerTitle>
135
+ <MediaBannerDescription>
136
+ Put your idle crypto to work. Start staking SOL, ETH, ATOM and more
137
+ directly from Ledger Live
138
+ </MediaBannerDescription>
139
+ </MediaBanner>
140
+ </Box>
141
+ );
142
+ },
143
+ };
@@ -0,0 +1,77 @@
1
+ import { describe, it, expect, jest } from '@jest/globals';
2
+ import { ledgerLiveThemes } from '@ledgerhq/lumen-design-core';
3
+ import { fireEvent, render } from '@testing-library/react-native';
4
+ import { type ReactNode } from 'react';
5
+ import { ThemeProvider } from '../ThemeProvider/ThemeProvider';
6
+ import {
7
+ MediaBanner,
8
+ MediaBannerTitle,
9
+ MediaBannerDescription,
10
+ } from './MediaBanner';
11
+
12
+ const TestWrapper = ({ children }: { children: ReactNode }) => (
13
+ <ThemeProvider themes={ledgerLiveThemes} colorScheme='dark' locale='en'>
14
+ {children}
15
+ </ThemeProvider>
16
+ );
17
+
18
+ const IMAGE_URL = 'https://example.com/image.jpg';
19
+
20
+ describe('MediaBanner', () => {
21
+ it('should render title and description', () => {
22
+ const { getByText } = render(
23
+ <TestWrapper>
24
+ <MediaBanner imageUrl={IMAGE_URL}>
25
+ <MediaBannerTitle>Banner Title</MediaBannerTitle>
26
+ <MediaBannerDescription>Banner description</MediaBannerDescription>
27
+ </MediaBanner>
28
+ </TestWrapper>,
29
+ );
30
+
31
+ getByText('Banner Title');
32
+ getByText('Banner description');
33
+ });
34
+
35
+ it('should call onClose when close button is pressed', () => {
36
+ const handleClose = jest.fn();
37
+ const { getByTestId } = render(
38
+ <TestWrapper>
39
+ <MediaBanner imageUrl={IMAGE_URL} onClose={handleClose}>
40
+ <MediaBannerTitle>Title</MediaBannerTitle>
41
+ </MediaBanner>
42
+ </TestWrapper>,
43
+ );
44
+
45
+ const closeButton = getByTestId('media-banner-close-button');
46
+ expect(closeButton).toBeTruthy();
47
+ fireEvent.press(closeButton);
48
+ expect(handleClose).toHaveBeenCalledTimes(1);
49
+ });
50
+
51
+ it('should apply surface background color', () => {
52
+ const { getByTestId } = render(
53
+ <TestWrapper>
54
+ <MediaBanner testID='media-banner' imageUrl={IMAGE_URL}>
55
+ <MediaBannerTitle>Title</MediaBannerTitle>
56
+ </MediaBanner>
57
+ </TestWrapper>,
58
+ );
59
+
60
+ const banner = getByTestId('media-banner');
61
+ expect(banner.props.style.backgroundColor).toBe(
62
+ ledgerLiveThemes.dark.colors.bg.surface,
63
+ );
64
+ });
65
+
66
+ it('should render with imageUrl prop', () => {
67
+ const { getByTestId } = render(
68
+ <TestWrapper>
69
+ <MediaBanner testID='media-banner' imageUrl={IMAGE_URL}>
70
+ <MediaBannerTitle>Title</MediaBannerTitle>
71
+ </MediaBanner>
72
+ </TestWrapper>,
73
+ );
74
+
75
+ expect(getByTestId('media-banner')).toBeTruthy();
76
+ });
77
+ });
@@ -0,0 +1,172 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { Image, StyleSheet } from 'react-native';
3
+ import { useCommonTranslation } from '../../../i18n';
4
+ import { useStyleSheet, useTheme } from '../../../styles';
5
+ import { Close } from '../../Symbols';
6
+ import { InteractiveIcon } from '../InteractiveIcon';
7
+ import { Box, LinearGradient, Pressable, Text } from '../Utility';
8
+ import {
9
+ MediaBannerDescriptionProps,
10
+ MediaBannerProps,
11
+ MediaBannerTitleProps,
12
+ } from './types';
13
+
14
+ /**
15
+ * A promotional banner with a background image, title, description, and an optional close button.
16
+ *
17
+ * @see {@link https://ldls.vercel.app/?path=/docs/communication-mediabanner--docs Storybook}
18
+ */
19
+ export function MediaBanner({
20
+ lx,
21
+ style,
22
+ imageUrl,
23
+ onClose,
24
+ closeAccessibilityLabel,
25
+ children,
26
+ ...props
27
+ }: MediaBannerProps) {
28
+ const { t: translate } = useCommonTranslation();
29
+ const { theme: t } = useTheme();
30
+ const [imageLoadError, setImageLoadError] = useState(false);
31
+
32
+ useEffect(() => {
33
+ setImageLoadError(false);
34
+ }, [imageUrl]);
35
+
36
+ const showImage = imageUrl && !imageLoadError;
37
+
38
+ const styles = useStyleSheet(
39
+ (t) => ({
40
+ container: {
41
+ backgroundColor: t.colors.bg.surface,
42
+ borderRadius: t.borderRadius.md,
43
+ overflow: 'hidden',
44
+ flexDirection: 'row',
45
+ height: t.sizes.s72,
46
+ },
47
+ contentWrapper: {
48
+ flex: 1,
49
+ overflow: 'hidden',
50
+ justifyContent: 'center',
51
+ paddingHorizontal: t.spacings.s12,
52
+ paddingVertical: t.spacings.s2,
53
+ },
54
+ contentContainer: {
55
+ paddingVertical: t.spacings.s12,
56
+ gap: 4,
57
+ },
58
+ closeButton: {
59
+ position: 'absolute',
60
+ top: 8.5,
61
+ right: 8.5,
62
+ },
63
+ }),
64
+ [],
65
+ );
66
+
67
+ return (
68
+ <Pressable lx={lx} style={[styles.container, style]} {...props}>
69
+ <Box style={styles.contentWrapper}>
70
+ <Box style={styles.contentContainer}>{children}</Box>
71
+ </Box>
72
+ <Box style={{ width: 120 }}>
73
+ {showImage && (
74
+ <Image
75
+ source={{ uri: imageUrl }}
76
+ style={StyleSheet.absoluteFill}
77
+ resizeMode='cover'
78
+ onError={() => setImageLoadError(true)}
79
+ accessible={false}
80
+ />
81
+ )}
82
+ <LinearGradient
83
+ direction='to-topright'
84
+ stops={[
85
+ { color: t.colors.bg.black, opacity: 0, offset: 0.67 },
86
+ { color: t.colors.bg.black, opacity: 0.8 },
87
+ ]}
88
+ style={StyleSheet.absoluteFill}
89
+ accessible={false}
90
+ pointerEvents='none'
91
+ />
92
+ </Box>
93
+ {onClose && (
94
+ <Box style={styles.closeButton}>
95
+ <InteractiveIcon
96
+ testID='media-banner-close-button'
97
+ iconType='stroked'
98
+ appearance='white'
99
+ onPress={onClose}
100
+ accessibilityLabel={
101
+ closeAccessibilityLabel ||
102
+ translate('components.banner.closeAriaLabel')
103
+ }
104
+ >
105
+ <Close size={16} />
106
+ </InteractiveIcon>
107
+ </Box>
108
+ )}
109
+ </Pressable>
110
+ );
111
+ }
112
+
113
+ /**
114
+ * The title of the MediaBanner. Clamps at 1 line.
115
+ */
116
+ export function MediaBannerTitle({
117
+ lx,
118
+ style,
119
+ children,
120
+ ...props
121
+ }: MediaBannerTitleProps) {
122
+ const styles = useStyleSheet(
123
+ (t) => ({
124
+ title: StyleSheet.flatten([
125
+ t.typographies.body2SemiBold,
126
+ {
127
+ color: t.colors.text.base,
128
+ },
129
+ ]),
130
+ }),
131
+ [],
132
+ );
133
+
134
+ return (
135
+ <Text lx={lx} style={[styles.title, style]} numberOfLines={1} {...props}>
136
+ {children}
137
+ </Text>
138
+ );
139
+ }
140
+
141
+ /**
142
+ * The description of the MediaBanner. Clamps at 2 lines.
143
+ */
144
+ export function MediaBannerDescription({
145
+ lx,
146
+ style,
147
+ children,
148
+ ...props
149
+ }: MediaBannerDescriptionProps) {
150
+ const styles = useStyleSheet(
151
+ (t) => ({
152
+ description: StyleSheet.flatten([
153
+ t.typographies.body3,
154
+ {
155
+ color: t.colors.text.muted,
156
+ },
157
+ ]),
158
+ }),
159
+ [],
160
+ );
161
+
162
+ return (
163
+ <Text
164
+ lx={lx}
165
+ style={[styles.description, style]}
166
+ numberOfLines={2}
167
+ {...props}
168
+ >
169
+ {children}
170
+ </Text>
171
+ );
172
+ }
@@ -0,0 +1,2 @@
1
+ export * from './MediaBanner';
2
+ export * from './types';
@@ -0,0 +1,44 @@
1
+ import { ReactNode } from 'react';
2
+ import { StyledPressableProps, StyledTextProps } from '../../../styles';
3
+
4
+ /**
5
+ * Props for the MediaBanner root component.
6
+ */
7
+ export type MediaBannerProps = {
8
+ /**
9
+ * URL of the background image displayed on the right side.
10
+ */
11
+ imageUrl: string;
12
+ /**
13
+ * Optional close action callback.
14
+ */
15
+ onClose?: () => void;
16
+ /**
17
+ * Optional accessibility label for the close button.
18
+ */
19
+ closeAccessibilityLabel?: string;
20
+ /**
21
+ * The banner content (MediaBannerTitle, MediaBannerDescription).
22
+ */
23
+ children: ReactNode;
24
+ } & Omit<StyledPressableProps, 'children'>;
25
+
26
+ /**
27
+ * Props for the MediaBannerTitle component.
28
+ */
29
+ export type MediaBannerTitleProps = {
30
+ /**
31
+ * The title text content.
32
+ */
33
+ children: ReactNode;
34
+ } & Omit<StyledTextProps, 'children'>;
35
+
36
+ /**
37
+ * Props for the MediaBannerDescription component.
38
+ */
39
+ export type MediaBannerDescriptionProps = {
40
+ /**
41
+ * The description text content.
42
+ */
43
+ children: ReactNode;
44
+ } & Omit<StyledTextProps, 'children'>;
@@ -47,6 +47,12 @@ Tags can be displayed with or without an icon.
47
47
 
48
48
  <Canvas of={TagStories.ContentTypeShowcase} />
49
49
 
50
+ ### Truncation
51
+
52
+ When a tag's label exceeds the available space, the text is automatically truncated with an ellipsis.
53
+
54
+ <Canvas of={TagStories.TruncateShowcase} />
55
+
50
56
  ### Accessibility
51
57
 
52
58
  To be implemented:
@@ -82,3 +82,11 @@ export const ContentTypeShowcase: Story = {
82
82
  </Box>
83
83
  ),
84
84
  };
85
+
86
+ export const TruncateShowcase: Story = {
87
+ render: () => (
88
+ <Box lx={{ width: 's176' }}>
89
+ <Tag label='Very long custom Tag text that should truncate' />
90
+ </Box>
91
+ ),
92
+ };
@@ -155,7 +155,9 @@ export const Tag = ({
155
155
  {...props}
156
156
  >
157
157
  {IconComponent && <IconComponent size={iconSize} style={styles.icon} />}
158
- <Text style={styles.text}>{label}</Text>
158
+ <Text style={styles.text} numberOfLines={1}>
159
+ {label}
160
+ </Text>
159
161
  </Box>
160
162
  );
161
163
  };
@@ -16,6 +16,7 @@ export * from './IconButton';
16
16
  export * from './InteractiveIcon';
17
17
  export * from './Link';
18
18
  export * from './ListItem';
19
+ export * from './MediaBanner';
19
20
  export * from './MediaCard';
20
21
  export * from './NavBar';
21
22
  export * from './PageIndicator';
@@ -43,7 +43,7 @@ export const Csv = createIcon(
43
43
  />
44
44
  <Path
45
45
  fill='currentColor'
46
- d='M1.86 13.656a.467.467 0 0 1 .641.156.13.13 0 0 0 .043.044q.015.01.04.01h.426a.08.08 0 0 0 .079-.078.08.08 0 0 0-.062-.078l-.728-.183a1.012 1.012 0 0 1 .247-1.994h.426c.39 0 .704.217.878.502a.467.467 0 0 1-.797.486.13.13 0 0 0-.042-.044.1.1 0 0 0-.039-.01h-.426a.079.079 0 0 0-.02.155l.73.183A1.012 1.012 0 0 1 3.01 14.8h-.426c-.391 0-.705-.217-.879-.503a.467.467 0 0 1 .156-.64m2.34.01v-1c0-.625.507-1.133 1.133-1.133H6a.467.467 0 0 1 0 .934h-.667a.2.2 0 0 0-.2.2v1c0 .11.09.2.2.2H6a.467.467 0 0 1 0 .933h-.667A1.134 1.134 0 0 1 4.2 13.667m5.01-2.115c.248.07.392.327.323.575l-.656 2.334a.47.47 0 0 1-.45.34H7.99a.47.47 0 0 1-.45-.34l-.656-2.334a.467.467 0 0 1 .899-.252l.425 1.514.426-1.514a.467.467 0 0 1 .576-.323'
46
+ d='M4.483 13.656a.467.467 0 0 1 .641.156q.022.034.043.044.015.01.04.01h.426a.08.08 0 0 0 .079-.078.08.08 0 0 0-.062-.078l-.728-.183a1.013 1.013 0 0 1 .247-1.994h.426c.39 0 .704.217.878.502a.467.467 0 0 1-.797.486.13.13 0 0 0-.042-.044.1.1 0 0 0-.039-.01H5.17a.079.079 0 0 0-.02.155l.73.183a1.012 1.012 0 0 1-.246 1.995h-.427c-.39 0-.705-.217-.878-.503a.467.467 0 0 1 .155-.64m4.727-2.105c.248.07.392.327.323.575l-.656 2.334a.47.47 0 0 1-.45.34H7.99a.47.47 0 0 1-.45-.34l-.656-2.334a.467.467 0 0 1 .899-.252l.425 1.514.426-1.514a.467.467 0 0 1 .576-.323M1.538 12.667v1c0 .626.508 1.133 1.134 1.133h.666a.467.467 0 0 0 0-.934h-.666a.2.2 0 0 1-.2-.2v-1c0-.11.09-.2.2-.2h.666a.467.467 0 0 0 0-.933h-.666c-.626 0-1.134.508-1.134 1.134'
47
47
  />
48
48
  </Svg>,
49
49
  );
@@ -0,0 +1,42 @@
1
+ import Svg, { Path } from 'react-native-svg';
2
+ import createIcon from '../../Components/Icon/createIcon';
3
+
4
+ /**
5
+ * TriangleDown icon component for React Native.
6
+ *
7
+ * This icon component is automatically generated from SVG files and uses the createIcon utility
8
+ * to create a consistent icon interface. It supports all standard SVG props (from react-native-svg)
9
+ * and additional size variants defined in the Icon component.
10
+ *
11
+ * @component
12
+ * @param {16 | 20 | 24 | 40 | 48 | 56} [size=24] - The size of the icon in pixels.
13
+ * @param {string} [color] - The color of the icon.
14
+ * @param {SVGProps} [...props] - All standard SVG element props (from react-native-svg).
15
+ *
16
+ * @example
17
+ * // Basic usage with default size (24px)
18
+ * import { TriangleDown } from '@ledgerhq/lumen-ui-rnative/symbols';
19
+ *
20
+ * <TriangleDown />
21
+ *
22
+ * @example
23
+ * // With custom size and style
24
+ * <TriangleDown size={40} color="warning" lx={{ marginTop: 's4' }} />
25
+ *
26
+ * @example
27
+ * // Used within a Button component
28
+ * import { Button } from '@ledgerhq/lumen-ui-rnative';
29
+ *
30
+ * <Button icon={TriangleDown} size="md">
31
+ * Click me
32
+ * </Button>
33
+ */
34
+ export const TriangleDown = createIcon(
35
+ 'TriangleDown',
36
+ <Svg width={24} height={24} fill='currentColor' viewBox='0 0 16 16'>
37
+ <Path
38
+ fill='currentColor'
39
+ d='M13.038 5.347 8.82 12.06a1 1 0 0 1-1.696-.004L2.95 5.343a1 1 0 0 1 .85-1.528h8.39a1 1 0 0 1 .848 1.532'
40
+ />
41
+ </Svg>,
42
+ );
@@ -0,0 +1,42 @@
1
+ import Svg, { Path } from 'react-native-svg';
2
+ import createIcon from '../../Components/Icon/createIcon';
3
+
4
+ /**
5
+ * TriangleUp icon component for React Native.
6
+ *
7
+ * This icon component is automatically generated from SVG files and uses the createIcon utility
8
+ * to create a consistent icon interface. It supports all standard SVG props (from react-native-svg)
9
+ * and additional size variants defined in the Icon component.
10
+ *
11
+ * @component
12
+ * @param {16 | 20 | 24 | 40 | 48 | 56} [size=24] - The size of the icon in pixels.
13
+ * @param {string} [color] - The color of the icon.
14
+ * @param {SVGProps} [...props] - All standard SVG element props (from react-native-svg).
15
+ *
16
+ * @example
17
+ * // Basic usage with default size (24px)
18
+ * import { TriangleUp } from '@ledgerhq/lumen-ui-rnative/symbols';
19
+ *
20
+ * <TriangleUp />
21
+ *
22
+ * @example
23
+ * // With custom size and style
24
+ * <TriangleUp size={40} color="warning" lx={{ marginTop: 's4' }} />
25
+ *
26
+ * @example
27
+ * // Used within a Button component
28
+ * import { Button } from '@ledgerhq/lumen-ui-rnative';
29
+ *
30
+ * <Button icon={TriangleUp} size="md">
31
+ * Click me
32
+ * </Button>
33
+ */
34
+ export const TriangleUp = createIcon(
35
+ 'TriangleUp',
36
+ <Svg width={24} height={24} fill='currentColor' viewBox='0 0 16 16'>
37
+ <Path
38
+ fill='currentColor'
39
+ d='M13.038 11.512 8.82 4.798a1 1 0 0 0-1.696.004L2.95 11.516a1 1 0 0 0 .85 1.528h8.39a1 1 0 0 0 .848-1.532'
40
+ />
41
+ </Svg>,
42
+ );
@@ -238,6 +238,8 @@ export { Tools } from './Icons/Tools';
238
238
  export { TransferHorizontal } from './Icons/TransferHorizontal';
239
239
  export { TransferVertical } from './Icons/TransferVertical';
240
240
  export { Trash } from './Icons/Trash';
241
+ export { TriangleDown } from './Icons/TriangleDown';
242
+ export { TriangleUp } from './Icons/TriangleUp';
241
243
  export { Truck } from './Icons/Truck';
242
244
  export { Twitter } from './Icons/Twitter';
243
245
  export { Unlink } from './Icons/Unlink';