Skip to content

Commit

Permalink
make spinner a component (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
samuelcolvin authored Feb 12, 2024
1 parent 10a0a66 commit f26041e
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 23 deletions.
13 changes: 13 additions & 0 deletions demo/components_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ class Delivery(BaseModel):
],
class_name='border-top mt-3 pt-1',
),
c.Div(
components=[
c.Heading(text='Spinner', level=2),
c.Paragraph(
text=(
'A component displayed while waiting for content to load, '
'this is also used automatically while loading server content.'
)
),
c.Spinner(text='Content incoming...'),
],
class_name='border-top mt-3 pt-1',
),
c.Div(
components=[
c.Heading(text='Video', level=2),
Expand Down
8 changes: 8 additions & 0 deletions src/npm-fastui-bootstrap/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,5 +150,13 @@ export const classNameGenerator: ClassNameGenerator = ({
} else {
return 'error-alert alert alert-danger m-3'
}
case 'Spinner':
if (subElement === 'text') {
return 'd-flex justify-content-center mb-2'
} else if (subElement === 'animation') {
return 'd-flex justify-content-center'
} else {
return 'my-4'
}
}
}
7 changes: 0 additions & 7 deletions src/npm-fastui-prebuilt/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ export default function App() {
classNameGenerator={bootstrap.classNameGenerator}
customRender={customRender}
NotFound={NotFound}
Spinner={Spinner}
Transition={Transition}
/>
)
Expand All @@ -30,12 +29,6 @@ const NotFound = ({ url }: { url: string }) => (
</div>
)

const Spinner = () => (
<div className="container d-flex justify-content-center my-3" role="status">
<div className="spinner" />
</div>
)

const Transition: FC<{ children: ReactNode; transitioning: boolean }> = ({ children, transitioning }) => (
<>
<div className={renderClassName({ 'transition-overlay': true, transitioning })} />
Expand Down
15 changes: 7 additions & 8 deletions src/npm-fastui-prebuilt/src/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,17 @@ h6 {
}

// custom spinner from https://cssloaders.github.io/

.spinner,
.spinner:before,
.spinner:after {
.fastui-spinner-animation,
.fastui-spinner-animation:before,
.fastui-spinner-animation:after {
border-radius: 50%;
width: 2.5em;
height: 2.5em;
animation-fill-mode: both;
animation: dots 1.8s infinite ease-in-out;
animation: spinner-dots 1.8s infinite ease-in-out;
}
.spinner {
.fastui-spinner-animation {
top: -2.5em;
color: var(--bs-dark);
font-size: 7px;
position: relative;
Expand All @@ -105,8 +105,7 @@ h6 {
left: 3.5em;
}
}

@keyframes dots {
@keyframes spinner-dots {
0%,
80%,
100% {
Expand Down
2 changes: 0 additions & 2 deletions src/npm-fastui/src/Defaults.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { FC, ReactNode } from 'react'

export const DefaultSpinner: FC = () => <div>loading...</div>

export const DefaultNotFound: FC<{ url: string }> = ({ url }) => <div>Page not found: {url}</div>

// default here does nothing
Expand Down
9 changes: 5 additions & 4 deletions src/npm-fastui/src/components/ServerLoad.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,16 @@ import type { ServerLoad, PageEvent, FastProps } from '../models'

import { ErrorContext } from '../hooks/error'
import { useRequest, useSSE } from '../tools'
import { DefaultSpinner, DefaultNotFound, DefaultTransition } from '../Defaults'
import { DefaultNotFound, DefaultTransition } from '../Defaults'
import { ConfigContext } from '../hooks/config'
import { usePageEventListen } from '../events'
import { EventContextProvider, useEventContext } from '../hooks/eventContext'
import { LocationContext } from '../hooks/locationContext'

import { AnyCompList } from './index'

import { SpinnerComp } from './spinner'

export const ServerLoadComp: FC<ServerLoad> = ({ path, components, loadTrigger, sse }) => {
if (components) {
return <ServerLoadDefer path={path} components={components} loadTrigger={loadTrigger} sse={sse} />
Expand Down Expand Up @@ -103,8 +105,7 @@ const Render: FC<{ propsList: FastProps[] | null; notFoundUrl?: string; transiti
transitioning,
}) => {
const { error } = useContext(ErrorContext)
const { Spinner, NotFound, Transition } = useContext(ConfigContext)
const SpinnerComp = Spinner ?? DefaultSpinner
const { NotFound, Transition } = useContext(ConfigContext)
const NotFoundComp = NotFound ?? DefaultNotFound
const TransitionComp = Transition ?? DefaultTransition

Expand All @@ -114,7 +115,7 @@ const Render: FC<{ propsList: FastProps[] | null; notFoundUrl?: string; transiti
if (error) {
return <></>
} else {
return <SpinnerComp />
return <SpinnerComp type="Spinner" />
}
} else {
return (
Expand Down
4 changes: 4 additions & 0 deletions src/npm-fastui/src/components/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { IframeComp } from './Iframe'
import { VideoComp } from './video'
import { FireEventComp } from './FireEvent'
import { ErrorComp } from './error'
import { SpinnerComp } from './spinner'
import { CustomComp } from './Custom'

// TODO some better way to export components
Expand Down Expand Up @@ -73,6 +74,7 @@ export {
VideoComp,
FireEventComp,
ErrorComp,
SpinnerComp,
CustomComp,
LinkRender,
}
Expand Down Expand Up @@ -160,6 +162,8 @@ export const AnyComp: FC<FastProps> = (props) => {
return <FireEventComp {...props} />
case 'Error':
return <ErrorComp {...props} />
case 'Spinner':
return <SpinnerComp {...props} />
case 'Custom':
return <CustomComp {...props} />
default:
Expand Down
18 changes: 18 additions & 0 deletions src/npm-fastui/src/components/spinner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { FC } from 'react'

import type { Spinner } from '../models'

import { useClassName } from '../hooks/className'

export const SpinnerComp: FC<Spinner> = (props) => {
const { text } = props

return (
<div className={useClassName(props)}>
<div className={useClassName(props, { el: 'text' })}>{text}</div>
<div className={useClassName(props, { el: 'animation' })}>
<div className="fastui-spinner-animation">loading...</div>
</div>
</div>
)
}
1 change: 0 additions & 1 deletion src/npm-fastui/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export interface FastUIProps {
APIPathMode?: 'append' | 'query'
// start of the path to remove from the URL before making a request to the API
APIPathStrip?: string
Spinner?: FC
NotFound?: FC<{ url: string }>
Transition?: FC<{ children: ReactNode; transitioning: boolean }>
classNameGenerator?: ClassNameGenerator
Expand Down
6 changes: 6 additions & 0 deletions src/npm-fastui/src/models.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export type FastProps =
| Video
| FireEvent
| Error
| Spinner
| Custom
| Table
| Pagination
Expand Down Expand Up @@ -256,6 +257,11 @@ export interface Error {
type: 'Error'
children?: ReactNode
}
export interface Spinner {
text?: string
className?: ClassName
type: 'Spinner'
}
export interface Custom {
data: JsonData
subType: string
Expand Down
11 changes: 10 additions & 1 deletion src/python-fastui/fastui/components/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
from .tables import Pagination, Table

__all__ = (
# first we include everything from `AnyComponent`
# first we include all components from this file
'Text',
'Paragraph',
'PageTitle',
Expand All @@ -48,7 +48,9 @@
'Iframe',
'FireEvent',
'Error',
'Spinner',
'Custom',
# then we include components from other files
'Table',
'Pagination',
'Display',
Expand Down Expand Up @@ -291,6 +293,12 @@ def __get_pydantic_json_schema__(
return json_schema


class Spinner(_p.BaseModel, extra='forbid'):
text: _t.Union[str, None] = None
class_name: _class_name.ClassNameField = None
type: _t.Literal['Spinner'] = 'Spinner'


class Custom(_p.BaseModel, extra='forbid'):
data: _types.JsonData
sub_type: str = _p.Field(serialization_alias='subType')
Expand Down Expand Up @@ -322,6 +330,7 @@ class Custom(_p.BaseModel, extra='forbid'):
Video,
FireEvent,
Error,
Spinner,
Custom,
Table,
Pagination,
Expand Down

0 comments on commit f26041e

Please sign in to comment.