mui-treasury
itemapp-messengersource: ok · refreshed
App Messenger
A app-messenger item.
npx shadcn add "https://mui-treasury.com/r/app-messenger.json"free
Where it goes
chat
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · light@mui/material@emotion/react@emotion/styled@mui/icons-material
Registry dependencies
https://www.mui-treasury.com/r/layout-core.json
Files12 · source cached 10/8/2026, 6:17:14 AM
layout/app-messenger/app-messenger.tsx
'use client';
import React from 'react';
import Box from '@mui/material/Box';
import Container from '@mui/material/Container';
import CssBaseline from '@mui/material/CssBaseline';
import Toolbar from '@mui/material/Toolbar';
import {
ThemeProvider,
createTheme,
responsiveFontSizes,
styled,
} from '@mui/material/styles';
import {
Content,
EdgeSidebar,
EdgeSidebarContent,
Footer,
Header,
InsetAvoidingView,
InsetContent,
InsetSidebar,
Root,
} from '../layout-core';
import {
ChatBar,
ChatDialog,
ChatList,
ChatSettings,
ChatsHeader,
ConversationHead,
MessengerSearch,
} from './components';
const StyledHeader = styled(Header)(() => ({
boxShadow: '0 1px 2px 0 rgba(0, 0, 0, .10)',
backgroundColor: '#ffffff',
}));
const theme = responsiveFontSizes(
createTheme({
palette: {
primary: {
main: 'rgb(0, 153, 255)',
},
background: {
default: '#fff',
},
},
typography: {
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
body1: {
fontSize: `${15 / 16}rem`,
},
},
components: {
MuiCssBaseline: {
styleOverrides: {
'strong, b': {
fontWeight: 'bold',
},
},
},
},
}),
);
// @ts-expect-error theme uses vars in MUI but this layout needs it nullified
theme.vars = null;
export function LayoutV6AppMessenger() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<Root standalone>
<StyledHeader height="64px" sx={{ position: 'relative' }}>
<Toolbar disableGutters sx={{ flex: 'auto' }}>
<ConversationHead />
</Toolbar>
</StyledHeader>
<EdgeSidebar
permanentAutoCollapse="md"
variant={{
xs: [
'permanent',
{
width: '25cqw',
collapsedWidth: '80px',
},
],
}}
>
<EdgeSidebarContent>
<ChatsHeader />
<Box
sx={{
p: '4px 16px 12px',
}}
>
<MessengerSearch />
</Box>
<ChatList />
</EdgeSidebarContent>
</EdgeSidebar>
<Content>
<ChatDialog />
<InsetSidebar position="absolute" width="25cqw">
<InsetContent>
<ChatSettings />
</InsetContent>
</InsetSidebar>
</Content>
<Footer>
<Container disableGutters>
<InsetAvoidingView>
<Box
sx={{
display: 'flex',
alignItems: 'center',
p: 1,
}}
>
<ChatBar />
</Box>
</InsetAvoidingView>
</Container>
</Footer>
</Root>
</ThemeProvider>
);
}
layout/app-messenger/components/ChatBar.tsx
'use client';
import React from 'react';
import AddCircle from '@mui/icons-material/AddCircle';
import Gif from '@mui/icons-material/Gif';
import ImageIcon from '@mui/icons-material/Image';
import Note from '@mui/icons-material/Note';
import TagFaces from '@mui/icons-material/TagFaces';
import ThumbUp from '@mui/icons-material/ThumbUp';
import InputAdornment from '@mui/material/InputAdornment';
import InputBase from '@mui/material/InputBase';
interface ChatBarProps {
concise?: boolean;
}
const ChatBar = ({ concise }: ChatBarProps) => {
const styles = {
icon: {
color: 'rgb(0, 153, 255)',
width: 44,
height: 44,
padding: '6px',
'&:not(:first-child)': {
marginLeft: '4px',
},
},
input: {
flex: 'auto',
borderRadius: '40px',
paddingLeft: '16px',
backgroundColor: 'rgba(0,0,0,0.04)',
margin: '0 8px',
height: 36,
fontSize: 13,
},
};
return (
<>
<AddCircle sx={styles.icon} />
{!concise && (
<>
<Gif sx={styles.icon} />
<Note sx={styles.icon} />
<ImageIcon sx={styles.icon} />
</>
)}
<InputBase
placeholder={'Type a message...'}
endAdornment={
<InputAdornment position={'end'}>
<TagFaces sx={styles.icon} />
</InputAdornment>
}
sx={styles.input}
/>
<ThumbUp sx={styles.icon} />
</>
);
};
export default ChatBar;
layout/app-messenger/components/ChatDialog.tsx
'use client';
import React from 'react';
import Box from '@mui/material/Box';
import Typography from '@mui/material/Typography';
import ChatMsg from './ChatMsg';
const AVATAR = 'https://i.pravatar.cc/300?img=13';
const ChatDialog = () => {
return (
<Box
sx={{
p: '16px 30px 12px 10px',
}}
>
<ChatMsg
avatar={AVATAR}
messages={[
'Hi Jenny, How r u today?',
'Did you train yesterday',
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Volutpat lacus laoreet non curabitur gravida.',
]}
/>
<Typography
sx={{
fontWeight: 500,
color: 'rgba(0,0,0,0.4)',
margin: '12px 0',
fontSize: 12,
textAlign: 'center',
}}
>
FRI 1:46 PM
</Typography>
<ChatMsg
side={'right'}
messages={[
"Great! What's about you?",
'Of course I did. Speaking of which check this out',
{
type: 'image',
alt: 'sticker',
src: 'https://www.messenger.com/stickers/asset/?sticker_id=702110433208381&image_type=BestEffortImage',
},
'Commodo ullamcorper a lacus vestibulum sed arcu. Sed faucibus turpis in eu mi bibendum neque egestas. Maecenas volutpat blandit aliquam etiam erat velit. Massa placerat duis ultricies lacus sed turpis tincidunt id aliquet. Suspendisse sed nisi lacus sed viverra.',
]}
/>
<Typography
sx={{
fontWeight: 500,
color: 'rgba(0,0,0,0.4)',
margin: '12px 0',
fontSize: 12,
textAlign: 'center',
}}
>
FRI 4:18 PM
</Typography>
<ChatMsg
avatar={AVATAR}
messages={[
'Im good.',
'See u later.',
{
type: 'image',
alt: 'sticker',
src: 'https://scontent.fbkk12-3.fna.fbcdn.net/v/t39.1997-6/47165057_2150118098374296_5034322199196991488_n.png?_nc_cat=1&_nc_eui2=AeGsL8WciYpwOySYRQINElIdV9NubJ7ZbWTW9J5-DlXHPiLCKR8Zvvd4nVyPH4Wa8kceFiL10mXvokNFcEJx9JWz-6XLYgCLmOgTniFDbSjUPw&_nc_ohc=pewFeK6M1ZIAQkL5L9QR2FZcwYjZ0FTWid2zHeUqboLU4azOITkLVGaog&_nc_ht=scontent.fbkk12-3.fna&oh=27a2a48aabccd4cdae4ec4f3f775daa9&oe=5EAF0F3B',
},
]}
/>
</Box>
);
};
export default ChatDialog;
layout/app-messenger/components/ChatList.tsx
'use client';
import React from 'react';
import ChatListItem from './ChatListItem';
const data = [
{
avatar: 'https://i.pravatar.cc/300?img=11',
name: 'Jordyn Frank',
info: 'You sent a photo \u2022 2:04 PM',
responded: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=12',
name: 'Marwan Combs',
info: 'Where r u? \u2022 1:54 PM',
bold: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=13',
name: 'Imaad Casey',
info: 'You: Good to see u \u2022 SAT',
active: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=14',
name: 'Philip Rhodes',
info: 'You: Lorem ipsum \u2022 THU',
responded: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=15',
name: 'Chardonnay Raymond',
info: 'Chardonnay called you \u2022 THU',
},
{
avatar: 'https://i.pravatar.cc/300?img=16',
name: 'Akram Farmer',
info: 'You: still look forw... \u2022 THU',
responded: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=17',
name: 'Nichola Mackie',
info: 'You: https://mui... \u2022 DEC 10',
},
{
avatar: 'https://i.pravatar.cc/300?img=18',
name: 'Ines Page',
info: 'You called Ines \u2022 DEC 9',
},
{
avatar: 'https://i.pravatar.cc/300?img=19',
name: 'Ephraim Gonzalez',
info: 'I think you can d... \u2022 DEC 9',
responded: true,
},
{
avatar: 'https://i.pravatar.cc/300?img=20',
name: 'Tyrell Stark',
info: 'Okay, I think... \u2022 DEC 6',
},
{
avatar: 'https://i.pravatar.cc/300?img=21',
name: 'Tasha Whitmore',
info: 'You sent an attach... \u2022 NOV 30',
},
{
avatar: 'https://i.pravatar.cc/300?img=22',
name: 'Hawwa Davenport',
info: 'okay kub \u2022 NOV 28',
},
];
interface ChatListProps {
concise?: boolean;
}
const ChatList = ({ concise }: ChatListProps) => {
return (
<>
{data.map((item) => (
<ChatListItem key={item.name} {...item} concise={concise} />
))}
</>
);
};
export default ChatList;
layout/app-messenger/components/ChatListItem.tsx
'use client';
import React from 'react';
import MoreHoriz from '@mui/icons-material/MoreHoriz';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
interface ChatListItemProps {
bold?: boolean;
active?: boolean;
avatar?: string;
name?: string;
info?: string;
responded?: boolean;
concise?: boolean;
}
const ChatListItem = ({
bold,
active,
avatar,
name,
info,
responded,
concise,
}: ChatListItemProps) => {
return (
<Box
sx={{
px: 1,
}}
>
<ListItemButton
sx={{
paddingLeft: '8px',
paddingRight: '8px',
borderRadius: '10px',
...(active && {
backgroundColor: 'rgba(0, 0, 0, .05)',
}),
'&:hover': {
'& .ChatListItem-dot': {
display: 'none',
},
'& .ChatListItem-responded': {
display: 'none',
},
'& .ChatListItem-more': {
visibility: 'visible',
},
},
}}
>
<Avatar
src={avatar}
sx={{ width: 50, height: 50, marginRight: '12px' }}
/>
{!concise && (
<>
<ListItemText
primary={name}
secondary={info}
slotProps={{
primary: {
noWrap: true,
sx: { ...(bold && { fontWeight: 'bold' }) },
},
secondary: {
noWrap: true,
sx: {
fontSize: 13,
color: '#999',
...(bold && {
fontWeight: 'bold',
color: 'text.primary',
}),
},
},
}}
/>
<Box
sx={{
position: 'relative',
}}
>
<MoreHoriz
className="ChatListItem-more"
sx={{ visibility: 'hidden', fontSize: 20 }}
/>
{bold && (
<Box
className="ChatListItem-dot"
sx={{
width: 12,
height: 12,
backgroundColor: '#09f',
borderRadius: '50%',
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
}}
/>
)}
{responded && (
<Avatar
src={avatar}
className="ChatListItem-responded"
sx={{
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 16,
height: 16,
}}
/>
)}
</Box>
</>
)}
</ListItemButton>
</Box>
);
};
export default ChatListItem;
layout/app-messenger/components/ChatMsg.tsx
'use client';
import React from 'react';
import MoreHoriz from '@mui/icons-material/MoreHoriz';
import Reply from '@mui/icons-material/Reply';
import TagFaces from '@mui/icons-material/TagFaces';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import Grid from '@mui/material/Grid';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import { useTheme } from '@mui/material/styles';
type ChatMessage =
| string
| { type: 'image'; alt: string; src: string; [key: string]: unknown };
interface ChatMsgProps {
avatar?: string;
messages?: ChatMessage[];
side?: 'left' | 'right';
}
const ChatMsg = ({
avatar = '',
messages = [],
side = 'left',
}: ChatMsgProps) => {
const { spacing, palette } = useTheme();
const radius = spacing(2.5);
const rightBgColor = palette.primary.main;
const attachClass = (index: number) => {
if (index === 0) {
return {
leftFirst: {
borderTopLeftRadius: radius,
},
rightFirst: {
borderTopRightRadius: radius,
},
}[`${side}First`];
}
if (index === messages.length - 1) {
return {
leftLast: {
borderBottomLeftRadius: radius,
},
rightLast: {
borderBottomRightRadius: radius,
},
}[`${side}Last`];
}
return '';
};
return (
<Grid
container
spacing={2}
sx={{
justifyContent: side === 'right' ? 'flex-end' : 'flex-start',
}}
>
{side === 'left' && (
<Grid size="auto">
<Avatar src={avatar} sx={{ width: 30, height: 30 }} />
</Grid>
)}
<Grid size="grow">
{messages.map((msg, i) => {
const key = typeof msg === 'string' ? i : msg.src || i;
return (
<Box
key={key}
sx={{
...(side === 'right' && {
marginLeft: 'auto',
}),
'& .MuiIconButton-root': {
opacity: 0,
padding: '6px',
color: 'rgba(0,0,0,0.34)',
'&:hover': {
color: 'rgba(0,0,0,0.87)',
opacity: 1,
},
margin: '0 4px',
'& svg': {
fontSize: 20,
},
},
}}
>
<Box
sx={{
display: 'flex',
alignItems: 'center',
marginBottom: '4px',
'&:hover .MuiIconButton-root': {
opacity: 1,
},
...{
left: {
textAlign: 'left' as const,
},
right: {
textAlign: 'right' as const,
flexDirection: 'row-reverse' as const,
},
}[side],
}}
>
{typeof msg === 'string' && (
<Typography
align={'left'}
sx={{
maxWidth: '70%',
padding: spacing(1, 2),
borderRadius: '4px',
display: 'inline-block',
wordBreak: 'break-word',
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"',
fontSize: '14px',
...{
left: {
borderTopRightRadius: radius,
borderBottomRightRadius: radius,
backgroundColor: palette.grey[100],
},
right: {
borderTopLeftRadius: radius,
borderBottomLeftRadius: radius,
backgroundColor: rightBgColor,
color: palette.common.white,
},
}[side],
...attachClass(i),
}}
>
{msg}
</Typography>
)}
{typeof msg === 'object' && msg.type === 'image' && (
<Box
component="img"
alt={msg.alt}
src={msg.src}
sx={{ maxWidth: 120, maxHeight: 120 }}
/>
)}
<IconButton>
<TagFaces />
</IconButton>
<IconButton>
<Reply />
</IconButton>
<IconButton>
<MoreHoriz />
</IconButton>
</Box>
</Box>
);
})}
</Grid>
</Grid>
);
};
export default ChatMsg;
layout/app-messenger/components/ChatSettings.tsx
'use client';
import React from 'react';
import Edit from '@mui/icons-material/Edit';
import FormatPaint from '@mui/icons-material/FormatPaint';
import KeyboardArrowDown from '@mui/icons-material/KeyboardArrowDown';
import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft';
import Search from '@mui/icons-material/Search';
import ThumbUp from '@mui/icons-material/ThumbUp';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import Divider from '@mui/material/Divider';
import Typography from '@mui/material/Typography';
import { styled } from '@mui/material/styles';
const StyledAvatar = styled(Avatar)(() => ({
width: 100,
height: 100,
margin: 'auto',
}));
const TypographyName = styled(Typography)(() => ({
marginTop: '14px',
fontSize: '22px !important',
fontWeight: 'bold',
}));
interface SettingHeaderProps {
children: React.ReactNode;
opened?: boolean;
}
const SettingHeader = ({ children, opened }: SettingHeaderProps) => {
return (
<Box
sx={{
p: '14px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
'&:hover': {
backgroundColor: 'rgba(0,0,0,0.08)',
},
}}
>
<Typography
sx={{
'&:hover': {
backgroundColor: 'rgba(0,0,0,0.08)',
},
}}
>
{children}
</Typography>
{opened ? <KeyboardArrowDown /> : <KeyboardArrowLeft />}
</Box>
);
};
interface SettingProps {
label: string;
icon: React.ReactElement;
blue?: boolean;
}
const Setting = ({ label, icon, blue }: SettingProps) => {
return (
<Box
sx={{
height: '44px',
pl: '14px',
pr: '12px',
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
}}
>
<Typography variant={'body2'}>{label}</Typography>
{React.cloneElement(icon as never, {
sx: {
padding: '6px',
borderRadius: '50%',
backgroundColor: 'rgba(0,0,0,0.04)',
width: 32,
height: 32,
...(blue && {
color: 'rgb(0, 153, 255)',
background: 'none',
}),
},
})}
</Box>
);
};
const ChatSettings = () => {
return (
<div>
<Box
sx={{
p: '14px 14px 16px 14px',
textAlign: 'center',
}}
>
<StyledAvatar src={'https://i.pravatar.cc/300?img=13'} />
<TypographyName variant={'h1'} align={'center'}>
Imaad Casey
</TypographyName>
</Box>
<Divider />
<SettingHeader opened>Options</SettingHeader>
<Box
sx={{
pb: 2,
}}
>
<Setting label={'Search in Conversation'} icon={<Search />} />
<Setting label={'Edit Nicknames'} icon={<Edit />} />
<Setting label={'Change Theme'} icon={<FormatPaint />} blue />
<Setting label={'Change Emoji'} icon={<ThumbUp />} blue />
</Box>
<Divider />
<SettingHeader>Privacy & Support</SettingHeader>
<Divider />
<SettingHeader>Shared files</SettingHeader>
<Divider />
<SettingHeader>Shared Photos</SettingHeader>
</div>
);
};
export default ChatSettings;
layout/app-messenger/components/ChatsHeader.tsx
'use client';
import React from 'react';
import Edit from '@mui/icons-material/Edit';
import SettingsApplications from '@mui/icons-material/SettingsApplications';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
const ChatsHeader = () => {
return (
<Box
sx={{
py: '10px',
px: 2,
display: 'flex',
alignItems: 'center',
}}
>
<Avatar alt={'me'} src={'https://i.pravatar.cc/300?img=10'} />
<Typography variant={'h4'} sx={{ flex: 'auto', marginLeft: '16px' }}>
<b>Chats</b>
</Typography>
<IconButton
sx={{
padding: '8px',
backgroundColor: 'rgba(0, 0, 0, .04)',
'&:not(:last-child)': {
marginRight: '16px',
},
}}
>
<SettingsApplications />
</IconButton>
<IconButton
sx={{
padding: '8px',
backgroundColor: 'rgba(0, 0, 0, .04)',
'&:not(:last-child)': {
marginRight: '16px',
},
}}
>
<Edit />
</IconButton>
</Box>
);
};
export default ChatsHeader;
layout/app-messenger/components/ConversationHead.tsx
'use client';
import React from 'react';
import Info from '@mui/icons-material/Info';
import Phone from '@mui/icons-material/Phone';
import Videocam from '@mui/icons-material/Videocam';
import Avatar from '@mui/material/Avatar';
import Box from '@mui/material/Box';
import IconButton from '@mui/material/IconButton';
import ListItem from '@mui/material/ListItem';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import ListItemText from '@mui/material/ListItemText';
const ConversationHead = () => {
return (
<Box sx={{ width: '100%' }}>
<ListItem
sx={{ padding: '8px 8px 8px 16px' }}
secondaryAction={
<>
<IconButton
sx={{
'& svg': {
color: 'rgb(0, 153, 255)',
},
}}
>
<Phone />
</IconButton>
<IconButton
sx={{
'& svg': {
color: 'rgb(0, 153, 255)',
},
}}
>
<Videocam />
</IconButton>
<IconButton
sx={{
'& svg': {
color: 'rgb(0, 153, 255)',
},
}}
>
<Info />
</IconButton>
</>
}
>
<ListItemAvatar>
<Avatar src={'https://i.pravatar.cc/300?img=13'} />
</ListItemAvatar>
<ListItemText
primary={'Imaad Casey'}
secondary={'active 17m ago'}
slotProps={{
primary: {
sx: {
fontWeight: 'bold',
},
},
secondary: {
sx: {
fontSize: 12,
},
},
}}
/>
</ListItem>
</Box>
);
};
export default ConversationHead;
layout/app-messenger/components/MessengerSearch.tsx
'use client';
import React from 'react';
import Search from '@mui/icons-material/Search';
import InputAdornment from '@mui/material/InputAdornment';
import InputBase from '@mui/material/InputBase';
const MessengerSearch = () => {
return (
<InputBase
startAdornment={
<InputAdornment
position={'start'}
sx={{
paddingLeft: '12px',
'& svg': {
color: 'rgba(0,0,0,0.38)',
},
}}
>
<Search />
</InputAdornment>
}
placeholder={'Search Messenger'}
sx={{
backgroundColor: 'rgba(0, 0, 0, .04)',
borderRadius: '40px',
width: '100%',
'& .MuiInputBase-input': {
boxSizing: 'border-box',
minHeight: 36,
},
}}
/>
);
};
export default MessengerSearch;
layout/app-messenger/components/index.ts
export { default as ChatsHeader } from './ChatsHeader';
export { default as MessengerSearch } from './MessengerSearch';
export { default as ChatListItem } from './ChatListItem';
export { default as ChatList } from './ChatList';
export { default as ConversationHead } from './ConversationHead';
export { default as ChatSettings } from './ChatSettings';
export { default as ChatBar } from './ChatBar';
export { default as ChatDialog } from './ChatDialog';
layout/app-messenger/index.ts
export * from './app-messenger';
export * from './ChatBar';
export { default as ChatBar } from './ChatBar';
export * from './ChatDialog';
export { default as ChatDialog } from './ChatDialog';
export * from './ChatList';
export { default as ChatList } from './ChatList';
export * from './ChatListItem';
export { default as ChatListItem } from './ChatListItem';
export * from './ChatMsg';
export { default as ChatMsg } from './ChatMsg';
export * from './ChatSettings';
export { default as ChatSettings } from './ChatSettings';
export * from './ChatsHeader';
export { default as ChatsHeader } from './ChatsHeader';
export * from './ConversationHead';
export { default as ConversationHead } from './ConversationHead';
export * from './MessengerSearch';
export { default as MessengerSearch } from './MessengerSearch';
export * from './index';