Skip to content

Commit 5d4195c

Browse files
authored
Add FItem primitive (#600)
* Rename FTileDivider to FItemDivider * Phase 1 (Extract FItem out of FTile) * Move FItem to foundation * Migrate FSelect * Fix divider rendering oddity * Add support for dividers to FSelect * Fix FSidebarItem * Update CLI * Update windows-latest goldens * Fix typos * Prepare Forui for review --------- Co-authored-by: Pante <[email protected]>
1 parent 204c9f6 commit 5d4195c

File tree

902 files changed

+3036
-1331
lines changed

Some content is hidden

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

902 files changed

+3036
-1331
lines changed

docs/app/docs/form/select/page.mdx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ FSelect<String>(
7575
description: const Text('Select your country of residence'),
7676
hint: 'Choose a country',
7777
format: (value) => value.toUpperCase(),
78+
divider: FItemDivider.none,
7879
onChange: (value) => print('Selected country: $value'),
7980
onSaved: (value) => print('Saved country: $value'),
8081
style: FSelectStyle.inherit(...),
@@ -89,9 +90,11 @@ FSelect<String>(
8990
children: [
9091
FSelectSection(
9192
label: const Text('North American Countries'),
93+
divider: FItemDivider.none,
9294
children: [
9395
FSelectItem.from(
9496
child: const Text('United States'),
97+
divider: FItemDivider.none,
9598
value: 'us',
9699
),
97100
FSelectItem(
@@ -145,6 +148,7 @@ FSelect<User>.search(
145148
description: const Text('Search and select a user'),
146149
builder: (context, styles, child) => child!,
147150
format: (user) => '${user.firstName} ${user.lastName}',
151+
divider: FItemDivider.none,
148152
hint: 'Search users...',
149153
popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400),
150154
clearable: true,
@@ -187,6 +191,7 @@ FSelect<User>.searchFromMap(
187191
description: const Text('Search and select a user'),
188192
builder: (context, styles, child) => child!,
189193
format: (user) => '${user.firstName} ${user.lastName}',
194+
divider: FItemDivider.none,
190195
hint: 'Search users...',
191196
popoverConstraints: const FAutoWidthPortalConstraints(maxHeight: 400),
192197
clearable: true,
@@ -215,6 +220,45 @@ FSelect<User>.searchFromMap(
215220

216221
## Examples
217222

223+
### Detailed
224+
225+
<Tabs items={['Preview', 'Code']}>
226+
<Tabs.Tab>
227+
<Widget name='select' variant='detailed' query={{}} height={400}/>
228+
</Tabs.Tab>
229+
<Tabs.Tab>
230+
```dart copy
231+
class DetailedSelectPage extends StatelessWidget {
232+
@override
233+
Widget build(BuildContext context) => FSelect<String>(
234+
hint: 'Type',
235+
format: (s) => s,
236+
children: [
237+
FSelectItem.from(
238+
prefix: const Icon(FIcons.bug),
239+
title: const Text('Bug'),
240+
subtitle: const Text('An unexpected problem or behavior'),
241+
value: 'Bug',
242+
),
243+
FSelectItem.from(
244+
prefix: const Icon(FIcons.filePlus2),
245+
title: const Text('Feature'),
246+
subtitle: const Text('A new feature or enhancement'),
247+
value: 'Feature',
248+
),
249+
FSelectItem.from(
250+
prefix: const Icon(FIcons.messageCircleQuestion),
251+
title: const Text('Question'),
252+
subtitle: const Text('A question or clarification'),
253+
value: 'Question',
254+
),
255+
],
256+
);
257+
}
258+
```
259+
</Tabs.Tab>
260+
</Tabs>
261+
218262
### Sections
219263

220264
<Tabs items={['Preview', 'Code']}>
@@ -303,6 +347,44 @@ FSelect<User>.searchFromMap(
303347
</Tabs.Tab>
304348
</Tabs>
305349

350+
### Dividers
351+
352+
<Tabs items={['Preview', 'Code']}>
353+
<Tabs.Tab>
354+
<Widget name='select' variant='divider' query={{}} height={400}/>
355+
</Tabs.Tab>
356+
<Tabs.Tab>
357+
```dart {5, 10} copy
358+
class DividerSelectPage extends StatelessWidget {
359+
@override
360+
Widget build(BuildContext context) => FSelect<String>(
361+
hint: 'Select a level',
362+
divider: FItemDivider.full,
363+
format: (s) => s,
364+
children: [
365+
FSelectSection.fromMap(
366+
label: const Text('Level 1'),
367+
divider: FItemDivider.indented,
368+
items: {
369+
for (final item in ['A', 'B']) item: '1$item',
370+
},
371+
),
372+
FSelectSection.fromMap(
373+
label: const Text('Level 2'),
374+
items: {
375+
for (final item in ['A', 'B']) item: '2$item',
376+
},
377+
),
378+
FSelectItem('Level 3', '3'),
379+
FSelectItem('Level 4', '4'),
380+
],
381+
);
382+
}
383+
```
384+
</Tabs.Tab>
385+
</Tabs>
386+
387+
306388
### Searchable
307389

308390
#### Sync
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import {Callout} from "nextra/components";
2+
import { Tabs } from 'nextra/components';
3+
import { Widget } from '@/components/demo/widget.tsx';
4+
import LinkBadge from '@/components/ui/link-badge/link-badge.tsx';
5+
import LinkBadgeGroup from '@/components/ui/link-badge/link-badge-group.tsx';
6+
7+
# Item
8+
9+
An item is typically used to group related information together.
10+
11+
<LinkBadgeGroup>
12+
<LinkBadge label="API Reference" href="https://pub.dev/documentation/forui/latest/forui.foundation/FItem-class.html"/>
13+
</LinkBadgeGroup>
14+
15+
<Tabs items={['Preview', 'Code']}>
16+
<Tabs.Tab>
17+
<Widget name='item' variant='default' query={{}}/>
18+
</Tabs.Tab>
19+
<Tabs.Tab>
20+
```dart copy
21+
FItem(
22+
prefix: Icon(FIcons.user),
23+
title: const Text('Personalization'),
24+
suffix: Icon(FIcons.chevronRight),
25+
onPress: () { },
26+
);
27+
```
28+
</Tabs.Tab>
29+
</Tabs>
30+
31+
## CLI
32+
33+
To generate and customize this style:
34+
35+
```shell copy
36+
dart run forui style create item
37+
```
38+
39+
## Usage
40+
41+
### `FItem(...)`
42+
43+
```dart copy
44+
FItem(
45+
style: FFItemStyle(...),
46+
prefix: Icon(FIcons.user),
47+
title: const Text('Title'),
48+
subtitle: const Text('Subtitle'),
49+
details: const Text('Details'),
50+
suffix: Icon(FIcons.chevronRight),
51+
semanticsLabel: 'Label',
52+
enabled: true,
53+
selected: false,
54+
onFocusChange: (focused) {},
55+
onHoverChange: (hovered) {},
56+
onStateChange: (states) {},
57+
onPress: () {},
58+
onLongPress: () {},
59+
);
60+
```
61+
62+
### `FItem.raw(...)`
63+
64+
```dart copy
65+
FItem.raw(
66+
style: FItemStyle(...),
67+
prefix: Icon(FIcons.user),
68+
child: const Text('Title'),
69+
semanticsLabel: 'Label',
70+
enabled: true,
71+
selected: false,
72+
onFocusChange: (focused) {},
73+
onHoverChange: (hovered) {},
74+
onStateChange: (states) {},
75+
onPress: () {},
76+
onLongPress: () {},
77+
);
78+
```
79+
80+
## Examples
81+
82+
### Untappable
83+
84+
<Tabs items={['Preview', 'Code']}>
85+
<Tabs.Tab>
86+
<Widget name='item' variant='default' query={{tappable: false}}/>
87+
</Tabs.Tab>
88+
<Tabs.Tab>
89+
```dart copy
90+
FItem(
91+
prefix: Icon(FIcons.user),
92+
title: const Text('Personalization'),
93+
suffix: Icon(FIcons.chevronRight),
94+
);
95+
```
96+
</Tabs.Tab>
97+
</Tabs>
98+
99+
### Disabled
100+
101+
<Tabs items={['Preview', 'Code']}>
102+
<Tabs.Tab>
103+
<Widget name='item' variant='default' query={{enabled: false}}/>
104+
</Tabs.Tab>
105+
<Tabs.Tab>
106+
```dart {2} copy
107+
FItem(
108+
enabled: false,
109+
prefix: Icon(FIcons.user),
110+
title: const Text('Personalization'),
111+
suffix: Icon(FIcons.chevronRight),
112+
onPress: () { },
113+
);
114+
```
115+
</Tabs.Tab>
116+
</Tabs>
117+
118+
### With Subtitle
119+
120+
<Tabs items={['Preview', 'Code']}>
121+
<Tabs.Tab>
122+
<Widget name='item' variant='subtitle' query={{}}/>
123+
</Tabs.Tab>
124+
<Tabs.Tab>
125+
```dart {4} copy
126+
FItem(
127+
prefix: Icon(FIcons.bell),
128+
title: const Text('Notifications'),
129+
subtitle: const Text('Banners, Sounds, Badges'),
130+
suffix: Icon(FIcons.chevronRight),
131+
onPress: () {},
132+
);
133+
```
134+
</Tabs.Tab>
135+
</Tabs>
136+
137+
### With Details
138+
139+
<Tabs items={['Preview', 'Code']}>
140+
<Tabs.Tab>
141+
<Widget name='item' variant='details' query={{}}/>
142+
</Tabs.Tab>
143+
<Tabs.Tab>
144+
```dart {4} copy
145+
FItem(
146+
prefix: Icon(FIcons.wifi),
147+
title: const Text('WiFi'),
148+
details: const Text('Forus Labs (5G)'),
149+
suffix: Icon(FIcons.chevronRight),
150+
onPress: () {},
151+
);
152+
```
153+
</Tabs.Tab>
154+
</Tabs>

docs/app/docs/tile/select-menu-tile/page.mdx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ FSelectMenuTile<Value>(
7676
maxHeight: 200,
7777
dragStartBehavior: DragStartBehavior.start,
7878
physics: const ClampingScrollPhysics(),
79-
divider: FTileDivider.indented,
79+
divider: FItemDivider.indented,
8080
label: const Text('Sidebar'),
8181
description: const Text('Select the items you want to display in the sidebar.'),
8282
errorBuilder: (context, error) => Text(error),
@@ -116,7 +116,7 @@ FSelectMenuTile<Value>.builder(
116116
maxHeight: 200,
117117
dragStartBehavior: DragStartBehavior.start,
118118
physics: const ClampingScrollPhysics(),
119-
divider: FTileDivider.indented,
119+
divider: FItemDivider.indented,
120120
label: const Text('Sidebar'),
121121
description: const Text('Select the items you want to display in the sidebar.'),
122122
errorBuilder: (context, error) => Text(error),

docs/app/docs/tile/select-tile-group/page.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ FSelectTileGroup<Value>(
7474
physics: const ClampingScrollPhysics(),
7575
label: const Text('Sidebar'),
7676
description: const Text('Select the items you want to display in the sidebar.'),
77-
divider: FTileDivider.indented,
77+
divider: FItemDivider.indented,
7878
onChange: (all) => print(all),
7979
onSelect: (selection) => print(selection),
8080
children: [
@@ -100,7 +100,7 @@ FSelectTileGroup<Value>.builder(
100100
label: const Text('Settings'),
101101
description: const Text('Personalize your experience'),
102102
semanticsLabel: 'Settings',
103-
divider: FTileDivider.indented,
103+
divider: FItemDivider.indented,
104104
onChange: (all) => print(all),
105105
onSelect: (selection) => print(selection),
106106
tileBuilder: (context, index) => index < 10 ? FSelectTile(
@@ -356,7 +356,7 @@ FSelectTileGroup<Value>.builder(
356356
357357
FSelectTileGroup<Sidebar>(
358358
selectController: FSelectTileGroupController(values: {Sidebar.recents}),
359-
divider: FTileDivider.full,
359+
divider: FItemDivider.full,
360360
label: const Text('Sidebar'),
361361
description: const Text('These will be shown in the sidebar.'),
362362
children: [
@@ -394,7 +394,7 @@ FSelectTileGroup<Value>.builder(
394394
395395
FSelectTileGroup<Sidebar>(
396396
selectController: FSelectTileGroupController(values: {Sidebar.recents}),
397-
divider: FTileDivider.none,
397+
divider: FItemDivider.none,
398398
label: const Text('Sidebar'),
399399
description: const Text('These will be shown in the sidebar.'),
400400
children: [

docs/app/docs/tile/tile-group/page.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ FTileGroup(
6464
label: const Text('Settings'),
6565
description: const Text('Personalize your experience'),
6666
semanticsLabel: 'Settings',
67-
divider: FTileDivider.indented,
67+
divider: FItemDivider.indented,
6868
children: [],
6969
);
7070
```
@@ -82,7 +82,7 @@ FTileGroup.builder(
8282
label: const Text('Settings'),
8383
description: const Text('Personalize your experience'),
8484
semanticsLabel: 'Settings',
85-
divider: FTileDivider.indented,
85+
divider: FItemDivider.indented,
8686
tileBuilder: (context, index) => index < 10 ? FTile(title: Text('Tile $index')) : null,
8787
count: 100,
8888
);
@@ -99,7 +99,7 @@ FTileGroup.merge(
9999
physics: const ClampingScrollPhysics(),
100100
label: const Text('Settings'),
101101
semanticsLabel: 'Settings',
102-
divider: FTileDivider.indented,
102+
divider: FItemDivider.indented,
103103
children: [],
104104
);
105105
```
@@ -241,7 +241,7 @@ several sections.
241241
```dart {3} copy
242242
FTileGroup(
243243
label: const Text('Settings'),
244-
divider: FTileDivider.full,
244+
divider: FItemDivider.full,
245245
children: [
246246
FTile(
247247
prefix: Icon(FIcons.user),
@@ -272,7 +272,7 @@ several sections.
272272
```dart {3} copy
273273
FTileGroup(
274274
label: const Text('Settings'),
275-
divider: FTileDivider.none,
275+
divider: FItemDivider.none,
276276
children: [
277277
FTile(
278278
prefix: Icon(FIcons.user),

0 commit comments

Comments
 (0)