New clickable card that behaves like a button (#3248)
This commit is contained in:
parent
df6526311a
commit
573fb2ff03
5 changed files with 43 additions and 24 deletions
32
apps/admin-ui/src/components/keycloak-card/ClickableCard.tsx
Normal file
32
apps/admin-ui/src/components/keycloak-card/ClickableCard.tsx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import { KeyboardEvent } from "react";
|
||||||
|
import { Card, CardProps } from "@patternfly/react-core";
|
||||||
|
|
||||||
|
type ClickableCardProps = Omit<CardProps, "onClick"> & {
|
||||||
|
onClick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ClickableCard = ({
|
||||||
|
children,
|
||||||
|
onClick,
|
||||||
|
...rest
|
||||||
|
}: ClickableCardProps) => {
|
||||||
|
const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
|
||||||
|
if (e.key === " " || e.key === "Enter" || e.key === "Spacebar") {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
className="keycloak-empty-state-card"
|
||||||
|
role="button"
|
||||||
|
aria-pressed="false"
|
||||||
|
tabIndex={0}
|
||||||
|
isHoverable
|
||||||
|
onKeyDown={onKeyDown}
|
||||||
|
onClick={onClick}
|
||||||
|
{...rest}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
|
@ -1,6 +1,5 @@
|
||||||
import { ReactElement, useState } from "react";
|
import { ReactElement, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Card,
|
|
||||||
CardHeader,
|
CardHeader,
|
||||||
CardActions,
|
CardActions,
|
||||||
CardTitle,
|
CardTitle,
|
||||||
|
@ -15,6 +14,7 @@ import {
|
||||||
import "./keycloak-card.css";
|
import "./keycloak-card.css";
|
||||||
import { useRouteMatch } from "react-router-dom";
|
import { useRouteMatch } from "react-router-dom";
|
||||||
import { useNavigate } from "react-router-dom-v5-compat";
|
import { useNavigate } from "react-router-dom-v5-compat";
|
||||||
|
import { ClickableCard } from "./ClickableCard";
|
||||||
|
|
||||||
export type KeycloakCardProps = {
|
export type KeycloakCardProps = {
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -54,7 +54,7 @@ export const KeycloakCard = ({
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card role="button" isSelectable onClick={openSettings}>
|
<ClickableCard isSelectable onClick={openSettings}>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardActions>
|
<CardActions>
|
||||||
{dropdownItems && (
|
{dropdownItems && (
|
||||||
|
@ -84,6 +84,6 @@ export const KeycloakCard = ({
|
||||||
</FlexItem>
|
</FlexItem>
|
||||||
</Flex>
|
</Flex>
|
||||||
</CardFooter>
|
</CardFooter>
|
||||||
</Card>
|
</ClickableCard>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,6 @@ import {
|
||||||
Badge,
|
Badge,
|
||||||
Button,
|
Button,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
Card,
|
|
||||||
CardTitle,
|
CardTitle,
|
||||||
Dropdown,
|
Dropdown,
|
||||||
DropdownGroup,
|
DropdownGroup,
|
||||||
|
@ -39,6 +38,7 @@ import { ManageOrderDialog } from "./ManageOrderDialog";
|
||||||
import { toIdentityProvider } from "./routes/IdentityProvider";
|
import { toIdentityProvider } from "./routes/IdentityProvider";
|
||||||
import { toIdentityProviderCreate } from "./routes/IdentityProviderCreate";
|
import { toIdentityProviderCreate } from "./routes/IdentityProviderCreate";
|
||||||
import helpUrls from "../help-urls";
|
import helpUrls from "../help-urls";
|
||||||
|
import { ClickableCard } from "../components/keycloak-card/ClickableCard";
|
||||||
|
|
||||||
export default function IdentityProvidersSection() {
|
export default function IdentityProvidersSection() {
|
||||||
const { t } = useTranslation("identity-providers");
|
const { t } = useTranslation("identity-providers");
|
||||||
|
@ -190,11 +190,8 @@ export default function IdentityProvidersSection() {
|
||||||
<hr className="pf-u-mb-lg" />
|
<hr className="pf-u-mb-lg" />
|
||||||
<Gallery hasGutter>
|
<Gallery hasGutter>
|
||||||
{sortBy(identityProviders[group], "name").map((provider) => (
|
{sortBy(identityProviders[group], "name").map((provider) => (
|
||||||
<Card
|
<ClickableCard
|
||||||
className="keycloak-empty-state-card"
|
|
||||||
role="button"
|
|
||||||
key={provider.id}
|
key={provider.id}
|
||||||
isHoverable
|
|
||||||
data-testid={`${provider.id}-card`}
|
data-testid={`${provider.id}-card`}
|
||||||
onClick={() => navigateToCreate(provider.id)}
|
onClick={() => navigateToCreate(provider.id)}
|
||||||
>
|
>
|
||||||
|
@ -206,7 +203,7 @@ export default function IdentityProvidersSection() {
|
||||||
<SplitItem isFilled>{provider.name}</SplitItem>
|
<SplitItem isFilled>{provider.name}</SplitItem>
|
||||||
</Split>
|
</Split>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</Card>
|
</ClickableCard>
|
||||||
))}
|
))}
|
||||||
</Gallery>
|
</Gallery>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
|
|
@ -12,7 +12,6 @@ export const FontAwesomeIcon = ({ icon }: FontAwesomeIconProps) => {
|
||||||
<img
|
<img
|
||||||
src={environment.resourceUrl + "/bitbucket-brands.svg"}
|
src={environment.resourceUrl + "/bitbucket-brands.svg"}
|
||||||
{...styles}
|
{...styles}
|
||||||
aria-label="bitbucket icon"
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "microsoft":
|
case "microsoft":
|
||||||
|
@ -20,7 +19,6 @@ export const FontAwesomeIcon = ({ icon }: FontAwesomeIconProps) => {
|
||||||
<img
|
<img
|
||||||
src={environment.resourceUrl + "/microsoft-brands.svg"}
|
src={environment.resourceUrl + "/microsoft-brands.svg"}
|
||||||
{...styles}
|
{...styles}
|
||||||
aria-label="microsoft icon"
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "instagram":
|
case "instagram":
|
||||||
|
@ -28,16 +26,11 @@ export const FontAwesomeIcon = ({ icon }: FontAwesomeIconProps) => {
|
||||||
<img
|
<img
|
||||||
src={environment.resourceUrl + "/instagram-brands.svg"}
|
src={environment.resourceUrl + "/instagram-brands.svg"}
|
||||||
{...styles}
|
{...styles}
|
||||||
aria-label="instagram icon"
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
case "paypal":
|
case "paypal":
|
||||||
return (
|
return (
|
||||||
<img
|
<img src={environment.resourceUrl + "/paypal-brands.svg"} {...styles} />
|
||||||
src={environment.resourceUrl + "/paypal-brands.svg"}
|
|
||||||
{...styles}
|
|
||||||
aria-label="paypal icon"
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {
|
import {
|
||||||
AlertVariant,
|
AlertVariant,
|
||||||
ButtonVariant,
|
ButtonVariant,
|
||||||
Card,
|
|
||||||
CardTitle,
|
CardTitle,
|
||||||
DropdownItem,
|
DropdownItem,
|
||||||
Gallery,
|
Gallery,
|
||||||
|
@ -28,9 +27,10 @@ import { useRealm } from "../context/realm-context/RealmContext";
|
||||||
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
import { useServerInfo } from "../context/server-info/ServerInfoProvider";
|
||||||
import { toUpperCase } from "../util";
|
import { toUpperCase } from "../util";
|
||||||
import { toProvider } from "./routes/NewProvider";
|
import { toProvider } from "./routes/NewProvider";
|
||||||
|
import { ClickableCard } from "../components/keycloak-card/ClickableCard";
|
||||||
|
import helpUrls from "../help-urls";
|
||||||
|
|
||||||
import "./user-federation.css";
|
import "./user-federation.css";
|
||||||
import helpUrls from "../help-urls";
|
|
||||||
|
|
||||||
export default function UserFederationSection() {
|
export default function UserFederationSection() {
|
||||||
const [userFederations, setUserFederations] =
|
const [userFederations, setUserFederations] =
|
||||||
|
@ -193,11 +193,8 @@ export default function UserFederationSection() {
|
||||||
<hr className="pf-u-mb-lg" />
|
<hr className="pf-u-mb-lg" />
|
||||||
<Gallery hasGutter>
|
<Gallery hasGutter>
|
||||||
{providers.map((p) => (
|
{providers.map((p) => (
|
||||||
<Card
|
<ClickableCard
|
||||||
key={p.id}
|
key={p.id}
|
||||||
className="keycloak-empty-state-card"
|
|
||||||
role="button"
|
|
||||||
isHoverable
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
navigate(toProvider({ realm, providerId: p.id! }))
|
navigate(toProvider({ realm, providerId: p.id! }))
|
||||||
}
|
}
|
||||||
|
@ -216,7 +213,7 @@ export default function UserFederationSection() {
|
||||||
</SplitItem>
|
</SplitItem>
|
||||||
</Split>
|
</Split>
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</Card>
|
</ClickableCard>
|
||||||
))}
|
))}
|
||||||
</Gallery>
|
</Gallery>
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in a new issue