@ledgerhq/lumen-ui-rnative 0.0.51 → 0.0.53
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/package.json +2 -2
- package/dist/src/i18n/locales/de.json +21 -1
- package/dist/src/i18n/locales/en.json +3 -0
- package/dist/src/i18n/locales/es.json +21 -1
- package/dist/src/i18n/locales/fr.json +4 -1
- package/dist/src/i18n/locales/ja.json +21 -1
- package/dist/src/i18n/locales/ko.json +21 -1
- package/dist/src/i18n/locales/pt.json +21 -1
- package/dist/src/i18n/locales/ru.json +21 -1
- package/dist/src/i18n/locales/th.json +21 -1
- package/dist/src/i18n/locales/tr.json +21 -1
- package/dist/src/i18n/locales/zh.json +21 -1
- package/dist/src/lib/Components/BaseInput/BaseInput.d.ts +1 -0
- package/dist/src/lib/Components/BaseInput/BaseInput.d.ts.map +1 -1
- package/dist/src/lib/Components/BaseInput/BaseInput.js +6 -2
- package/dist/src/lib/Components/BaseInput/types.d.ts +5 -1
- package/dist/src/lib/Components/BaseInput/types.d.ts.map +1 -1
- package/dist/src/lib/Components/SearchInput/SearchInput.d.ts +3 -1
- package/dist/src/lib/Components/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/src/lib/Components/SearchInput/SearchInput.js +12 -2
- package/dist/src/lib/Components/SearchInput/SearchInput.stories.d.ts.map +1 -1
- package/dist/src/lib/Components/SearchInput/SearchInput.stories.js +3 -0
- package/dist/src/lib/Components/SearchInput/types.d.ts +7 -1
- package/dist/src/lib/Components/SearchInput/types.d.ts.map +1 -1
- package/dist/src/lib/Components/Tile/Tile.d.ts.map +1 -1
- package/dist/src/lib/Components/Tile/Tile.js +1 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.d.ts +32 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.js +75 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts +11 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.js +107 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/index.d.ts +3 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/index.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/index.js +2 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/types.d.ts +32 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/types.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/LinearGradient/types.js +1 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.d.ts +31 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.js +52 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts +10 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.js +101 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/index.d.ts +3 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/index.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/index.js +2 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/types.d.ts +32 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/types.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/RadialGradient/types.js +1 -0
- package/dist/src/lib/Components/Utility/Gradient/gradient.types.d.ts +21 -0
- package/dist/src/lib/Components/Utility/Gradient/gradient.types.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/gradient.types.js +1 -0
- package/dist/src/lib/Components/Utility/Gradient/utils/resolveGradientColor.d.ts +21 -0
- package/dist/src/lib/Components/Utility/Gradient/utils/resolveGradientColor.d.ts.map +1 -0
- package/dist/src/lib/Components/Utility/Gradient/utils/resolveGradientColor.js +38 -0
- package/dist/src/lib/Components/Utility/index.d.ts +2 -0
- package/dist/src/lib/Components/Utility/index.d.ts.map +1 -1
- package/dist/src/lib/Components/Utility/index.js +2 -0
- package/package.json +2 -2
- package/src/i18n/locales/de.json +22 -2
- package/src/i18n/locales/en.json +4 -1
- package/src/i18n/locales/es.json +22 -2
- package/src/i18n/locales/fr.json +5 -2
- package/src/i18n/locales/ja.json +22 -2
- package/src/i18n/locales/ko.json +22 -2
- package/src/i18n/locales/pt.json +22 -2
- package/src/i18n/locales/ru.json +22 -2
- package/src/i18n/locales/th.json +22 -2
- package/src/i18n/locales/tr.json +22 -2
- package/src/i18n/locales/zh.json +22 -2
- package/src/lib/Components/BaseInput/BaseInput.tsx +7 -2
- package/src/lib/Components/BaseInput/types.ts +5 -1
- package/src/lib/Components/SearchInput/SearchInput.stories.tsx +3 -0
- package/src/lib/Components/SearchInput/SearchInput.tsx +32 -8
- package/src/lib/Components/SearchInput/types.ts +7 -1
- package/src/lib/Components/Tile/Tile.tsx +1 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.mdx +142 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.stories.tsx +173 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.test.tsx +69 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/LinearGradient.tsx +127 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/index.ts +2 -0
- package/src/lib/Components/Utility/Gradient/LinearGradient/types.ts +42 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.mdx +109 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.stories.tsx +148 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.test.tsx +69 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/RadialGradient.tsx +102 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/index.ts +2 -0
- package/src/lib/Components/Utility/Gradient/RadialGradient/types.ts +32 -0
- package/src/lib/Components/Utility/Gradient/gradient.types.ts +22 -0
- package/src/lib/Components/Utility/Gradient/utils/resolveGradientColor.test.ts +144 -0
- package/src/lib/Components/Utility/Gradient/utils/resolveGradientColor.ts +59 -0
- package/src/lib/Components/Utility/index.ts +2 -0
package/src/i18n/locales/ja.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "QRコードをスキャン"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "インプットを削除"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "読み込み中"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "戻る",
|
|
14
|
+
"closeAriaLabel": "閉じる"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "閉じる"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(新しいタブで開く)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/ko.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "QR 코드 스캔"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "입력 값 지우기"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "로딩중"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "돌아가기",
|
|
14
|
+
"closeAriaLabel": "닫기"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "닫기"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(새 탭에서 열기)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/pt.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "Escanear QR Code"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "Limpar input"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "Carregando"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "Voltar",
|
|
14
|
+
"closeAriaLabel": "Fechar"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "Fechar"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(abre em uma nova aba)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/ru.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "Сканировать QR-код"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "Очистить поле"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "Загрузка"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "Назад",
|
|
14
|
+
"closeAriaLabel": "Закрыть"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "Закрыть"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(открывается в новой вкладке)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/th.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "สแกน QR Code"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "ล้างอินพุต"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "กำลังโหลด"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "ย้อนกลับ",
|
|
14
|
+
"closeAriaLabel": "ปิด"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "ปิด"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(เปิดในแท็บใหม่)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/tr.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "Karekodu okut"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "Girdiyi temizle"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "Yükleniyor"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "Geri dön",
|
|
14
|
+
"closeAriaLabel": "Kapat"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "Kapat"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(yeni sekmede açılır)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/i18n/locales/zh.json
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
1
|
{
|
|
2
|
-
"components": {
|
|
3
|
-
|
|
2
|
+
"components": {
|
|
3
|
+
"addressInput": {
|
|
4
|
+
"qrCodeAriaLabel": "扫描二维码"
|
|
5
|
+
},
|
|
6
|
+
"baseInput": {
|
|
7
|
+
"clearInputAriaLabel": "清空输入框"
|
|
8
|
+
},
|
|
9
|
+
"spinner": {
|
|
10
|
+
"loadingAriaLabel": "加载中"
|
|
11
|
+
},
|
|
12
|
+
"bottomSheetHeader": {
|
|
13
|
+
"goBackAriaLabel": "返回",
|
|
14
|
+
"closeAriaLabel": "关闭"
|
|
15
|
+
},
|
|
16
|
+
"banner": {
|
|
17
|
+
"closeAriaLabel": "关闭"
|
|
18
|
+
},
|
|
19
|
+
"link": {
|
|
20
|
+
"opensInNewTabAriaLabel": "(在新选项卡中打开)"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -18,6 +18,7 @@ export const BaseInput = React.forwardRef<TextInput, BaseInputProps>(
|
|
|
18
18
|
{
|
|
19
19
|
lx,
|
|
20
20
|
style,
|
|
21
|
+
containerStyle,
|
|
21
22
|
inputStyle,
|
|
22
23
|
labelStyle,
|
|
23
24
|
label,
|
|
@@ -100,7 +101,7 @@ export const BaseInput = React.forwardRef<TextInput, BaseInputProps>(
|
|
|
100
101
|
return (
|
|
101
102
|
<Box lx={lx} style={style}>
|
|
102
103
|
<Pressable
|
|
103
|
-
style={styles.container}
|
|
104
|
+
style={StyleSheet.flatten([styles.container, containerStyle])}
|
|
104
105
|
onPress={() => inputRef.current?.focus()}
|
|
105
106
|
disabled={!editable}
|
|
106
107
|
>
|
|
@@ -109,7 +110,11 @@ export const BaseInput = React.forwardRef<TextInput, BaseInputProps>(
|
|
|
109
110
|
<TextInput
|
|
110
111
|
ref={inputRef}
|
|
111
112
|
value={value}
|
|
112
|
-
style={[
|
|
113
|
+
style={StyleSheet.flatten([
|
|
114
|
+
styles.input,
|
|
115
|
+
{ lineHeight: 0 },
|
|
116
|
+
inputStyle,
|
|
117
|
+
])}
|
|
113
118
|
onFocus={() => setIsFocused(true)}
|
|
114
119
|
onBlur={() => setIsFocused(false)}
|
|
115
120
|
onChangeText={handleChangeText}
|
|
@@ -12,9 +12,13 @@ export type BaseInputProps = {
|
|
|
12
12
|
*/
|
|
13
13
|
label?: string;
|
|
14
14
|
/**
|
|
15
|
-
* Additional styles to apply to the
|
|
15
|
+
* Additional styles to apply to the outer wrapper element.
|
|
16
16
|
*/
|
|
17
17
|
style?: StyleProp<ViewStyle>;
|
|
18
|
+
/**
|
|
19
|
+
* Additional styles to apply to the inner container element (Pressable).
|
|
20
|
+
*/
|
|
21
|
+
containerStyle?: StyleProp<ViewStyle>;
|
|
18
22
|
/**
|
|
19
23
|
* Additional styles to apply to the input element.
|
|
20
24
|
*/
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { TextInput } from 'react-native';
|
|
3
|
+
import { useStyleSheet } from '../../../styles';
|
|
3
4
|
import { Search as SearchIcon } from '../../Symbols';
|
|
4
5
|
import { BaseInput } from '../BaseInput';
|
|
5
6
|
import { type SearchInputProps } from './types';
|
|
@@ -7,14 +8,37 @@ import { type SearchInputProps } from './types';
|
|
|
7
8
|
export const SearchInput = React.forwardRef<
|
|
8
9
|
React.ElementRef<typeof TextInput>,
|
|
9
10
|
SearchInputProps
|
|
10
|
-
>(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
>(
|
|
12
|
+
(
|
|
13
|
+
{ appearance = 'plain', style, containerStyle, inputStyle, ...props },
|
|
14
|
+
ref,
|
|
15
|
+
) => {
|
|
16
|
+
const styles = useAppearanceStyles(appearance);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<BaseInput
|
|
20
|
+
ref={ref}
|
|
21
|
+
prefix={<SearchIcon size={20} color='muted' accessible={false} />}
|
|
22
|
+
style={style}
|
|
23
|
+
containerStyle={[containerStyle, styles.container]}
|
|
24
|
+
inputStyle={[inputStyle, styles.input]}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const useAppearanceStyles = (appearance: 'plain' | 'transparent') => {
|
|
32
|
+
return useStyleSheet(
|
|
33
|
+
(t) => ({
|
|
34
|
+
container:
|
|
35
|
+
appearance === 'transparent'
|
|
36
|
+
? { backgroundColor: t.colors.bg.mutedTransparent }
|
|
37
|
+
: {},
|
|
38
|
+
input: { backgroundColor: 'transparent' },
|
|
39
|
+
}),
|
|
40
|
+
[appearance],
|
|
17
41
|
);
|
|
18
|
-
}
|
|
42
|
+
};
|
|
19
43
|
|
|
20
44
|
SearchInput.displayName = 'SearchInput';
|
|
@@ -2,4 +2,10 @@ import { BaseInputProps } from '../BaseInput';
|
|
|
2
2
|
import { BoxProps } from '../Utility';
|
|
3
3
|
|
|
4
4
|
export type SearchInputProps = Omit<BaseInputProps, 'prefix' | 'label'> &
|
|
5
|
-
BoxProps
|
|
5
|
+
BoxProps & {
|
|
6
|
+
/**
|
|
7
|
+
* The visual appearance of the search input
|
|
8
|
+
* @default 'plain'
|
|
9
|
+
*/
|
|
10
|
+
appearance?: 'plain' | 'transparent';
|
|
11
|
+
};
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { Meta, Canvas, Controls } from '@storybook/addon-docs/blocks';
|
|
2
|
+
import * as LinearGradientStories from './LinearGradient.stories';
|
|
3
|
+
import { CustomTabs, Tab } from '../../../../../../.storybook/components';
|
|
4
|
+
|
|
5
|
+
<Meta title='Utility/LinearGradient' of={LinearGradientStories} />
|
|
6
|
+
|
|
7
|
+
# LinearGradient
|
|
8
|
+
|
|
9
|
+
<CustomTabs>
|
|
10
|
+
<Tab label="Overview ">
|
|
11
|
+
|
|
12
|
+
## Introduction
|
|
13
|
+
|
|
14
|
+
LinearGradient renders a linear gradient background using `react-native-svg`.
|
|
15
|
+
It extends Box, supporting all `lx` style props for layout and sizing.
|
|
16
|
+
|
|
17
|
+
## Anatomy
|
|
18
|
+
|
|
19
|
+
<Canvas of={LinearGradientStories.Base} />
|
|
20
|
+
<Controls of={LinearGradientStories.Base} />
|
|
21
|
+
|
|
22
|
+
## Properties
|
|
23
|
+
|
|
24
|
+
### Direction
|
|
25
|
+
|
|
26
|
+
Supports preset directions or custom angles in degrees:
|
|
27
|
+
|
|
28
|
+
<Canvas of={LinearGradientStories.DirectionShowcase} />
|
|
29
|
+
|
|
30
|
+
### With Children
|
|
31
|
+
|
|
32
|
+
Content renders on top of the gradient:
|
|
33
|
+
|
|
34
|
+
<Canvas of={LinearGradientStories.WithChildren} />
|
|
35
|
+
|
|
36
|
+
### Multiple Stops
|
|
37
|
+
|
|
38
|
+
The `offset` prop controls where each color appears along the gradient (0 = start, 1 = end).
|
|
39
|
+
When omitted, stops are distributed evenly.
|
|
40
|
+
For example, 3 stops without offsets will be placed at 0, 0.5, and 1.
|
|
41
|
+
|
|
42
|
+
<Canvas of={LinearGradientStories.WithMultipleStops} />
|
|
43
|
+
|
|
44
|
+
### Crypto Gradients
|
|
45
|
+
|
|
46
|
+
The `theme` object expose a `colors.gradients.crypto` object that contains gradient definitions for each crypto token.
|
|
47
|
+
|
|
48
|
+
<Canvas of={LinearGradientStories.CryptoGradients} />
|
|
49
|
+
|
|
50
|
+
</Tab>
|
|
51
|
+
|
|
52
|
+
<Tab label="Implementation ">
|
|
53
|
+
|
|
54
|
+
## Setup
|
|
55
|
+
|
|
56
|
+
Install and set up the library with our [Setup Guide →](?path=/docs/getting-started-setup--docs).
|
|
57
|
+
|
|
58
|
+
## Basic Usage
|
|
59
|
+
|
|
60
|
+
The `direction` prop accepts preset strings like `to-bottom`, `to-right`, or diagonal variants.
|
|
61
|
+
Use design tokens for colors to ensure theme consistency.
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
import { LinearGradient } from '@ledgerhq/lumen-ui-rnative';
|
|
65
|
+
|
|
66
|
+
<LinearGradient
|
|
67
|
+
direction="to-bottom"
|
|
68
|
+
stops={[{ color: 'accent' }, { color: 'active', opacity: 0 }]}
|
|
69
|
+
lx={{ height: 's192', width: 's192', borderRadius: 'lg' }}
|
|
70
|
+
/>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Custom Angle
|
|
74
|
+
|
|
75
|
+
Pass a number to `direction` for precise angle control.
|
|
76
|
+
Angles follow convention:
|
|
77
|
+
- 0° points up
|
|
78
|
+
- 90° points right
|
|
79
|
+
- 180° points down
|
|
80
|
+
- 270° points left
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
<LinearGradient
|
|
84
|
+
direction={45}
|
|
85
|
+
stops={[{ color: 'accent' }, { color: 'active' }]}
|
|
86
|
+
lx={{ height: 's80', width: 's80' }}
|
|
87
|
+
/>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### With Children
|
|
91
|
+
|
|
92
|
+
The gradient acts as a background. Children are rendered on top and define the component's height when no explicit size is set.
|
|
93
|
+
|
|
94
|
+
```tsx
|
|
95
|
+
<LinearGradient
|
|
96
|
+
direction="to-bottomright"
|
|
97
|
+
stops={[{ color: 'accent' }, { color: 'active', opacity: 0 }]}
|
|
98
|
+
lx={{ padding: 's24', borderRadius: 'lg' }}
|
|
99
|
+
>
|
|
100
|
+
<Text lx={{ color: 'base' }}>Content on gradient</Text>
|
|
101
|
+
</LinearGradient>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Stops API
|
|
105
|
+
|
|
106
|
+
Each stop defines a color at a position.
|
|
107
|
+
Use `opacity: 0` for fade-out effects.
|
|
108
|
+
Colors support both design tokens (`'accent'`) and raw values (`'#FF6B6B'`).
|
|
109
|
+
|
|
110
|
+
**Default behavior when `offset` is omitted:** stops are evenly distributed.
|
|
111
|
+
- With 2 stops → `[0, 1]`.
|
|
112
|
+
- With 3 stops → `[0, 0.5, 1]`.
|
|
113
|
+
- With 4 stops → `[0, 0.33, 0.66, 1]`.
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
type GradientStop = {
|
|
117
|
+
color: BackgroundColorToken | string; // Token or raw color
|
|
118
|
+
offset?: number; // 0-1, auto-spread if omitted
|
|
119
|
+
opacity?: number; // 0-1, defaults to 1
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### Crypto Gradients
|
|
124
|
+
|
|
125
|
+
The `theme` object expose a `colors.gradients.crypto` object that contains gradient definitions for each crypto token.
|
|
126
|
+
|
|
127
|
+
```tsx
|
|
128
|
+
import { useTheme } from '@ledgerhq/lumen-ui-rnative';
|
|
129
|
+
|
|
130
|
+
const { theme } = useTheme();
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<LinearGradient
|
|
134
|
+
stops={theme.colors.gradients.crypto.bitcoin}
|
|
135
|
+
lx={{ padding: 's24', borderRadius: 'lg' }}
|
|
136
|
+
direction="to-bottomright"
|
|
137
|
+
/>
|
|
138
|
+
);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
</Tab>
|
|
142
|
+
</CustomTabs>
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-native-web-vite';
|
|
2
|
+
import { useTheme } from 'src/styles';
|
|
3
|
+
import { Box } from '../../Box';
|
|
4
|
+
import { Text } from '../../Text';
|
|
5
|
+
import { LinearGradient } from './LinearGradient';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof LinearGradient> = {
|
|
8
|
+
component: LinearGradient,
|
|
9
|
+
title: 'Utility/LinearGradient',
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'centered',
|
|
12
|
+
backgrounds: { default: 'light' },
|
|
13
|
+
docs: {
|
|
14
|
+
source: {
|
|
15
|
+
language: 'tsx',
|
|
16
|
+
format: true,
|
|
17
|
+
type: 'code',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default meta;
|
|
24
|
+
type Story = StoryObj<typeof LinearGradient>;
|
|
25
|
+
|
|
26
|
+
export const Base: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
direction: 'to-bottom',
|
|
29
|
+
stops: [{ color: 'accent' }, { color: 'active', opacity: 0 }],
|
|
30
|
+
lx: {
|
|
31
|
+
width: 's192',
|
|
32
|
+
height: 's56',
|
|
33
|
+
borderRadius: 'lg',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const DirectionShowcase: Story = {
|
|
39
|
+
render: () => {
|
|
40
|
+
const orientations = [
|
|
41
|
+
'to-bottom',
|
|
42
|
+
'to-right',
|
|
43
|
+
'to-top',
|
|
44
|
+
'to-left',
|
|
45
|
+
'to-bottomright',
|
|
46
|
+
'to-bottomleft',
|
|
47
|
+
'to-topright',
|
|
48
|
+
'to-topleft',
|
|
49
|
+
0,
|
|
50
|
+
90,
|
|
51
|
+
180,
|
|
52
|
+
270,
|
|
53
|
+
] as const;
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<Box lx={{ flexDirection: 'row', flexWrap: 'wrap', gap: 's20' }}>
|
|
57
|
+
{orientations.map((orientation) => {
|
|
58
|
+
return (
|
|
59
|
+
<Box key={orientation} lx={{ gap: 's4' }}>
|
|
60
|
+
<LinearGradient
|
|
61
|
+
direction={orientation}
|
|
62
|
+
stops={[{ color: 'accent' }, { color: 'active', opacity: 0 }]}
|
|
63
|
+
lx={{ height: 's40', width: 's176', borderRadius: 'md' }}
|
|
64
|
+
/>
|
|
65
|
+
<Text typography='body4' lx={{ color: 'base' }}>
|
|
66
|
+
{orientation}
|
|
67
|
+
</Text>
|
|
68
|
+
</Box>
|
|
69
|
+
);
|
|
70
|
+
})}
|
|
71
|
+
</Box>
|
|
72
|
+
);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const WithChildren: Story = {
|
|
77
|
+
args: {
|
|
78
|
+
direction: 'to-bottomright',
|
|
79
|
+
stops: [{ color: 'accent' }, { color: 'active', opacity: 0, offset: 0.75 }],
|
|
80
|
+
lx: {
|
|
81
|
+
padding: 's24',
|
|
82
|
+
borderRadius: 'lg',
|
|
83
|
+
width: 's288',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
render: (args) => (
|
|
87
|
+
<LinearGradient {...args}>
|
|
88
|
+
<Text typography='heading2SemiBold' lx={{ color: 'base' }}>
|
|
89
|
+
With Children
|
|
90
|
+
</Text>
|
|
91
|
+
<Text typography='body2' lx={{ color: 'base', marginTop: 's8' }}>
|
|
92
|
+
Adapt height based on content.
|
|
93
|
+
</Text>
|
|
94
|
+
<Text typography='body3' lx={{ color: 'base', marginTop: 's8' }}>
|
|
95
|
+
Lorem ipsum dolor sit amet consectetur adipisicing elit consectetur
|
|
96
|
+
adipisicing elit adipisicing elit. Mas adename labin anet.
|
|
97
|
+
</Text>
|
|
98
|
+
</LinearGradient>
|
|
99
|
+
),
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const WithMultipleStops: Story = {
|
|
103
|
+
args: {
|
|
104
|
+
direction: 'to-right',
|
|
105
|
+
stops: [
|
|
106
|
+
{ color: 'accent', offset: 0, opacity: 1 },
|
|
107
|
+
{ color: 'warning', offset: 0.5, opacity: 1 },
|
|
108
|
+
{ color: 'errorStrong', offset: 1, opacity: 1 },
|
|
109
|
+
],
|
|
110
|
+
lx: {
|
|
111
|
+
borderRadius: 'md',
|
|
112
|
+
height: 's56',
|
|
113
|
+
width: 's288',
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
render: (args) => {
|
|
117
|
+
const { theme } = useTheme();
|
|
118
|
+
console.log({ theme });
|
|
119
|
+
return (
|
|
120
|
+
<Box lx={{ gap: 's12' }}>
|
|
121
|
+
<LinearGradient {...args} />
|
|
122
|
+
<Box lx={{ flexDirection: 'row', justifyContent: 'space-between' }}>
|
|
123
|
+
<Text>accent</Text>
|
|
124
|
+
<Text>warning</Text>
|
|
125
|
+
<Text>errorStrong</Text>
|
|
126
|
+
</Box>
|
|
127
|
+
</Box>
|
|
128
|
+
);
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
export const CryptoGradients: Story = {
|
|
133
|
+
args: {
|
|
134
|
+
direction: 'to-bottomright',
|
|
135
|
+
lx: {
|
|
136
|
+
borderRadius: 'md',
|
|
137
|
+
height: 's56',
|
|
138
|
+
width: 's288',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
render: (args) => {
|
|
142
|
+
const { theme } = useTheme();
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<Box
|
|
146
|
+
lx={{
|
|
147
|
+
gap: 's20',
|
|
148
|
+
flexDirection: 'row',
|
|
149
|
+
flexWrap: 'wrap',
|
|
150
|
+
}}
|
|
151
|
+
>
|
|
152
|
+
{Object.entries(theme.colors.gradients.crypto).map(
|
|
153
|
+
([key, gradient]) => (
|
|
154
|
+
<Box key={key} lx={{ gap: 's4' }}>
|
|
155
|
+
<LinearGradient
|
|
156
|
+
{...args}
|
|
157
|
+
lx={{
|
|
158
|
+
height: 's40',
|
|
159
|
+
width: 's176',
|
|
160
|
+
borderRadius: 'md',
|
|
161
|
+
}}
|
|
162
|
+
stops={gradient}
|
|
163
|
+
></LinearGradient>
|
|
164
|
+
<Text typography='body4' lx={{ color: 'base' }}>
|
|
165
|
+
{key}
|
|
166
|
+
</Text>
|
|
167
|
+
</Box>
|
|
168
|
+
),
|
|
169
|
+
)}
|
|
170
|
+
</Box>
|
|
171
|
+
);
|
|
172
|
+
},
|
|
173
|
+
};
|