diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7657972a..924f7cd8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,11 @@
-## 0.15.4
+## 0.16.0
+- **FEAT**: New `ShadTimePicker` and `ShadDatePickerFormField` components.
+- **FIX**: `maxLength`, `maxLengthEnforcement` and `showCursor` not working on `ShadInput`
+- **FIX**: `ShadCalendar` range day button text style when `disableSecondaryBorder` is `true`.
- **CHORE**: Set minimum Flutter version to `3.24.0`
- **CHORE**: Remove `trackColor` from `ShadSwitch` (thanks to @RaghavTheGreat)
+- **FIX**: `ShadSlider` `onChanged` called on every controller update (thanks to @helightdev).
## 0.15.3
diff --git a/README.md b/README.md
index bd4ea91a..4c8c4f28 100644
--- a/README.md
+++ b/README.md
@@ -63,6 +63,7 @@ See the [documentation](https://flutter-shadcn-ui.mariuti.com/) to interact with
- [x] [Table](https://flutter-shadcn-ui.mariuti.com/components/table/)
- [x] [Tabs](https://flutter-shadcn-ui.mariuti.com/components/tabs/)
- [ ] TextArea
+- [x] [Time Picker](https://flutter-shadcn-ui.mariuti.com/components/time-picker/)
- [x] [Toast](https://flutter-shadcn-ui.mariuti.com/components/toast/)
- [ ] Toggle
- [ ] ToggleGroup
diff --git a/docs/src/content/docs/Components/form.mdx b/docs/src/content/docs/Components/form.mdx
index 91883f89..9db567b7 100644
--- a/docs/src/content/docs/Components/form.mdx
+++ b/docs/src/content/docs/Components/form.mdx
@@ -81,3 +81,4 @@ See the following links for more examples on how to use the `ShadForm` component
- [Select](../select#form)
- [RadioGroup](../radio-group#form)
- [DatePicker](../date-picker#form)
+- [TimePicker](../time-picker#form)
diff --git a/docs/src/content/docs/Components/time-picker.mdx b/docs/src/content/docs/Components/time-picker.mdx
new file mode 100644
index 00000000..62c6838f
--- /dev/null
+++ b/docs/src/content/docs/Components/time-picker.mdx
@@ -0,0 +1,64 @@
+---
+title: Time Picker
+sidebar:
+ order: 4
+---
+
+import Preview from "../../../components/Preview.astro";
+
+A time picker component.
+
+
+
+```dart
+class PrimaryTimePicker extends StatelessWidget {
+ const PrimaryTimePicker({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return ConstrainedBox(
+ constraints: const BoxConstraints(maxWidth: 600),
+ child: const ShadTimePicker(
+ trailing: Padding(
+ padding: EdgeInsets.only(left: 8, top: 14),
+ child: ShadImage.square(LucideIcons.clock4, size: 16),
+ ),
+ ),
+ );
+ }
+}
+```
+
+
+
+## Form
+
+
+
+```dart
+ShadTimePickerFormField(
+ label: const Text('Pick a time'),
+ onChanged: print,
+ description:
+ const Text('The time of the day you want to pick'),
+ validator: (v) => v == null ? 'A time is required' : null,
+)
+```
+
+
+
+## ShadTimePickerFormField.period
+
+
+
+```dart
+ShadTimePickerFormField.period(
+ label: const Text('Pick a time'),
+ onChanged: print,
+ description:
+ const Text('The time of the day you want to pick'),
+ validator: (v) => v == null ? 'A time is required' : null,
+),
+```
+
+
diff --git a/example/lib/main.dart b/example/lib/main.dart
index d32e7197..5099f3c5 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -28,6 +28,8 @@ import 'package:example/pages/switch.dart';
import 'package:example/pages/switch_form_field.dart';
import 'package:example/pages/tabs.dart';
import 'package:example/pages/table.dart';
+import 'package:example/pages/time_picker.dart';
+import 'package:example/pages/time_picker_form_field.dart';
import 'package:example/pages/toast.dart';
import 'package:example/pages/tooltip.dart';
import 'package:example/pages/typography.dart';
@@ -72,6 +74,8 @@ final routes = {
'/switch-form-field': (_) => const SwitchFormFieldPage(),
'/table': (_) => const TablePage(),
'/tabs': (_) => const TabsPage(),
+ '/time-picker': (_) => const TimePickerPage(),
+ '/time-picker-form-field': (_) => const TimePickerFormFieldPage(),
'/toast': (_) => const ToastPage(),
'/tooltip': (_) => const TooltipPage(),
'/typography': (_) => const TypographyPage(),
diff --git a/example/lib/pages/time_picker.dart b/example/lib/pages/time_picker.dart
new file mode 100644
index 00000000..8cbdae70
--- /dev/null
+++ b/example/lib/pages/time_picker.dart
@@ -0,0 +1,37 @@
+import 'package:example/common/base_scaffold.dart';
+import 'package:flutter/material.dart';
+import 'package:shadcn_ui/shadcn_ui.dart';
+
+class TimePickerPage extends StatelessWidget {
+ const TimePickerPage({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BaseScaffold(
+ appBarTitle: 'TimePicker',
+ children: [
+ ConstrainedBox(
+ constraints: const BoxConstraints(maxWidth: 600),
+ child: ShadTimePicker(
+ trailing: const Padding(
+ padding: EdgeInsets.only(left: 8, top: 14),
+ child: ShadImage.square(LucideIcons.clock4, size: 16),
+ ),
+ onChanged: (time) {
+ print('time: $time');
+ },
+ ),
+ ),
+ ConstrainedBox(
+ constraints: const BoxConstraints(maxWidth: 600),
+ child: ShadTimePicker.period(
+ crossAxisAlignment: WrapCrossAlignment.end,
+ onChanged: (time) {
+ print('time: $time');
+ },
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/example/lib/pages/time_picker_form_field.dart b/example/lib/pages/time_picker_form_field.dart
new file mode 100644
index 00000000..d3431d54
--- /dev/null
+++ b/example/lib/pages/time_picker_form_field.dart
@@ -0,0 +1,101 @@
+// ignore_for_file: avoid_print
+
+import 'dart:convert';
+
+import 'package:example/common/base_scaffold.dart';
+import 'package:example/common/properties/bool_property.dart';
+import 'package:example/common/properties/enum_property.dart';
+import 'package:flutter/material.dart';
+import 'package:shadcn_ui/shadcn_ui.dart';
+
+class TimePickerFormFieldPage extends StatefulWidget {
+ const TimePickerFormFieldPage({super.key});
+
+ @override
+ State createState() =>
+ _TimePickerFormFieldPageState();
+}
+
+class _TimePickerFormFieldPageState extends State {
+ bool enabled = true;
+ var autovalidateMode = ShadAutovalidateMode.alwaysAfterFirstValidation;
+ Map