appkit-mantine
reflex.dev components based on MantineUI
A Reflex wrapper library exposing the full Mantine UI v9.5.2 component suite — inputs, buttons, overlays, navigation, layout, data display, feedback, charts, maps, scheduling and more — for building robust, type-safe Python web applications.
✨ Features
- 🧩 Full Component Coverage - 90+ components across inputs, buttons, overlays, navigation, layout, data display, feedback, charts, maps, scheduling, and typography
- 🔒 Type-Safe - Full type annotations with IDE autocomplete support for all props and event handlers (
.pyistubs for every component) - 📚 Rich Examples - Production-ready code examples for every component with common patterns and edge cases
- 🏗️ Clean Architecture - Inheritance-based design (
MantineComponentBase→MantineLayoutComponentBase→MantineInputComponentBase) eliminating code duplication across ~40 common props - 🎨 Mantine Integration - Seamless integration with Mantine's theming, color modes, and design system;
MantineProvideris auto-injected - ⚡ Modern Stack - Built on Reflex 0.9.6+ with React 18 and Mantine 9.5.2
📦 Installation
Using pip
pip install appkit-mantine
Using uv (recommended)
uv add appkit-mantine
Development Installation
For local development or to run the demo application:
# Clone the repository
git clone https://github.com/jenreh/appkit.git
cd appkit
# Install with uv (installs workspace components)
uv sync
# Run the demo app
reflex run
🚀 Quick Start
import reflex as rx
import appkit_mantine as mn
class FormState(rx.State):
email: str = ""
password: str = ""
def login_form() -> rx.Component:
return rx.container(
rx.vstack(
rx.heading("Login"),
# Basic input with validation
mn.form.input(
label="Email",
placeholder="you@example.com",
value=FormState.email,
on_change=FormState.set_email,
required=True,
type="email",
),
# Password input with visibility toggle
mn.password_input(
label="Password",
value=FormState.password,
on_change=FormState.set_password,
required=True,
),
rx.button("Sign In", on_click=FormState.handle_login),
spacing="4",
),
max_width="400px",
)
app = rx.App()
app.add_page(login_form)
📋 Available Components
Inputs
| Component | Description | Documentation |
|---|---|---|
text_input |
Basic text input / text inputs showcase | Guide |
input |
Polymorphic base input element with sections, variants, sizes | Examples |
password_input |
Password field with visibility toggle | Examples |
number_input |
Numeric input with formatting, min/max, step controls | Examples |
textarea |
Multi-line text input with auto-resize | Guide |
json_input |
JSON input with formatting, validation, parser, pretty printing | Examples |
masked_input |
Input masking for phone numbers, credit cards, custom patterns (uncontrolled) | Guide |
color_input / color_picker |
Color entry and swatch picker | Examples |
file_input / dropzone |
File selection input and drag-and-drop upload zone | Examples |
rating, pin_input, chip, fieldset |
Additional form primitives | Examples |
checkbox, radio, switch, segmented_control |
Toggle-style inputs | Examples |
slider, range_slider, hue_slider, alpha_slider, angle_slider |
Slider family | Examples |
select, multi_select, autocomplete, combobox, tags_input, tree_select |
Selection and combobox-based inputs | Examples |
cascader |
Hierarchical select drilling down through cascading columns | Examples |
rich_select |
Advanced select component with search and grouping | Examples |
date_input, date_picker, date_picker_input, date_time_picker, time_input, time_picker, month_picker, year_picker, calendar |
Full date/time picker family | Examples |
rich_text_editor |
WYSIWYG editor powered by Tiptap | Guide |
Buttons
| Component | Description | Documentation |
|---|---|---|
action_icon |
Lightweight button for icons with size, variant, radius, disabled state | Examples |
button |
Button with variants, sizes, gradient, loading states, sections | Examples |
close_button, unstyled_button |
Additional button variants | Examples |
Overlays
| Component | Description | Documentation |
|---|---|---|
modal |
Accessible overlay dialog with focus trap and scroll lock | Examples |
drawer |
Overlay drawer area sliding from any side | Docs |
alert_dialog |
Confirmation/alert dialog with focus management | Examples |
popover, hover_card, tooltip, dialog, overlay, loading_overlay |
Contextual overlays | Examples |
menu, menubar |
Dropdown and application menus | Examples |
Navigation & Layout
| Component | Description | Documentation |
|---|---|---|
nav_link, tabs, breadcrumbs, pagination, stepper, anchor, burger, table_of_contents |
Navigation primitives | Examples |
navigation_progress |
Page loading progress indicator | Examples |
app_shell, container, stack, group, grid, simple_grid, flex, center, space, divider, affix, scroller, splitter |
Layout building blocks | Examples |
scroll_area |
Scrollable container with custom scrollbars and virtualization | Examples |
floating_window |
Draggable floating panel, resizable via the resize_handle sub-component |
Examples |
Data Display & Feedback
| Component | Description | Documentation |
|---|---|---|
table |
Table component for tabular data display | Examples |
accordion, avatar, badge, card, data_list, empty_state, image, indicator, kbd, paper, spoiler, theme_icon, timeline |
Data display components | Examples |
alert, loader, notification, progress, ring_progress, skeleton |
Feedback components | Examples |
tree, carousel |
Hierarchical and carousel display | Examples |
number_formatter |
Formats numeric input with parser/formatter, returns parsed value | Examples |
Charts
| Component | Description | Documentation |
|---|---|---|
area_chart, bar_chart, line_chart, pie_chart, donut_chart, radar_chart, radial_bar_chart, scatter_chart, composite_chart, bubble_chart, funnel_chart, heatmap, treemap, sankey_chart, sunburst_chart, bullet_chart, sparkline, bars_list |
Recharts-powered charting components | Examples |
chart_brush |
Range selector (brush) for area/bar/line/composite charts | Examples |
Maps & Scheduling
| Component | Description | Documentation |
|---|---|---|
map, MapMarker, MapControls, MapNavigation, MapDirectionsPanel, MapArc, MapGeoJSON, MapRoute, MapClusterLayer |
MapLibre-based map components | Examples |
schedule, resources_schedule, resources_day_view, resources_week_view, resources_month_view, agenda_view |
Calendar/resource scheduling components | Examples / Resources |
Typography & Markdown
| Component | Description | Documentation |
|---|---|---|
text, title, code, mark, highlight, blockquote, list_ |
Typography primitives | Examples |
markdown_preview |
Markdown renderer with Mermaid diagrams and math support | Examples |
Common Props (Inherited by All Inputs)
All input components inherit ~40 common props from MantineInputComponentBase:
# Input.Wrapper props
label = "Field Label"
description = "Helper text"
error = "Validation error"
required = True
with_asterisk = True # Show red asterisk for required fields
# Visual variants
variant = "filled" # "default" | "filled" | "unstyled"
size = "md" # "xs" | "sm" | "md" | "lg" | "xl"
radius = "md" # "xs" | "sm" | "md" | "lg" | "xl"
# State management
value = State.field_value
default_value = "Initial value"
placeholder = "Enter text..."
disabled = False
# Sections (icons, buttons)
left_section = rx.icon("search")
right_section = rx.button("Clear")
left_section_pointer_events = "none" # Click-through
# Mantine style props
w = "100%" # width
maw = "500px" # max-width
m = "md" # margin
p = "sm" # padding
# Event handlers
on_change = State.handle_change
on_focus = State.handle_focus
on_blur = State.handle_blur
📖 Usage Examples
Basic Input with Validation
import reflex as rx
import appkit_mantine as mn
class EmailState(rx.State):
email: str = ""
error: str = ""
def validate_email(self):
if "@" not in self.email:
self.error = "Invalid email format"
else:
self.error = ""
def email_input():
return mn.form.input(
label="Email Address",
description="We'll never share your email",
placeholder="you@example.com",
value=EmailState.email,
on_change=EmailState.set_email,
on_blur=EmailState.validate_email,
error=EmailState.error,
required=True,
type="email",
left_section=rx.icon("mail"),
)
Number Input with Formatting
class PriceState(rx.State):
price: float = 0.0
def price_input():
return mn.number_input(
label="Product Price",
value=PriceState.price,
on_change=PriceState.set_price,
prefix="$",
decimal_scale=2,
fixed_decimal_scale=True,
thousand_separator=",",
min=0,
max=999999.99,
step=0.01,
)
Masked Input (Phone Number)
class PhoneState(rx.State):
phone: str = ""
def handle_phone(self, value: str) -> None:
self.phone = value
def phone_input():
# Use as an UNCONTROLLED component: default_value + on_change (not value)
return mn.masked_input(
label="Phone Number",
mask="+1 (000) 000-0000",
default_value="+1 (555) 123-4567",
on_change=PhoneState.handle_phone,
placeholder="+1 (555) 123-4567",
)
Date Input with Constraints
from datetime import date, timedelta
class BookingState(rx.State):
checkin: str = ""
def date_picker():
today = date.today()
max_date = today + timedelta(days=365)
return mn.date_input(
label="Check-in Date",
value=BookingState.checkin,
on_change=BookingState.set_checkin,
min_date=today.isoformat(),
max_date=max_date.isoformat(),
clear_button_props={"aria_label": "Clear date"},
)
Rich Text Editor
class EditorState(rx.State):
content: str = "<p>Start typing...</p>"
def editor():
return mn.rich_text_editor(
value=EditorState.content,
on_change=EditorState.set_content,
toolbar_config=mn.EditorToolbarConfig(
controls=[
mn.ToolbarControlGroup.FORMATTING,
mn.ToolbarControlGroup.LISTS,
mn.ToolbarControlGroup.LINKS,
]
),
)
Action Icon
def action_icon_example():
return mn.action_icon(
rx.icon("heart"),
variant="filled",
color="red",
size="lg",
on_click=State.like_item,
)
Autocomplete
class SearchState(rx.State):
query: str = ""
def autocomplete_example():
return mn.autocomplete(
label="Search",
placeholder="Type to search...",
data=["Apple", "Banana", "Cherry"],
value=SearchState.query,
on_change=SearchState.set_query,
)
Button
def button_example():
return mn.button(
"Click me",
variant="gradient",
gradient={"from": "blue", "to": "cyan"},
size="lg",
on_click=State.handle_click,
)
Combobox
def combobox_example():
return mn.combobox(
label="Select option",
data=[
{"value": "react", "label": "React"},
{"value": "vue", "label": "Vue"},
],
on_option_submit=State.set_selected,
)
Input
def input_example():
return mn.input(
placeholder="Enter text...",
left_section=rx.icon("search"),
right_section=rx.button("Clear"),
)
JSON Input
class JsonState(rx.State):
data: str = '{"name": "example"}'
def json_input_example():
return mn.json_input(
label="JSON Data",
value=JsonState.data,
on_change=JsonState.set_data,
format_on_blur=True,
)
Nav Link
def nav_link_example():
return mn.nav_link(
label="Dashboard",
left_section=rx.icon("home"),
active=True,
on_click=State.navigate_to_dashboard,
)
Number Formatter
class PriceState(rx.State):
amount: float = 1234.56
def number_formatter_example():
return mn.number_formatter(
value=PriceState.amount,
prefix="$",
thousand_separator=",",
decimal_scale=2,
)
Select
class SelectState(rx.State):
choice: str = ""
def select_example():
return mn.select(
label="Choose one",
data=["Option 1", "Option 2", "Option 3"],
value=SelectState.choice,
on_change=SelectState.set_choice,
)
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file appkit_mantine-1.14.0.tar.gz.
File metadata
- Download URL: appkit_mantine-1.14.0.tar.gz
- Upload date:
- Size: 250.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
61618112244a3d48cbf007c57c41623582374dee8f6fdfe6df29bfccd24e1647
|
|
| MD5 |
7f125b28e551c138d193504d1b6effcc
|
|
| BLAKE2b-256 |
b62fa10756bc5fab7569b9abb15c0f1ae9b26bfa8bbb5ef0921a7285c7df579e
|
File details
Details for the file appkit_mantine-1.14.0-py3-none-any.whl.
File metadata
- Download URL: appkit_mantine-1.14.0-py3-none-any.whl
- Upload date:
- Size: 308.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.12.6 {"installer":{"name":"uv","version":"0.12.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
57d918bbb159780ec0a97c5e5b48aff6bc56833be370378062a90b02dfd04ca5
|
|
| MD5 |
377a9db41957ce9259b748bf170f0cd9
|
|
| BLAKE2b-256 |
64c87039386ebb55446aeed53ddee4ee6e5626aa0bacfd273f92c2fd4f460c78
|