mirror of
https://github.com/Unleash/unleash.git
synced 2025-07-26 13:48:33 +02:00
Chore/remove badges from tab order (#9643)
Makes badges not tabbable by default instead of tabbable by default. Turns out, badges aren't tabbable by default and they never were until I made them as much (for some reason that I don't quite understand now). Anyway, I've gone through the list of uses for the Badge element and made any element that should be reachable by tab either have an explicit tab index (if it's within a tooltip, for instance), or be wrapped in a Link (instead of having an on-click handler). The two places I've wrapped it in a link, I've also gone and changed the item group to be a list (for HTML semantics). I've also updated some spacing for the profile tab. Application list (one is before, one is after. don't remember which is which; it's now a list):   Profile page (now a list + improved spacing) Before:   After:  
This commit is contained in:
parent
fc0383620b
commit
398246c3ec
@ -88,7 +88,6 @@ export const RequestSummary: FC<Props> = ({
|
||||
: 'error'
|
||||
: 'neutral'
|
||||
}
|
||||
tabIndex={-1}
|
||||
>
|
||||
{usageTotal.toLocaleString(
|
||||
locationSettings.locale ?? 'en-US',
|
||||
|
@ -14,7 +14,7 @@ import { ApplicationIssues } from './ApplicationIssues/ApplicationIssues';
|
||||
import { ApplicationChart } from './ApplicationChart';
|
||||
import TopicOutlinedIcon from '@mui/icons-material/TopicOutlined';
|
||||
import { Badge } from '../common/Badge/Badge';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { usePlausibleTracker } from 'hooks/usePlausibleTracker';
|
||||
import { useEffect } from 'react';
|
||||
import { useFeedback } from '../feedbackNew/useFeedback';
|
||||
@ -35,11 +35,22 @@ const ApplicationContainer = styled(Box)(({ theme }) => ({
|
||||
alignSelf: 'stretch',
|
||||
}));
|
||||
|
||||
const ProjectContainer = styled(Box)(({ theme }) => ({
|
||||
const ProjectContainer = styled('ul')(({ theme }) => ({
|
||||
padding: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
gap: theme.spacing(2),
|
||||
alignSelf: 'stretch',
|
||||
listStyle: 'none',
|
||||
}));
|
||||
|
||||
const StyledBadgeLink = styled(Link)(({ theme }) => ({
|
||||
':hover,:focus-visible': {
|
||||
outline: 'none',
|
||||
'> *': {
|
||||
outline: `1px solid ${theme.palette.primary.main}`,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const ApplicationHeader = styled('div')(({ theme }) => ({
|
||||
@ -97,18 +108,18 @@ const ApplicationOverview = () => {
|
||||
<ProjectContainer>
|
||||
Application is connected to these projects:
|
||||
{data.projects.map((project) => (
|
||||
<Badge
|
||||
sx={{ cursor: 'pointer' }}
|
||||
key={project}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate(`/projects/${project}`);
|
||||
}}
|
||||
color='secondary'
|
||||
icon={<TopicOutlinedIcon />}
|
||||
>
|
||||
{project}
|
||||
</Badge>
|
||||
<li key={project}>
|
||||
<StyledBadgeLink
|
||||
to={`/projects/${project}`}
|
||||
>
|
||||
<Badge
|
||||
color='secondary'
|
||||
icon={<TopicOutlinedIcon />}
|
||||
>
|
||||
{project}
|
||||
</Badge>
|
||||
</StyledBadgeLink>
|
||||
</li>
|
||||
))}
|
||||
</ProjectContainer>
|
||||
<Button
|
||||
|
@ -97,14 +97,12 @@ export const Badge: FC<IBadgeProps> = forwardRef(
|
||||
className,
|
||||
sx,
|
||||
children,
|
||||
tabIndex = 0,
|
||||
...props
|
||||
}: IBadgeProps,
|
||||
ref: ForwardedRef<HTMLDivElement>,
|
||||
) => (
|
||||
<StyledBadge
|
||||
as={as}
|
||||
tabIndex={tabIndex}
|
||||
color={color}
|
||||
icon={icon}
|
||||
className={className}
|
||||
|
@ -27,7 +27,12 @@ export const RoleBadge = ({ roleId, hideIcon, children }: IRoleBadgeProps) => {
|
||||
|
||||
return (
|
||||
<HtmlTooltip title={<RoleDescription roleId={roleId} tooltip />} arrow>
|
||||
<Badge color='success' icon={icon} sx={{ cursor: 'pointer' }}>
|
||||
<Badge
|
||||
tabIndex={0}
|
||||
color='success'
|
||||
icon={icon}
|
||||
sx={{ cursor: 'pointer' }}
|
||||
>
|
||||
{role.name}
|
||||
</Badge>
|
||||
</HtmlTooltip>
|
||||
|
@ -342,7 +342,9 @@ export const PrimaryFeatureInfo: FC<{
|
||||
/>
|
||||
{archivedAt && (
|
||||
<HtmlTooltip arrow title={archivedDate} describeChild>
|
||||
<Badge color='neutral'>Archived</Badge>
|
||||
<Badge tabIndex={0} color='neutral'>
|
||||
Archived
|
||||
</Badge>
|
||||
</HtmlTooltip>
|
||||
)}
|
||||
</FeatureNameAndType>
|
||||
|
@ -117,13 +117,11 @@ export const FeatureDetails = ({
|
||||
<p>
|
||||
{feature?.strategies?.result !== 'unknown' ? (
|
||||
<PlaygroundResultChip
|
||||
tabindex={-1}
|
||||
enabled={feature.isEnabled}
|
||||
label={feature.isEnabled ? 'True' : 'False'}
|
||||
/>
|
||||
) : (
|
||||
<PlaygroundResultChip
|
||||
tabindex={-1}
|
||||
enabled='unknown'
|
||||
label={'Unknown'}
|
||||
showIcon={false}
|
||||
|
@ -14,14 +14,12 @@ interface IResultChipProps {
|
||||
label: string;
|
||||
// Result icon - defaults to true
|
||||
showIcon?: boolean;
|
||||
tabindex?: number;
|
||||
}
|
||||
|
||||
export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
||||
enabled,
|
||||
label,
|
||||
showIcon = true,
|
||||
tabindex,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const flagOverviewRedesign = useUiFlag('flagOverviewRedesign');
|
||||
@ -73,7 +71,6 @@ export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
||||
condition={typeof enabled === 'boolean' && Boolean(enabled)}
|
||||
show={
|
||||
<Badge
|
||||
tabIndex={tabindex}
|
||||
color='success'
|
||||
icon={showIcon ? icon : undefined}
|
||||
>
|
||||
@ -81,11 +78,7 @@ export const PlaygroundResultChip: VFC<IResultChipProps> = ({
|
||||
</Badge>
|
||||
}
|
||||
elseShow={
|
||||
<Badge
|
||||
color='error'
|
||||
icon={showIcon ? icon : undefined}
|
||||
tabIndex={tabindex}
|
||||
>
|
||||
<Badge color='error' icon={showIcon ? icon : undefined}>
|
||||
{label}
|
||||
</Badge>
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ export const PlaygroundResultChip: FC<ResultChipProps> = ({
|
||||
|
||||
return (
|
||||
<Badge
|
||||
tabIndex={-1}
|
||||
color={color}
|
||||
icon={
|
||||
showIcon ? (
|
||||
|
@ -15,7 +15,7 @@ import { useProfile } from 'hooks/api/getters/useProfile/useProfile';
|
||||
import { useLocationSettings } from 'hooks/useLocationSettings';
|
||||
import type { IUser } from 'interfaces/user';
|
||||
import TopicOutlinedIcon from '@mui/icons-material/TopicOutlined';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { RoleBadge } from 'component/common/RoleBadge/RoleBadge';
|
||||
@ -56,14 +56,19 @@ const StyledSectionLabel = styled(Typography)(({ theme }) => ({
|
||||
const StyledAccess = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
gap: theme.spacing(2),
|
||||
'& > div > p': {
|
||||
marginBottom: theme.spacing(1.5),
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledBadge = styled(Badge)(({ theme }) => ({
|
||||
cursor: 'pointer',
|
||||
marginRight: theme.spacing(1),
|
||||
const StyledBadgeLink = styled(Link)(({ theme }) => ({
|
||||
':hover,:focus-visible': {
|
||||
outline: 'none',
|
||||
'> *': {
|
||||
outline: `2px solid ${theme.palette.primary.main}`,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledDivider = styled('div')(({ theme }) => ({
|
||||
@ -86,6 +91,14 @@ interface IProfileTabProps {
|
||||
user: IUser;
|
||||
}
|
||||
|
||||
const ProjectList = styled('ul')(({ theme }) => ({
|
||||
listStyle: 'none',
|
||||
padding: 0,
|
||||
display: 'flex',
|
||||
flexFlow: 'row wrap',
|
||||
gap: theme.spacing(1),
|
||||
}));
|
||||
|
||||
export const ProfileTab = ({ user }: IProfileTabProps) => {
|
||||
const { profile, refetchProfile } = useProfile();
|
||||
const navigate = useNavigate();
|
||||
@ -158,33 +171,40 @@ export const ProfileTab = ({ user }: IProfileTabProps) => {
|
||||
<Typography variant='body2'>Projects</Typography>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(profile?.projects.length)}
|
||||
show={profile?.projects.map((project) => (
|
||||
<Tooltip
|
||||
key={project}
|
||||
title='View project'
|
||||
arrow
|
||||
placement='bottom-end'
|
||||
describeChild
|
||||
>
|
||||
<StyledBadge
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
navigate(`/projects/${project}`);
|
||||
}}
|
||||
color='secondary'
|
||||
icon={<TopicOutlinedIcon />}
|
||||
>
|
||||
{project}
|
||||
</StyledBadge>
|
||||
</Tooltip>
|
||||
))}
|
||||
show={
|
||||
<ProjectList>
|
||||
{profile?.projects.map((project) => (
|
||||
<li key={project}>
|
||||
<Tooltip
|
||||
title='View project'
|
||||
arrow
|
||||
placement='bottom-end'
|
||||
describeChild
|
||||
>
|
||||
<StyledBadgeLink
|
||||
to={`/projects/${project}`}
|
||||
>
|
||||
<Badge
|
||||
color='secondary'
|
||||
icon={
|
||||
<TopicOutlinedIcon />
|
||||
}
|
||||
>
|
||||
{project}
|
||||
</Badge>
|
||||
</StyledBadgeLink>
|
||||
</Tooltip>
|
||||
</li>
|
||||
))}
|
||||
</ProjectList>
|
||||
}
|
||||
elseShow={
|
||||
<Tooltip
|
||||
title='You are not assigned to any projects'
|
||||
arrow
|
||||
describeChild
|
||||
>
|
||||
<Badge>No projects</Badge>
|
||||
<Badge tabIndex={0}>No projects</Badge>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
|
Loading…
Reference in New Issue
Block a user