Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix/hint position #3469

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions demo/src/screens/componentScreens/HintsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type HintScreenProps = {};
export default class HintsScreen extends Component<HintScreenProps> {
state = {
showHint: true,
showSecondHint: false,
useShortMessage: false,
showBottomHint: false,
showIcon: false,
Expand All @@ -28,6 +29,10 @@ export default class HintsScreen extends Component<HintScreenProps> {
this.setState({showHint: !this.state.showHint});
};

toggleSecondHint = () => {
this.setState({showSecondHint: !this.state.showSecondHint});
};

toggleHintPosition = () => {
this.setState({
showBottomHint: !this.state.showBottomHint
Expand Down Expand Up @@ -118,6 +123,7 @@ export default class HintsScreen extends Component<HintScreenProps> {
render() {
const {
showHint,
showSecondHint,
showBottomHint,
showIcon,
targetPosition,
Expand Down Expand Up @@ -215,6 +221,20 @@ export default class HintsScreen extends Component<HintScreenProps> {
</View>
</>
)}

<View marginT-100 row center>
{targetPosition !== 'flex-start' && <Text marginH-s3>Text pushing button</Text>}
<Hint
message={'Hint'}
visible={showSecondHint}
onBackgroundPress={this.toggleSecondHint}
useSideTip={false}

>
<Button label="Button" onPress={this.toggleSecondHint}/>
</Hint>
{targetPosition === 'flex-start' && <Text marginH-s3>Text pushing button</Text>}
</View>
</View>

{this.renderOptionsFAB()}
Expand Down
68 changes: 55 additions & 13 deletions src/components/hint/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const middleTip = require('./assets/hintTipMiddle.png');
const DEFAULT_COLOR = Colors.$backgroundPrimaryHeavy;
const DEFAULT_HINT_OFFSET = Spacings.s4;
const DEFAULT_EDGE_MARGINS = Spacings.s5;
const HINT_MIN_WIDTH = 68;

enum TARGET_POSITIONS {
LEFT = 'left',
Expand Down Expand Up @@ -153,6 +154,7 @@ interface HintState {
targetLayout?: HintTargetFrame;
targetLayoutInWindow?: HintTargetFrame;
hintUnmounted: boolean;
hintMessageWidth?: number;
}

/**
Expand All @@ -178,7 +180,8 @@ class Hint extends Component<HintProps, HintState> {
state = {
targetLayoutInWindow: undefined as {x: number; y: number; width: number; height: number} | undefined,
targetLayout: this.props.targetFrame,
hintUnmounted: !this.props.visible
hintUnmounted: !this.props.visible,
hintMessageWidth: undefined
};

visibleAnimated = new Animated.Value(Number(!!this.props.visible));
Expand Down Expand Up @@ -222,6 +225,12 @@ class Hint extends Component<HintProps, HintState> {
this.focusAccessibilityOnHint();
};

setHintLayout = ({nativeEvent: {layout}}: LayoutChangeEvent) => {
if (!this.state.hintMessageWidth) {
this.setState({hintMessageWidth: layout.width});
}
};

onTargetLayout = ({nativeEvent: {layout}}: LayoutChangeEvent) => {
if (!_.isEqual(this.state.targetLayout, layout)) {
this.setState({targetLayout: layout});
Expand Down Expand Up @@ -278,7 +287,7 @@ class Hint extends Component<HintProps, HintState> {
}

get edgeMargins() {
const {edgeMargins = DEFAULT_EDGE_MARGINS} = this.props;
const {edgeMargins = this.isUsingModal() ? DEFAULT_EDGE_MARGINS : 0} = this.props;
return edgeMargins;
}

Expand All @@ -292,17 +301,21 @@ class Hint extends Component<HintProps, HintState> {
return this.getTargetPositionOnScreen() !== TARGET_POSITIONS.CENTER;
}

get isShortMessage() {
const {hintMessageWidth} = this.state;
return hintMessageWidth && hintMessageWidth < Constants.screenWidth / 2;
}

getTargetPositionOnScreen() {
if (this.targetLayout?.x !== undefined && this.targetLayout?.width) {
const targetMidPosition = this.targetLayout.x + this.targetLayout.width / 2;

if (targetMidPosition > this.containerWidth * (2 / 3)) {
if (targetMidPosition > this.containerWidth * (4 / 5)) {
return TARGET_POSITIONS.RIGHT;
} else if (targetMidPosition < this.containerWidth * (1 / 3)) {
} else if (targetMidPosition < this.containerWidth * (1 / 5)) {
return TARGET_POSITIONS.LEFT;
}
}

return TARGET_POSITIONS.CENTER;
}

Expand Down Expand Up @@ -405,6 +418,29 @@ class Hint extends Component<HintProps, HintState> {
return tipPositionStyle;
}

getHintOffsetForShortMessage = () => {
const {hintMessageWidth = 0} = this.state;

let hintMessageOffset = 0;
if (this.isShortMessage) {
const targetPosition = this.getTipPosition();
if (targetPosition?.right) {
hintMessageOffset = -targetPosition?.right + hintMessageWidth / 2;
}

if (targetPosition?.left) {
hintMessageOffset = targetPosition?.left as number;
if (this.getTargetPositionOnScreen() === TARGET_POSITIONS.CENTER) {
hintMessageOffset -= Constants.screenWidth / 2;
} else {
hintMessageOffset -= hintMessageWidth / 2;
}
}
}

return hintMessageOffset;
};

isUsingModal = () => {
const {onBackgroundPress, useModal} = this.props;
return onBackgroundPress && useModal;
Expand Down Expand Up @@ -451,7 +487,7 @@ class Hint extends Component<HintProps, HintState> {
return <Image tintColor={color} source={source} style={[styles.hintTip, this.getTipPosition(), flipStyle]}/>;
}

renderContent() {
renderHint() {
const {
message,
messageStyle,
Expand All @@ -466,18 +502,23 @@ class Hint extends Component<HintProps, HintState> {
testID
} = this.props;

const hintMessageOffset = this.getHintOffsetForShortMessage();

return (
<View
testID={`${testID}.message`}
row
centerV
centerH={!!hintMessageOffset}
style={[
styles.hint,
!removePaddings && styles.hintPaddings,
visible && enableShadow && styles.containerShadow,
{backgroundColor: color},
!_.isUndefined(borderRadius) && {borderRadius}
!_.isUndefined(borderRadius) && {borderRadius},
hintMessageOffset ? {left: hintMessageOffset} : undefined
]}
onLayout={this.setHintLayout}
ref={this.hintRef}
>
{customContent}
Expand All @@ -491,7 +532,7 @@ class Hint extends Component<HintProps, HintState> {
);
}

renderHint() {
renderHintContainer() {
const {onPress, testID} = this.props;
const opacity = onPress ? 0.9 : 1.0;

Expand All @@ -510,15 +551,15 @@ class Hint extends Component<HintProps, HintState> {
testID={testID}
>
<TouchableOpacity activeOpacity={opacity} onPress={onPress}>
{this.renderContent()}
{this.renderHint()}
</TouchableOpacity>
{this.renderHintTip()}
</View>
);
}
}

renderHintContainer() {
renderHintAnchor() {
const {style, ...others} = this.props;
return (
<View
Expand All @@ -528,7 +569,7 @@ class Hint extends Component<HintProps, HintState> {
testID={undefined}
style={[styles.container, style, this.getContainerPosition(), !this.isUsingModal() && styles.overlayContainer]}
>
{this.renderHint()}
{this.renderHintContainer()}
</View>
);
}
Expand Down Expand Up @@ -592,13 +633,13 @@ class Hint extends Component<HintProps, HintState> {
testID={`${testID}.modal`}
>
{this.renderMockChildren()}
{this.renderHintContainer()}
{this.renderHintAnchor()}
</Modal>
) : (
<>
{this.renderOverlay()}
{this.renderMockChildren()}
{this.renderHintContainer()}
{this.renderHintAnchor()}
</>
)}
</>
Expand Down Expand Up @@ -644,6 +685,7 @@ const styles = StyleSheet.create({
position: 'absolute'
},
hint: {
minWidth: HINT_MIN_WIDTH,
maxWidth: Math.min(Constants.windowWidth - 2 * Spacings.s4, 400),
borderRadius: BorderRadiuses.br60,
backgroundColor: DEFAULT_COLOR
Expand Down