Skip to content

GridListItem - horizontal alignment support #3001

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

Merged
merged 10 commits into from
Apr 9, 2024
Merged
6 changes: 6 additions & 0 deletions src/components/gridListItem/gridListItem.api.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@
"description": "Custom container styling for inline text"
},
{"name": "alignToStart", "type": "boolean", "description": "Should content be align to start", "default": "center"},
{
"name": "horizontalAlignment",
"type": "ItemHorizontalAlignmentProp",
"description": "Content horizontal alignment (default is center)",
"default": "center"
},
{"name": "containerStyle", "type": "ViewStyle", "description": "Custom container style"},
{"name": "onPress", "type": "TouchableOpacityProps['onPress']", "description": "The item's action handler"},
{
Expand Down
66 changes: 60 additions & 6 deletions src/components/gridListItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import _ from 'lodash';
import React, {Component} from 'react';
import {StyleProp, StyleSheet, ViewStyle} from 'react-native';
import memoize from 'memoize-one';
import * as Modifiers from '../../commons/modifiers';
import {Colors, Spacings, Typography} from 'style';
import View, {ViewProps} from '../view';
import TouchableOpacity, {TouchableOpacityProps} from '../touchableOpacity';
import Text from '../text';
import Image, {ImageProps} from '../image';

export enum ItemHorizontalAlignment {
left = 'left',
center = 'center',
right = 'right'
}

export type ItemHorizontalAlignmentProp = ItemHorizontalAlignment | `${ItemHorizontalAlignment}`;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good name...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I don't see why we need to declare this type


export interface GridListItemProps {
/**
* Image props object for rendering an image item
Expand Down Expand Up @@ -85,6 +94,10 @@ export interface GridListItemProps {
* Should content be align to start (default is center)
*/
alignToStart?: boolean;
/**
* Content horizontal alignment (default is center)
*/
horizontalAlignment?: ItemHorizontalAlignmentProp;
Copy link
Collaborator

@Inbal-Tish Inbal-Tish Mar 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this prop? Why the user can't just pass 'alignItems' in the containerStyle prop, and 'textAlign' in the style prop?

/**
* Custom container style
*/
Expand Down Expand Up @@ -121,7 +134,8 @@ class GridListItem extends Component<GridListItemProps> {
static displayName = 'GridListItem';

static defaultProps = {
itemSize: 48
itemSize: 48,
horizontalAlignment: ItemHorizontalAlignment.center
};

state = {};
Expand All @@ -139,14 +153,33 @@ class GridListItem extends Component<GridListItemProps> {
return {width: itemSize as number, height: itemSize as number};
}

getHorizontalAlignmentStyle = memoize(horizontalAlignment => {
switch (horizontalAlignment) {
case ItemHorizontalAlignment.left:
return {contentStyle: styles.contentAlignedToStart, containerStyle: styles.containerAlignedToStart};
case ItemHorizontalAlignment.right:
return {contentStyle: styles.contentAlignedToEnd, containerStyle: styles.containerAlignedToEnd};
default:
return {contentStyle: styles.contentAlignedToCenter, containerStyle: styles.containerAlignedToCenter};
}
});

renderContent({text, typography, color, numberOfLines = 1, style, testID}: RenderContentType) {
const {alignToStart} = this.props;
const {alignToStart, horizontalAlignment} = this.props;
const horizontalAlignmentStyle = this.getHorizontalAlignmentStyle(horizontalAlignment);
if (text) {
return (
<Text
testID={testID}
// @ts-ignore
style={[style, Typography[typography], color && {color}, alignToStart && styles.contentAlignedToStart]}
style={[
style,
//@ts-ignore
Typography[typography],
color && {color},
alignToStart && styles.contentAlignedToStart,
horizontalAlignmentStyle.contentStyle
]}
numberOfLines={numberOfLines}
>
{text}
Expand All @@ -160,6 +193,7 @@ class GridListItem extends Component<GridListItemProps> {
testID,
imageProps,
alignToStart,
horizontalAlignment,
containerStyle,
containerProps = {},
renderCustomItem,
Expand Down Expand Up @@ -190,22 +224,30 @@ class GridListItem extends Component<GridListItemProps> {
const textContainerStyle = overlayText ? {style: [styles.overlayText, overlayTextContainerStyle]} : null;
const imageBorderRadius = imageProps?.borderRadius;
const {hitSlop, ...otherContainerProps} = containerProps; // eslint-disable-line
const horizontalAlignmentStyle = this.getHorizontalAlignmentStyle(horizontalAlignment);

return (
<Container
style={[styles.container, alignToStart && styles.containerAlignedToStart, {width}, containerStyle]}
style={[
styles.container,
alignToStart ? styles.containerAlignedToStart : horizontalAlignmentStyle.containerStyle,
{width},
containerStyle
]}
{...otherContainerProps}
onPress={hasPress ? this.onItemPress : undefined}
accessible={renderCustomItem ? true : undefined}
{...Modifiers.extractAccessibilityProps(this.props)}
>
{imageProps && (
<View style={[{borderRadius: imageBorderRadius}, imageStyle]}>
<View style={[{borderRadius: imageBorderRadius}, horizontalAlignmentStyle.containerStyle, imageStyle]}>
<Image {...imageProps} style={[imageStyle, imageProps?.style]}/>
{children}
</View>
)}
{!_.isNil(renderCustomItem) && <View style={{width}}>{renderCustomItem()}</View>}
{!_.isNil(renderCustomItem) && (
<View style={[horizontalAlignmentStyle.containerStyle, {width}]}>{renderCustomItem()}</View>
)}
{hasOverlay && <View style={[styles.overlay, this.getItemSizeObj()]}>{renderOverlay?.()}</View>}
<TextContainer {...textContainerStyle}>
{this.renderContent({
Expand Down Expand Up @@ -246,6 +288,12 @@ const styles = StyleSheet.create({
containerAlignedToStart: {
alignItems: 'flex-start'
},
containerAlignedToCenter: {
alignItems: 'center'
},
containerAlignedToEnd: {
alignItems: 'flex-end'
},
title: {
marginTop: Spacings.s1,
textAlign: 'center',
Expand All @@ -262,6 +310,12 @@ const styles = StyleSheet.create({
contentAlignedToStart: {
textAlign: 'left'
},
contentAlignedToCenter: {
textAlign: 'center'
},
contentAlignedToEnd: {
textAlign: 'right'
},
overlay: {
position: 'absolute',
left: 0,
Expand Down