Exported source
accent = ColoredFactory("accent", "Accent color utilities for form controls like checkboxes, radio buttons, and range sliders") # The accent color factoryUtilities for controlling the accented color of form controls (like checkboxes, radio buttons, and range sliders):
Test accent color utilities.
def test_interactivity_accent_examples():
"""Test accent color utilities."""
# Test all 22 color families
assert str(accent.red._500) == "accent-red-500"
assert str(accent.orange._500) == "accent-orange-500"
assert str(accent.amber._500) == "accent-amber-500"
assert str(accent.yellow._500) == "accent-yellow-500"
assert str(accent.lime._500) == "accent-lime-500"
assert str(accent.green._500) == "accent-green-500"
assert str(accent.emerald._500) == "accent-emerald-500"
assert str(accent.teal._500) == "accent-teal-500"
assert str(accent.cyan._500) == "accent-cyan-500"
assert str(accent.sky._500) == "accent-sky-500"
assert str(accent.blue._500) == "accent-blue-500"
assert str(accent.indigo._500) == "accent-indigo-500"
assert str(accent.violet._500) == "accent-violet-500"
assert str(accent.purple._500) == "accent-purple-500"
assert str(accent.fuchsia._500) == "accent-fuchsia-500"
assert str(accent.pink._500) == "accent-pink-500"
assert str(accent.rose._500) == "accent-rose-500"
assert str(accent.slate._500) == "accent-slate-500"
assert str(accent.gray._500) == "accent-gray-500"
assert str(accent.zinc._500) == "accent-zinc-500"
assert str(accent.neutral._500) == "accent-neutral-500"
assert str(accent.stone._500) == "accent-stone-500"
# Special colors
assert str(accent.inherit) == "accent-inherit"
assert str(accent.current) == "accent-current"
assert str(accent.transparent) == "accent-transparent"
assert str(accent.black) == "accent-black"
assert str(accent.white) == "accent-white"
# Arbitrary values
assert str(accent("#ff0000")) == "accent-[#ff0000]"
assert str(accent("--custom-accent")) == "accent-(--custom-accent)"
# Run the tests
test_interactivity_accent_examples()Utilities for suppressing native form control styling:
Test appearance utilities.
Utilities for controlling the color of the text input cursor:
Test caret color utilities.
def test_interactivity_caret_examples():
"""Test caret color utilities."""
# Test all 22 color families
assert str(caret.red._500) == "caret-red-500"
assert str(caret.orange._500) == "caret-orange-500"
assert str(caret.amber._500) == "caret-amber-500"
assert str(caret.yellow._500) == "caret-yellow-500"
assert str(caret.lime._500) == "caret-lime-500"
assert str(caret.green._500) == "caret-green-500"
assert str(caret.emerald._500) == "caret-emerald-500"
assert str(caret.teal._500) == "caret-teal-500"
assert str(caret.cyan._500) == "caret-cyan-500"
assert str(caret.sky._500) == "caret-sky-500"
assert str(caret.blue._500) == "caret-blue-500"
assert str(caret.indigo._500) == "caret-indigo-500"
assert str(caret.violet._500) == "caret-violet-500"
assert str(caret.purple._500) == "caret-purple-500"
assert str(caret.fuchsia._500) == "caret-fuchsia-500"
assert str(caret.pink._500) == "caret-pink-500"
assert str(caret.rose._500) == "caret-rose-500"
assert str(caret.slate._500) == "caret-slate-500"
assert str(caret.gray._500) == "caret-gray-500"
assert str(caret.zinc._500) == "caret-zinc-500"
assert str(caret.neutral._500) == "caret-neutral-500"
assert str(caret.stone._500) == "caret-stone-500"
# Special colors
assert str(caret.inherit) == "caret-inherit"
assert str(caret.current) == "caret-current"
assert str(caret.transparent) == "caret-transparent"
assert str(caret.black) == "caret-black"
assert str(caret.white) == "caret-white"
# Arbitrary values
assert str(caret("#ff0000")) == "caret-[#ff0000]"
assert str(caret("--custom-caret")) == "caret-(--custom-caret)"
# Run the tests
test_interactivity_caret_examples()Utilities for controlling the color scheme of an element:
Test color scheme utilities.
scheme = SimpleFactory(
{
"normal": "scheme-normal",
"dark": "scheme-dark",
"light": "scheme-light",
"light_dark": "scheme-light-dark",
"only_dark": "scheme-only-dark",
"only_light": "scheme-only-light"
},
"Color scheme utilities for controlling the preferred color scheme of an element"
) # Color scheme factorydef test_interactivity_scheme_examples():
"""Test color scheme utilities."""
assert str(scheme.normal) == "scheme-normal"
assert str(scheme.dark) == "scheme-dark"
assert str(scheme.light) == "scheme-light"
assert str(scheme.light_dark) == "scheme-light-dark"
assert str(scheme.only_dark) == "scheme-only-dark"
assert str(scheme.only_light) == "scheme-only-light"
# Run the tests
test_interactivity_scheme_examples()Utilities for controlling the cursor style when hovering over an element:
Factory for cursor utilities with arbitrary value support.
Test cursor utilities.
cursor = CursorFactory(
{
"auto": "cursor-auto",
"default": "cursor-default",
"pointer": "cursor-pointer",
"wait": "cursor-wait",
"text": "cursor-text",
"move": "cursor-move",
"help": "cursor-help",
"not-allowed": "cursor-not-allowed",
"none": "cursor-none",
"context-menu": "cursor-context-menu",
"progress": "cursor-progress",
"cell": "cursor-cell",
"crosshair": "cursor-crosshair",
"vertical-text": "cursor-vertical-text",
"alias": "cursor-alias",
"copy": "cursor-copy",
"no-drop": "cursor-no-drop",
"grab": "cursor-grab",
"grabbing": "cursor-grabbing",
"all-scroll": "cursor-all-scroll",
"col-resize": "cursor-col-resize",
"row-resize": "cursor-row-resize",
"n-resize": "cursor-n-resize",
"e-resize": "cursor-e-resize",
"s-resize": "cursor-s-resize",
"w-resize": "cursor-w-resize",
"ne-resize": "cursor-ne-resize",
"nw-resize": "cursor-nw-resize",
"se-resize": "cursor-se-resize",
"sw-resize": "cursor-sw-resize",
"ew-resize": "cursor-ew-resize",
"ns-resize": "cursor-ns-resize",
"nesw-resize": "cursor-nesw-resize",
"nwse-resize": "cursor-nwse-resize",
"zoom-in": "cursor-zoom-in",
"zoom-out": "cursor-zoom-out"
},
"Cursor utilities for controlling the cursor style when hovering over an element"
) # Cursor factorydef test_interactivity_cursor_examples():
"""Test cursor utilities."""
# Common cursors
assert str(cursor.auto) == "cursor-auto"
assert str(cursor.default) == "cursor-default"
assert str(cursor.pointer) == "cursor-pointer"
assert str(cursor.wait) == "cursor-wait"
assert str(cursor.text) == "cursor-text"
assert str(cursor.move) == "cursor-move"
assert str(cursor.help) == "cursor-help"
assert str(cursor.not_allowed) == "cursor-not-allowed"
# Resize cursors
assert str(cursor.n_resize) == "cursor-n-resize"
assert str(cursor.ne_resize) == "cursor-ne-resize"
assert str(cursor.col_resize) == "cursor-col-resize"
assert str(cursor.row_resize) == "cursor-row-resize"
# Special cursors
assert str(cursor.grab) == "cursor-grab"
assert str(cursor.grabbing) == "cursor-grabbing"
assert str(cursor.zoom_in) == "cursor-zoom-in"
assert str(cursor.zoom_out) == "cursor-zoom-out"
# Custom properties and arbitrary values
assert cursor("--custom-cursor") == "cursor-(--custom-cursor)"
assert cursor("url(cursor.png), auto") == "cursor-[url(cursor.png), auto]"
# Run the tests
test_interactivity_cursor_examples()Utilities for controlling the sizing of form controls:
Test field sizing utilities.
Utilities for controlling whether an element responds to pointer events:
Test pointer events utilities.
Utilities for controlling how an element can be resized:
Test resize utilities.
Utilities for controlling the scroll behavior of an element:
Test scroll behavior utilities.
Utilities for controlling the scroll offset around items in a snap container:
Test scroll margin utilities.
scroll_m = DirectionalScaledFactory("scroll-m", SPACING_CONFIG, "Scroll margin utilities for controlling scroll offset margins") # The scroll margin factory
# Additional directional scroll margin utilities for logical properties
scroll_ms = ScaledFactory("scroll-ms", SPACING_CONFIG, "Scroll margin inline-start utilities") # scroll-margin-inline-start
scroll_me = ScaledFactory("scroll-me", SPACING_CONFIG, "Scroll margin inline-end utilities") # scroll-margin-inline-enddef test_interactivity_scroll_margin_examples():
"""Test scroll margin utilities."""
# All sides
assert str(scroll_m(4)) == "scroll-m-4"
assert str(scroll_m(0)) == "scroll-m-0"
assert str(scroll_m.px) == "scroll-m-px"
# Directional
assert str(scroll_m.t(4)) == "scroll-mt-4"
assert str(scroll_m.r(4)) == "scroll-mr-4"
assert str(scroll_m.b(4)) == "scroll-mb-4"
assert str(scroll_m.l(4)) == "scroll-ml-4"
assert str(scroll_m.x(8)) == "scroll-mx-8"
assert str(scroll_m.y(8)) == "scroll-my-8"
# Negative values
assert str(scroll_m.negative(4)) == "-scroll-m-4"
assert str(scroll_m.t.negative(2)) == "-scroll-mt-2"
# Logical properties
assert str(scroll_ms(4)) == "scroll-ms-4"
assert str(scroll_me(4)) == "scroll-me-4"
assert str(scroll_ms.negative(2)) == "-scroll-ms-2"
# Arbitrary values
assert str(scroll_m("10px")) == "scroll-m-[10px]"
assert str(scroll_m("--custom-margin")) == "scroll-m-(--custom-margin)"
# Run the tests
test_interactivity_scroll_margin_examples()Utilities for controlling an element’s scroll offset within a snap container:
Test scroll padding utilities.
scroll_p = DirectionalScaledFactory("scroll-p", SPACING_CONFIG, "Scroll padding utilities for controlling scroll offset padding") # The scroll padding factory
# Additional directional scroll padding utilities for logical properties
scroll_ps = ScaledFactory("scroll-ps", SPACING_CONFIG, "Scroll padding inline-start utilities") # scroll-padding-inline-start
scroll_pe = ScaledFactory("scroll-pe", SPACING_CONFIG, "Scroll padding inline-end utilities") # scroll-padding-inline-enddef test_interactivity_scroll_padding_examples():
"""Test scroll padding utilities."""
# All sides
assert str(scroll_p(4)) == "scroll-p-4"
assert str(scroll_p(0)) == "scroll-p-0"
assert str(scroll_p.px) == "scroll-p-px"
# Directional
assert str(scroll_p.t(4)) == "scroll-pt-4"
assert str(scroll_p.r(4)) == "scroll-pr-4"
assert str(scroll_p.b(4)) == "scroll-pb-4"
assert str(scroll_p.l(4)) == "scroll-pl-4"
assert str(scroll_p.x(8)) == "scroll-px-8"
assert str(scroll_p.y(8)) == "scroll-py-8"
# Negative values
assert str(scroll_p.negative(4)) == "-scroll-p-4"
assert str(scroll_p.t.negative(2)) == "-scroll-pt-2"
# Logical properties
assert str(scroll_ps(4)) == "scroll-ps-4"
assert str(scroll_pe(4)) == "scroll-pe-4"
assert str(scroll_ps.negative(2)) == "-scroll-ps-2"
# Arbitrary values
assert str(scroll_p("10px")) == "scroll-p-[10px]"
assert str(scroll_p("--custom-padding")) == "scroll-p-(--custom-padding)"
# Run the tests
test_interactivity_scroll_padding_examples()Utilities for controlling scroll snap behavior:
Control the scroll snap alignment of an element:
Control whether you can skip past possible snap positions:
Control how strictly snap points are enforced in a snap container:
Test scroll snap utilities.
def test_interactivity_scroll_snap_examples():
"""Test scroll snap utilities."""
# Snap align
assert str(snap_align.start) == "snap-start"
assert str(snap_align.end) == "snap-end"
assert str(snap_align.center) == "snap-center"
assert str(snap_align.none) == "snap-align-none"
# Snap stop
assert str(snap_stop.normal) == "snap-normal"
assert str(snap_stop.always) == "snap-always"
# Snap type
assert str(snap.none) == "snap-none"
assert str(snap.x) == "snap-x"
assert str(snap.y) == "snap-y"
assert str(snap.both) == "snap-both"
assert str(snap.mandatory) == "snap-mandatory"
assert str(snap.proximity) == "snap-proximity"
# Run the tests
test_interactivity_scroll_snap_examples()Utilities for controlling how an element can be scrolled and zoomed on touchscreens:
Test touch action utilities.
touch = SimpleFactory(
{
"auto": "touch-auto",
"none": "touch-none",
"pan-x": "touch-pan-x",
"pan-left": "touch-pan-left",
"pan-right": "touch-pan-right",
"pan-y": "touch-pan-y",
"pan-up": "touch-pan-up",
"pan-down": "touch-pan-down",
"pinch-zoom": "touch-pinch-zoom",
"manipulation": "touch-manipulation"
},
"Touch action utilities for controlling touch gestures on touch devices"
) # Touch action factorydef test_interactivity_touch_action_examples():
"""Test touch action utilities."""
assert str(touch.auto) == "touch-auto"
assert str(touch.none) == "touch-none"
assert str(touch.pan_x) == "touch-pan-x"
assert str(touch.pan_left) == "touch-pan-left"
assert str(touch.pan_right) == "touch-pan-right"
assert str(touch.pan_y) == "touch-pan-y"
assert str(touch.pan_up) == "touch-pan-up"
assert str(touch.pan_down) == "touch-pan-down"
assert str(touch.pinch_zoom) == "touch-pinch-zoom"
assert str(touch.manipulation) == "touch-manipulation"
# Run the tests
test_interactivity_touch_action_examples()Utilities for controlling whether the user can select text in an element:
Test user select utilities.
def test_interactivity_user_select_examples():
"""Test user select utilities."""
assert str(select.none) == "select-none"
assert str(select.text) == "select-text"
assert str(select.all) == "select-all"
assert str(select.auto) == "select-auto"
# Run the tests
test_interactivity_user_select_examples()Utilities for optimizing upcoming animations of elements that are expected to change:
Factory for will-change utilities with arbitrary value support.
Test will-change utilities.
def test_interactivity_will_change_examples():
"""Test will-change utilities."""
# Standard values
assert str(will_change.auto) == "will-change-auto"
assert str(will_change.scroll) == "will-change-scroll"
assert str(will_change.contents) == "will-change-contents"
assert str(will_change.transform) == "will-change-transform"
# Custom properties and arbitrary values
assert will_change("--custom-property") == "will-change---custom-property"
assert will_change("opacity, transform") == "will-change-[opacity, transform]"
assert will_change("left, top") == "will-change-[left, top]"
# Run the tests
test_interactivity_will_change_examples()Let’s see how to use these interactivity utilities in real FastHTML components:
Test interactivity utilities in form components.
def test_interactivity_form_fasthtml_examples():
"""Test interactivity utilities in form components."""
from fasthtml.common import Input, Textarea, Button, Div, Label
from cjm_fasthtml_tailwind.utilities.sizing import w, h
from cjm_fasthtml_tailwind.utilities.spacing import p
from cjm_fasthtml_tailwind.utilities.borders import border, rounded
from cjm_fasthtml_tailwind.utilities.backgrounds import bg
from cjm_fasthtml_tailwind.utilities.typography import font_size, text_color
from cjm_fasthtml_tailwind.utilities.layout import display_tw
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, grid_display
# Custom styled checkbox with accent color
checkbox = Input(
type="checkbox",
cls=combine_classes(
accent.blue._500,
cursor.pointer,
w(4),
h(4)
)
)
assert "accent-blue-500" in checkbox.attrs['class']
assert "cursor-pointer" in checkbox.attrs['class']
# Text input with custom caret color
text_input = Input(
type="text",
placeholder="Type here...",
cls=combine_classes(
caret.red._500,
appearance.none,
p.x(4),
p.y(2),
border(),
rounded.full
)
)
assert "caret-red-500" in text_input.attrs['class']
assert "appearance-none" in text_input.attrs['class']
# Resizable textarea
textarea = Textarea(
placeholder="Enter your message...",
cls=combine_classes(
resize.y,
field_sizing.content,
p(3),
border(),
rounded.full
)
)
assert "resize-y" in textarea.attrs['class']
assert "field-sizing-content" in textarea.attrs['class']
# Interactive button with hover states
button = Button(
"Click me",
cls=combine_classes(
cursor.pointer,
select.none,
pointer_events.auto,
bg.blue._500,
text_color.white,
p.x(4),
p.y(2),
rounded.full,
bg.blue._600.hover
)
)
assert "cursor-pointer" in button.attrs['class']
assert "select-none" in button.attrs['class']
# Return all examples in a grid layout
return Div(
checkbox,
text_input,
textarea,
button,
cls=combine_classes(grid_display, gap(5))
)
# Run the tests
test_interactivity_form_fasthtml_examples()Test scroll snap utilities in carousel/gallery components.
def test_interactivity_scroll_snap_fasthtml_examples():
"""Test scroll snap utilities in carousel/gallery components."""
from fasthtml.common import Div, Img
from cjm_fasthtml_tailwind.utilities.layout import display_tw, overflow
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, shrink, grid_display, flex_display
from cjm_fasthtml_tailwind.utilities.sizing import w, h
# Horizontal scroll snap container
carousel_container = Div(
cls=combine_classes(
snap.x,
snap.mandatory,
scroll.smooth,
scroll_p.x(4),
flex_display,
overflow.x.auto,
gap(4)
)
)
assert "snap-x" in carousel_container.attrs['class']
assert "snap-mandatory" in carousel_container.attrs['class']
assert "scroll-smooth" in carousel_container.attrs['class']
assert "scroll-px-4" in carousel_container.attrs['class']
# Snap items within the container
snap_item = Div(
Img(src="https://img.daisyui.com/images/stock/photo-1559703248-dcaaec9fab78.webp", alt="Gallery image"),
cls=combine_classes(
snap_align.center,
snap_stop.always,
shrink._0,
w(80)
)
)
assert "snap-center" in snap_item.attrs['class']
assert "snap-always" in snap_item.attrs['class']
# Vertical scroll snap for sections
vertical_snap = Div(
cls=combine_classes(
snap.y,
snap.proximity,
scroll_m.y(2),
h.screen,
overflow.y.auto
)
)
assert "snap-y" in vertical_snap.attrs['class']
assert "snap-proximity" in vertical_snap.attrs['class']
assert "scroll-my-2" in vertical_snap.attrs['class']
# Return all examples in a grid layout
return Div(
carousel_container,
snap_item,
vertical_snap,
cls=combine_classes(grid_display, gap(5))
)
# Run the tests
test_interactivity_scroll_snap_fasthtml_examples()
Test touch and mobile interaction utilities.
def test_interactivity_touch_mobile_fasthtml_examples():
"""Test touch and mobile interaction utilities."""
from fasthtml.common import Div, Img, Code
from cjm_fasthtml_tailwind.utilities.layout import position, overflow, display_tw
from cjm_fasthtml_tailwind.utilities.spacing import p
from cjm_fasthtml_tailwind.utilities.backgrounds import bg
from cjm_fasthtml_tailwind.utilities.typography import font_size, text_color
from cjm_fasthtml_tailwind.utilities.borders import rounded
from cjm_fasthtml_tailwind.utilities.transitions_and_animation import transition
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, grid_display
# Touch-enabled image viewer
image_viewer = Div(
Img(src="https://img.daisyui.com/images/stock/photo-1559703248-dcaaec9fab78.webp", alt="Photo"),
cls=combine_classes(
touch.pinch_zoom,
cursor.zoom_in,
select.none,
position.relative,
overflow.hidden
)
)
assert "touch-pinch-zoom" in image_viewer.attrs['class']
assert "cursor-zoom-in" in image_viewer.attrs['class']
# Draggable element
draggable = Div(
"Drag me",
cls=combine_classes(
cursor.grab,
cursor.grabbing.active,
touch.none,
select.none,
p(4),
bg.gray._200,
rounded.full
)
)
assert "cursor-grab" in draggable.attrs['class']
assert "touch-none" in draggable.attrs['class']
# Code block with selection
code_block = Code(
"console.log('Hello World');",
cls=combine_classes(
select.all,
cursor.text,
display_tw.block,
p(3),
bg.gray._900,
text_color.gray._100,
rounded.full
)
)
assert "select-all" in code_block.attrs['class']
assert "cursor-text" in code_block.attrs['class']
# Touch-friendly swipe area
swipe_area = Div(
cls=combine_classes(
touch.pan_x,
will_change.transform,
transition.transform
)
)
assert "touch-pan-x" in swipe_area.attrs['class']
assert "will-change-transform" in swipe_area.attrs['class']
# Return all examples in a grid layout
return Div(
image_viewer,
draggable,
code_block,
swipe_area,
cls=combine_classes(grid_display, gap(5))
)
# Run the tests
test_interactivity_touch_mobile_fasthtml_examples()
console.log('Hello World');Some advanced use cases demonstrating how these utilities work together:
Test advanced combinations of interactivity utilities.
def test_interactivity_advanced_fasthtml_examples():
"""Test advanced combinations of interactivity utilities."""
from fasthtml.common import Div, Input, Form, Pre
from cjm_fasthtml_tailwind.utilities.spacing import p, m
from cjm_fasthtml_tailwind.utilities.backgrounds import bg
from cjm_fasthtml_tailwind.utilities.typography import font_size, font_weight, font_family, text_color
from cjm_fasthtml_tailwind.utilities.borders import rounded
from cjm_fasthtml_tailwind.utilities.layout import position, overflow
from cjm_fasthtml_tailwind.utilities.transforms import scale_tw, transform
from cjm_fasthtml_tailwind.utilities.transitions_and_animation import transition, duration
from cjm_fasthtml_tailwind.utilities.flexbox_and_grid import gap, grid_display
# Dark mode form with custom styling
dark_form = Form(
Input(
type="checkbox",
cls=combine_classes(
accent.purple._500,
scheme.dark,
cursor.pointer,
m.r(2)
)
),
Input(
type="text",
cls=combine_classes(
caret.purple._400,
appearance.none,
scheme.dark,
bg.gray._800,
text_color.white,
p.x(3),
p.y(2),
rounded.full
)
),
cls=combine_classes(
scheme.dark,
p(6),
bg.gray._900,
rounded.lg
)
)
assert "scheme-dark" in dark_form.attrs['class']
assert "accent-purple-500" in dark_form.children[0].attrs['class']
assert "caret-purple-400" in dark_form.children[1].attrs['class']
# Interactive code editor mockup
code_editor = Div(
Pre(
"def hello():\n print('Hello, World!')",
cls=combine_classes(
select.text,
cursor.text,
caret.green._400,
resize.both,
scroll.auto,
scroll_p(4),
font_family.mono,
bg.gray._900,
text_color.gray._100,
p(4),
rounded.full,
overflow.auto
)
),
cls=combine_classes(
pointer_events.auto,
position.relative
)
)
assert "select-text" in code_editor.children[0].attrs['class']
assert "cursor-text" in code_editor.children[0].attrs['class']
assert "resize" in code_editor.children[0].attrs['class']
assert "scroll-p-4" in code_editor.children[0].attrs['class']
# Complex interactive element with animation hints
animated_card = Div(
"Animated Card",
cls=combine_classes(
cursor.pointer,
will_change("transform, opacity"),
touch.manipulation,
select.none,
transition.all,
duration._300,
scale_tw(105).hover
)
)
assert "cursor-pointer" in animated_card.attrs['class']
assert "will-change-[transform, opacity]" in animated_card.attrs['class']
assert "touch-manipulation" in animated_card.attrs['class']
# Return all examples in a grid layout
return Div(
dark_form,
code_editor,
animated_card,
cls=combine_classes(grid_display, gap(5))
)
# Run the tests
test_interactivity_advanced_fasthtml_examples()def hello():
print('Hello, World!')