Reputation: 350
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
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