1
0
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):

![image](https://github.com/user-attachments/assets/66fdabf7-7a80-46cb-b302-6242c16ad43e)

![image](https://github.com/user-attachments/assets/660506ce-0ec4-417f-bb3a-3fbf23d5591c)


Profile page (now a list + improved spacing)

Before:

![image](https://github.com/user-attachments/assets/17a841e6-d500-410e-8f11-4c78ca0e9e12)

![image](https://github.com/user-attachments/assets/38a60e67-682e-45b5-9312-f4c2013192bb)

After:

![image](https://github.com/user-attachments/assets/602f3d06-0b7e-4a10-9958-fb565fb6d06b)


![image](https://github.com/user-attachments/assets/67c7d39c-cdf9-4586-98d9-63ceff4fd867)
This commit is contained in:
Thomas Heartman 2025-03-28 16:05:32 +01:00 committed by GitHub
parent fc0383620b
commit 398246c3ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 80 additions and 55 deletions

View File

@ -88,7 +88,6 @@ export const RequestSummary: FC<Props> = ({
: 'error'
: 'neutral'
}
tabIndex={-1}
>
{usageTotal.toLocaleString(
locationSettings.locale ?? 'en-US',

View File

@ -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

View File

@ -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}

View File

@ -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>

View File

@ -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>

View File

@ -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}

View File

@ -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>
}

View File

@ -32,7 +32,6 @@ export const PlaygroundResultChip: FC<ResultChipProps> = ({
return (
<Badge
tabIndex={-1}
color={color}
icon={
showIcon ? (

View File

@ -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>
}
/>