Skip to content

Commit

Permalink
Version 2: Improve provider list (#147)
Browse files Browse the repository at this point in the history
* Improve providers list accessibility

* Add loading skeleton

* Add loading to app

---------

Co-authored-by: alex-slobodian <[email protected]>
  • Loading branch information
OleksandrSPV and aleksandr-slobodian authored May 29, 2024
1 parent c970d5a commit 581503d
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 26 deletions.
16 changes: 6 additions & 10 deletions src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,12 @@ export function App() {
return (
<>
<CertificatesSidebar className={styles.sidebar}>
{fetching.providers === "pending" ? (
// TODO: add loading skeleton
"Loading providers list..."
) : (
<CertificatesProvidersList
providers={providers}
currentProviderId={currentProviderId}
onSelect={handleProviderChange}
/>
)}
<CertificatesProvidersList
providers={providers}
currentProviderId={currentProviderId}
onSelect={handleProviderChange}
loading={!fetching.providers || fetching.providers === "pending"}
/>
</CertificatesSidebar>
<CertificatesTopbar
className={styles.top_bar}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import { useTranslation } from "react-i18next";
import clsx from "clsx";
import { Typography } from "@peculiar/react-components";
import ProviderIcon from "../../icons/provider.svg?react";
import SmartcardIcon from "../../icons/smartcard.svg?react";
import styles from "./styles/index.module.scss";

interface CertificatesProvidersListItemProps {
provider: IProviderInfo;
provider: Pick<IProviderInfo, "id" | "name" | "isRemovable" | "readOnly">;
isSelected: boolean;
onClick: (id: string) => void;
}
Expand All @@ -20,15 +21,19 @@ export const CertificatesProvidersListItem: React.FunctionComponent<

return (
<li
tabIndex={0}
className={clsx(styles.list_item, {
[styles.current_list_item]: isSelected,
})}
onClick={() => {
onClick && onClick(provider.id);
onClick(provider.id);
}}
onKeyDown={(event) =>
["Enter"].includes(event.code) && onClick(provider.id)
}
>
<div className={styles.list_item_icon_wrapper}>
<ProviderIcon />
{provider.isRemovable ? <SmartcardIcon /> : <ProviderIcon />}
</div>
<div className={styles.list_item_name_wrapper}>
<Typography
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
display: flex;
flex-direction: column;
justify-content: center;
color: var(--pv-color-gray-9);
svg {
width: var(--pv-size-base-6);
height: var(--pv-size-base-6);
Expand Down Expand Up @@ -39,11 +40,13 @@
background-color: var(--pv-color-primary-tint-5);
cursor: default;

.list_item_icon_wrapper svg circle {
fill: var(--pv-color-primary);
}
.list_item_icon_wrapper svg path {
stroke: var(--pv-color-primary);
.list_item_icon_wrapper {
color: var(--pv-color-primary);
}
}

&:focus-visible {
outline: 1px solid var(--pv-color-primary);
z-index: 1;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { Meta, StoryObj } from "@storybook/react";
import { fn } from "@storybook/test";
import { CertificatesProvidersList } from "./CertificatesProvidersList";

const meta: Meta<typeof CertificatesProvidersList> = {
title: "Components/CertificatesProvidersList",
component: CertificatesProvidersList,
};

export default meta;
type Story = StoryObj<typeof CertificatesProvidersList>;

export const Default: Story = {
args: {
currentProviderId: "1",
providers: [
{
id: "1",
name: "Provider 1",
isRemovable: false,
readOnly: true,
},
{
id: "2",
name: "Provider 2",
isRemovable: false,
readOnly: true,
},
{
id: "3",
name: "Smartcard",
isRemovable: true,
readOnly: true,
},
],
onSelect: fn(),
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,20 @@ import { IProviderInfo } from "@peculiar/fortify-client-core";
import { useTranslation } from "react-i18next";
import { CertificatesProvidersListItem } from "../certificates-providers-list-item";
import AttentionCircleIcon from "../../icons/attention-circle.svg?react";
import { Typography } from "@peculiar/react-components";
import { Skeleton, Typography } from "@peculiar/react-components";
import styles from "./styles/index.module.scss";

interface CertificatesProvidersListProps {
providers: IProviderInfo[];
providers: Pick<IProviderInfo, "id" | "name" | "isRemovable" | "readOnly">[];
currentProviderId?: string;
onSelect?: (id: string) => void;
loading?: boolean;
}

export const CertificatesProvidersList: React.FunctionComponent<
CertificatesProvidersListProps
> = (props) => {
const { providers, currentProviderId, onSelect } = props;
const { providers, currentProviderId, loading, onSelect } = props;
const { t } = useTranslation();

return (
Expand All @@ -24,7 +25,17 @@ export const CertificatesProvidersList: React.FunctionComponent<
{t("providers.list.label")}
</Typography>

{!providers?.length ? (
{loading ? (
<div className={styles.loading_skeleton}>
{[...Array(4).keys()].map((index) => (
<Skeleton
className={styles.loading_skeleton_item}
key={`scel-itm-${index}`}
height={50}
/>
))}
</div>
) : !providers?.length ? (
<div className={styles.empty_list}>
<div className={styles.empty_list_icon}>
<AttentionCircleIcon />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,28 @@
}

.list_wrapper {
padding: 0 var(--pv-size-base-2);
padding: 1px var(--pv-size-base-2);
max-height: 100%;
overflow-y: scroll;
.list {
display: flex;
flex-direction: column;
}
}
.loading_skeleton {
padding: 0 var(--pv-size-base-2);
.loading_skeleton_item {
&:nth-child(1) {
width: 92%;
}
&:nth-child(2) {
width: 71%;
}
&:nth-child(4) {
width: 78%;
}
}
}
}

.empty_list {
Expand Down
6 changes: 3 additions & 3 deletions src/icons/provider.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/icons/smartcard.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 581503d

Please sign in to comment.