Skip to content

Commit 85b48fc

Browse files
Dejiahsamuelcolvin
andauthored
Added footer component (#61)
Co-authored-by: Samuel Colvin <s@muelcolvin.com>
1 parent 106d6c5 commit 85b48fc

File tree

12 files changed

+132
-38
lines changed

12 files changed

+132
-38
lines changed

demo/main.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ def api_index() -> list[AnyComponent]:
2828
* `Link` — example [here](/components#link-list)
2929
* `LinkList` — example [here](/components#link-list)
3030
* `Navbar` — see the top of this page
31+
* `Footer` — see the bottom of this page
3132
* `Modal` — static example [here](/components#button-and-modal), dynamic content example [here](/components#dynamic-modal)
3233
* `ServerLoad` — see [dynamic modal example](/components#dynamic-modal) and [SSE example](/components#server-load-sse)
3334
* `Image` - example [here](/components#image)

demo/shared.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,14 @@ def demo_page(*components: AnyComponent, title: str | None = None) -> list[AnyCo
4040
*components,
4141
],
4242
),
43+
c.Footer(
44+
extra_text='FastUI Demo',
45+
links=[
46+
c.Link(
47+
components=[c.Text(text='Github')], on_click=GoToEvent(url='https://github.com/pydantic/FastUI')
48+
),
49+
c.Link(components=[c.Text(text='PyPI')], on_click=GoToEvent(url='https://pypi.org/project/fastui/')),
50+
c.Link(components=[c.Text(text='NPM')], on_click=GoToEvent(url='https://www.npmjs.com/org/pydantic/')),
51+
],
52+
),
4353
]

demo/tests.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ def test_api_root():
4040
],
4141
'type': 'Page',
4242
},
43+
{
44+
'extraText': 'FastUI Demo',
45+
'links': IsList(length=3),
46+
'type': 'Footer',
47+
},
4348
]
4449

4550

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { FC } from 'react'
2+
import { components, models, useClassName } from 'fastui'
3+
4+
export const Footer: FC<models.Footer> = (props) => {
5+
const links = props.links.map((link) => {
6+
link.mode = link.mode || 'footer'
7+
return link
8+
})
9+
const extraProp = useClassName(props, { el: 'extra' })
10+
return (
11+
<footer className={useClassName(props)}>
12+
<ul className={useClassName(props, { el: 'link-list' })}>
13+
{links.map((link, i) => (
14+
<li key={i} className="nav-item">
15+
<components.LinkComp {...link} />
16+
</li>
17+
))}
18+
</ul>
19+
{props.extraText && <div className={extraProp}>{props.extraText}</div>}
20+
</footer>
21+
)
22+
}

src/npm-fastui-bootstrap/src/index.tsx

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ import type { ClassNameGenerator, CustomRender, models } from 'fastui'
55
import { Modal } from './modal'
66
import { Navbar } from './navbar'
77
import { Pagination } from './pagination'
8+
import { Footer } from './footer'
89

910
export const customRender: CustomRender = (props) => {
1011
const { type } = props
1112
switch (type) {
1213
case 'Navbar':
1314
return () => <Navbar {...props} />
15+
case 'Footer':
16+
return () => <Footer {...props} />
1417
case 'Modal':
1518
return () => <Modal {...props} />
1619
case 'Pagination':
@@ -26,7 +29,7 @@ export const classNameGenerator: ClassNameGenerator = ({
2629
const { type } = props
2730
switch (type) {
2831
case 'Page':
29-
return 'container mt-80'
32+
return 'container mt-80 mb-3 page'
3033
case 'Button':
3134
return 'btn btn-primary'
3235
case 'Table':
@@ -104,10 +107,20 @@ export const classNameGenerator: ClassNameGenerator = ({
104107
default:
105108
return 'border-bottom fixed-top bg-body'
106109
}
110+
case 'Footer':
111+
switch (subElement) {
112+
case 'link-list':
113+
return 'nav justify-content-center pb-1'
114+
case 'extra':
115+
return 'text-center text-muted pb-3'
116+
default:
117+
return 'border-top pt-1 mt-auto bg-body'
118+
}
107119
case 'Link':
108120
return {
109121
active: pathMatch(props.active, fullPath),
110-
'nav-link': props.mode === 'navbar' || props.mode === 'tabs',
122+
'nav-link': props.mode === 'navbar' || props.mode === 'tabs' || props.mode === 'footer',
123+
'text-muted': props.mode === 'footer',
111124
}
112125
case 'LinkList':
113126
if (subElement === 'link-list-item' && props.mode) {

src/npm-fastui-prebuilt/src/App.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,14 @@ import { FC, ReactNode } from 'react'
44

55
export default function App() {
66
return (
7-
<div className="top-offset">
8-
<FastUI
9-
rootUrl="/api"
10-
classNameGenerator={bootstrap.classNameGenerator}
11-
customRender={customRender}
12-
NotFound={NotFound}
13-
Spinner={Spinner}
14-
Transition={Transition}
15-
/>
16-
</div>
7+
<FastUI
8+
rootUrl="/api"
9+
classNameGenerator={bootstrap.classNameGenerator}
10+
customRender={customRender}
11+
NotFound={NotFound}
12+
Spinner={Spinner}
13+
Transition={Transition}
14+
/>
1715
)
1816
}
1917

@@ -33,10 +31,10 @@ const Spinner = () => (
3331
)
3432

3533
const Transition: FC<{ children: ReactNode; transitioning: boolean }> = ({ children, transitioning }) => (
36-
<div>
34+
<>
3735
<div className={renderClassName({ 'transition-overlay': true, transitioning })} />
3836
{children}
39-
</div>
37+
</>
4038
)
4139

4240
const customRender: CustomRender = (props) => {

src/npm-fastui-prebuilt/src/main.scss

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,20 @@ $link-color: #0d6efd; // bootstrap primary
33

44
@import 'bootstrap/scss/bootstrap';
55

6+
html, body, #root {
7+
height: 100%;
8+
}
9+
10+
#root {
11+
display: flex;
12+
flex-direction: column;
13+
}
14+
15+
.page {
16+
// margin-top because the top is sticky
17+
margin-top: 70px;
18+
}
19+
620
:root {
721
--bs-font-sans-serif: 'IBM Plex Sans', sans-serif;
822
--bs-code-color: rgb(31, 35, 40);
@@ -19,16 +33,8 @@ body {
1933
backdrop-filter: blur(8px);
2034
}
2135

22-
.top-offset {
23-
margin-top: 70px;
24-
h1,
25-
h2,
26-
h3,
27-
h4,
28-
h5,
29-
h6 {
30-
scroll-margin-top: 60px;
31-
}
36+
h1, h2, h3, h4, h5, h6 {
37+
scroll-margin-top: 60px;
3238
}
3339

3440
.transition-overlay {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { Footer } from '../models'
2+
3+
import { useClassName } from '../hooks/className'
4+
5+
import { LinkComp } from './link'
6+
7+
export const FooterComp = (props: Footer) => {
8+
const links = props.links.map((link) => {
9+
link.mode = link.mode || 'footer'
10+
return link
11+
})
12+
const extraTextClassName = useClassName(props, { el: 'extra' })
13+
return (
14+
<footer className={useClassName(props)}>
15+
{links.map((link, i) => (
16+
<LinkComp key={i} {...link} />
17+
))}
18+
{props.extraText && <div className={extraTextClassName}>{props.extraText}</div>}
19+
</footer>
20+
)
21+
}

src/npm-fastui/src/components/index.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { PaginationComp } from './pagination'
3131
import { DetailsComp } from './details'
3232
import { DisplayComp } from './display'
3333
import { JsonComp } from './Json'
34+
import { FooterComp } from './footer'
3435
import { ServerLoadComp } from './ServerLoad'
3536
import { ImageComp } from './image'
3637
import { IframeComp } from './Iframe'
@@ -63,6 +64,7 @@ export {
6364
DetailsComp,
6465
DisplayComp,
6566
JsonComp,
67+
FooterComp,
6668
ServerLoadComp,
6769
ImageComp,
6870
IframeComp,
@@ -116,6 +118,8 @@ export const AnyComp: FC<FastProps> = (props) => {
116118
return <LinkListComp {...props} />
117119
case 'Navbar':
118120
return <NavbarComp {...props} />
121+
case 'Footer':
122+
return <FooterComp {...props} />
119123
case 'Form':
120124
case 'ModelForm':
121125
return <FormComp {...props} />

src/npm-fastui/src/index.tsx

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,15 @@ export interface FastUIProps {
3636
export function FastUI(props: FastUIProps) {
3737
const { classNameGenerator, DisplayError, devMode, ...rest } = props
3838
return (
39-
<div className="fastui">
40-
<ErrorContextProvider DisplayError={DisplayError}>
41-
<LocationProvider>
42-
<ClassNameContext.Provider value={classNameGenerator ?? null}>
43-
<ConfigContext.Provider value={rest}>
44-
<DevReload enabled={devMode} />
45-
<FastUIController />
46-
</ConfigContext.Provider>
47-
</ClassNameContext.Provider>
48-
</LocationProvider>
49-
</ErrorContextProvider>
50-
</div>
39+
<ErrorContextProvider DisplayError={DisplayError}>
40+
<LocationProvider>
41+
<ClassNameContext.Provider value={classNameGenerator ?? null}>
42+
<ConfigContext.Provider value={rest}>
43+
<DevReload enabled={devMode} />
44+
<FastUIController />
45+
</ConfigContext.Provider>
46+
</ClassNameContext.Provider>
47+
</LocationProvider>
48+
</ErrorContextProvider>
5149
)
5250
}

0 commit comments

Comments
 (0)