Skip to main content
Unlisted page
This page is unlisted. Search engines will not index it, and only users having a direct link can access it.

This component is an example of Atomic Design composition. The Button molecule is built from smaller atoms (Icon and Label) and receives its behavior and appearance through props.

Imports

import type { ButtonInterface } from './Button.interface'

Imports the TypeScript interface that defines the props the component accepts.

import { ButtonSizes, ButtonTypes, IconSizes, LabelTypes } from '@/components/_types_'

Imports enums that provide predefined values for button types, sizes, icon sizes, and label types. Using enums prevents invalid values and improves consistency.

import { Icon, Label } from '@/components/atoms'

Imports two atomic components used to build the button.


Component Definition

const Button = ({ testID, type, size, icon, text, action, disabled }: ButtonInterface) => {

The component receives its properties through destructuring.

Example:

<Button
text="Save"
icon="save"
type={ButtonTypes.PRIMARY}
size={ButtonSizes.MEDIUM}
action={saveData}
/>

Event Handler

const __handleAction = () => action && action()

Executes the supplied callback if it exists.

Equivalent to:

if (action) {
action()
}

When the button is clicked, this function triggers the action.


Rendering the Icon

const __renderIcon = () => icon && <Icon icon={icon} />

Conditionally renders an icon.

If:

icon="save"

it produces:

<Icon icon="save" />

If no icon is provided, nothing is rendered.


Rendering the Text

const __renderText = () => text && <Label text={text} type={LabelTypes.BUTTON} />

Conditionally renders a label.

If:

text="Save"

it produces:

<Label text="Save" type={LabelTypes.BUTTON} />

This keeps text styling centralized inside the Label atom.


Rendering the "Next" Arrow

const __renderNext = () => {
if (type === ButtonTypes.NEXT) {
return <Icon icon={'arrowRight'} size={IconSizes.LARGE} />
}
}

Adds an arrow icon only when the button type is NEXT.

Example:

<Button
text="Continue"
type={ButtonTypes.NEXT}
/>

Produces:

Continue →

Rendered Markup

<div
data-testid={testID}
data-object-type={type ?? ButtonTypes.PRIMARY}
data-object-size={size ?? ButtonSizes.MEDIUM}
data-disabled={disabled ? 'true' : 'false'}
className={`Button`}
onClick={() => __handleAction()}
>

data-testid

Used by testing frameworks:

<div data-testid="button-save">

Allows automated tests to find the element.


data-object-type

Stores the button type.

Example:

<div data-object-type="primary">

Useful for CSS selectors or debugging.


data-object-size

Stores the button size.

Example:

<div data-object-size="large">

Allows styling such as:

.Button[data-object-size='large'] {
padding: 1rem 2rem;
}

data-disabled

Stores disabled state.

Example:

<div data-disabled="true">

className

className="Button"

Provides the base CSS class.


Click Handler

onClick={() => __handleAction()}

Calls the action when the button is clicked.

A simpler version would be:

onClick={__handleAction}

Children

{__renderIcon()}
{__renderText()}
{__renderNext()}

The button is assembled from three optional parts:

  1. Custom icon
  2. Label text
  3. Next-arrow icon

Depending on the props, different combinations appear.


Atomic Design Classification

ComponentAtomic LevelReason
IconAtomSmallest reusable UI element
LabelAtomSmallest reusable text element
ButtonMoleculeCombines multiple atoms into one interaction

The component demonstrates a core Atomic Design principle: compose larger UI elements from smaller reusable building blocks rather than mixing raw HTML and styling directly into higher-level components.