MM-62621 - a11y fixes channel info bottom menu (#29910)

* MM-62621 - a11y fixes channel info bottom menu

* fix translations

* add back library import style

* remove unnecesary pseudo menu aria roles and turn into plain buttons

* fix translations

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Этот коммит содержится в:
Pablo Vélez
2025-01-30 07:39:22 -05:00
коммит произвёл GitHub
родитель 8c3490b3d8
Коммит dc06bb2155
3 изменённых файлов: 81 добавлений и 78 удалений

Просмотреть файл

@@ -42,19 +42,15 @@ export interface Props {
channelStats: ChannelStats;
currentUser: UserProfile;
currentTeam: Team;
isArchived: boolean;
isFavorite: boolean;
isMuted: boolean;
isInvitingPeople: boolean;
isMobile: boolean;
canManageMembers: boolean;
canManageProperties: boolean;
dmUser?: DMUser;
channelMembers: UserProfile[];
actions: {
closeRightHandSide: () => void;
unfavoriteChannel: (channelId: string) => void;
@@ -155,36 +151,26 @@ const ChannelInfoRhs = ({
isMobile={isMobile}
onClose={actions.closeRightHandSide}
/>
<TopButtons
channelType={channel.type}
channelURL={channelURL}
isFavorite={isFavorite}
isMuted={isMuted}
isInvitingPeople={isInvitingPeople}
canAddPeople={canManageMembers}
actions={{toggleFavorite, toggleMute, addPeople}}
/>
<AboutArea
channel={channel}
dmUser={dmUser}
gmUsers={gmUsers}
canEditChannelProperties={canEditChannelProperties}
actions={{
editChannelHeader,
editChannelPurpose,
}}
/>
<Divider/>
<Menu
channel={channel}
channelStats={channelStats}

Просмотреть файл

@@ -11,10 +11,33 @@ import LoadingSpinner from 'components/widgets/loading/loading_spinner';
import {Constants} from 'utils/constants';
const MenuItemContainer = styled.div`
padding: 8px 16px;
flex: 1;
const MenuContainer = styled.nav`
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 16px 0;
font-size: 14px;
line-height: 20px;
color: rgb(var(--center-channel-color-rgb));
`;
const MenuItemButton = styled.button`
display: flex;
flex-direction: row;
align-items: center;
width: 100%;
height: 40px;
padding: 8px 16px;
background: none;
border: none;
text-align: left;
cursor: pointer;
&:hover {
background: rgba(var(--center-channel-color-rgb), 0.08);
}
`;
const Icon = styled.div`
@@ -40,56 +63,38 @@ const Badge = styled.div`
`;
interface MenuItemProps {
className?: string;
icon: JSX.Element;
text: string;
opensSubpanel?: boolean;
badge?: string|number|JSX.Element;
badge?: string | number | JSX.Element;
onClick: () => void;
}
const menuItem = ({icon, text, className, opensSubpanel, badge, onClick}: MenuItemProps) => {
function MenuItem(props: MenuItemProps) {
const {icon, text, opensSubpanel, badge, onClick} = props;
const hasRightSide = (badge !== undefined) || opensSubpanel;
return (
<div className={className}>
<MenuItemContainer onClick={onClick}>
<Icon>{icon}</Icon>
<MenuItemText>
{text}
</MenuItemText>
{hasRightSide && (
<RightSide>
{badge !== undefined && (
<Badge>{badge}</Badge>
)}
{opensSubpanel && (
<Icon><i className='icon icon-chevron-right'/></Icon>
)}
</RightSide>
)}
</MenuItemContainer>
</div>
<MenuItemButton
onClick={onClick}
aria-label={text}
type='button'
>
<Icon>{icon}</Icon>
<MenuItemText>{text}</MenuItemText>
{hasRightSide && (
<RightSide>
{badge !== undefined && (
<Badge>{badge}</Badge>
)}
{opensSubpanel && (
<Icon><i className='icon icon-chevron-right'/></Icon>
)}
</RightSide>
)}
</MenuItemButton>
);
};
const MenuItem = styled(menuItem)`
display: flex;
width: 100%;
height: 40px;
flex-direction: row;
align-items: center;
cursor: pointer;
&:hover {
background: rgba(var(--center-channel-color-rgb), 0.08);
${Icon} {
color: rgba(var(--center-channel-color-rgb), var(--icon-opacity-hover));
}
}
`;
}
interface MenuProps {
channel: Channel;
@@ -107,8 +112,16 @@ interface MenuProps {
};
}
const Menu = ({channel, channelStats, isArchived, className, actions}: MenuProps) => {
export default function Menu(props: MenuProps) {
const {formatMessage} = useIntl();
const {
channel,
channelStats,
isArchived,
className,
actions,
} = props;
const [loadingStats, setLoadingStats] = useState(true);
const showNotificationPreferences = channel.type !== Constants.DM_CHANNEL && !isArchived;
@@ -125,21 +138,31 @@ const Menu = ({channel, channelStats, isArchived, className, actions}: MenuProps
}, [channel.id]);
return (
<div
<MenuContainer
className={className}
data-testid='channel_info_rhs-menu'
aria-label={formatMessage({
id: 'channel_info_rhs.menu.title',
defaultMessage: 'Channel Info Actions',
})}
>
{showNotificationPreferences && (
<MenuItem
icon={<i className='icon icon-bell-outline'/>}
text={formatMessage({id: 'channel_info_rhs.menu.notification_preferences', defaultMessage: 'Notification Preferences'})}
text={formatMessage({
id: 'channel_info_rhs.menu.notification_preferences',
defaultMessage: 'Notification Preferences',
})}
onClick={actions.openNotificationSettings}
/>
)}
{showMembers && (
<MenuItem
icon={<i className='icon icon-account-outline'/>}
text={formatMessage({id: 'channel_info_rhs.menu.members', defaultMessage: 'Members'})}
text={formatMessage({
id: 'channel_info_rhs.menu.members',
defaultMessage: 'Members',
})}
opensSubpanel={true}
badge={channelStats.member_count}
onClick={() => actions.showChannelMembers(channel.id)}
@@ -147,31 +170,24 @@ const Menu = ({channel, channelStats, isArchived, className, actions}: MenuProps
)}
<MenuItem
icon={<i className='icon icon-pin-outline'/>}
text={formatMessage({id: 'channel_info_rhs.menu.pinned', defaultMessage: 'Pinned messages'})}
text={formatMessage({
id: 'channel_info_rhs.menu.pinned',
defaultMessage: 'Pinned messages',
})}
opensSubpanel={true}
badge={channelStats?.pinnedpost_count}
onClick={() => actions.showPinnedPosts(channel.id)}
/>
<MenuItem
icon={<i className='icon icon-file-text-outline'/>}
text={formatMessage({id: 'channel_info_rhs.menu.files', defaultMessage: 'Files'})}
text={formatMessage({
id: 'channel_info_rhs.menu.files',
defaultMessage: 'Files',
})}
opensSubpanel={true}
badge={loadingStats ? <LoadingSpinner/> : fileCount}
onClick={() => actions.showChannelFiles(channel.id)}
/>
</div>
</MenuContainer>
);
};
const StyledMenu = styled(Menu)`
display: flex;
flex-direction: column;
align-items: flex-start;
padding: 16px 0;
font-size: 14px;
line-height: 20px;
color: rgb(var(--center-channel-color-rgb));
`;
export default StyledMenu;
}

Просмотреть файл

@@ -3261,6 +3261,7 @@
"channel_info_rhs.menu.members": "Members",
"channel_info_rhs.menu.notification_preferences": "Notification Preferences",
"channel_info_rhs.menu.pinned": "Pinned messages",
"channel_info_rhs.menu.title": "Channel Info Actions",
"channel_info_rhs.top_buttons.add_people": "Add People",
"channel_info_rhs.top_buttons.add_people.tooltip": "Add team members to this channel",
"channel_info_rhs.top_buttons.copied": "Copied",