Skip to content

Commit 8ae3799

Browse files
committed
feat(*): improve docs and refactor
1 parent 7b8d41e commit 8ae3799

10 files changed

Lines changed: 219 additions & 1270 deletions

File tree

docs/CustomizeTheme.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ import { ThemeProvider } from 'paramount-ui'
4343

4444
## Components
4545

46-
In the same `ThemeProvider` as above, use `components` option. For available style options for each component, see `getStyles` callback in corresponding component docs
46+
In the same `ThemeProvider` as above, use `components` option. See `Customization` section in corresponding component docs
4747

4848
```
4949
import { ThemeProvider } from 'paramount-ui'
@@ -91,7 +91,7 @@ import { ThemeProvider } from 'paramount-ui'
9191

9292
## Component Instance
9393

94-
Each component exposes `getStyles` callback, which can be used to override component styles. This prop takes highest precedence in styling a component
94+
Each component exposes `getStyles` callback, which can be used to override component styles. See `Customization` section in corresponding component docs
9595

9696
```
9797
import { Button } from 'paramount-ui'

src/components/Alert/Alert.mdx

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,34 +13,39 @@ Give feedback to the user about an action or state
1313
### Usage
1414

1515
<Playground>
16-
<Alert
17-
title="Title"
18-
description="Message"
19-
intent="success"
20-
getStyles={(props, theme) => ({
21-
bodyStyle: {},
22-
containerStyle: {},
23-
})}
24-
/>
25-
</Playground>
26-
27-
### Variants
28-
29-
<Playground>
30-
<Box paddingVertical={16}>
16+
<Box paddingVertical={8}>
3117
<Alert title="Info" description="Message" />
3218
</Box>
33-
<Box paddingVertical={16}>
19+
<Box paddingVertical={8}>
3420
<Alert intent="success" title="Success" description="Message" />
3521
</Box>
36-
<Box paddingVertical={16}>
22+
<Box paddingVertical={8}>
3723
<Alert intent="warning" title="Warning" description="Message" />
3824
</Box>
39-
<Box paddingVertical={16}>
25+
<Box paddingVertical={8}>
4026
<Alert intent="danger" title="Danger" description="Message" />
4127
</Box>
4228
</Playground>
4329

30+
### Customization
31+
32+
Use `getStyles` prop
33+
34+
```
35+
AlertStyleProps {
36+
intent: Intent;
37+
}
38+
39+
AlertStyles {
40+
containerStyle: ViewStyle;
41+
bodyStyle: ViewStyle;
42+
titleStyle: TextStyle;
43+
descriptionStyle: TextStyle;
44+
}
45+
46+
getStyles={(AlertStyleProps, Theme) => AlertStyles}
47+
```
48+
4449
### Props
4550

4651
<Props of={Alert} />

src/components/Alert/Alert.styles.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export interface AlertStyles {
77
containerStyle: ViewStyle;
88
bodyStyle: ViewStyle;
99
titleStyle: TextStyle;
10-
textStyle: TextStyle;
10+
descriptionStyle: TextStyle;
1111
}
1212

1313
export interface AlertStyleProps {
@@ -34,7 +34,7 @@ export const getAlertStyles: GetAlertStyles = ({ intent }, theme) => {
3434
padding: 16,
3535
...theme.elevations[2],
3636
},
37-
textStyle: {},
37+
descriptionStyle: {},
3838
titleStyle: {},
3939
};
4040
};

src/components/Alert/Alert.tsx

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,21 @@ import { AlertStyles, GetAlertStyles, getAlertStyles } from './Alert.styles';
1414
* Alert properties
1515
*/
1616
export interface AlertProps {
17-
/** Title of the alert */
17+
/** Title of the alert. */
1818
title?: string;
19-
/** Description of the alert */
19+
/** Description of the alert. */
2020
description?: string;
21-
/** Used to locate this view in end-to-end tests */
22-
testID?: string;
23-
/** Replace the icon of the alert on the left */
21+
/** Replace the icon of the alert on the left. Set to null to remove icon */
2422
icon?: React.ReactNode;
2523
/**
26-
* Intent of the alert
24+
* Intent of the alert.
2725
* @default info
2826
*/
2927
intent?: Intent;
30-
31-
/** Callback to get element styles */
28+
/** Callback to get element styles. */
3229
getStyles?: ReplaceReturnType<GetAlertStyles, DeepPartial<AlertStyles>>;
30+
/** Used to locate this view in end-to-end tests. */
31+
testID?: string;
3332
}
3433

3534
const resolveIcon = (intent: Intent) => {
@@ -60,22 +59,32 @@ export const Alert = (props: AlertProps) => {
6059

6160
const theme = useTheme();
6261

63-
const { containerStyle, bodyStyle } = mergeStyles(
64-
getAlertStyles,
65-
getStyles,
66-
theme.components.getAlertStyles,
67-
)({ intent }, theme);
62+
const {
63+
containerStyle,
64+
bodyStyle,
65+
descriptionStyle,
66+
titleStyle,
67+
} = mergeStyles(getAlertStyles, getStyles, theme.components.getAlertStyles)(
68+
{ intent },
69+
theme,
70+
);
6871

6972
return (
7073
<View style={containerStyle} testID={testID}>
71-
{icon || (
72-
<Box paddingRight={16} justifyContent="center">
73-
{resolveIcon(intent)}
74-
</Box>
75-
)}
74+
{icon === null
75+
? null
76+
: icon || (
77+
<Box paddingRight={16} justifyContent="center">
78+
{resolveIcon(intent)}
79+
</Box>
80+
)}
7681
<View style={bodyStyle}>
77-
<Text weight="bold">{title}</Text>
78-
<Text>{description}</Text>
82+
<Text getStyles={() => ({ textStyle: titleStyle })} weight="bold">
83+
{title}
84+
</Text>
85+
<Text getStyles={() => ({ textStyle: descriptionStyle })}>
86+
{description}
87+
</Text>
7988
</View>
8089
</View>
8190
);

src/components/Avatar/Avatar.mdx

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,43 @@ menu: Components
44
---
55

66
import { Playground, Props } from 'docz';
7-
import { Avatar } from '..';
7+
import { Avatar, Box } from '..';
88

99
# Avatar
1010

11+
Display avatar image, with default for name initials
12+
1113
### Usage
1214

1315
<Playground>
1416
<Avatar
17+
source={{ uri: 'https://picsum.photos/100/100', width: 100, height: 100 }}
18+
// Defaults to name if source is not provided
1519
name="Bill Gates"
16-
source={{ uri: 'https://picsum.photos/200/200' }}
17-
size={40}
18-
isSolid={false}
19-
color="automatic"
20-
getInitials={(name, fallback) =>
21-
name ? `${name.charAt(0)}${name.charAt(5)}` : 'A'
22-
}
23-
getStyles={(props, theme) => ({
24-
boxStyle: {},
25-
textStyle: {},
26-
imageStyle: {},
27-
})}
2820
/>
2921
</Playground>
3022

31-
### Automatic name usage
23+
### Customization
3224

33-
<Playground>
34-
<Avatar name="Bill Gates" />
35-
</Playground>
25+
Using `getStyles` prop
26+
27+
```
28+
AvatarStylesProps {
29+
name?: string;
30+
color: AvatarColor;
31+
isSolid: boolean;
32+
size: number;
33+
sizeLimitOneCharacter: number;
34+
}
35+
36+
AvatarStyles {
37+
containerStyle: ViewStyle;
38+
textStyle: TextStyle;
39+
imageStyle: ImageStyle;
40+
}
41+
42+
getStyles={(AvatarStylesProps, Theme) => AvatarStyles}
43+
```
3644

3745
### Props
3846

src/components/Avatar/Avatar.styles.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export type AvatarColor = 'automatic' | keyof FillColors;
2323
export interface AvatarStylesProps {
2424
name?: string;
2525
color: AvatarColor;
26-
hashValue?: string;
2726
isSolid: boolean;
2827
size: number;
2928
sizeLimitOneCharacter: number;
@@ -74,13 +73,13 @@ export type GetAvatarStyles = (
7473
) => AvatarStyles;
7574

7675
export const getAvatarStyles: GetAvatarStyles = (
77-
{ name, color, hashValue, isSolid, size = 24, sizeLimitOneCharacter = 20 },
76+
{ name, color, isSolid, size = 24, sizeLimitOneCharacter = 20 },
7877
theme,
7978
) => {
8079
let colorProps;
8180
const fills = theme.fills;
8281
if (color === 'automatic') {
83-
const newHashValue = hashCode(hashValue || name);
82+
const newHashValue = hashCode(name);
8483
colorProps = getAvatarProps(theme.fills, {
8584
color,
8685
hashValue: newHashValue,

src/components/Avatar/Avatar.tsx

Lines changed: 22 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { Image, ImageSourcePropType, View } from 'react-native';
33
import { DeepPartial } from 'ts-essentials';
44

55
import { useTheme } from '../../theme';
6-
import { FillColors } from '../../theme/Theme';
6+
import { FillColor } from '../../theme/Theme';
77
import { mergeStyles, ReplaceReturnType } from '../../utils/mergeStyles';
88
import { Text } from '../Typography';
99
import {
@@ -15,7 +15,7 @@ import {
1515
// https://github.com/segmentio/evergreen/blob/master/source/avatar/README.md
1616
export type GetInitialsType = (name?: string, fallback?: string) => string;
1717

18-
const globalGetInitials: GetInitialsType = (name, fallback = '?') => {
18+
const getInitials: GetInitialsType = (name, fallback = '?') => {
1919
if (!name) return fallback;
2020

2121
return name
@@ -27,58 +27,34 @@ const globalGetInitials: GetInitialsType = (name, fallback = '?') => {
2727
};
2828

2929
export interface AvatarProps {
30-
/**
31-
* The source attribute of the image.
32-
* When it's not available, render initials instead.
33-
*/
30+
/** The source attribute of the image. When it's not available, render initials instead. */
3431
source?: ImageSourcePropType;
35-
36-
/**
37-
* The size of the avatar.
38-
*/
32+
/** The size of the avatar. */
3933
size?: number;
40-
4134
/**
4235
* The name used for the initials and title attribute.
36+
* @default 48
4337
*/
4438
name?: string;
45-
46-
/**
47-
* The value used for the hash function.
48-
* The name is used as the hashValue by default.
49-
* When dealing with anonymous users you should use the id instead.
50-
*/
51-
hashValue?: string;
52-
5339
/**
5440
* When true, render a solid avatar.
41+
* @default false
5542
*/
5643
isSolid?: boolean;
57-
5844
/**
5945
* The color used for the avatar.
6046
* When the value is `automatic`, use the hash function to determine the color.
47+
* @default automatic
6148
*/
62-
color?: 'automatic' | keyof FillColors;
63-
64-
/**
65-
* Function to get the initials based on the name.
66-
*/
67-
getInitials?: GetInitialsType;
68-
69-
/**
70-
* When true, force show the initials.
71-
* This is useful in some cases when using Gravatar and transparent pngs.
72-
*/
73-
forceShowInitials?: boolean;
74-
49+
color?: 'automatic' | FillColor;
7550
/**
7651
* When the size is smaller than this number, use a single initial for the avatar.
52+
* @default 20
7753
*/
7854
sizeLimitOneCharacter?: number;
79-
55+
/** Callback to get element styles. */
8056
getStyles?: ReplaceReturnType<GetAvatarStyles, DeepPartial<AvatarStyles>>;
81-
57+
/** Used to locate this view in end-to-end tests. */
8258
testID?: string;
8359
}
8460

@@ -88,19 +64,18 @@ export const Avatar = (props: AvatarProps) => {
8864
size = 48,
8965
name,
9066
isSolid = false,
91-
hashValue,
92-
getInitials = globalGetInitials,
9367
color = 'automatic',
94-
forceShowInitials = false,
9568
sizeLimitOneCharacter = 20,
9669
getStyles,
9770
testID,
9871
} = props;
9972

10073
const theme = useTheme();
10174

102-
const { imageHasFailedLoading } = { imageHasFailedLoading: false };
103-
const imageUnavailable = !source || imageHasFailedLoading;
75+
const [hasImageFailedLoading, setHasImageFailedLoading] = React.useState(
76+
false,
77+
);
78+
const imageUnavailable = !source || hasImageFailedLoading;
10479

10580
let initials = getInitials(name);
10681
if (size <= sizeLimitOneCharacter) {
@@ -114,7 +89,6 @@ export const Avatar = (props: AvatarProps) => {
11489
)(
11590
{
11691
color,
117-
hashValue,
11892
isSolid,
11993
name,
12094
size,
@@ -125,17 +99,15 @@ export const Avatar = (props: AvatarProps) => {
12599

126100
return (
127101
<View style={containerStyle} testID={testID}>
128-
{(imageUnavailable || forceShowInitials) && (
129-
<Text
130-
getStyles={() => ({
131-
textStyle,
132-
})}
133-
>
134-
{initials}
135-
</Text>
102+
{imageUnavailable && (
103+
<Text getStyles={() => ({ textStyle })}>{initials}</Text>
136104
)}
137105
{!imageUnavailable && !!source && (
138-
<Image source={source} style={imageStyle} />
106+
<Image
107+
onError={() => setHasImageFailedLoading(true)}
108+
source={source}
109+
style={imageStyle}
110+
/>
139111
)}
140112
</View>
141113
);

0 commit comments

Comments
 (0)