<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.21.6/dist/js/uikit.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/uikit@3.21.6/dist/js/uikit-icons.min.js"></script>
<script type="module" src="https://unpkg.com/franken-wc@0.0.6/dist/js/wc.iife.js"></script>
<link rel="stylesheet" href="https://unpkg.com/franken-wc@0.0.6/dist/css/blue.min.css">
<style>
#notebook-container { max-width: none; }
.output_html * { list-style-type: none !important; }
</style>
Core
The building blocks to the UI
Imports
Theme / Headers
You can select a theme color to and get all the headers.
Theme
Theme (value, names=None, module=None, qualname=None, type=None, start=1)
An enumeration.
= Theme.blue.headers()
hdrs = FastHTML(hdrs=hdrs) app
Text Style
TextT
TextT (value, names=None, module=None, qualname=None, type=None, start=1)
Text Styles from https://franken-ui.dev/docs/text
# print(enum_to_markdown_table(TextT))
TextFont
TextFont (value, names=None, module=None, qualname=None, type=None, start=1)
Combinations of TextT that are particularly useful
Basic Components
Alert
Alert (*c, cls=(), **kwargs)
Headings
H1
H1 (*c:fastcore.xml.FT|str, cls:enum.Enum|str|tuple=(), **kwargs)
A H1 with Uk Styling
Type | Default | Details | |
---|---|---|---|
c | fastcore.xml.FT | str | ||
cls | enum.Enum | str | tuple | () | |
kwargs | |||
Returns | FT | Heading with class=uk-h1 cls |
H2
H2 (*c:fastcore.xml.FT|str, cls:enum.Enum|str|tuple=(), **kwargs)
A H2 with Uk Styling
Type | Default | Details | |
---|---|---|---|
c | fastcore.xml.FT | str | ||
cls | enum.Enum | str | tuple | () | |
kwargs | |||
Returns | FT | Heading with class=uk-h2 cls |
H3
H3 (*c:fastcore.xml.FT|str, cls:enum.Enum|str|tuple=(), **kwargs)
A H3 with Uk Styling
Type | Default | Details | |
---|---|---|---|
c | fastcore.xml.FT | str | ||
cls | enum.Enum | str | tuple | () | |
kwargs | |||
Returns | FT | Heading with class=uk-h3 cls |
H4
H4 (*c:fastcore.xml.FT|str, cls:enum.Enum|str|tuple=(), **kwargs)
A H4 with Uk Styling
Type | Default | Details | |
---|---|---|---|
c | fastcore.xml.FT | str | ||
cls | enum.Enum | str | tuple | () | |
kwargs | |||
Returns | FT | Heading with class=uk-h4 cls |
Titled
Titled (title:str='FastHTML app', *args, cls='container', **kwargs)
show(Div("Titled"),
Titled("Heading 1 (H1)"),
H1("Heading 2 (H2)"),
H2("Heading 3 (H3)"),
H3("Heading 4 (H4)"))) H4(
Titled
Heading 1 (H1)
Heading 2 (H2)
Heading 3 (H3)
Heading 4 (H4)
Dividers
DividerT
DividerT (value, names=None, module=None, qualname=None, type=None, start=1)
An enumeration.
Divider
Divider (*args, cls=<DividerT.icon: 'uk-divider-icon'>, **kwargs)
UkHSplit
UkHSplit (*c, cls=(), line_cls=(), text_cls=())
show(UkHSplit())
UkHLine
UkHLine (lwidth=2, y_space=4)
show(UkHLine())
Articles & Containers & Sections
ArticleMeta
ArticleMeta (*c, cls=(), **kwargs)
ArticleTitle
ArticleTitle (*c, cls=(), **kwargs)
Article
Article (*c, cls=(), **kwargs)
"Article Title"), ArticleMeta("By: John Doe"))) show(Article(ArticleTitle(
ContainerT
ContainerT (value, names=None, module=None, qualname=None, type=None, start=1)
Max width container sizes from https://franken-ui.dev/docs/container
Container
Container (*c, cls=(), **kwargs)
show(Container("This is a container with a custom background color.",
=ContainerT.xsmall,
cls="background-color: #e6f2ff; padding: 20px; border-radius: 5px;"
style ))
SectionT
SectionT (value, names=None, module=None, qualname=None, type=None, start=1)
Section styles from UIkit
# Markdown(enum_to_markdown_table(SectionT))
Section
Section (*c, cls=(), **kwargs)
Forms & Inputs
Legend
Legend (*c, cls=(), **kwargs)
Fieldset
Fieldset (*c, cls=(), **kwargs)
Switch
Switch (*c, cls='min-w-9', **kwargs)
TextArea
TextArea (*c, cls=(), **kwargs)
Toggle_switch
Toggle_switch (*c, cls=(), **kwargs)
Range
Range (*c, cls=(), **kwargs)
CheckboxX
CheckboxX (*c, cls=(), **kwargs)
Radio
Radio (*c, cls=(), **kwargs)
Select
Select (*option, cls=(), **kwargs)
Input
Input (*c, cls=(), **kwargs)
FormLabel
FormLabel (*c, cls=(), **kwargs)
show(Form(
Fieldset("Fieldset Legend 1"),
Legend("Input: ", Input()),
FormLabel("Select: ", Select(fh.Option("Option 1"), fh.Option("Option 2"))),
FormLabel("Radio: ", Radio()),
FormLabel("Checkbox: ", CheckboxX()),
FormLabel("Button: ", Button("Click me")),
FormLabel(='space-x-4'),
cls
Fieldset("Fieldset Legend 2"),
Legend("Range: ", Range()),
FormLabel("Toggle switch: ", Toggle_switch()),
FormLabel("TextArea: ", TextArea()),
FormLabel("Switch: ", Switch()),
FormLabel(='space-x-4'),
cls="space-y-6"
cls ))
LabelT
LabelT (value, names=None, module=None, qualname=None, type=None, start=1)
An enumeration.
Label
Label (*c, cls=(), **kwargs)
show(Div("Default"),
Label("Primary",cls=LabelT.primary),
Label("Secondary",cls=LabelT.secondary),
Label("Default",cls=LabelT.danger),
Label( ))
UkFormSection
UkFormSection (title, description, *c, button_txt='Update', outer_margin=6, inner_margin=6)
Labeled Inputs
Inputs of various types often go with a label. Because of this we created functions to do this for you along with properly linking the for
attribute from the lable to the input. We also have some nice defaults, such as putting a little spacing between the label and the input
GenericLabelInput
GenericLabelInput (label:str|fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), cls='', id='', input_fn=<function noop>, **kwargs)
Div(Label,Input)
component with Uk styling injected appropriately. Generally you should higher level API, such as UkTextArea
which is created for you in this library
LabelInput
LabelInput (*args, cls='space-y-2', lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), id='')
'My Label',id='myid')) show(LabelInput(
LabelRadio
LabelRadio (label:str|fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), cls='flex items-center space-x-2', id='', **kwargs)
Div(Label,Input)
component with Uk styling injected appropriately. Generally you should higher level API, such as UkTextArea
which is created for you in this library
'My Label',id='myid')) show(LabelRadio(
LabelCheckboxX
LabelCheckboxX (label:str|fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), cls='flex items- center space-x-2', id='', **kwargs)
Div(Label,Input)
component with Uk styling injected appropriately. Generally you should higher level API, such as UkTextArea
which is created for you in this library
'My Label',id='myid')) show(LabelCheckboxX(
LabelRange
LabelRange (*args, cls='space-y-2', lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), id='')
'My Label',id='myid')) show(LabelRange(
LabelTextArea
LabelTextArea (*args, cls='space-y-2', lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), id='')
'mylabel',container=Form)) show(LabelTextArea(
LabelSwitch
LabelSwitch (*args, cls='space-x-2', lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), id='')
'mylabel',id='myid')) show(LabelSwitch(
LabelSelect
LabelSelect (*option, label:str|fastcore.xml.FT, lbl_cls='', input_cls='', container=functools.partial(<function ft at 0x7f0a6c6657e0>, 'div', void_=False), cls='space-y-2', id='', **kwargs)
Div(Label,Input)
component with Uk styling injected appropriately. Generally you should higher level API, such as UkTextArea
which is created for you in this library
1),Option(2),label='My Label', id='myid')) show(LabelSelect(Option(
Options
Options (*c, selected_idx:int=None, disabled_idxs:set=None)
Helper function to wrap things into Option
s for use in UkSelect
# list(map(to_xml,Options('option1','option2','option3', selected_idx=1, disabled_idxs={0,2})))
UK Select is a custom select that has more functionality than the basic select. One particularly useful feature is the searchable
, which allows the user to type to search for options in the Select.
UkSelect
UkSelect (*option, inp_cls=(), cls=('space-y-2',), id='', name='', placeholder='', searchable=False, **kwargs)
Creates a select dropdown with uk styling
LabelUkSelect
LabelUkSelect (*option, label=(), lbl_cls=(), inp_cls=(), cls=('space-y-2',), id='', name='', placeholder='', searchable=False, **kwargs)
Creates a select dropdown with uk styling
1),Option(2),label='My Label', id='myid', searchable=True)) show(UkSelect(Option(
Links
AT
AT (value, names=None, module=None, qualname=None, type=None, start=1)
Link styles from https://franken-ui.dev/docs/link
='space-x-4')(('Default Link'),
show(Div(cls'Muted Link', cls=AT.muted),
A('Text Link', cls=AT.text),
A('Reset Link', cls=AT.reset))) A(
Lists
ListT
ListT (value, names=None, module=None, qualname=None, type=None, start=1)
List styles from https://franken-ui.dev/docs/list
List
List (*c, cls=(), **kwargs)
= [(style,str(cls)) for style,cls in ListT.__members__.items()]
list_options def create_list(style, cls): return List(fh.Li("Item 1"), fh.Li("Item 2"), cls=cls)
= [Div(H4(f"{style} List:"), create_list(style, cls)) for style, cls in list_options]
lists *lists, cls="grid grid-cols-4")) show(Div(
disc List:
- Item 1
- Item 2
circle List:
- Item 1
- Item 2
square List:
- Item 1
- Item 2
decimal List:
- Item 1
- Item 2
hyphen List:
- Item 1
- Item 2
muted List:
- Item 1
- Item 2
primary List:
- Item 1
- Item 2
secondary List:
- Item 1
- Item 2
bullet List:
- Item 1
- Item 2
divider List:
- Item 1
- Item 2
striped List:
- Item 1
- Item 2
Modal
ModalTitle
ModalTitle (*c, cls=(), **kwargs)
ModalBody
ModalBody (*c, cls=(), **kwargs)
ModalHeader
ModalHeader (*c, cls=(), **kwargs)
ModalDialog
ModalDialog (*c, cls=(), **kwargs)
ModalContainer
ModalContainer (*c, cls=(), **kwargs)
'Modal Close Button', cls=ButtonT.primary)) show(ModalCloseButton(
Modal
Modal (*c, header=None, footer=None, cls=(), dialog_cls=(), header_cls='p-6', body_cls='space-y-6', footer_cls=(), id='', **kwargs)
Create a Modal using the appropriate Modal classes to put the boilerplate in the appropriate places for you*
Show(Div("Open Modal",uk_toggle="target: #my-modal" ),
Button("Simple Test Modal"),
Modal(ModalTitle("With some somewhat brief content to show that it works!", cls=TextFont.muted_sm),
P(=ModalCloseButton("Close", cls=ButtonT.primary),id='my-modal'))) footer
Padding | Positioning
PaddingT
PaddingT (value, names=None, module=None, qualname=None, type=None, start=1)
Padding Modifiers from https://franken-ui.dev/docs/padding
PositionT
PositionT (value, names=None, module=None, qualname=None, type=None, start=1)
Position modifiers from https://franken-ui.dev/docs/position
Other
Placeholder
Placeholder (*c, cls=(), **kwargs)
"Placeholder")) show(Placeholder(
Progress
Progress (*c, cls=(), value='', max='', **kwargs)
=20, max=100)) show(Progress(value
Icons and Avatars
UkIcon
UkIcon (icon, height=None, width=None, stroke_width=None, cls=(), **kwargs)
UkIconLink
UkIconLink (icon, height=None, width=None, stroke_width=None, cls=(), button=False, **kwargs)
class IconButtonT(VEnum):
= 'uk-icon-button-xsmall'
xsmall = 'uk-icon-button-small'
small = 'uk-icon-button-outline' outline
DiceBearAvatar
DiceBearAvatar (seed_name, h=20, w=20)
Type | Default | Details | |
---|---|---|---|
seed_name | Seed name (ie ‘Isaac Flath’) | ||
h | int | 20 | Height |
w | int | 20 | Width |
'Isaac Flath', 20, 20)) show(DiceBearAvatar(
Flexbox | Grid
The most common pattern for spacing it to organize the general high level page layout with a Grid
, and smaller components with Flex
.
Play Flex Box Froggy to get an understanding of flex box.
FlexT
FlexT (value, names=None, module=None, qualname=None, type=None, start=1)
Flexbox modifiers from UIkit
GridT
GridT (value, names=None, module=None, qualname=None, type=None, start=1)
Grid modifiers from UIkit
Grid
Grid (*div, cols=None, cls=<GridT.small: 'uk-grid-small'>, **kwargs)
Creates a grid with the given number of columns, often used for a grid of cards
*map(Button, "abcdef"),cols=3)) show(Grid(
We can use the FlexT
enum above to create Div
s that arrange components in a flex box in different ways.
For example, FullySpacedDiv
applies a very common pattern so we’ve made a function that helps to this for you. But if you look at the code, it’s really just using the enum to apply the right combonation of flex classes.
FullySpacedDiv
FullySpacedDiv (*c, cls='uk-width-1-1', **kwargs)
Creates a flex div with it’s components having as much space between them as possible
Exported source
def FullySpacedDiv(*c, # Components
='uk-width-1-1',# Classes for outer div
cls**kwargs # Additional args for outer div
# Div with spaced components via flex classes
): "Creates a flex div with it's components having as much space between them as possible"
= stringify(cls)
cls return Div(cls=(FlexT.block,FlexT.between,FlexT.middle,cls), **kwargs)(*c)
from functools import partial
= partial(Button,cls=ButtonT.primary) _button
*map(_button, range(3)))) show(FullySpacedDiv(
CenteredDiv
CenteredDiv (*c, cls='space-y-4', **kwargs)
Creates a flex div with it’s components centered in it
*map(_button, range(3)))) show(CenteredDiv(
LAlignedDiv
LAlignedDiv (*c, cls='space-x-4', **kwargs)
Creates a flex div with it’s components aligned to the left
*map(_button, range(3)))) show(LAlignedDiv(
RAlignedDiv
RAlignedDiv (*c, cls='space-x-4', **kwargs)
Creates a flex div with it’s components aligned to the right
*map(_button, range(3)))) show(RAlignedDiv(
VStackedDiv
VStackedDiv (*c, cls='space-y-4', **kwargs)
*map(_button, range(3)))) show(VStackedDiv(
HStackedDiv
HStackedDiv (*c, cls='space-x-4', **kwargs)
*map(_button, range(3)))) show(HStackedDiv(
DropDown
Tabs
TabContainer
TabContainer (*li, cls='', alt=False, **kwargs)
show(Container(TabContainer("Active",href='#', cls='uk-active')),
Li(A("Item",href='#')),
Li(A("Item",href='#')),
Li(A("Disabled",href='#', cls='uk-disabled')),
Li(A(=True))) alt
Cards
CardT
CardT (value, names=None, module=None, qualname=None, type=None, start=1)
Card styles from UIkit
CardContainer
CardContainer (*c, cls=<CardT.default: 'uk-card-default'>, **kwargs)
CardBody
CardBody (*c, cls=(), **kwargs)
CardHeader
CardHeader (*c, cls=(), **kwargs)
CardTitle
CardTitle (*c, cls=(), **kwargs)
CardTitle
CardTitle (*c, cls=(), **kwargs)
Card
Card (*c, header=None, footer=None, body_cls='space-y-6', header_cls=(), footer_cls=(), cls=(), **kwargs)
show(
Card("Input"),LabelRange("Range")),
Form(LabelInput(=Div(CardTitle("Header"),P("A card with header and footer",cls=TextFont.muted_sm)),
header=LAlignedDiv(Button("Footer Submit button")),
footer
) )
A card with header and footer
Tables
TableT
TableT (value, names=None, module=None, qualname=None, type=None, start=1)
An enumeration.
Table
Table (*args, cls=(<TableT.middle: 'uk-table-middle'>, <TableT.divider: 'uk-table-divider'>, <TableT.hover: 'uk-table-hover'>, <TableT.small: 'uk-table-small'>), **kwargs)
Tbody
Tbody (*rows, cls=(), sortable=False, **kwargs)
Thead
Thead (*rows, cls=(), **kwargs)
Tr
Tr (*cells, cls=(), **kwargs)
Th
Th (*args, cls=(), shrink=False, expand=False, small=False)
Td
Td (*args, cls=(), shrink=False, expand=False, small=False)
show(
Table('Name'), Th('Age'), Th('City'))),
Thead(Tr(Th('Alice'), Td('25'), Td('New York')),
Tbody(Tr(Td('Bob'), Td('30'), Td('San Francisco')),
Tr(Td('Charlie'), Td('35'), Td('London'))),
Tr(Td('Total'), Td('90'))))
Tfoot(Tr(Td( )
Name | Age | City |
---|---|---|
Alice | 25 | New York |
Bob | 30 | San Francisco |
Charlie | 35 | London |
Total | 90 |
TableFromLists
TableFromLists (header_data, body_data, footer_data=None, header_cell_render=<function Th>, body_cell_render=<function Td>, footer_cell_render=<function Td>, cls=(<TableT.middle: 'uk-table-middle'>, <TableT.divider: 'uk-table-divider'>, <TableT.hover: 'uk-table-hover'>, <TableT.small: 'uk- table-small'>), sortable=False, **kwargs)
# Test the function
= ['Name', 'Age', 'City']
header = [['Alice', '25', 'New York'],
body 'Bob', '30', 'San Francisco'],
['Charlie', '35', 'London']]
[= ['Total', '90']
footer
show(TableFromLists(header, body, footer))
Name | Age | City |
---|---|---|
Alice | 25 | New York |
Bob | 30 | San Francisco |
Charlie | 35 | London |
Total | 90 |
TableFromDicts
TableFromDicts (header_data:Sequence, body_data:Sequence[dict], footer_data=None, header_cell_render=<function Th>, body_cell_render=<function <lambda>>, footer_cell_render=<function <lambda>>, cls=(<TableT.middle: 'uk-table-middle'>, <TableT.divider: 'uk-table-divider'>, <TableT.hover: 'uk-table-hover'>, <TableT.small: 'uk-table-small'>), sortable=False, **kwargs)
# Example usage:
def header_render(v): return Th(v.upper())
def body_render(k, v):
match k.lower():
case 'name': return Td(v['name'], cls='font-bold')
case 'age': return Td(f"{v['age']} years")
case _: return Td(v[k.lower()])
= ['Name', 'Age', 'City']
header_data = [{'name': 'Alice', 'age': 30, 'city': 'New York'},
body_data 'name': 'Bob', 'age': 25, 'city': 'London'}]
{
=header_render, body_cell_render=body_render)) show(TableFromDicts(header_data, body_data, header_cell_render
NAME | AGE | CITY |
---|---|---|
Alice | 30 years | New York |
Bob | 25 years | London |
Markdown
apply_classes
apply_classes (html_str:str, class_map=None, class_map_mods=None)
= apply_classes("<div><h1>Hello, world!</h1></div>", class_map_mods={'h1': 'uk-h1 my-4 mb-4'})
_test assert _test == '<div><h1 class="uk-h1 my-4 mb-4">Hello, world!</h1></div>'
render_md
render_md (md_content)
_
<script>
window.addEventListener('load', function() {
for (let i = 1; i <= 6; i++) {
document.querySelectorAll(`h${i}`).forEach(el => {
.classList.add(`uk-h${i}`);
el;
})
};
})
document.querySelectorAll('.sidebar-item-text').forEach(el => {
.style.visibility = 'visible';
el
})
</script>