mirror of
https://github.com/Steffo99/sophon.git
synced 2024-12-22 14:54:22 +00:00
💥 Add icons and refactor authorization components
This commit is contained in:
parent
285105fe00
commit
dbf4ee8d23
11 changed files with 233 additions and 150 deletions
|
@ -1,42 +1,31 @@
|
||||||
import {navigate} from "@reach/router"
|
import {faCog} from "@fortawesome/free-solid-svg-icons"
|
||||||
import {Box, Form, Heading, Idiomatic as I} from "@steffo/bluelib-react"
|
import {Box, Form, Heading, Idiomatic as I} from "@steffo/bluelib-react"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
import {useInstanceContext} from "../../contexts/instance"
|
import {IconText} from "../elements/IconText"
|
||||||
|
import {AuthorizationAdminPageButton} from "./AuthorizationAdminPageButton"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Box that allows the user to access the Sophon administration page.
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
export function AuthorizationAdminBox(): JSX.Element {
|
export function AuthorizationAdminBox(): JSX.Element {
|
||||||
const instance = useInstanceContext()
|
|
||||||
const authorization = useAuthorizationContext()
|
const authorization = useAuthorizationContext()
|
||||||
|
|
||||||
const canAdministrate =
|
const enabled =
|
||||||
React.useMemo(
|
React.useMemo(
|
||||||
() => (
|
() => authorization && !authorization.state.running && authorization.state.token === undefined,
|
||||||
authorization !== undefined && authorization.state.token === undefined && !authorization.state.running
|
|
||||||
),
|
|
||||||
[authorization],
|
[authorization],
|
||||||
)
|
)
|
||||||
|
|
||||||
const doAdministrate =
|
|
||||||
React.useCallback(
|
|
||||||
async () => {
|
|
||||||
if(!instance) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if(!instance.state.url) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
await navigate(`${instance.state.url}admin`)
|
|
||||||
},
|
|
||||||
[instance],
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box disabled={!canAdministrate}>
|
<Box disabled={!enabled}>
|
||||||
<Heading level={3}>
|
<Heading level={3}>
|
||||||
Server administration
|
<IconText icon={faCog}>
|
||||||
|
Server administration
|
||||||
|
</IconText>
|
||||||
</Heading>
|
</Heading>
|
||||||
<p>
|
<p>
|
||||||
To configure the Sophon server, an account with <I>superuser</I> access is required.
|
To configure the Sophon server, an account with <I>superuser</I> access is required.
|
||||||
|
@ -46,9 +35,7 @@ export function AuthorizationAdminBox(): JSX.Element {
|
||||||
</p>
|
</p>
|
||||||
<Form>
|
<Form>
|
||||||
<Form.Row>
|
<Form.Row>
|
||||||
<Form.Button disabled={!canAdministrate} onClick={doAdministrate}>
|
<AuthorizationAdminPageButton disabled={!enabled}/>
|
||||||
Administrate
|
|
||||||
</Form.Button>
|
|
||||||
</Form.Row>
|
</Form.Row>
|
||||||
</Form>
|
</Form>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
import {faCog} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import {navigate} from "@reach/router"
|
||||||
|
import {Button} from "@steffo/bluelib-react"
|
||||||
|
import * as React from "react"
|
||||||
|
import {useInstanceContext} from "../../contexts/instance"
|
||||||
|
import {CanBeDisabled} from "../../types/ExtraTypes"
|
||||||
|
import {IconText} from "../elements/IconText"
|
||||||
|
|
||||||
|
|
||||||
|
export function AuthorizationAdminPageButton({disabled = false}: CanBeDisabled): JSX.Element {
|
||||||
|
const instance = useInstanceContext()
|
||||||
|
|
||||||
|
const canAdministrate =
|
||||||
|
React.useMemo(
|
||||||
|
() => !disabled && instance,
|
||||||
|
[disabled, instance],
|
||||||
|
)
|
||||||
|
|
||||||
|
const doAdministrate =
|
||||||
|
React.useCallback(
|
||||||
|
async () => {
|
||||||
|
await navigate(`${instance!.state.url}admin`)
|
||||||
|
},
|
||||||
|
[instance],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button disabled={!canAdministrate} onClick={doAdministrate}>
|
||||||
|
<IconText icon={faCog}>
|
||||||
|
Go to the admin page
|
||||||
|
</IconText>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,8 +1,10 @@
|
||||||
|
import {faUser} from "@fortawesome/free-regular-svg-icons"
|
||||||
import {faLock, faUniversity} from "@fortawesome/free-solid-svg-icons"
|
import {faLock, faUniversity} from "@fortawesome/free-solid-svg-icons"
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
||||||
import {Box, Form, Heading, Idiomatic as I} from "@steffo/bluelib-react"
|
import {Box, Form, Heading, Idiomatic as I} from "@steffo/bluelib-react"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
|
import {IconText} from "../elements/IconText"
|
||||||
|
|
||||||
|
|
||||||
export function AuthorizationBrowseBox(): JSX.Element {
|
export function AuthorizationBrowseBox(): JSX.Element {
|
||||||
|
@ -18,15 +20,7 @@ export function AuthorizationBrowseBox(): JSX.Element {
|
||||||
|
|
||||||
const doBrowse =
|
const doBrowse =
|
||||||
React.useCallback(
|
React.useCallback(
|
||||||
async () => {
|
() => authorization!.dispatch({type: "browse"}),
|
||||||
if(!authorization) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
authorization.dispatch({
|
|
||||||
type: "browse",
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[authorization],
|
[authorization],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,7 +28,9 @@ export function AuthorizationBrowseBox(): JSX.Element {
|
||||||
// By disabling the box, the login box is highlighted while a login attempt is running, making the user focus on the login attempt
|
// By disabling the box, the login box is highlighted while a login attempt is running, making the user focus on the login attempt
|
||||||
<Box disabled={!canBrowse}>
|
<Box disabled={!canBrowse}>
|
||||||
<Heading level={3}>
|
<Heading level={3}>
|
||||||
Browse as guest
|
<IconText icon={faUser}>
|
||||||
|
Browse as guest
|
||||||
|
</IconText>
|
||||||
</Heading>
|
</Heading>
|
||||||
<p>
|
<p>
|
||||||
You can browse Sophon without an account.
|
You can browse Sophon without an account.
|
||||||
|
@ -45,7 +41,9 @@ export function AuthorizationBrowseBox(): JSX.Element {
|
||||||
<Form>
|
<Form>
|
||||||
<Form.Row>
|
<Form.Row>
|
||||||
<Form.Button disabled={!canBrowse} onClick={doBrowse}>
|
<Form.Button disabled={!canBrowse} onClick={doBrowse}>
|
||||||
Browse
|
<IconText icon={faUser}>
|
||||||
|
Browse as guest
|
||||||
|
</IconText>
|
||||||
</Form.Button>
|
</Form.Button>
|
||||||
</Form.Row>
|
</Form.Row>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {faSignInAlt} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import {navigate} from "@reach/router"
|
||||||
|
import {Button} from "@steffo/bluelib-react"
|
||||||
|
import * as React from "react"
|
||||||
|
import {useInstanceContext} from "../../contexts/instance"
|
||||||
|
import {useSophonPath} from "../../hooks/useSophonPath"
|
||||||
|
import {CanBeDisabled} from "../../types/ExtraTypes"
|
||||||
|
import {IconText} from "../elements/IconText"
|
||||||
|
|
||||||
|
|
||||||
|
export function AuthorizationGoToSophonButton({disabled = false}: CanBeDisabled): JSX.Element {
|
||||||
|
const instance = useInstanceContext()
|
||||||
|
const location = useSophonPath()
|
||||||
|
|
||||||
|
const canGoTo =
|
||||||
|
React.useMemo(
|
||||||
|
() => !disabled && instance && !location.loggedIn,
|
||||||
|
[disabled, instance, location],
|
||||||
|
)
|
||||||
|
|
||||||
|
const doGoTo =
|
||||||
|
React.useCallback(
|
||||||
|
() => navigate("l/logged-in/"),
|
||||||
|
[],
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button onClick={doGoTo} disabled={!canGoTo}>
|
||||||
|
<IconText icon={faSignInAlt}>
|
||||||
|
Go to {instance?.state.details?.name}
|
||||||
|
</IconText>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
import {faUser as faUserRegular} from "@fortawesome/free-regular-svg-icons"
|
||||||
|
import {faClipboardCheck, faUser as faUserSolid} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import {Box, BringAttention as B, Form, Heading} from "@steffo/bluelib-react"
|
||||||
|
import * as React from "react"
|
||||||
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
|
import {IconText} from "../elements/IconText"
|
||||||
|
import {AuthorizationGoToSophonButton} from "./AuthorizationGoToSophonButton"
|
||||||
|
import {AuthorizationLogoutButton} from "./AuthorizationLogoutButton"
|
||||||
|
|
||||||
|
|
||||||
|
export function AuthorizationLoggedInBox(): JSX.Element {
|
||||||
|
const authorization = useAuthorizationContext()
|
||||||
|
|
||||||
|
const loggedUsername = React.useMemo(
|
||||||
|
() => {
|
||||||
|
if(!authorization?.state.user) {
|
||||||
|
return (
|
||||||
|
<B>
|
||||||
|
<IconText icon={faUserRegular}>
|
||||||
|
a guest
|
||||||
|
</IconText>
|
||||||
|
</B>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (
|
||||||
|
<B>
|
||||||
|
<IconText icon={faUserSolid}>
|
||||||
|
{authorization.state.user.username}
|
||||||
|
</IconText>
|
||||||
|
</B>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[authorization],
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Heading level={3}>
|
||||||
|
<IconText icon={faClipboardCheck}>
|
||||||
|
Logged in
|
||||||
|
</IconText>
|
||||||
|
</Heading>
|
||||||
|
<p>
|
||||||
|
You are currently logged in as {loggedUsername}.
|
||||||
|
</p>
|
||||||
|
<Form>
|
||||||
|
<Form.Row>
|
||||||
|
<AuthorizationGoToSophonButton/>
|
||||||
|
</Form.Row>
|
||||||
|
</Form>
|
||||||
|
<p>
|
||||||
|
To use a different account with Sophon, you'll need to logout from your current one first.
|
||||||
|
</p>
|
||||||
|
<Form>
|
||||||
|
<Form.Row>
|
||||||
|
<AuthorizationLogoutButton/>
|
||||||
|
</Form.Row>
|
||||||
|
</Form>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
import {faExclamationCircle} from "@fortawesome/free-solid-svg-icons"
|
import {faUser} from "@fortawesome/free-solid-svg-icons"
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
|
||||||
import {Box, Form, Heading, useFormState} from "@steffo/bluelib-react"
|
import {Box, Form, Heading, useFormState} from "@steffo/bluelib-react"
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
import {SophonToken, SophonUser} from "../../types/SophonTypes"
|
import {SophonToken, SophonUser} from "../../types/SophonTypes"
|
||||||
import {Validators} from "../../utils/Validators"
|
import {Validators} from "../../utils/Validators"
|
||||||
import {Loading} from "../elements/Loading"
|
import {IconText} from "../elements/IconText"
|
||||||
import {useInstanceAxios} from "../instance/useInstanceAxios"
|
import {useInstanceAxios} from "../instance/useInstanceAxios"
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,9 +73,6 @@ export function AuthorizationLoginBox(): JSX.Element {
|
||||||
if(!authorization) {
|
if(!authorization) {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if(authorization.state.running) {
|
|
||||||
return "color-yellow"
|
|
||||||
}
|
|
||||||
if(error) {
|
if(error) {
|
||||||
return "color-red"
|
return "color-red"
|
||||||
}
|
}
|
||||||
|
@ -85,24 +81,12 @@ export function AuthorizationLoginBox(): JSX.Element {
|
||||||
[authorization, error],
|
[authorization, error],
|
||||||
)
|
)
|
||||||
|
|
||||||
const buttonText =
|
|
||||||
React.useMemo<JSX.Element | null>(
|
|
||||||
() => {
|
|
||||||
if(authorization?.state.running) {
|
|
||||||
return <Loading text={"Logging in..."}/>
|
|
||||||
}
|
|
||||||
if(error) {
|
|
||||||
return <><FontAwesomeIcon icon={faExclamationCircle}/> Login</>
|
|
||||||
}
|
|
||||||
return <>Login</>
|
|
||||||
},
|
|
||||||
[error, authorization],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box disabled={!canLogin}>
|
<Box disabled={!canLogin}>
|
||||||
<Heading level={3}>
|
<Heading level={3}>
|
||||||
Login
|
<IconText icon={faUser}>
|
||||||
|
Login
|
||||||
|
</IconText>
|
||||||
</Heading>
|
</Heading>
|
||||||
<p>
|
<p>
|
||||||
To use most features of Sophon, an account is required.
|
To use most features of Sophon, an account is required.
|
||||||
|
@ -128,7 +112,9 @@ export function AuthorizationLoginBox(): JSX.Element {
|
||||||
/>
|
/>
|
||||||
<Form.Row>
|
<Form.Row>
|
||||||
<Form.Button type={"submit"} bluelibClassNames={buttonColor} disabled={!canClickLogin} onClick={doLogin}>
|
<Form.Button type={"submit"} bluelibClassNames={buttonColor} disabled={!canClickLogin} onClick={doLogin}>
|
||||||
{buttonText}
|
<IconText icon={faUser} spin={authorization?.state.running}>
|
||||||
|
Login
|
||||||
|
</IconText>
|
||||||
</Form.Button>
|
</Form.Button>
|
||||||
</Form.Row>
|
</Form.Row>
|
||||||
</Form>
|
</Form>
|
||||||
|
|
|
@ -1,86 +0,0 @@
|
||||||
import {faUser as faUserRegular} from "@fortawesome/free-regular-svg-icons"
|
|
||||||
import {faChevronRight, faExclamationCircle, faSignOutAlt, faTimesCircle, faUser as faUserSolid} from "@fortawesome/free-solid-svg-icons"
|
|
||||||
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
|
||||||
import {navigate} from "@reach/router"
|
|
||||||
import {Box, Form, Heading, Idiomatic as I} from "@steffo/bluelib-react"
|
|
||||||
import * as React from "react"
|
|
||||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
|
||||||
|
|
||||||
|
|
||||||
export function AuthorizationLogoutBox(): JSX.Element {
|
|
||||||
const authorization = useAuthorizationContext()
|
|
||||||
|
|
||||||
const loggedUsername = React.useMemo(
|
|
||||||
() => {
|
|
||||||
if(!authorization) {
|
|
||||||
return <I bluelibClassNames={"color-red"}>
|
|
||||||
<FontAwesomeIcon icon={faExclamationCircle}/> Not in a AuthorizationContext
|
|
||||||
</I>
|
|
||||||
}
|
|
||||||
else if(authorization.state.user === undefined) {
|
|
||||||
return <I bluelibClassNames={"color-red"}>
|
|
||||||
<FontAwesomeIcon icon={faTimesCircle}/> Not logged in
|
|
||||||
</I>
|
|
||||||
}
|
|
||||||
else if(authorization.state.user === null) {
|
|
||||||
return <I>
|
|
||||||
<FontAwesomeIcon icon={faUserRegular}/> a guest
|
|
||||||
</I>
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return <I>
|
|
||||||
<FontAwesomeIcon icon={faUserSolid}/> {authorization.state.user.username}
|
|
||||||
</I>
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[authorization],
|
|
||||||
)
|
|
||||||
|
|
||||||
const canLogout = React.useMemo(
|
|
||||||
() => (
|
|
||||||
authorization !== undefined && authorization.state.user !== undefined && !authorization.state.running
|
|
||||||
),
|
|
||||||
[authorization],
|
|
||||||
)
|
|
||||||
|
|
||||||
const doLogout = React.useCallback(
|
|
||||||
() => {
|
|
||||||
if(!authorization) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
authorization.dispatch({
|
|
||||||
type: "clear",
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[authorization],
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box disabled={!canLogout}>
|
|
||||||
<Heading level={3}>
|
|
||||||
Logout
|
|
||||||
</Heading>
|
|
||||||
<p>
|
|
||||||
You are currently logged in as {loggedUsername}.
|
|
||||||
</p>
|
|
||||||
<Form>
|
|
||||||
<Form.Row>
|
|
||||||
<Form.Button onClick={() => navigate("l/logged-in/")}>
|
|
||||||
<FontAwesomeIcon icon={faChevronRight}/> Continue to Sophon
|
|
||||||
</Form.Button>
|
|
||||||
</Form.Row>
|
|
||||||
</Form>
|
|
||||||
<p>
|
|
||||||
To use a different account with Sophon, you'll need to logout from your current one first.
|
|
||||||
</p>
|
|
||||||
<Form>
|
|
||||||
<Form.Row>
|
|
||||||
<Form.Button disabled={!canLogout} onClick={doLogout}>
|
|
||||||
<FontAwesomeIcon icon={faSignOutAlt}/> Logout
|
|
||||||
</Form.Button>
|
|
||||||
</Form.Row>
|
|
||||||
</Form>
|
|
||||||
</Box>
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import {faSignOutAlt} from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import {Button} from "@steffo/bluelib-react"
|
||||||
|
import * as React from "react"
|
||||||
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
|
import {CanBeDisabled} from "../../types/ExtraTypes"
|
||||||
|
import {IconText} from "../elements/IconText"
|
||||||
|
|
||||||
|
|
||||||
|
export function AuthorizationLogoutButton({disabled = false}: CanBeDisabled): JSX.Element {
|
||||||
|
const authorization =
|
||||||
|
useAuthorizationContext()
|
||||||
|
|
||||||
|
const canLogout =
|
||||||
|
React.useMemo(
|
||||||
|
() => (
|
||||||
|
!disabled && authorization !== undefined && authorization.state.user !== undefined && !authorization.state.running
|
||||||
|
),
|
||||||
|
[disabled, authorization],
|
||||||
|
)
|
||||||
|
|
||||||
|
const onClick =
|
||||||
|
React.useCallback(
|
||||||
|
() => authorization!.dispatch({type: "clear"}),
|
||||||
|
[authorization],
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button disabled={!canLogout} onClick={onClick}>
|
||||||
|
<IconText icon={faSignOutAlt}>
|
||||||
|
Logout
|
||||||
|
</IconText>
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
|
@ -3,8 +3,8 @@ import * as React from "react"
|
||||||
import {useAuthorizationContext} from "../../contexts/authorization"
|
import {useAuthorizationContext} from "../../contexts/authorization"
|
||||||
import {AuthorizationAdminBox} from "./AuthorizationAdminBox"
|
import {AuthorizationAdminBox} from "./AuthorizationAdminBox"
|
||||||
import {AuthorizationBrowseBox} from "./AuthorizationBrowseBox"
|
import {AuthorizationBrowseBox} from "./AuthorizationBrowseBox"
|
||||||
|
import {AuthorizationLoggedInBox} from "./AuthorizationLoggedInBox"
|
||||||
import {AuthorizationLoginBox} from "./AuthorizationLoginBox"
|
import {AuthorizationLoginBox} from "./AuthorizationLoginBox"
|
||||||
import {AuthorizationLogoutBox} from "./AuthorizationLogoutBox"
|
|
||||||
|
|
||||||
|
|
||||||
export function AuthorizationStepPage(): JSX.Element | null {
|
export function AuthorizationStepPage(): JSX.Element | null {
|
||||||
|
@ -18,7 +18,7 @@ export function AuthorizationStepPage(): JSX.Element | null {
|
||||||
if(authorization.state.token === null) {
|
if(authorization.state.token === null) {
|
||||||
return (
|
return (
|
||||||
<Chapter>
|
<Chapter>
|
||||||
<AuthorizationLogoutBox/>
|
<AuthorizationLoggedInBox/>
|
||||||
<AuthorizationLoginBox/>
|
<AuthorizationLoginBox/>
|
||||||
<AuthorizationAdminBox/>
|
<AuthorizationAdminBox/>
|
||||||
</Chapter>
|
</Chapter>
|
||||||
|
@ -28,7 +28,7 @@ export function AuthorizationStepPage(): JSX.Element | null {
|
||||||
return (
|
return (
|
||||||
<Chapter>
|
<Chapter>
|
||||||
<AuthorizationBrowseBox/>
|
<AuthorizationBrowseBox/>
|
||||||
<AuthorizationLogoutBox/>
|
<AuthorizationLoggedInBox/>
|
||||||
<AuthorizationAdminBox/>
|
<AuthorizationAdminBox/>
|
||||||
</Chapter>
|
</Chapter>
|
||||||
)
|
)
|
||||||
|
|
24
frontend/src/components/elements/IconText.tsx
Normal file
24
frontend/src/components/elements/IconText.tsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import {FontAwesomeIcon, FontAwesomeIconProps} from "@fortawesome/react-fontawesome"
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The props of {@link IconText}.
|
||||||
|
*/
|
||||||
|
export interface IconTextProps extends FontAwesomeIconProps {
|
||||||
|
children: React.ReactNode,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A {@link FontAwesomeIcon} (`icon`) followed by some text (`children`).
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
export function IconText({children, ...props}: IconTextProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<FontAwesomeIcon {...props}/> {children}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
|
@ -40,3 +40,11 @@ export interface WithViewSet<T> {
|
||||||
export interface WithSlug {
|
export interface WithSlug {
|
||||||
slug: string,
|
slug: string,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Props of an object that can be disabled.
|
||||||
|
*/
|
||||||
|
export interface CanBeDisabled {
|
||||||
|
disabled?: boolean,
|
||||||
|
}
|
Loading…
Reference in a new issue