Mantine UI input components for Reflex with type safety and comprehensive examples
Project description
appkit-mantine
reflex.dev components based on MantineUI
A Reflex wrapper library focusing on Mantine UI v8.3.3 input components, designed for building robust forms and data entry interfaces in Python web applications.
✨ Features
- 🎯 Input-Focused - Comprehensive coverage of form inputs: text, password, number, date, masked inputs, textarea, and rich text editor
- 🔒 Type-Safe - Full type annotations with IDE autocomplete support for all props and event handlers
- 📚 Rich Examples - Production-ready code examples for every component with common patterns and edge cases
- 🏗️ Clean Architecture - Inheritance-based design eliminating code duplication across 40+ common props
- 🎨 Mantine Integration - Seamless integration with Mantine's theming, color modes, and design system
- ⚡ Modern Stack - Built on Reflex 0.8.13+ with React 18 and Mantine 8.3.3
📦 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
⚠️ Pre-release Notice: This library is in development. APIs may change before the 1.0 release.
🚀 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 |
date_input |
Date picker with range constraints and formatting | 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 |
select |
Dropdown select with data array, inherits input props | Examples |
multi_select |
Multi-select dropdown for selecting multiple values | Examples |
rich_select |
Advanced select component with search and grouping | Examples |
tags_input |
Free-form tags input component | Examples |
autocomplete |
Autocomplete input with string data array | Examples |
rich_text_editor |
WYSIWYG editor powered by Tiptap | Guide |
masked_input |
Input masking for phone numbers, credit cards, custom patterns | 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 |
Overlays
| Component | Description | Documentation |
|---|---|---|
modal |
Accessible overlay dialog with focus trap and scroll lock | Examples |
drawer |
Overlay drawer area sliding from any side | Docs |
Others
| Component | Description | Documentation |
|---|---|---|
markdown_preview |
Markdown renderer with Mermaid diagrams and math support | Examples |
navigation_progress |
Page loading progress indicator | Examples |
nav_link |
Navigation link with label, description, icons, nested links, active/disabled states | Examples |
number_formatter |
Formats numeric input with parser/formatter, returns parsed value | Examples |
scroll_area |
Scrollable container with custom scrollbars and virtualization | Examples |
table |
Table component for tabular data display | 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 phone_input():
return mn.masked_input(
label="Phone Number",
mask="+1 (000) 000-0000",
value=PhoneState.phone,
on_accept=PhoneState.set_phone, # Note: on_accept, not on_change
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.
Project details
Release history Release notifications | RSS feed
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.2.1.tar.gz.
File metadata
- Download URL: appkit_mantine-1.2.1.tar.gz
- Upload date:
- Size: 69.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0aec7d06c4b4f116ab4cc4bf341dcb8aada48e6c3f9928b949c662de8957e0fd
|
|
| MD5 |
1b3d76629d0aaffae7073adf0b2639c0
|
|
| BLAKE2b-256 |
0099e87ad45b6c945f1da93f0d8951ad744a7f1d1826411e70016c621505f8b5
|
File details
Details for the file appkit_mantine-1.2.1-py3-none-any.whl.
File metadata
- Download URL: appkit_mantine-1.2.1-py3-none-any.whl
- Upload date:
- Size: 64.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8dc13cb3e3ad3dbadd148c6c5e1e9c05fed7b1de0ac397e84e2a58f34f197ff
|
|
| MD5 |
c96d1852332147cbfa53ddd1ef709b3e
|
|
| BLAKE2b-256 |
f0b5042eac6eb715baf1349829aa38f7fb0f64aa1402e4bdbfe47bf274536eca
|