0

I'm currently creating a React App using the Atomic Design methodology. I'm implementing a series of molecules to define a list row.

I currently have this IconTextItem that implements an IconItem

import { Icon, IconProps } from '@components/icon';
import {
    TopBottomText,
    TopBottomTextProps,
} from '@ds/molecules/Text/TopBottomText';
import type { FunctionComponent } from 'react';
import React from 'react';
import { IconItem, IconItemProps } from '../IconItem';

export type IconTextItemProps = {
    icon: IconProps;
    onPress?(): void;
    middleText?: TopBottomTextProps;
    endText?: TopBottomTextProps;
    endIcon?: IconProps;
    containerStyle?: IconItemProps['containerStyle'];
};

export const IconTextItem: FunctionComponent<IconTextItemProps> = props => {
    const { icon, middleText, endText, endIcon } = props;
    return (
        <IconItem
            containerStyle={props.containerStyle}
            onPress={props.onPress}
            icon={icon}
            middle={<TopBottomText {...middleText} />}
            right={
                <>
                    {endText && <TopBottomText {...endText} />}
                    {endIcon && <Icon {...endIcon} />}
                </>
            }
        />
    );
};

This is the IconItem component:

import React from 'react';
import { Icon, IconProps } from '@components/icon';
import type { FunctionComponent } from 'react';
import { BaseItem, BaseItemProps } from '../BaseItem';

export type IconItemProps = {
    icon: IconProps;
    onPress?(): void;
    middle?: JSX.Element;
    right?: JSX.Element;
    containerStyle?: BaseItemProps['containerStyle'];
};

export const IconItem: FunctionComponent<IconItemProps> = props => {
    const { icon, ...otherProps } = props;
    return <BaseItem left={<Icon {...icon} />} {...otherProps} />;
};

Here's the BaseItem

import { Touchable } from '@components/buttons';
import { Flex, FlexProps } from '@ds/molecules/Layouts/utilities/Flex';
import type { FunctionComponent } from 'react';
import React from 'react';

export type BaseItemProps = {
    onPress?(): void;
    left?: JSX.Element;
    middle?: JSX.Element;
    right?: JSX.Element;
    containerStyle?: FlexProps['style'];
};

export const BaseItem: FunctionComponent<BaseItemProps> = props => {
    const { left, middle, right, onPress, containerStyle } = props;
    const main = (
        <Flex flexDirection="row" alignItems="center" style={containerStyle}>
            {left && (
                <Flex justifySelf="flex-left" mr="3x">
                    {left}
                </Flex>
            )}
            {middle && (
                <Flex justifySelf="flex-left" style={{ flex: 1 }}>
                    {middle}
                </Flex>
            )}
            {right && (
                <Flex style={{ alignItems: 'flex-end', flex: 1 }}>{right}</Flex>
            )}
        </Flex>
    );

    if (onPress) {
        return <Touchable onPress={onPress}>{main}</Touchable>;
    }

    return main;
};

Now, I want to implement a variant of the IconTextItem that will hold its icon property as optional.

The problem is that both: IconItem and IconTextItem enforces the icon property to be passed as required.

I don't think that lexing the requirement at the property will be a good idea, as I want it to be present for those cases.

This makes me think of the following two approaches:

  1. Create an optional OptionalIconItem (need a better name) that will hold the icon as optional, and then wrap another component that passes the icon as required.

  2. Create a variant: one optional and the other required, leaving me the approach on #1 but everything is defined in a single component.

Which approach should I take, or is there a better way to approach this problem?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.