Judoboy Alex
Judoboy Alex

Reputation: 350

How to align icon to the text Title, while Title is being aligned to the bottom elements?

I'm building this Toast component and I would like to align Title of Toast with icon on the left and "close" icon to the right. I know that best way to achieve it is to wrap all three elements in a div then use display:flex with align-items: center. But trick is that Title is already wrapped in div with class mid-container and flex is applied with column direction in order to align with items to the bottom which are content and action button. Alternative way is to use top: 4px to the icon, but that is not responsive and I prefer to align it with flex if possible. Is there a way to include Title with flex in both horizontal and vertical direction? Or is there a alternative way? https://stackblitz.com/edit/react-ts-3pqxym?file=App.tsx,toast.md,Toast%2FToast.tsx,style.css

Toast.tsx

export const Toast = ({title, description, actionLabel, actionButtonCallback, close, timeout = 2000}: IToast) => {
  useTimeout(close, timeout);

  return (
    <div className="toast-container">
     
      <div style={{ display: 'flex'}}>
        <span className='icon'><FaAmazon /></span>
        <div className='mid-container'>
          <div className="title">{title}</div>
          <div className="toast__text">{description}</div>
          <button style={{ width: '100px' }} onClick={actionButtonCallback}>{actionLabel}</button>
        </div>   
      </div>
      <button onClick={close} className="toast__close-btn"><FaWindowClose/></button>
    </div>
  )
}

styles.css

.toasts-wrapper {
  position: absolute;
  bottom: 20px;
  right: 20px;
}

.toast-container {
  border: 2px solid transparent;
  background-color: #fafafa;
  border-radius: 4px;
  max-width: 380px;
  min-width: 240px;
  box-shadow: 0px 0px 5px rgba(0, 0, 0, .2);
  margin-top: 16px;
  display: flex;
  position: relative;
  cursor: pointer;
  align-items: flex-start;
  width: 100%;
  animation: slide-in-right 0.3s ease-in-out forwards;
}

@keyframes slide-in-right {
  0% {
    transform: translateX(100%);
    opacity: 0;
  }
  100% {
    transform: translateX(0);
    opacity: 1;
  }
}

.toast__close-btn {
  border: none;
  background-color: transparent;
  font-size: 16px;
  margin-right: 8px;
  cursor: pointer;
  margin-left: auto;
}

.title {
  font-weight: bold;
}

.mid-container {
  display: flex;
  flex-direction: column;
}

.icon {
  flex: none;
  margin-right: 10px;
  font-size: 16px;
  /* top: 4px; */
}

* {
  box-sizing: border-box;
}

button {
  display : flex;
  align-items: center;
}

Upvotes: 0

Views: 113

Answers (1)

ashirhusaain
ashirhusaain

Reputation: 265

First you need to redesign icon, title and close button. I have put all of those things in a single div. Then you need to apply height 16px to your icon span (reason is your icon svg is 16 x 16 but span taking 16x 20, applying height : 16px will fix this).Then apply align items: center on div containing icon, title and close button.

Here is the code:

Toast.tsx

import * as React from 'react';
import { useMemo } from 'react';
import '../style.css';
import { FaAmazon, FaWindowClose } from 'react-icons/fa';
import { useTimeout } from '../Hooks/useTimeout';

export interface IToast {
  timeout?: number;
  status?: 'Success' | 'Error' | 'Neutral';
  type?: 'default' | 'micro';
  title?: string;
  description?: string;
  actionLabel?: string;
  actionButtonCallback?: () => void;
  open?: boolean;
  close?: () => void;
}

export const Toast = ({
  title,
  description,
  actionLabel,
  actionButtonCallback,
  close,
  timeout = 2000,
}: IToast) => {
  useTimeout(close, timeout);

  return (
    <div className="toast-container">
      <div style={{ display: 'flex', alignItems: 'center' }}>
        <span className="icon" style={{ innerHeight: '16px' }}>
          <FaAmazon />
        </span>
        <div className="title">{title}</div>
        <button onClick={close} className="toast__close-btn">
          <FaWindowClose />
        </button>
      </div>
      <div className="mid-container">
        <div className="toast__text">{description}</div>
        <button style={{ width: '100px' }} onClick={actionButtonCallback}>
          {actionLabel}
        </button>
      </div>
    </div>
  );
};

Upvotes: 0

Related Questions