Skip to content

Commit

Permalink
fix: css and styling (#8)
Browse files Browse the repository at this point in the history
* fix: codebox styling

* fix: width of codebox code

* feat: add image heading to card

* fix: button social text centering

* fix: conditional settings rendering

* feat: auth card heading image

* chore: cleanup

* style: format

* fix: button social text centering

* fix: error messages

* style: format
  • Loading branch information
Benehiko authored Sep 27, 2022
1 parent e630738 commit eb6099b
Show file tree
Hide file tree
Showing 28 changed files with 664 additions and 60 deletions.
13 changes: 9 additions & 4 deletions src/react-components/button-social.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import React from "react"
import {
buttonSocialIconStyle,
buttonSocialIconEndStyle,
buttonSocialIconStartStyle,
ButtonSocialStyle,
buttonSocialStyle,
buttonSocialTitleStyle,
} from "../theme/button-social.css"
import cn from "classnames"

Expand Down Expand Up @@ -42,8 +42,13 @@ export const ButtonSocial = ({
style={{ width: fullWidth ? "100%" : "auto" }}
{...props}
>
<i className={cn(brandClass, buttonSocialIconStyle({ size }))}></i>
<div className={buttonSocialTitleStyle}>{title}</div>
<i className={cn(brandClass, buttonSocialIconStartStyle({ size }))}></i>
{title}
{/* add another hidden icon to the end to center the text */}
<i
className={cn(brandClass, buttonSocialIconEndStyle({ size }))}
style={{ visibility: "hidden", opacity: 0 }}
></i>
</button>
</div>
)
Expand Down
16 changes: 15 additions & 1 deletion src/react-components/card.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import React from "react"
import { cardStyle, cardTitleStyle, gridStyle } from "../theme"
import { cardStyle, cardTitleImage, cardTitleStyle, gridStyle } from "../theme"
import { typographyStyle } from "../theme"
import cn from "classnames"

export interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
heading: string | React.ReactNode
image?: string | React.ReactNode
className?: string
children?: React.ReactNode
}

export const Card = ({
heading,
image,
className,
children,
...props
Expand All @@ -24,6 +26,18 @@ export const Card = ({
{...props}
>
<div className={gridStyle({ gap: 32 })}>
<div className={cardTitleImage}>
{typeof image === "string" ? (
<img
src={image}
alt={`${heading}-image`}
width="100%"
height="100%"
/>
) : (
image
)}
</div>
<div className={cardTitleStyle}>
{typeof heading === "string" ? (
<h3 className={typographyStyle({ type: "regular", size: "small" })}>
Expand Down
22 changes: 14 additions & 8 deletions src/react-components/ory/helpers/error-messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { gridStyle } from "../../../theme"
import { Message } from "../../message"

export type NodeMessagesProps = {
nodes: UiNode[]
nodes?: UiNode[]
uiMessages?: Array<UiText>
}

Expand All @@ -26,18 +26,24 @@ export const NodeMessages = ({
nodes,
uiMessages,
}: NodeMessagesProps): JSX.Element | null => {
const $groupMessages = nodes.reduce<JSX.Element[]>((groups, { messages }) => {
groups.concat(
messages.map(({ text, id }) => nodeMessage({ text, id, key: id })),
)
return groups
}, [])
const $groupMessages = nodes?.reduce<JSX.Element[]>(
(groups, { messages }) => {
groups = groups.concat(
messages.map(({ text, id }) => nodeMessage({ text, id, key: id })),
)
return groups
},
[],
)

const $messages = uiMessages?.map(({ text, id }, key) =>
nodeMessage({ text, id, key }),
)

return ($messages && $messages.length > 0) || $groupMessages.length > 0 ? (
console.dir({ $groupMessages, $messages })

return ($messages && $messages.length > 0) ||
($groupMessages && $groupMessages.length > 0) ? (
<div className={gridStyle({ gap: 16 })}>
{$messages}
{$groupMessages}
Expand Down
1 change: 1 addition & 0 deletions src/react-components/ory/sections/link-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const LinkSection = ({ nodes }: LinkSectionProps): JSX.Element => (
nodes={filterNodesByGroups({
nodes: nodes,
groups: "link",
withoutDefaultGroup: true,
})}
/>
<div className={gridStyle({ gap: 16 })}>
Expand Down
6 changes: 5 additions & 1 deletion src/react-components/ory/sections/login-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ export const LoginSection = ({
return (
<div className={gridStyle({ gap: 32 })}>
<NodeMessages
nodes={filterNodesByGroups({ nodes: nodes, groups: "password" })}
nodes={filterNodesByGroups({
nodes: nodes,
groups: "password",
withoutDefaultGroup: true,
})}
/>
<div className={gridStyle({ gap: 16 })}>
<FilterFlowNodes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const LookupSecretsSection = ({
nodes={filterNodesByGroups({
nodes: nodes,
groups: "lookup_secret",
withoutDefaultGroup: true,
})}
/>
<FilterFlowNodes
Expand Down
6 changes: 5 additions & 1 deletion src/react-components/ory/sections/oidc-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ export const OIDCSection = (flow: SelfServiceFlow): JSX.Element | null => {
return hasOIDC(flow.ui.nodes) ? (
<div className={gridStyle({ gap: 32 })}>
<NodeMessages
nodes={filterNodesByGroups({ nodes: flow.ui.nodes, groups: "oidc" })}
nodes={filterNodesByGroups({
nodes: flow.ui.nodes,
groups: "oidc",
withoutDefaultGroup: true,
})}
/>

{filterNodesByGroups({
Expand Down
6 changes: 5 additions & 1 deletion src/react-components/ory/sections/registration-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ export const RegistrationSection = ({
return hasPassword(nodes) ? (
<div className={gridStyle({ gap: 32 })}>
<NodeMessages
nodes={filterNodesByGroups({ nodes: nodes, groups: "password" })}
nodes={filterNodesByGroups({
nodes: nodes,
groups: "password",
withoutDefaultGroup: true,
})}
/>
<div className={gridStyle({ gap: 16 })}>
<FilterFlowNodes
Expand Down
1 change: 0 additions & 1 deletion src/react-components/ory/user-auth-card.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,6 @@ test("ory auth card recovery flow", async ({ mount }) => {
await expect(component.locator('a[href="/login"]')).toBeVisible()
})

// TODO: change to 2fa flow fixture
test("ory auth card login 2fa flow", async ({ mount }) => {
const component = await mount(
<UserAuthCard
Expand Down
25 changes: 12 additions & 13 deletions src/react-components/ory/user-auth-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export type UserAuthCardProps = {
| RegistrationSectionAdditionalProps
| RecoverySectionAdditionalProps
| VerificationSectionAdditionalProps
cardImage?: string | React.ReactElement
includeScripts?: boolean
icon?: string
className?: string
Expand All @@ -64,6 +65,7 @@ export const UserAuthCard = ({
title,
flowType,
additionalProps,
cardImage,
onSubmit,
includeScripts,
}: UserAuthCardProps): JSX.Element => {
Expand Down Expand Up @@ -170,7 +172,7 @@ export const UserAuthCard = ({
.map((flow, index) =>
index > 0 ? (
<>
<Divider text="or" /> {flow}
<Divider /> {flow}
</>
) : (
flow
Expand Down Expand Up @@ -246,19 +248,16 @@ export const UserAuthCard = ({
{title}
</h2>
}
image={cardImage}
>
<div className={gridStyle({ gap: 32 })}>
{flow.ui.messages &&
flow.ui.messages.length > 0 &&
flow.ui.messages.map((m) => (
<Message
key={m.id}
severity={"error"}
data-testid={`ui/message/${m.id}`}
>
{m.text}
</Message>
))}
<NodeMessages
nodes={filterNodesByGroups({
nodes: flow.ui.nodes,
groups: "default",
})}
uiMessages={flow.ui.messages}
/>
{$oidc && (
<>
<Divider />
Expand Down Expand Up @@ -292,7 +291,7 @@ export const UserAuthCard = ({

{canShowPasswordless() && (
<>
<Divider text="or" />
<Divider />
<UserAuthForm
flow={flow}
submitOnEnter={true}
Expand Down
63 changes: 45 additions & 18 deletions src/react-components/ory/user-settings-card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react"
import { SelfServiceSettingsFlow } from "@ory/client"
import { gridStyle } from "../../theme"
import { colorSprinkle, gridStyle, typographyStyle } from "../../theme"
import { WebAuthnSettingsSection } from "./sections/webauthn-settings-section"
import { LookupSecretSettingsSection } from "./sections/lookup-secret-settings-section"
import {
Expand All @@ -12,9 +12,14 @@ import { PasswordSettingsSection } from "./sections/password-settings-section"
import { useScriptNodes } from "./helpers/node-script"
import { OIDCSettingsSection } from "./sections/oidc-settings-section"
import { TOTPSettingsSection } from "./sections/totp-settings-section"
import { Card } from "../card"
import { Divider } from "../divider"
import { Typography } from "../typography"
import {
hasLookupSecret,
hasOIDC,
hasPassword,
hasTotp,
hasWebauthn,
} from "./helpers/utils"
import cn from "classnames"

export type UserSettingsFlowType =
| "profile"
Expand Down Expand Up @@ -42,44 +47,66 @@ export const UserSettingsCard = ({
useScriptNodes({ nodes: flow.ui.nodes })
}

let $flow = null
let hasFlow = false
let $flow: JSX.Element | null = null
let cardTitle = ""

switch (flowType) {
case "profile":
hasFlow = true
cardTitle = title || "Profile Settings"
$flow = <ProfileSettingsSection flow={flow} />
break
case "password":
cardTitle = title || "Change Password"
$flow = <PasswordSettingsSection flow={flow} />
if (hasPassword(flow.ui.nodes)) {
hasFlow = true
cardTitle = title || "Change Password"
$flow = <PasswordSettingsSection flow={flow} />
}
break
case "webauthn":
cardTitle = title || "Manage Hardware Tokens"
$flow = <WebAuthnSettingsSection flow={flow} />
if (hasWebauthn(flow.ui.nodes)) {
hasFlow = true
cardTitle = title || "Manage Hardware Tokens"
$flow = <WebAuthnSettingsSection flow={flow} />
}
break
case "lookupSecret":
cardTitle = title || "Manage 2FA Backup Recovery Codes"
$flow = <LookupSecretSettingsSection flow={flow} />
if (hasLookupSecret(flow.ui.nodes)) {
hasFlow = true
cardTitle = title || "Manage 2FA Backup Recovery Codes"
$flow = <LookupSecretSettingsSection flow={flow} />
}
break
case "oidc":
cardTitle = title || "Social Sign In"
$flow = <OIDCSettingsSection flow={flow} />
if (hasOIDC(flow.ui.nodes)) {
hasFlow = true
cardTitle = title || "Social Sign In"
$flow = <OIDCSettingsSection flow={flow} />
}
break
case "totp":
cardTitle = title || "Manage 2FA TOTP Authenticator App"
$flow = <TOTPSettingsSection flow={flow} />
if (hasTotp(flow.ui.nodes)) {
hasFlow = true
cardTitle = title || "Manage 2FA TOTP Authenticator App"
$flow = <TOTPSettingsSection flow={flow} />
}
break
default:
$flow = null
}

return $flow ? (
return hasFlow ? (
<div className={gridStyle({ gap: 32 })}>
{cardTitle && (
<Typography size={"headline26"} color={"foregroundDefault"}>
<h3
className={cn(
typographyStyle({ size: "headline26", type: "regular" }),
colorSprinkle({ color: "foregroundDefault" }),
)}
>
{cardTitle}
</Typography>
</h3>
)}
<UserAuthForm flow={flow} onSubmit={onSubmit}>
{$flow}
Expand Down
10 changes: 9 additions & 1 deletion src/stories/Card.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from "react"
import { Story, ComponentMeta } from "@storybook/react"
import { Container } from "./storyhelper"
import { Card, CardProps, Message } from "../react-components"
import logo from "./assets/logo.svg"

export default {
title: "Component/Card",
Expand All @@ -17,6 +18,13 @@ const Template: Story<CardProps> = (args: CardProps) => (
export const NormalCard = Template.bind({})

NormalCard.args = {
header: "Normal Title",
heading: "Normal Title",
children: <Message severity="error">This is an error message.</Message>,
}

export const LogoHeadingCard = Template.bind({})

LogoHeadingCard.args = {
heading: "Logo Heading",
image: logo,
}
Loading

0 comments on commit eb6099b

Please sign in to comment.