Skip to content

Commit 4e1c879

Browse files
Panteclaude
andauthored
Improve FDialog with touch/desktop styles and image support (#948)
* Refine tab swipe implementation * Improve FDialog with touch/desktop styles, image support, and expanded test coverage - Add image parameter to FDialog constructors - Introduce FDialogContentStyles extension type with touch/desktop differentiation - Rework spacing model with titlePadding, bodyPadding, imageSpacing, expandActions - Left-align VerticalContent (was center) - Add comprehensive golden tests for touch and desktop variants - Update docs_snippets usages and changelog Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Prepare Forui for review * Update goldens * Update changelog --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Pante <Pante@users.noreply.github.com>
1 parent 9d506e8 commit 4e1c879

142 files changed

Lines changed: 957 additions & 533 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/content/docs/navigation/tabs.mdx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ description: A set of layered sections of content—known as tab entries—that
44
apiReference: https://pub.dev/documentation/forui/latest/forui.widgets.tabs/
55
---
66

7+
import { Callout } from 'fumadocs-ui/components/callout';
78
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
89
import { Widget } from '@/components/demo/widget';
910
import { CodeSnippet } from '@/components/code-snippet/code-snippet';
1011
import { UsageSnippet } from '@/components/usage-snippet/usage-snippet';
1112
import defaultSnippet from '@/snippets/examples/tabs/default.json';
13+
import swipeableSnippet from '@/snippets/examples/tabs/swipeable.json';
1214
import tabsUsage from '@/snippets/usages/widgets/tabs/tabs.json';
1315
import tabEntryUsage from '@/snippets/usages/widgets/tabs/tabEntry.json';
1416

@@ -43,11 +45,18 @@ To generate a specific style for customization:
4345

4446
## Examples
4547

46-
### Behavior
48+
### Swipeable
4749

48-
#### Swipe Navigation
50+
<Callout type="info">
51+
Hold `Shift` while scrolling to swipe between tabs on desktop and web.
52+
</Callout>
4953

50-
The tab content area supports horizontal swipe navigation when `expands` is true and `swipeablePhysics` resolves to an enabled value.
54+
<Tabs items={['Preview', 'Code']}>
55+
<Tab value="Preview">
56+
<Widget name='tabs' variant='swipeable' height={500}/>
57+
</Tab>
58+
<Tab value="Code">
59+
<CodeSnippet snippet={swipeableSnippet} />
60+
</Tab>
61+
</Tabs>
5162

52-
- **Defaults:** On non-desktop platforms (mobile and web), `swipeablePhysics` defaults to an enabled value, so swipe navigation is on when `expands` is true. On desktop it defaults to disabled. Use `swipeablePhysics` to override.
53-
- **Physics:** When swipe navigation is enabled, the scroll physics default to `BouncingScrollPhysics`.

docs_snippets/lib/examples/widgets/tabs.dart

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,55 @@ class TabsPage extends Example {
5555
],
5656
);
5757
}
58+
59+
@RoutePage()
60+
class SwipeableTabsPage extends Example {
61+
SwipeableTabsPage({@queryParam super.theme});
62+
63+
@override
64+
Widget example(BuildContext _) => Padding(
65+
padding: const .all(16),
66+
child: SizedBox(
67+
height: 350,
68+
child: FTabs(
69+
// {@highlight}
70+
expands: true,
71+
// {@endhighlight}
72+
children: [
73+
.entry(
74+
label: const Text('Account'),
75+
child: FCard(
76+
title: const Text('Account'),
77+
subtitle: const Text('Make changes to your account here. Click save when you are done.'),
78+
child: Column(
79+
children: [
80+
const FTextField(label: Text('Name'), hint: 'John Renalo'),
81+
const SizedBox(height: 10),
82+
const FTextField(label: Text('Email'), hint: 'john@doe.com'),
83+
const SizedBox(height: 16),
84+
FButton(child: const Text('Save'), onPress: () {}),
85+
],
86+
),
87+
),
88+
),
89+
.entry(
90+
label: const Text('Password'),
91+
child: FCard(
92+
title: const Text('Password'),
93+
subtitle: const Text('Change your password here. After saving, you will be logged out.'),
94+
child: Column(
95+
children: [
96+
const FTextField(label: Text('Current password')),
97+
const SizedBox(height: 10),
98+
const FTextField(label: Text('New password')),
99+
const SizedBox(height: 16),
100+
FButton(child: const Text('Save'), onPress: () {}),
101+
],
102+
),
103+
),
104+
),
105+
],
106+
),
107+
),
108+
);
109+
}

docs_snippets/lib/main.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ class _AppRouter extends RootStackRouter {
231231
AutoRoute(path: '/switch/disabled', page: DisabledSwitchRoute.page),
232232
AutoRoute(path: '/switch/form', page: FormSwitchRoute.page),
233233
AutoRoute(path: '/tabs/default', page: TabsRoute.page),
234+
AutoRoute(path: '/tabs/swipeable', page: SwipeableTabsRoute.page),
234235
AutoRoute(path: '/tappable/default', page: TappableRoute.page),
235236
AutoRoute(path: '/tappable/bounce', page: TappableBounceRoute.page),
236237
AutoRoute(path: '/tappable-group/default', page: TappableGroupRoute.page),

docs_snippets/lib/usages/widgets/dialog.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final dialog = FDialog(
1717
// {@endcategory}
1818
// {@category "Core"}
1919
style: const .delta(insetPadding: .value(.zero)),
20+
image: null,
2021
title: const Text('Title'),
2122
body: const Text('Body'),
2223
actions: [FButton(onPress: () {}, child: const Text('Action'))],
@@ -35,6 +36,7 @@ final adaptive = FDialog.adaptive(
3536
// {@endcategory}
3637
// {@category "Core"}
3738
style: const .delta(insetPadding: .value(.zero)),
39+
image: null,
3840
title: const Text('Title'),
3941
body: const Text('Body'),
4042
actions: [FButton(onPress: () {}, child: const Text('Action'))],

docs_snippets/lib/usages/widgets/tabs.dart

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,10 @@ final tabs = FTabs(
88
// {@category "Control"}
99
control: const .managed(),
1010
// {@endcategory}
11-
// {@category "Tab Bar"}
12-
scrollable: false,
13-
// {@endcategory}
1411
// {@category "Core"}
15-
swipeablePhysics: null,
12+
scrollable: false,
1613
physics: null,
14+
contentPhysics: const BouncingScrollPhysics(),
1715
style: const .delta(spacing: 10),
1816
mouseCursor: .defer,
1917
onPress: (index) {},

forui/CHANGELOG.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,21 @@
99
* Fix default text styles created by `FTypography` to include a `fontFamily`.
1010

1111

12+
### `FDialog`
13+
We've adjusted `FDialog`'s styling to be more visually pleasing on touch devices.
14+
15+
* Add `FDialog.image` parameter.
16+
* Add `FDialogContentStyle.titlePadding`.
17+
* Add `FDialogContentStyle.bodyPadding`.
18+
* Add `FDialogContentStyle.imageSpacing`.
19+
* Add `FDialogContentStyle.expandActions`.
20+
* Add `FDialogContentStyles` extension type.
21+
22+
* **Breaking** Change `FDialogContentStyle` fields to have defaults instead of being required.
23+
* **Breaking** Change `VerticalContent` alignment from center to start.
24+
* **Breaking** Remove `FDialogContentStyle.bodySpacing`. Use `FDialogContentStyle.titleSpacing` instead.
25+
26+
1227
### `FItem`
1328
* Add `FInheritedItemCallbacks`.
1429
* Add `FItemMixin.submenu(...)` shorthand for `FSubmenuItem`.
@@ -28,9 +43,10 @@
2843

2944

3045
### `FTabs`
31-
* Add swipe navigation when `expands` is true. When swipe navigation is enabled (i.e. `expands` is true and `swipeablePhysics` resolves to true), the content area's `physics` defaults to `BouncingScrollPhysics`.
32-
* Add `FTabs.swipeablePhysics` to toggle swipe navigation independently from `scrollable`.
33-
* Add assertion to catch `FTabs(expands: true)` in containers with unbounded height.
46+
* Add swipe/scroll navigation when `expands` is true, with `BouncingScrollPhysics` by default.
47+
* Add `FTabs.contentPhysics` to customize the content area's scroll physics.
48+
49+
* **Breaking** Remove `FTabs.swipeablePhysics`. Use `FTabs.contentPhysics` instead.
3450

3551

3652
### `FTile`

forui/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ Forui provides the following widgets:
9191
- Picker
9292
- Radio
9393
- Multi-select
94+
- OTP Field
9495
- Select
9596
- Select Group
9697
- Slider

forui/bin/commands/style/style.dart

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

forui/example/assets/profile.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

forui/example/pubspec.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ dependencies:
3131
flutter_hooks: ^0.21.0
3232
forui:
3333
intl: any
34+
lottie: ^3.3.2
3435
sugar: ^4.0.0
3536
wakelock_plus: ^1.2.8
3637

@@ -49,6 +50,8 @@ flutter:
4950
# assets:
5051
# - images/a_dot_burr.jpeg
5152
# - images/a_dot_ham.jpeg
53+
assets:
54+
- assets/profile.json
5255

5356
# An image asset can refer to one or more resolution-specific "variants", see
5457
# https://flutter.dev/assets-and-images/#resolution-aware

0 commit comments

Comments
 (0)