Input
In ProgressDark modeRTLA text input field with labels, icons, and validation.
Installation
Copy the component into your project using the CLI:
$ronakcn add input
Usage
Import and use the component in your Flutter widget tree:
lib/pages/example.dart
import 'package:flutter/material.dart';
import '../components/input/input.dart';
class ExamplePage extends StatelessWidget {
const ExamplePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('RcnInput Example')),
body: Center(
child: RcnInput(
// Configure props here
),
),
);
}
}Variants
Input ships with the following variants:
default
A plain text input field.
with-label
Input with a floating label above.
with-icon
Input with a prefix or suffix icon.
with-error
Input showing an error state with message.
disabled
A non-interactive disabled input.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | String | '' | Current value of the input. |
onChanged* | ValueChanged<String> | — | Called when the value changes. |
placeholder | String? | null | Placeholder text shown when empty. |
label | String? | null | Label displayed above the input. |
prefixIcon | Widget? | null | Icon shown at the start of the input. |
suffixIcon | Widget? | null | Icon shown at the end of the input. |
errorText | String? | null | Error message shown below the input. |
enabled | bool | true | Whether the input is interactive. |
obscureText | bool | false | Hides text for password fields. |
keyboardType | TextInputType | TextInputType.text | Keyboard type for the input. |
Source files
lib/components/ui/input.dart
import 'package:flutter/material.dart';
class RcnInput extends StatelessWidget {
const RcnInput({
super.key,
this.value = '',
required this.onChanged,
this.placeholder,
this.label,
this.prefixIcon,
this.suffixIcon,
this.errorText,
this.enabled = true,
this.obscureText = false,
this.keyboardType = TextInputType.text,
this.controller,
});
final String value;
final ValueChanged<String> onChanged;
final String? placeholder;
final String? label;
final Widget? prefixIcon;
final Widget? suffixIcon;
final String? errorText;
final bool enabled;
final bool obscureText;
final TextInputType keyboardType;
final TextEditingController? controller;
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (label != null) ...[
Text(label!, style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: colors.onSurface)),
const SizedBox(height: 6),
],
TextField(
controller: controller,
onChanged: onChanged,
enabled: enabled,
obscureText: obscureText,
keyboardType: keyboardType,
style: TextStyle(fontSize: 14, color: colors.onSurface),
decoration: InputDecoration(
hintText: placeholder,
hintStyle: TextStyle(color: colors.onSurface.withOpacity(0.4)),
prefixIcon: prefixIcon,
suffixIcon: suffixIcon,
errorText: errorText,
contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: colors.outline),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: colors.primary, width: 2),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: BorderSide(color: colors.outline.withOpacity(0.4)),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(8),
borderSide: const BorderSide(color: Color(0xFFE11D48)),
),
),
),
],
);
}
}Version
0.1.0 · input category