mirror of
https://github.com/trezor/trezor-suite.git
synced 2026-02-19 16:22:25 +01:00
feat(suite-native): storybook atoms
This commit is contained in:
@@ -26,4 +26,12 @@ export default [
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
// TARGET: Storybook files anywhere in the project
|
||||
files: ['**/*.stories.@(ts|tsx|js|jsx)'],
|
||||
rules: {
|
||||
'import/no-default-export': 'off', // Storybook stories need default exports by design.
|
||||
'react-hooks/rules-of-hooks': 'off', // It is possible to use hooks in Storybook stories outside of the component (e.g in the render method).
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -363,3 +363,5 @@ export const colorVariants: Record<ThemeColorVariant, Colors> = {
|
||||
...colorsV2.dark,
|
||||
} as Colors,
|
||||
} as const;
|
||||
|
||||
export const COLOR_TOKENS = Object.keys(light);
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"react-native-safe-area-context": "5.6.1",
|
||||
"react-native-svg": "15.14.0",
|
||||
"react-redux": "9.2.0",
|
||||
"storybook": "^10.1.0",
|
||||
"type-fest": "4.24.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useSharedValue } from 'react-native-reanimated';
|
||||
import { AccordionItem, AccordionItemProps } from './AccordionItem';
|
||||
import { VStack } from '../Stack';
|
||||
|
||||
type AccordionListProps = {
|
||||
export type AccordionListProps = {
|
||||
items: Omit<AccordionItemProps, 'currentIndexOpened' | 'index' | 'isDividerDisplayed'>[];
|
||||
};
|
||||
|
||||
|
||||
@@ -12,10 +12,22 @@ import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
import { SurfaceElevation } from './types';
|
||||
|
||||
export type BadgeVariant = 'neutral' | 'green' | 'greenSubtle' | 'yellow' | 'red' | 'blue' | 'bold';
|
||||
export type BadgeSize = 'small' | 'medium';
|
||||
export const BADGE_VARIANTS = [
|
||||
'neutral',
|
||||
'green',
|
||||
'greenSubtle',
|
||||
'yellow',
|
||||
'red',
|
||||
'blue',
|
||||
'bold',
|
||||
] as const;
|
||||
export type BadgeVariant = (typeof BADGE_VARIANTS)[number];
|
||||
|
||||
export const BADGE_SIZES = ['small', 'medium'] as const;
|
||||
export type BadgeSize = (typeof BADGE_SIZES)[number];
|
||||
|
||||
type IconType = IconName | NetworkSymbol;
|
||||
type BadgeProps = {
|
||||
export type BadgeProps = {
|
||||
label: ReactNode;
|
||||
variant?: BadgeVariant;
|
||||
size?: BadgeSize;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Text } from './Text';
|
||||
|
||||
const INDENTED_BULLET_POINT_SYMBOL = ' \u2022 ';
|
||||
|
||||
type BulletListItemProps = {
|
||||
export type BulletListItemProps = {
|
||||
children: ReactNode;
|
||||
variant?: NativeTypographyStyle;
|
||||
color?: Color;
|
||||
|
||||
@@ -20,7 +20,11 @@ import {
|
||||
import { useButtonPressAnimatedStyle } from './useButtonPressAnimatedStyle';
|
||||
import { Loader } from '../Loader';
|
||||
import { AnimatedPressable } from '../Pressable';
|
||||
type IconButtonProps = Omit<PressableProps, 'style' | 'onPressIn' | 'onPressOut'> & {
|
||||
|
||||
export type IconButtonProps = Omit<
|
||||
PressableProps,
|
||||
'style' | 'onPressIn' | 'onPressOut' | 'children'
|
||||
> & {
|
||||
iconName: IconName;
|
||||
colorScheme?: ButtonColorScheme;
|
||||
size?: ButtonSize;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ButtonAccessoryView, ButtonProps, ButtonSize, buttonToTextSizeMap } fro
|
||||
|
||||
export type TextButtonVariant = 'primary' | 'tertiary' | 'blue';
|
||||
|
||||
type TextButtonProps = Omit<ButtonProps, 'colorScheme'> & {
|
||||
export type TextButtonProps = Omit<ButtonProps, 'colorScheme'> & {
|
||||
isUnderlined?: boolean;
|
||||
variant?: TextButtonVariant;
|
||||
isBold?: boolean;
|
||||
|
||||
@@ -14,7 +14,7 @@ const contentStyle = prepareNativeStyle(() => ({
|
||||
flexShrink: 1,
|
||||
}));
|
||||
|
||||
type CardWithIconLayoutProps = {
|
||||
export type CardWithIconLayoutProps = {
|
||||
icon: IconName;
|
||||
title: ReactNode;
|
||||
children: ReactNode;
|
||||
|
||||
@@ -14,7 +14,8 @@ import { HStack, VStack } from '../Stack';
|
||||
import { Text } from '../Text';
|
||||
import { Card } from './Card';
|
||||
|
||||
type CardVariant = 'normal' | 'danger' | 'primary';
|
||||
export const COMPACT_CARD_VARIANTS = ['normal', 'danger', 'primary'] as const;
|
||||
type CompactCardVariant = (typeof COMPACT_CARD_VARIANTS)[number];
|
||||
|
||||
export type CompactCardWithIconLayoutProps = {
|
||||
icon: IconName;
|
||||
@@ -23,7 +24,7 @@ export type CompactCardWithIconLayoutProps = {
|
||||
isDisabled?: boolean;
|
||||
alertBoxProps?: Omit<InlineAlertBoxProps, 'borderRadius'>;
|
||||
onPress?: () => void;
|
||||
variant?: CardVariant;
|
||||
variant?: CompactCardVariant;
|
||||
noShadow?: boolean;
|
||||
borderColor?: Color | null;
|
||||
} & PressableProps;
|
||||
@@ -58,7 +59,7 @@ export const cardVariantToColorsMap = {
|
||||
subtitleColor: 'textSecondaryHighlight',
|
||||
caretColor: 'iconPrimaryDefault',
|
||||
},
|
||||
} as const satisfies Record<CardVariant, CardColorScheme>;
|
||||
} as const satisfies Record<CompactCardVariant, CardColorScheme>;
|
||||
|
||||
const contentStyle = prepareNativeStyle(() => ({
|
||||
flexGrow: 1,
|
||||
|
||||
@@ -10,7 +10,7 @@ import { Headered } from '../Headered';
|
||||
import { HStack } from '../Stack';
|
||||
import { Text } from '../Text';
|
||||
|
||||
type HeaderedCardProps = CardProps & CardHeaderProps;
|
||||
export type HeaderedCardProps = CardProps & CardHeaderProps;
|
||||
|
||||
type CardHeaderProps = RequireAllOrNone<
|
||||
{
|
||||
|
||||
@@ -15,7 +15,7 @@ export type CardStepperMap<ContentIdType = undefined> = Record<
|
||||
}
|
||||
>;
|
||||
|
||||
type CardStepperProps<ContentIdType = undefined> = {
|
||||
export type CardStepperProps<ContentIdType = undefined> = {
|
||||
onFinish: () => void;
|
||||
primaryButtonText: ReactNode;
|
||||
secondaryButtonText: ReactNode;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { NativeStyleObject, prepareNativeStyle, useNativeStyles } from '@trezor/
|
||||
import { PressableOpacity } from './Pressable';
|
||||
import { ACCESSIBILITY_FONTSIZE_MULTIPLIER } from './Text';
|
||||
|
||||
type CheckBoxProps = {
|
||||
export type CheckBoxProps = {
|
||||
isChecked: boolean;
|
||||
isDisabled?: boolean;
|
||||
onChange: (value: boolean) => void;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { Color } from '@trezor/theme';
|
||||
|
||||
import { ENDLESS_ANIMATION_VALUE } from './constants';
|
||||
|
||||
type CircularSpinnerProps = {
|
||||
export type CircularSpinnerProps = {
|
||||
size: number;
|
||||
color: Color;
|
||||
width: number;
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
|
||||
import { Box, BoxProps } from './Box';
|
||||
|
||||
type DividerProps = Omit<BoxProps, 'style'> & {
|
||||
export type DividerProps = Omit<BoxProps, 'style'> & {
|
||||
style?: NativeStyleObject;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,7 +2,15 @@ import { IconName } from '@suite-native/icons';
|
||||
import { Color } from '@trezor/theme';
|
||||
|
||||
import { ButtonColorScheme } from '../Button/Button';
|
||||
export type AlertVariant = 'info' | 'critical' | 'neutral' | 'success' | 'warning';
|
||||
|
||||
export const FULL_ALERT_BOX_VARIANTS = [
|
||||
'info',
|
||||
'critical',
|
||||
'neutral',
|
||||
'success',
|
||||
'warning',
|
||||
] as const;
|
||||
export type AlertVariant = (typeof FULL_ALERT_BOX_VARIANTS)[number];
|
||||
|
||||
export type FullAlertStyles = {
|
||||
backgroundColor: Color;
|
||||
|
||||
@@ -7,9 +7,10 @@ import { Color } from '@trezor/theme';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type HintVariant = 'hint' | 'error' | 'info';
|
||||
export const HINT_VARIANTS = ['hint', 'error', 'info'] as const;
|
||||
export type HintVariant = (typeof HINT_VARIANTS)[number];
|
||||
|
||||
type HintProps = {
|
||||
export type HintProps = {
|
||||
variant?: HintVariant;
|
||||
style?: NativeStyleObject;
|
||||
children?: ReactNode;
|
||||
|
||||
@@ -35,7 +35,7 @@ const LOADER_ARC_OVAL_CONFIG = {
|
||||
height: CANVAS_SIZE - BORDER_WIDTH * 2,
|
||||
};
|
||||
|
||||
type HoldToConfirmButtonProps = {
|
||||
export type HoldToConfirmButtonProps = {
|
||||
onSuccess: () => void;
|
||||
isDisplayed?: SharedValue<boolean>;
|
||||
buttonLabelId?: TxKeyPath;
|
||||
|
||||
@@ -9,7 +9,10 @@ import { OrderedListIcon } from './OrderedListIcon';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type Variant = 'default' | 'blue' | 'red' | 'yellow' | 'primary';
|
||||
export const ICON_LIST_ITEM_VARIANTS = ['default', 'blue', 'red', 'yellow', 'primary'] as const;
|
||||
|
||||
export type IconListItemVariant = (typeof ICON_LIST_ITEM_VARIANTS)[number];
|
||||
|
||||
type IconColors = {
|
||||
iconColor: Color;
|
||||
iconBorderColor: Color;
|
||||
@@ -42,18 +45,18 @@ const iconColorsMap = {
|
||||
iconBorderColor: 'backgroundPrimaryDefault',
|
||||
iconBackgroundColor: 'backgroundPrimaryDefault',
|
||||
},
|
||||
} as const satisfies Record<Variant, IconColors>;
|
||||
} as const satisfies Record<IconListItemVariant, IconColors>;
|
||||
|
||||
type IconListItemProps = {
|
||||
export type IconListItemProps = {
|
||||
children: ReactNode;
|
||||
icon: IconName;
|
||||
iconSize?: IconSize;
|
||||
variant?: Variant;
|
||||
variant?: IconListItemVariant;
|
||||
verticalAlign?: FlexAlignType;
|
||||
spacing?: NativeSpacing | number;
|
||||
};
|
||||
|
||||
type IconListTextItemProps = IconListItemProps & {
|
||||
export type IconListTextItemProps = IconListItemProps & {
|
||||
textVariant?: NativeTypographyStyle;
|
||||
textColor?: Color;
|
||||
};
|
||||
|
||||
@@ -3,7 +3,14 @@ import { Color } from '@trezor/theme';
|
||||
|
||||
import { ButtonColorScheme } from '../Button/Button';
|
||||
|
||||
export type InlineAlertBoxVariant = 'info' | 'critical' | 'neutral' | 'success' | 'warning';
|
||||
export const INLINE_ALERT_BOX_VARIANTS = [
|
||||
'info',
|
||||
'critical',
|
||||
'neutral',
|
||||
'success',
|
||||
'warning',
|
||||
] as const;
|
||||
export type InlineAlertBoxVariant = (typeof INLINE_ALERT_BOX_VARIANTS)[number];
|
||||
|
||||
export type InlineAlertBoxStyles = {
|
||||
backgroundColor: Color;
|
||||
|
||||
@@ -6,10 +6,11 @@ import { Color } from '@trezor/theme';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type Variant = 'info' | 'success' | 'critical';
|
||||
export const INLINE_ALERT_TEXT_VARIANTS = ['info', 'success', 'critical'] as const;
|
||||
export type InlineAlertTextVariant = (typeof INLINE_ALERT_TEXT_VARIANTS)[number];
|
||||
|
||||
export type InlineAlertTextProps = {
|
||||
variant: Variant;
|
||||
variant: InlineAlertTextVariant;
|
||||
children: ReactNode;
|
||||
};
|
||||
|
||||
@@ -31,7 +32,7 @@ const variants = {
|
||||
icon: 'warningCircle',
|
||||
color: 'textAlertRed',
|
||||
},
|
||||
} as const satisfies Record<Variant, VariantConfig>;
|
||||
} as const satisfies Record<InlineAlertTextVariant, VariantConfig>;
|
||||
|
||||
export const InlineAlertText = ({ variant, children }: InlineAlertTextProps) => {
|
||||
const { color, icon } = variants[variant];
|
||||
|
||||
@@ -10,7 +10,7 @@ import { SearchInputMagnifyingGlass } from './SearchInputMagnifyingGlass';
|
||||
import { inputStyle, inputWrapperStyle } from './searchInputStyles';
|
||||
import { useSearchInputCallbacks } from './useSearchInputCallbacks';
|
||||
|
||||
export type SearchInputProps = {
|
||||
export type BaseSearchInputProps = {
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
isDisabled?: boolean;
|
||||
@@ -19,7 +19,7 @@ export type SearchInputProps = {
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
};
|
||||
export const BaseSearchInput = forwardRef<TextInput, SearchInputProps>(
|
||||
export const BaseSearchInput = forwardRef<TextInput, BaseSearchInputProps>(
|
||||
(
|
||||
{ onChange, placeholder, maxLength, isDisabled = false, elevation = '0', onFocus, onBlur },
|
||||
ref,
|
||||
|
||||
@@ -4,7 +4,7 @@ import { TextInput } from 'react-native';
|
||||
import { SurfaceElevation } from '../types';
|
||||
import { BaseSearchInput } from './BaseSearchInput';
|
||||
|
||||
type InputProps = {
|
||||
export type SearchInputProps = {
|
||||
onChange: (value: string) => void;
|
||||
placeholder?: string;
|
||||
isDisabled?: boolean;
|
||||
@@ -22,7 +22,7 @@ export const SearchInput = ({
|
||||
elevation = '0',
|
||||
onFocus,
|
||||
onBlur,
|
||||
}: InputProps) => {
|
||||
}: SearchInputProps) => {
|
||||
const searchInputRef = useRef<TextInput>(null);
|
||||
|
||||
return (
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Color } from '@trezor/theme';
|
||||
import { Box } from './Box';
|
||||
import { Text } from './Text';
|
||||
|
||||
type LoaderProps = {
|
||||
export type LoaderProps = {
|
||||
size?: ActivityIndicatorProps['size'];
|
||||
title?: ReactNode;
|
||||
color?: Color;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Box } from './Box';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type NumberedListItemProps = {
|
||||
export type NumberedListItemProps = {
|
||||
children: ReactNode;
|
||||
variant?: NativeTypographyStyle;
|
||||
color?: Color;
|
||||
|
||||
@@ -15,9 +15,10 @@ import { WarningIconSvg } from './WarningIconSvg';
|
||||
import { WarningShapeSvg } from './WarningShapeSvg';
|
||||
import { PictogramIconSvgProps } from './types';
|
||||
|
||||
export type PictogramVariant = 'success' | 'info' | 'warning' | 'critical';
|
||||
export const PICTOGRAM_VARIANTS = ['success', 'info', 'warning', 'critical'] as const;
|
||||
export type PictogramVariant = (typeof PICTOGRAM_VARIANTS)[number];
|
||||
|
||||
type PictogramProps = {
|
||||
export type PictogramProps = {
|
||||
variant: PictogramVariant;
|
||||
icon?: IconName;
|
||||
};
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
|
||||
import { CSSColor } from '@trezor/theme';
|
||||
|
||||
import { Box } from './Box';
|
||||
|
||||
type ProgressBarProps = {
|
||||
value: number; // Percentage value
|
||||
color: CSSColor;
|
||||
};
|
||||
|
||||
const PROGRESS_BAR_WIDTH = 82;
|
||||
const progressBarStyle = prepareNativeStyle(utils => ({
|
||||
height: 3,
|
||||
width: PROGRESS_BAR_WIDTH,
|
||||
backgroundColor: utils.colors.backgroundSurfaceElevationNegative,
|
||||
}));
|
||||
|
||||
const progressFillStyle = prepareNativeStyle<{ width: number; color: CSSColor }>(
|
||||
(_, { width, color }) => ({
|
||||
width: (width / 100) * PROGRESS_BAR_WIDTH,
|
||||
height: 3,
|
||||
backgroundColor: color,
|
||||
}),
|
||||
);
|
||||
|
||||
export const ProgressBar = ({ value, color }: ProgressBarProps) => {
|
||||
const { applyStyle } = useNativeStyles();
|
||||
|
||||
return (
|
||||
<Box style={applyStyle(progressBarStyle)}>
|
||||
<Box style={applyStyle(progressFillStyle, { width: value, color })} />
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -6,8 +6,9 @@ import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
|
||||
|
||||
const ANIMATION_SPEED = 1.5;
|
||||
|
||||
export type SpinnerLoadingState = 'success' | 'error' | 'idle';
|
||||
type SpinnerProps = {
|
||||
export const SPINNER_LOADING_STATES = ['success', 'error', 'idle'] as const;
|
||||
export type SpinnerLoadingState = (typeof SPINNER_LOADING_STATES)[number];
|
||||
export type SpinnerProps = {
|
||||
loadingState: SpinnerLoadingState;
|
||||
onComplete?: () => void;
|
||||
endFrame?: number;
|
||||
|
||||
@@ -13,7 +13,7 @@ import { paletteV1 } from '@trezor/theme';
|
||||
|
||||
import { ACCESSIBILITY_FONTSIZE_MULTIPLIER } from './Text';
|
||||
|
||||
type SwitchProps = {
|
||||
export type SwitchProps = {
|
||||
isChecked: boolean;
|
||||
onChange: (value: boolean) => void;
|
||||
isDisabled?: boolean; // Functionality of disabled works but styles are not implemented yet (waiting for design)
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Box } from './Box';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type TableProps = {
|
||||
export type TableProps = {
|
||||
children: ReactNode;
|
||||
};
|
||||
type TdProps = {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Box } from './Box';
|
||||
import { HStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type TextDividerProps = {
|
||||
export type TextDividerProps = {
|
||||
title?: TxKeyPath;
|
||||
horizontalMargin?: number;
|
||||
lineColor?: Color;
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { prepareNativeStyle, useNativeStyles } from '@trezor/styles';
|
||||
import { NativeTypographyStyle } from '@trezor/theme';
|
||||
|
||||
import { VStack } from './Stack';
|
||||
import { Text } from './Text';
|
||||
|
||||
type TitleHeaderProps = {
|
||||
title?: ReactNode;
|
||||
titleVariant?: NativeTypographyStyle;
|
||||
subtitle?: ReactNode;
|
||||
textAlign?: 'left' | 'center';
|
||||
};
|
||||
|
||||
const textStyle = prepareNativeStyle<{ textAlign: TitleHeaderProps['textAlign'] }>(
|
||||
(_, { textAlign }) => ({
|
||||
textAlign,
|
||||
width: '100%',
|
||||
}),
|
||||
);
|
||||
|
||||
export const TitleHeader = ({
|
||||
title,
|
||||
subtitle,
|
||||
titleVariant = 'titleSmall',
|
||||
textAlign = 'left',
|
||||
}: TitleHeaderProps) => {
|
||||
const { applyStyle } = useNativeStyles();
|
||||
|
||||
return (
|
||||
<VStack alignItems="center">
|
||||
{title && (
|
||||
<Text variant={titleVariant} style={applyStyle(textStyle, { textAlign })}>
|
||||
{title}
|
||||
</Text>
|
||||
)}
|
||||
{subtitle && (
|
||||
<Text color="textSubdued" style={applyStyle(textStyle, { textAlign })}>
|
||||
{subtitle}
|
||||
</Text>
|
||||
)}
|
||||
</VStack>
|
||||
);
|
||||
};
|
||||
|
||||
export const CenteredTitleHeader = ({
|
||||
title,
|
||||
subtitle,
|
||||
titleVariant = 'titleSmall',
|
||||
}: TitleHeaderProps) => (
|
||||
<TitleHeader titleVariant={titleVariant} title={title} subtitle={subtitle} textAlign="center" />
|
||||
);
|
||||
@@ -7,7 +7,7 @@ import { Pictogram, PictogramVariant } from '../Pictogram/Pictogram';
|
||||
import { VStack } from '../Stack';
|
||||
import { CenteredTitleHeader } from './CenteredTitleHeader';
|
||||
|
||||
type PictogramTitleHeaderProps = {
|
||||
export type PictogramTitleHeaderProps = {
|
||||
variant: PictogramVariant;
|
||||
icon?: IconName;
|
||||
title?: ReactNode;
|
||||
|
||||
@@ -9,7 +9,7 @@ import { HStack, VStack } from './Stack';
|
||||
import { Switch } from './Switch';
|
||||
import { Text } from './Text';
|
||||
|
||||
type TouchableSwitchRowProps = {
|
||||
export type TouchableSwitchRowProps = {
|
||||
icon: IconName;
|
||||
accessibilityLabel: string;
|
||||
text: ReactNode;
|
||||
|
||||
@@ -37,7 +37,6 @@ export * from './Badge';
|
||||
export * from './Divider';
|
||||
export * from './TextDivider';
|
||||
export * from './TitledSection';
|
||||
export * from './ProgressBar';
|
||||
export * from './Card/Card';
|
||||
export * from './Card/HeaderedCard';
|
||||
export * from './Card/CardDivider';
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import {
|
||||
FullAlertBox as FullAlertBoxComponent,
|
||||
FullAlertBoxProps,
|
||||
} from '../../FullAlertBox/FullAlertBox';
|
||||
import { FULL_ALERT_BOX_VARIANTS } from '../../FullAlertBox/presets';
|
||||
|
||||
type FullAlertBoxStory = StoryObj<FullAlertBoxProps>;
|
||||
|
||||
const meta: Meta<FullAlertBoxProps> = {
|
||||
title: 'Atoms/AlertBoxes',
|
||||
component: FullAlertBoxComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const FullAlertBox: FullAlertBoxStory = {
|
||||
name: 'FullAlertBox',
|
||||
args: {
|
||||
title: 'Title',
|
||||
description:
|
||||
'Very descriptive description. Read carefully or you will miss something important.',
|
||||
primaryButtonLabel: 'Primary',
|
||||
secondaryButtonLabel: 'Secondary',
|
||||
variant: 'info',
|
||||
iconName: undefined,
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
description: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
primaryButtonLabel: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
secondaryButtonLabel: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: FULL_ALERT_BOX_VARIANTS,
|
||||
},
|
||||
iconName: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import { FULL_ALERT_BOX_VARIANTS } from '../../FullAlertBox/presets';
|
||||
import {
|
||||
InlineAlertBox as InlineAlertBoxComponent,
|
||||
InlineAlertBoxProps,
|
||||
} from '../../InlineAlertBox/InlineAlertBox';
|
||||
|
||||
type InlineAlertBoxStory = StoryObj<InlineAlertBoxProps>;
|
||||
|
||||
const meta: Meta<InlineAlertBoxProps> = {
|
||||
title: 'Atoms/AlertBoxes',
|
||||
component: InlineAlertBoxComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const InlineAlertBox: InlineAlertBoxStory = {
|
||||
name: 'InlineAlertBox',
|
||||
args: {
|
||||
title: 'Something very important to communicate.',
|
||||
buttonLabel: 'Button',
|
||||
variant: 'info',
|
||||
iconName: undefined,
|
||||
buttonProps: undefined,
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
buttonLabel: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
viewLeft: {
|
||||
control: false,
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: FULL_ALERT_BOX_VARIANTS,
|
||||
},
|
||||
iconName: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
},
|
||||
};
|
||||
57
suite-native/atoms/src/stories/Badge.stories.tsx
Normal file
57
suite-native/atoms/src/stories/Badge.stories.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES, ICON_SIZES } from '@suite-native/icons';
|
||||
|
||||
import { BADGE_SIZES, BADGE_VARIANTS, Badge as BadgeComponent, BadgeProps } from '../Badge';
|
||||
import { SURFACE_ELEVATIONS } from '../types';
|
||||
|
||||
type BadgeStory = StoryObj<BadgeProps>;
|
||||
|
||||
const meta: Meta<BadgeProps> = {
|
||||
title: 'Atoms',
|
||||
component: BadgeComponent,
|
||||
render: args => <BadgeComponent {...args} style={{ alignSelf: 'center' }} />,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Badge: BadgeStory = {
|
||||
name: 'Badge',
|
||||
args: {
|
||||
label: 'badge',
|
||||
variant: 'green',
|
||||
size: 'medium',
|
||||
icon: undefined,
|
||||
iconSize: 'small',
|
||||
elevation: '0',
|
||||
isDisabled: false,
|
||||
},
|
||||
argTypes: {
|
||||
label: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: BADGE_VARIANTS,
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
options: BADGE_SIZES,
|
||||
},
|
||||
iconSize: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_SIZES,
|
||||
},
|
||||
elevation: {
|
||||
control: { type: 'select' },
|
||||
options: SURFACE_ELEVATIONS,
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable import/no-default-export */
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
@@ -8,19 +7,24 @@ import {
|
||||
BUTTON_SIZES,
|
||||
Button as ButtonComponent,
|
||||
ButtonProps,
|
||||
} from '../Button/Button';
|
||||
} from '../../Button/Button';
|
||||
|
||||
type ButtonStory = StoryObj<ButtonProps>;
|
||||
|
||||
const meta: Meta<ButtonProps> = {
|
||||
title: 'Atoms/buttons',
|
||||
title: 'Atoms/Buttons',
|
||||
component: ButtonComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Button: ButtonStory = {
|
||||
args: { children: 'Button', colorScheme: 'primary', size: 'medium' },
|
||||
args: {
|
||||
children: 'Press me',
|
||||
viewLeft: 'magnifyingGlass',
|
||||
colorScheme: 'primary',
|
||||
size: 'medium',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
type: 'string',
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import { BUTTON_COLOR_SCHEMES, BUTTON_SIZES } from '../../Button/Button';
|
||||
import { IconButton as IconButtonComponent, IconButtonProps } from '../../Button/IconButton';
|
||||
|
||||
type IconButtonStory = StoryObj<IconButtonProps>;
|
||||
|
||||
const meta: Meta<IconButtonProps> = {
|
||||
title: 'Atoms/Buttons',
|
||||
component: IconButtonComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const IconButton: IconButtonStory = {
|
||||
args: { colorScheme: 'primary', size: 'medium', iconName: 'magnifyingGlass' },
|
||||
argTypes: {
|
||||
iconName: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
colorScheme: {
|
||||
control: { type: 'select' },
|
||||
options: BUTTON_COLOR_SCHEMES,
|
||||
},
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
options: BUTTON_SIZES,
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isLoading: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,63 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import { BUTTON_COLOR_SCHEMES, BUTTON_SIZES } from '../../Button/Button';
|
||||
import { TextButton as TextButtonComponent, TextButtonProps } from '../../Button/TextButton';
|
||||
|
||||
type TextButtonStory = StoryObj<TextButtonProps>;
|
||||
|
||||
const meta: Meta<TextButtonProps> = {
|
||||
title: 'Atoms/Buttons',
|
||||
component: TextButtonComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const TextButton: TextButtonStory = {
|
||||
args: { children: 'Press me', viewLeft: 'magnifyingGlass', variant: 'primary', size: 'medium' },
|
||||
argTypes: {
|
||||
children: {
|
||||
type: 'string',
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: BUTTON_COLOR_SCHEMES,
|
||||
},
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
options: BUTTON_SIZES,
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isLoading: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
viewLeft: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
viewRight: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
isUnderlined: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isBold: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
justifyContent: {
|
||||
control: { type: 'select' },
|
||||
options: [
|
||||
'flex-start',
|
||||
'center',
|
||||
'flex-end',
|
||||
'space-between',
|
||||
'space-around',
|
||||
'space-evenly',
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
65
suite-native/atoms/src/stories/Cards/Card.stories.tsx
Normal file
65
suite-native/atoms/src/stories/Cards/Card.stories.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import { Card as CardComponent, CardProps } from '../../Card/Card';
|
||||
import { InlineAlertBoxProps } from '../../InlineAlertBox/InlineAlertBox';
|
||||
import { INLINE_ALERT_BOX_VARIANTS, InlineAlertBoxVariant } from '../../InlineAlertBox/presets';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type CardStory = StoryObj<CardProps>;
|
||||
|
||||
const meta: Meta<CardProps> = {
|
||||
title: 'Atoms/Cards',
|
||||
component: CardComponent,
|
||||
render: args => (
|
||||
<CardComponent {...args}>
|
||||
<Text>{args.children}</Text>
|
||||
</CardComponent>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Card: CardStory = {
|
||||
args: {
|
||||
children:
|
||||
'This is content inside the Card. It can be some very long text or even some other components. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: false,
|
||||
},
|
||||
noPadding: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
noShadow: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
borderColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
alertPosition: {
|
||||
name: 'Alert position',
|
||||
control: { type: 'select' },
|
||||
options: ['top', 'bottom'],
|
||||
},
|
||||
alertProps: {
|
||||
name: 'Alert variant',
|
||||
control: { type: 'select' },
|
||||
options: INLINE_ALERT_BOX_VARIANTS,
|
||||
mapping: INLINE_ALERT_BOX_VARIANTS.reduce(
|
||||
(acc, variant) => {
|
||||
acc[variant] = {
|
||||
title: `This is some very important ${variant} alert than needs to be highlighted`,
|
||||
variant,
|
||||
};
|
||||
|
||||
return acc;
|
||||
},
|
||||
{} as Record<InlineAlertBoxVariant, InlineAlertBoxProps>,
|
||||
),
|
||||
},
|
||||
},
|
||||
};
|
||||
69
suite-native/atoms/src/stories/Cards/CardStepper.stories.tsx
Normal file
69
suite-native/atoms/src/stories/Cards/CardStepper.stories.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import { View } from 'react-native';
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import {
|
||||
CardStepper as CardStepperComponent,
|
||||
CardStepperProps,
|
||||
} from '../../CardStepper/CardStepper';
|
||||
|
||||
type CardStepperStory = StoryObj<CardStepperProps>;
|
||||
|
||||
const meta: Meta<CardStepperProps> = {
|
||||
title: 'Atoms/Cards',
|
||||
component: CardStepperComponent,
|
||||
decorators: [
|
||||
Story => (
|
||||
<View style={{ width: '100%' }}>
|
||||
<Story />
|
||||
</View>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const CardStepper: CardStepperStory = {
|
||||
name: 'CardStepper',
|
||||
args: {
|
||||
primaryButtonText: 'Continue',
|
||||
secondaryButtonText: 'Cancel',
|
||||
buttonsActionType: 'primary',
|
||||
|
||||
onFinish: () => {},
|
||||
stepToContentMap: {
|
||||
1: {
|
||||
header: 'Read this',
|
||||
description: 'Step 1 description read this properly',
|
||||
icon: 'star',
|
||||
},
|
||||
2: {
|
||||
header: 'Then another one',
|
||||
description: 'This is step number two ;)',
|
||||
icon: 'timer',
|
||||
},
|
||||
3: {
|
||||
header: 'Still reading?',
|
||||
description: 'Step 3 description',
|
||||
icon: 'stack',
|
||||
},
|
||||
4: {
|
||||
header: 'Final step',
|
||||
description: 'Step 4 description',
|
||||
icon: 'flag',
|
||||
},
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
primaryButtonText: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
secondaryButtonText: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
buttonsActionType: {
|
||||
control: { type: 'select' },
|
||||
options: ['primary', 'destructive'],
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import { Card as CardStory } from './Card.stories';
|
||||
import {
|
||||
CardWithIconLayout as CardWithIconLayoutComponent,
|
||||
CardWithIconLayoutProps,
|
||||
} from '../../Card/CardWithIconLayout';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type CardWithIconLayoutStory = StoryObj<CardWithIconLayoutProps>;
|
||||
|
||||
const meta: Meta<CardWithIconLayoutProps> = {
|
||||
title: 'Atoms/Cards',
|
||||
component: CardWithIconLayoutComponent,
|
||||
render: args => (
|
||||
<CardWithIconLayoutComponent {...args}>
|
||||
<Text>{args.children}</Text>
|
||||
</CardWithIconLayoutComponent>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const CardWithIconLayout: CardWithIconLayoutStory = {
|
||||
name: 'CardWithIconLayout',
|
||||
args: {
|
||||
children: CardStory.args?.children,
|
||||
icon: 'flag',
|
||||
title: 'Card title',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: false,
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
alertBoxProps: CardStory.argTypes?.alertProps,
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,57 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import { Card as CardStory } from './Card.stories';
|
||||
import {
|
||||
COMPACT_CARD_VARIANTS,
|
||||
CompactCardWithIconLayout as CompactCardWithIconLayoutComponent,
|
||||
CompactCardWithIconLayoutProps,
|
||||
} from '../../Card/CompactCardWithIconLayout';
|
||||
|
||||
type CompactCardWithIconLayoutStory = StoryObj<CompactCardWithIconLayoutProps>;
|
||||
|
||||
const meta: Meta<CompactCardWithIconLayoutProps> = {
|
||||
title: 'Atoms/Cards',
|
||||
component: CompactCardWithIconLayoutComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const CompactCardWithIconLayout: CompactCardWithIconLayoutStory = {
|
||||
name: 'CompactCardWithIconLayout',
|
||||
args: {
|
||||
icon: 'flag',
|
||||
title: 'Card title that you can press to interact with',
|
||||
variant: 'primary',
|
||||
subtitle: 'This is a subtitle that you can use to describe the card',
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: COMPACT_CARD_VARIANTS,
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
noShadow: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
alertBoxProps: CardStory.argTypes?.alertProps,
|
||||
borderColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import { Card } from './Card.stories';
|
||||
import { HeaderedCard as HeaderedCardComponent, HeaderedCardProps } from '../../Card/HeaderedCard';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type HeaderedCardStory = StoryObj<HeaderedCardProps>;
|
||||
|
||||
const meta: Meta<HeaderedCardProps> = {
|
||||
title: 'Atoms/Cards',
|
||||
component: HeaderedCardComponent,
|
||||
render: args => (
|
||||
<HeaderedCardComponent {...args}>
|
||||
<Text>{args.children}</Text>
|
||||
</HeaderedCardComponent>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const HeaderedCard: HeaderedCardStory = {
|
||||
name: 'HeaderedCard',
|
||||
args: {
|
||||
buttonIcon: 'flag',
|
||||
buttonTitle: 'Button title',
|
||||
title: 'Card title',
|
||||
children: Card.args?.children,
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
buttonTitle: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
buttonIcon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
},
|
||||
};
|
||||
38
suite-native/atoms/src/stories/CircularSpinner.stories.tsx
Normal file
38
suite-native/atoms/src/stories/CircularSpinner.stories.tsx
Normal file
@@ -0,0 +1,38 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
CircularSpinner as CircularSpinnerComponent,
|
||||
CircularSpinnerProps,
|
||||
} from '../CircularSpinner';
|
||||
|
||||
type CircularSpinnerStory = StoryObj<CircularSpinnerProps>;
|
||||
|
||||
const meta: Meta<CircularSpinnerProps> = {
|
||||
title: 'Atoms',
|
||||
component: CircularSpinnerComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const CircularSpinner: CircularSpinnerStory = {
|
||||
name: 'CircularSpinner',
|
||||
args: {
|
||||
size: 50,
|
||||
color: 'textDefault',
|
||||
width: 5,
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
width: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
},
|
||||
};
|
||||
25
suite-native/atoms/src/stories/Dividers/Divider.stories.tsx
Normal file
25
suite-native/atoms/src/stories/Dividers/Divider.stories.tsx
Normal file
@@ -0,0 +1,25 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { Divider as DividerComponent, DividerProps } from '../../Divider';
|
||||
import { VStack } from '../../Stack';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type DividerStory = StoryObj<DividerProps>;
|
||||
|
||||
const meta: Meta<DividerProps> = {
|
||||
title: 'Atoms/Dividers',
|
||||
component: DividerComponent,
|
||||
render: args => (
|
||||
<VStack alignItems="center">
|
||||
<Text>Text above the divider</Text>
|
||||
<DividerComponent {...args} style={{ backgroundColor: '#afb3b9', width: '100%' }} />
|
||||
<Text>Text below the divider</Text>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Divider: DividerStory = {
|
||||
name: 'Divider',
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
import { View } from 'react-native';
|
||||
|
||||
import { type Meta, type StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import { VStack } from '../../Stack';
|
||||
import { Text } from '../../Text';
|
||||
import { TextDivider as TextDividerComponent, TextDividerProps } from '../../TextDivider';
|
||||
|
||||
type TextDividerStory = StoryObj<TextDividerProps>;
|
||||
|
||||
const meta: Meta<TextDividerProps> = {
|
||||
title: 'Atoms/Dividers',
|
||||
component: TextDividerComponent,
|
||||
render: args => (
|
||||
<VStack alignItems="center">
|
||||
<Text>Text above the divider</Text>
|
||||
<View style={{ width: '100%' }}>
|
||||
<TextDividerComponent {...args} />
|
||||
</View>
|
||||
<Text>Text below the divider</Text>
|
||||
</VStack>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const TextDivider: TextDividerStory = {
|
||||
name: 'Text Divider',
|
||||
args: {
|
||||
lineColor: 'textDefault',
|
||||
textColor: 'textDefault',
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
horizontalMargin: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
lineColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
textColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
},
|
||||
};
|
||||
29
suite-native/atoms/src/stories/Hint.stories.tsx
Normal file
29
suite-native/atoms/src/stories/Hint.stories.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { HINT_VARIANTS, Hint as HintComponent, HintProps } from '../Hint';
|
||||
|
||||
type HintStory = StoryObj<HintProps>;
|
||||
|
||||
const meta: Meta<HintProps> = {
|
||||
title: 'Atoms',
|
||||
component: HintComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Hint: HintStory = {
|
||||
name: 'Hint',
|
||||
args: {
|
||||
variant: 'hint',
|
||||
children: 'Hint message',
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: HINT_VARIANTS,
|
||||
},
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
},
|
||||
};
|
||||
33
suite-native/atoms/src/stories/InlineAlertText.stories.tsx
Normal file
33
suite-native/atoms/src/stories/InlineAlertText.stories.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import {
|
||||
INLINE_ALERT_TEXT_VARIANTS,
|
||||
InlineAlertText as InlineAlertTextComponent,
|
||||
InlineAlertTextProps,
|
||||
} from '../InlineAlertText';
|
||||
|
||||
type InlineAlertTextStory = StoryObj<InlineAlertTextProps>;
|
||||
|
||||
const meta: Meta<InlineAlertTextProps> = {
|
||||
title: 'Atoms',
|
||||
component: InlineAlertTextComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const InlineAlertText: InlineAlertTextStory = {
|
||||
name: 'InlineAlertText',
|
||||
args: {
|
||||
variant: 'info',
|
||||
children: 'Text message',
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: INLINE_ALERT_TEXT_VARIANTS,
|
||||
},
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
},
|
||||
};
|
||||
41
suite-native/atoms/src/stories/Inputs/Checkbox.stories.tsx
Normal file
41
suite-native/atoms/src/stories/Inputs/Checkbox.stories.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
import { useArgs } from 'storybook/preview-api';
|
||||
|
||||
import { CheckBox as CheckBoxComponent, CheckBoxProps } from '../../CheckBox';
|
||||
|
||||
type CheckBoxStory = StoryObj<CheckBoxProps>;
|
||||
|
||||
const meta: Meta<CheckBoxProps> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: CheckBoxComponent,
|
||||
render: args => {
|
||||
const [{ isChecked }, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<CheckBoxComponent
|
||||
{...args}
|
||||
isChecked={isChecked}
|
||||
onChange={() => updateArgs({ isChecked: !isChecked })}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const CheckBox: CheckBoxStory = {
|
||||
name: 'CheckBox',
|
||||
args: {
|
||||
isChecked: true,
|
||||
isDisabled: false,
|
||||
onChange: () => {},
|
||||
},
|
||||
argTypes: {
|
||||
isChecked: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
};
|
||||
48
suite-native/atoms/src/stories/Inputs/Radio.stories.tsx
Normal file
48
suite-native/atoms/src/stories/Inputs/Radio.stories.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { type Meta, type StoryObj } from '@storybook/react-native';
|
||||
import { useArgs } from 'storybook/preview-api';
|
||||
|
||||
import { Radio as RadioComponent, RadioProps } from '../../Radio';
|
||||
|
||||
type RadioStory = StoryObj<RadioProps<number>>;
|
||||
|
||||
const meta: Meta<RadioProps<number>> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: RadioComponent<number>,
|
||||
render: args => {
|
||||
const [{ isChecked }, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<RadioComponent
|
||||
{...args}
|
||||
isChecked={isChecked}
|
||||
onPress={() => updateArgs({ isChecked: !isChecked })}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Radio: RadioStory = {
|
||||
name: 'Radio',
|
||||
args: {
|
||||
value: 1,
|
||||
isChecked: true,
|
||||
isDisabled: false,
|
||||
activeColor: 'backgroundPrimaryDefault',
|
||||
},
|
||||
argTypes: {
|
||||
value: {
|
||||
control: false,
|
||||
},
|
||||
isChecked: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
activeColor: {
|
||||
control: { type: 'color' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { SearchInput as SearchInputComponent, SearchInputProps } from '../../Input/SearchInput';
|
||||
|
||||
type SearchInputStory = StoryObj<SearchInputProps>;
|
||||
|
||||
const meta: Meta<SearchInputProps> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: SearchInputComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const SearchInput: SearchInputStory = {
|
||||
name: 'SearchInput',
|
||||
args: {
|
||||
placeholder: 'Search for something',
|
||||
isDisabled: false,
|
||||
maxLength: 100,
|
||||
elevation: '0',
|
||||
onChange: () => {},
|
||||
},
|
||||
argTypes: {
|
||||
placeholder: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
maxLength: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
elevation: {
|
||||
control: { type: 'select' },
|
||||
options: ['0', '1'],
|
||||
},
|
||||
},
|
||||
};
|
||||
40
suite-native/atoms/src/stories/Inputs/Switch.stories.tsx
Normal file
40
suite-native/atoms/src/stories/Inputs/Switch.stories.tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
import { useArgs } from 'storybook/preview-api';
|
||||
|
||||
import { Switch as SwitchComponent, SwitchProps } from '../../Switch';
|
||||
|
||||
type SwitchStory = StoryObj<SwitchProps>;
|
||||
|
||||
const meta: Meta<SwitchProps> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: SwitchComponent,
|
||||
render: args => {
|
||||
const [{ isChecked }, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<SwitchComponent
|
||||
{...args}
|
||||
isChecked={isChecked}
|
||||
onChange={() => updateArgs({ isChecked: !isChecked })}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Switch: SwitchStory = {
|
||||
name: 'Switch',
|
||||
args: {
|
||||
isChecked: true,
|
||||
isDisabled: false,
|
||||
},
|
||||
argTypes: {
|
||||
isChecked: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
isDisabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
},
|
||||
};
|
||||
62
suite-native/atoms/src/stories/Inputs/TextInput.stories.tsx
Normal file
62
suite-native/atoms/src/stories/Inputs/TextInput.stories.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
import { useArgs } from 'storybook/preview-api';
|
||||
|
||||
import { Input as InputComponent, InputProps } from '../../Input/Input';
|
||||
import { InputWrapper } from '../../Input/InputWrapper';
|
||||
|
||||
type TextInputArgs = InputProps & { wrapperLabel: string; hint: string; error: string };
|
||||
|
||||
type TextInputStory = StoryObj<TextInputArgs>;
|
||||
|
||||
const meta: Meta<TextInputArgs> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: InputComponent,
|
||||
decorators: [
|
||||
(Story, { context: { args } }) => {
|
||||
const [{ value }, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<InputWrapper hint={args.hint} label={args.wrapperLabel} error={args.error}>
|
||||
<Story
|
||||
args={{
|
||||
...args,
|
||||
label: undefined,
|
||||
hasError: !!args.error,
|
||||
value,
|
||||
onChangeText: (text: string) => updateArgs({ value: text }),
|
||||
}}
|
||||
/>
|
||||
</InputWrapper>
|
||||
);
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const TextInput: TextInputStory = {
|
||||
name: 'TextInput',
|
||||
args: {
|
||||
value: '',
|
||||
wrapperLabel: 'Label',
|
||||
hint: 'This is a hint',
|
||||
placeholder: 'placeholder',
|
||||
},
|
||||
argTypes: {
|
||||
label: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
hint: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
value: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
placeholder: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
error: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,58 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
import { useArgs } from 'storybook/preview-api';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import {
|
||||
TouchableSwitchRow as TouchableSwitchRowComponent,
|
||||
TouchableSwitchRowProps,
|
||||
} from '../../TouchableSwitchRow';
|
||||
|
||||
type TouchableSwitchRowStory = StoryObj<TouchableSwitchRowProps>;
|
||||
|
||||
const meta: Meta<TouchableSwitchRowProps> = {
|
||||
title: 'Atoms/Inputs',
|
||||
component: TouchableSwitchRowComponent,
|
||||
render: args => {
|
||||
const [{ isChecked }, updateArgs] = useArgs();
|
||||
|
||||
return (
|
||||
<TouchableSwitchRowComponent
|
||||
{...args}
|
||||
isChecked={isChecked}
|
||||
onChange={() => updateArgs({ isChecked: !isChecked })}
|
||||
/>
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const TouchableSwitchRow: TouchableSwitchRowStory = {
|
||||
name: 'TouchableSwitchRow',
|
||||
args: {
|
||||
isChecked: true,
|
||||
icon: 'info',
|
||||
text: 'Toggle label',
|
||||
description: 'Toggle description that is more detailed.',
|
||||
accessibilityLabel: 'Info',
|
||||
},
|
||||
argTypes: {
|
||||
isChecked: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
text: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
description: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
accessibilityLabel: {
|
||||
control: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import {
|
||||
AccordionList as AccordionListComponent,
|
||||
AccordionListProps,
|
||||
} from '../../Accordion/AccordionList';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type AccordionListStory = StoryObj<AccordionListProps>;
|
||||
|
||||
const meta: Meta<AccordionListProps> = {
|
||||
title: 'Atoms/Lists',
|
||||
component: AccordionListComponent,
|
||||
decorators: [
|
||||
(_Story, context) => {
|
||||
const { args } = context;
|
||||
|
||||
const textWrappedArgs = {
|
||||
...args,
|
||||
items: args.items.map(item => ({
|
||||
...item,
|
||||
content: <Text variant="label">{item.content}</Text>,
|
||||
})),
|
||||
};
|
||||
|
||||
return <_Story args={textWrappedArgs} />;
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
const defaultAccordionItems: AccordionListProps['items'] = [
|
||||
{
|
||||
title: 'Can I connect my Trezor to Trezor Suite on Mobile?',
|
||||
content: `Yes, you can connect your Trezor Safe 7 and use the app to manage your crypto with ease and confidence. For all Trezor devices the app is designed to work as a companion to the desktop/web version of Trezor Suite. As we add more features, it’ll become a standalone mobile application to manage your crypto funds on the go.`,
|
||||
iconName: 'trezorSafe7',
|
||||
},
|
||||
{
|
||||
title: 'What is the difference between Portfolio Tracker and Connected Trezor functionality?',
|
||||
content:
|
||||
'Portfolio Tracker helps you monitor your account balances without having to physically connect your Trezor device. Simply sync your coin addresses and keep track of your crypto on the go. You can also combine coin addresses from multiple wallets or Trezor devices to track your whole portfolio in one place. Connected Trezor allows you to manage your funds protected by your Trezor device. You can verify receive addresses and check your balances and transactions. However, if you disconnect the Trezor, you’ll no longer see the data from the Trezor device.',
|
||||
iconName: 'wallet',
|
||||
},
|
||||
{
|
||||
title: 'What are public keys (XPUB) and receive addresses?',
|
||||
content:
|
||||
'An XPUB is a master public key for hierarchical deterministic wallets like bitcoin, generating multiple child keys and receive addresses for improved privacy. Ethereum uses a single, unchanging address for all transactions. For Ethereum, share only your address, while keeping your private key secure.',
|
||||
iconName: 'qrCode',
|
||||
},
|
||||
{
|
||||
title: 'My Trezor device can’t connect',
|
||||
content:
|
||||
'Check the devices are in close proximityMake sure bluetooth is enabled on both devicesRemove old Trezor device Bluetooth connectionsRestart your device(s)Turn Bluetooth on/off again on your mobile deviceForget and re-pair the devicesUpdate Trezor firmware and your mobile device OS',
|
||||
iconName: 'cableUsbC',
|
||||
},
|
||||
];
|
||||
|
||||
export const AccordionList: AccordionListStory = {
|
||||
args: { items: defaultAccordionItems },
|
||||
argTypes: {
|
||||
items: {
|
||||
control: { type: 'object' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS, nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
BulletListItem as BulletListItemComponent,
|
||||
BulletListItemProps,
|
||||
} from '../../BulletListItem';
|
||||
|
||||
type BulletListItemStory = StoryObj<BulletListItemProps>;
|
||||
|
||||
const meta: Meta<BulletListItemProps> = {
|
||||
title: 'Atoms/Lists',
|
||||
component: BulletListItemComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const BulletListItem: BulletListItemStory = {
|
||||
name: 'BulletListItem',
|
||||
args: {
|
||||
children: 'textual bullet point',
|
||||
variant: 'body',
|
||||
color: 'textDefault',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES, ICON_SIZES } from '@suite-native/icons';
|
||||
import { nativeSpacings, nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
ICON_LIST_ITEM_VARIANTS,
|
||||
IconListTextItem as IconListTextItemComponent,
|
||||
IconListTextItemProps,
|
||||
} from '../../IconListItem';
|
||||
|
||||
type IconListTextItemStory = StoryObj<IconListTextItemProps>;
|
||||
|
||||
const meta: Meta<IconListTextItemProps> = {
|
||||
title: 'Atoms/Lists',
|
||||
component: IconListTextItemComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const IconListTextItem: IconListTextItemStory = {
|
||||
name: 'IconListTextItem',
|
||||
args: {
|
||||
children: 'Text value',
|
||||
icon: 'discover',
|
||||
iconSize: 'medium',
|
||||
variant: 'default',
|
||||
verticalAlign: 'center',
|
||||
spacing: 'sp12',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
iconSize: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(ICON_SIZES),
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(ICON_LIST_ITEM_VARIANTS),
|
||||
},
|
||||
textVariant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
spacing: {
|
||||
control: { type: 'select' },
|
||||
options: Object.keys(nativeSpacings),
|
||||
},
|
||||
verticalAlign: {
|
||||
control: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS, nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
NumberedListItem as NumberedListItemComponent,
|
||||
NumberedListItemProps,
|
||||
} from '../../NumberedListItem';
|
||||
|
||||
type NumberedListItemStory = StoryObj<NumberedListItemProps>;
|
||||
|
||||
const meta: Meta<NumberedListItemProps> = {
|
||||
title: 'Atoms/Lists',
|
||||
component: NumberedListItemComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const NumberedListItem: NumberedListItemStory = {
|
||||
name: 'NumberedListItem',
|
||||
args: {
|
||||
children: 'value',
|
||||
variant: 'body',
|
||||
color: 'textDefault',
|
||||
number: 1,
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
number: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,65 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_SIZES } from '@suite-native/icons';
|
||||
import { COLOR_TOKENS, nativeBorders } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
OrderedListIcon as OrderedListIconComponent,
|
||||
OrderedListIconProps,
|
||||
} from '../../OrderedListIcon';
|
||||
import { HStack } from '../../Stack';
|
||||
import { Text } from '../../Text';
|
||||
|
||||
type OrderedListIconStory = StoryObj<OrderedListIconProps>;
|
||||
|
||||
const meta: Meta<OrderedListIconProps> = {
|
||||
title: 'Atoms/Lists',
|
||||
component: OrderedListIconComponent,
|
||||
decorators: [
|
||||
Story => (
|
||||
<HStack spacing="sp12" alignItems="center">
|
||||
<Story />
|
||||
<Text variant="body">Text value</Text>
|
||||
</HStack>
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const OrderedListIcon: OrderedListIconStory = {
|
||||
name: 'OrderedListIcon',
|
||||
args: {
|
||||
iconNumber: 1,
|
||||
iconBackgroundColor: 'backgroundTertiaryDefaultOnElevation1',
|
||||
iconBorderColor: 'borderElevation0',
|
||||
iconBorderRadius: 'r12',
|
||||
iconColor: 'textDefault',
|
||||
iconSize: 'mediumLarge',
|
||||
},
|
||||
argTypes: {
|
||||
iconNumber: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
iconBackgroundColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
iconBorderColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
iconBorderRadius: {
|
||||
control: { type: 'select' },
|
||||
options: Object.keys(nativeBorders.radii),
|
||||
},
|
||||
iconColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
iconSize: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(ICON_SIZES),
|
||||
},
|
||||
},
|
||||
};
|
||||
36
suite-native/atoms/src/stories/Loader.stories.tsx
Normal file
36
suite-native/atoms/src/stories/Loader.stories.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import { Loader as LoaderComponent, LoaderProps } from '../Loader';
|
||||
|
||||
type LoaderStory = StoryObj<LoaderProps>;
|
||||
|
||||
const meta: Meta<LoaderProps> = {
|
||||
title: 'Atoms',
|
||||
component: LoaderComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Loader: LoaderStory = {
|
||||
name: 'Loader',
|
||||
args: {
|
||||
size: 'large',
|
||||
title: 'Loading...',
|
||||
color: 'backgroundPrimaryDefault',
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
control: { type: 'select' },
|
||||
options: ['small', 'large'],
|
||||
},
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
},
|
||||
};
|
||||
36
suite-native/atoms/src/stories/Pictogram.stories.tsx
Normal file
36
suite-native/atoms/src/stories/Pictogram.stories.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
|
||||
import {
|
||||
PICTOGRAM_VARIANTS,
|
||||
Pictogram as PictogramComponent,
|
||||
PictogramProps,
|
||||
} from '../Pictogram/Pictogram';
|
||||
|
||||
type PictogramStory = StoryObj<PictogramProps>;
|
||||
|
||||
const meta: Meta<PictogramProps> = {
|
||||
title: 'Atoms',
|
||||
component: PictogramComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Pictogram: PictogramStory = {
|
||||
name: 'Pictogram',
|
||||
args: {
|
||||
variant: 'success',
|
||||
icon: undefined,
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: PICTOGRAM_VARIANTS,
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
},
|
||||
};
|
||||
34
suite-native/atoms/src/stories/PriceChangeBadge.stories.tsx
Normal file
34
suite-native/atoms/src/stories/PriceChangeBadge.stories.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { View } from 'react-native';
|
||||
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import {
|
||||
PriceChangeBadge as PriceChangeBadgeComponent,
|
||||
PriceChangeBadgeProps,
|
||||
} from '../PriceChangeBadge';
|
||||
|
||||
type PriceChangeBadgeStory = StoryObj<PriceChangeBadgeProps>;
|
||||
|
||||
const meta: Meta<PriceChangeBadgeProps> = {
|
||||
title: 'Atoms',
|
||||
component: PriceChangeBadgeComponent,
|
||||
render: args => (
|
||||
<View style={{ alignSelf: 'center' }}>
|
||||
<PriceChangeBadgeComponent {...args} />
|
||||
</View>
|
||||
),
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const PriceChangeBadge: PriceChangeBadgeStory = {
|
||||
name: 'PriceChangeBadge',
|
||||
args: {
|
||||
valuePercentageChange: 0.123,
|
||||
},
|
||||
argTypes: {
|
||||
valuePercentageChange: {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
},
|
||||
};
|
||||
49
suite-native/atoms/src/stories/RoundedIcon.stories.tsx
Normal file
49
suite-native/atoms/src/stories/RoundedIcon.stories.tsx
Normal file
@@ -0,0 +1,49 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_SIZES, icons } from '@suite-native/icons';
|
||||
import { COLOR_TOKENS } from '@trezor/theme';
|
||||
|
||||
import { RoundedIcon as RoundedIconComponent, RoundedIconProps } from '../RoundedIcon';
|
||||
|
||||
type RoundedIconStory = StoryObj<RoundedIconProps>;
|
||||
|
||||
const meta: Meta<RoundedIconProps> = {
|
||||
title: 'Atoms',
|
||||
component: RoundedIconComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const RoundedIcon: RoundedIconStory = {
|
||||
name: 'RoundedIcon',
|
||||
args: {
|
||||
name: 'flag',
|
||||
color: 'textPrimaryDefault',
|
||||
iconSize: 'mediumLarge',
|
||||
backgroundColor: 'backgroundTertiaryDefaultOnElevation1',
|
||||
containerSize: 48,
|
||||
},
|
||||
argTypes: {
|
||||
name: {
|
||||
control: { type: 'select' },
|
||||
options: Object.keys(icons),
|
||||
},
|
||||
iconSize: {
|
||||
control: { type: 'select' },
|
||||
options: Object.values(ICON_SIZES),
|
||||
},
|
||||
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
|
||||
backgroundColor: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
symbol: {
|
||||
control: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
41
suite-native/atoms/src/stories/Text.stories.tsx
Normal file
41
suite-native/atoms/src/stories/Text.stories.tsx
Normal file
@@ -0,0 +1,41 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { COLOR_TOKENS, nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import { Text as TextComponent, TextProps } from '../Text';
|
||||
|
||||
type TextStory = StoryObj<TextProps>;
|
||||
|
||||
const meta: Meta<TextProps> = {
|
||||
title: 'Atoms',
|
||||
component: TextComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const Text: TextStory = {
|
||||
name: 'Text',
|
||||
args: {
|
||||
children: 'Text value',
|
||||
variant: 'body',
|
||||
color: 'textDefault',
|
||||
textAlign: 'left',
|
||||
},
|
||||
argTypes: {
|
||||
children: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
textAlign: {
|
||||
control: { type: 'select' },
|
||||
options: ['left', 'center', 'right'],
|
||||
},
|
||||
color: {
|
||||
control: { type: 'select' },
|
||||
options: COLOR_TOKENS,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { ICON_NAMES } from '@suite-native/icons';
|
||||
import { nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import { PICTOGRAM_VARIANTS } from '../../Pictogram/Pictogram';
|
||||
import {
|
||||
PictogramTitleHeader as PictogramTitleHeaderComponent,
|
||||
PictogramTitleHeaderProps,
|
||||
} from '../../TitleHeader/PictogramTitleHeader';
|
||||
|
||||
type PictogramTitleHeaderStory = StoryObj<PictogramTitleHeaderProps>;
|
||||
|
||||
const meta: Meta<PictogramTitleHeaderProps> = {
|
||||
title: 'Atoms/TitleHeaders',
|
||||
component: PictogramTitleHeaderComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const PictogramTitleHeader: PictogramTitleHeaderStory = {
|
||||
name: 'PictogramTitleHeader',
|
||||
args: {
|
||||
variant: 'success',
|
||||
icon: undefined,
|
||||
title: 'Title message',
|
||||
subtitle: 'Something longer to say that has secondary informative value.',
|
||||
titleVariant: 'titleSmall',
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
control: { type: 'select' },
|
||||
options: PICTOGRAM_VARIANTS,
|
||||
},
|
||||
icon: {
|
||||
control: { type: 'select' },
|
||||
options: ICON_NAMES,
|
||||
},
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
titleVariant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react-native';
|
||||
|
||||
import { nativeSpacings, nativeTypographyStyles } from '@trezor/theme';
|
||||
|
||||
import {
|
||||
TitleHeader as TitleHeaderComponent,
|
||||
TitleHeaderProps,
|
||||
} from '../../TitleHeader/TitleHeader';
|
||||
|
||||
type TitleHeaderStory = StoryObj<TitleHeaderProps>;
|
||||
|
||||
const meta: Meta<TitleHeaderProps> = {
|
||||
title: 'Atoms/TitleHeaders',
|
||||
component: TitleHeaderComponent,
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
export const TitleHeader: TitleHeaderStory = {
|
||||
name: 'TitleHeader',
|
||||
args: {
|
||||
title: 'Title message',
|
||||
subtitle: 'Something longer to say that has secondary informative value.',
|
||||
titleVariant: 'titleSmall',
|
||||
textAlign: 'left',
|
||||
titleSpacing: 'sp8',
|
||||
},
|
||||
argTypes: {
|
||||
title: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
subtitle: {
|
||||
control: { type: 'text' },
|
||||
},
|
||||
titleVariant: {
|
||||
control: { type: 'select' },
|
||||
options: nativeTypographyStyles,
|
||||
},
|
||||
textAlign: {
|
||||
control: { type: 'select' },
|
||||
options: ['left', 'center'],
|
||||
},
|
||||
titleSpacing: {
|
||||
control: { type: 'select' },
|
||||
options: Object.keys(nativeSpacings),
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -7,4 +7,5 @@ export type TestProps = {
|
||||
['testID']?: string;
|
||||
};
|
||||
|
||||
export type SurfaceElevation = '0' | '1';
|
||||
export const SURFACE_ELEVATIONS = ['0', '1'] as const;
|
||||
export type SurfaceElevation = (typeof SURFACE_ELEVATIONS)[number];
|
||||
|
||||
@@ -32,6 +32,7 @@ export const iconSizes = {
|
||||
extraLarge: 32,
|
||||
} as const;
|
||||
|
||||
export const ICON_SIZES = Object.keys(iconSizes) as IconSize[];
|
||||
export type IconSize = keyof typeof iconSizes;
|
||||
|
||||
export const getIconSize = (size: IconSize | number) =>
|
||||
|
||||
@@ -3,7 +3,6 @@ import { INITIAL_VIEWPORTS } from 'storybook/viewport';
|
||||
|
||||
import { SHARED_DECORATORS } from '../decorators/decorators';
|
||||
|
||||
|
||||
import './fonts.css';
|
||||
|
||||
const preview: Preview = {
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import { intlDecorator } from './intlDecorator';
|
||||
import { themeDecorator } from './themeDecorator';
|
||||
|
||||
export const SHARED_DECORATORS = [
|
||||
intlDecorator,
|
||||
themeDecorator,
|
||||
] as const;
|
||||
export const SHARED_DECORATORS = [intlDecorator, themeDecorator] as const;
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import React from 'react';
|
||||
import { IntlProvider as ReactIntlProvider } from 'react-intl';
|
||||
|
||||
import { StoryContext } from '@storybook/react';
|
||||
|
||||
import enMessages from '@suite-native/intl/translations/en-US.json';
|
||||
|
||||
export const intlDecorator = (Story: React.FC, context: StoryContext) => (
|
||||
<ReactIntlProvider locale="en-US" messages={enMessages}>
|
||||
<Story />
|
||||
</ReactIntlProvider>
|
||||
);
|
||||
export const intlDecorator = (Story: React.FC) => (
|
||||
<ReactIntlProvider locale="en-US" messages={enMessages}>
|
||||
<Story />
|
||||
</ReactIntlProvider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user