-
-
Notifications
You must be signed in to change notification settings - Fork 31
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ae4e086
commit 7a8a20b
Showing
11 changed files
with
687 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
101 changes: 101 additions & 0 deletions
101
docs/lib/pages/docs/components/tab_pane/tab_pane_example_1.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import 'package:shadcn_flutter/shadcn_flutter.dart'; | ||
|
||
class TabPaneExample1 extends StatefulWidget { | ||
const TabPaneExample1({super.key}); | ||
|
||
@override | ||
State<TabPaneExample1> createState() => _TabPaneExample1State(); | ||
} | ||
|
||
class _TabPaneExample1State extends State<TabPaneExample1> { | ||
late List<TabItem> tabs; | ||
int focused = 0; | ||
|
||
@override | ||
void didChangeDependencies() { | ||
super.didChangeDependencies(); | ||
tabs = [ | ||
for (int i = 0; i < 3; i++) _buildTabItem(i), | ||
]; | ||
} | ||
|
||
TabItem _buildTabItem(int index) { | ||
return TabItem( | ||
key: ValueKey(index), | ||
title: Text('Tab ${index + 1}'), | ||
constraints: const BoxConstraints(minWidth: 150), | ||
leading: OutlinedContainer( | ||
backgroundColor: Colors.white, | ||
width: 18, | ||
height: 18, | ||
borderRadius: Theme.of(context).borderRadiusMd, | ||
child: Center( | ||
child: Text( | ||
(index + 1).toString(), | ||
style: TextStyle(color: Colors.black), | ||
).xSmall().bold(), | ||
), | ||
), | ||
trailing: IconButton.ghost( | ||
shape: ButtonShape.circle, | ||
size: ButtonSize.xSmall, | ||
icon: Icon(Icons.close), | ||
onPressed: () { | ||
setState(() { | ||
tabs.removeWhere((element) => element.key == ValueKey(index)); | ||
}); | ||
}, | ||
), | ||
); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return TabPane( | ||
tabs: tabs, | ||
focused: tabs | ||
.indexWhere((element) => (element.key as ValueKey).value == focused), | ||
onFocused: (value) { | ||
setState(() { | ||
focused = (tabs[value].key as ValueKey).value; | ||
}); | ||
}, | ||
onSort: (value) { | ||
setState(() { | ||
tabs = value; | ||
}); | ||
}, | ||
leading: [ | ||
IconButton.secondary( | ||
icon: Icon(Icons.arrow_drop_down), | ||
size: ButtonSize.small, | ||
density: ButtonDensity.iconDense, | ||
onPressed: () {}, | ||
), | ||
], | ||
trailing: [ | ||
IconButton.ghost( | ||
icon: Icon(Icons.add), | ||
size: ButtonSize.small, | ||
density: ButtonDensity.iconDense, | ||
onPressed: () { | ||
setState(() { | ||
int max = tabs.fold<int>(0, (previousValue, element) { | ||
return (element.key as ValueKey).value > previousValue | ||
? (element.key as ValueKey).value | ||
: previousValue; | ||
}); | ||
tabs.add(_buildTabItem(max + 1)); | ||
}); | ||
}, | ||
) | ||
], | ||
child: Container( | ||
child: Center( | ||
child: Text('Tab ${focused + 1}').xLarge().bold(), | ||
), | ||
height: 400, | ||
), | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import 'package:docs/pages/docs/component_page.dart'; | ||
import 'package:docs/pages/docs/components/tab_pane/tab_pane_example_1.dart'; | ||
import 'package:docs/pages/widget_usage_example.dart'; | ||
import 'package:shadcn_flutter/shadcn_flutter.dart'; | ||
|
||
class TabPaneExample extends StatelessWidget { | ||
const TabPaneExample({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ComponentPage( | ||
name: 'tab_pane', | ||
description: | ||
'A chrome-like tab pane that allows you to switch between different tabs.', | ||
displayName: 'Tab Pane', | ||
children: [ | ||
WidgetUsageExample( | ||
title: 'Tab Pane Example', | ||
child: TabPaneExample1(), | ||
path: 'lib/pages/docs/components/tab_pane/tab_pane_example_1.dart', | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import '../../../shadcn_flutter.dart'; | ||
|
||
class FadeScroll extends StatelessWidget { | ||
final double startOffset; | ||
final double endOffset; | ||
final double startCrossOffset; | ||
final double endCrossOffset; | ||
final Widget child; | ||
final ScrollController controller; | ||
final List<Color> gradient; | ||
|
||
const FadeScroll({ | ||
Key? key, | ||
required this.startOffset, | ||
required this.endOffset, | ||
required this.child, | ||
required this.controller, | ||
required this.gradient, | ||
this.startCrossOffset = 0, | ||
this.endCrossOffset = 0, | ||
}) : super(key: key); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return ListenableBuilder( | ||
listenable: controller, | ||
child: child, | ||
builder: (context, child) { | ||
if (!controller.hasClients) { | ||
return child!; | ||
} | ||
final position = controller.position.pixels; | ||
final max = controller.position.maxScrollExtent; | ||
final min = controller.position.minScrollExtent; | ||
final direction = controller.position.axis; | ||
final size = controller.position.viewportDimension; | ||
bool shouldFadeStart = position > min; | ||
bool shouldFadeEnd = position < max; | ||
if (!shouldFadeStart && !shouldFadeEnd) { | ||
return child!; | ||
} | ||
return ShaderMask( | ||
shaderCallback: (bounds) { | ||
Alignment start = direction == Axis.horizontal | ||
? Alignment.centerLeft | ||
: Alignment.topCenter; | ||
Alignment end = direction == Axis.horizontal | ||
? Alignment.centerRight | ||
: Alignment.bottomCenter; | ||
double relativeStart = startOffset / size; | ||
double relativeEnd = 1 - endOffset / size; | ||
List<double> stops = shouldFadeStart && shouldFadeEnd | ||
? [ | ||
for (int i = 0; i < gradient.length; i++) | ||
(i / gradient.length) * relativeStart, | ||
relativeStart, | ||
relativeEnd, | ||
for (int i = 1; i < gradient.length + 1; i++) | ||
relativeEnd + (i / gradient.length) * (1 - relativeEnd), | ||
] | ||
: shouldFadeStart | ||
? [ | ||
for (int i = 0; i < gradient.length; i++) | ||
(i / gradient.length) * relativeStart, | ||
relativeStart, | ||
1 | ||
] | ||
: [ | ||
0, | ||
relativeEnd, | ||
for (int i = 1; i < gradient.length + 1; i++) | ||
relativeEnd + | ||
(i / gradient.length) * (1 - relativeEnd), | ||
]; | ||
return LinearGradient( | ||
colors: [ | ||
if (shouldFadeStart) ...gradient, | ||
Colors.white, | ||
Colors.white, | ||
if (shouldFadeEnd) ...gradient.reversed, | ||
], | ||
stops: stops, | ||
begin: start, | ||
end: end, | ||
transform: const _ScaleGradient(Offset(1, 1.5))) | ||
.createShader(bounds); | ||
}, | ||
child: child!, | ||
); | ||
}, | ||
); | ||
} | ||
} | ||
|
||
class _ScaleGradient extends GradientTransform { | ||
final Offset scale; | ||
|
||
const _ScaleGradient(this.scale); | ||
|
||
@override | ||
Matrix4? transform(Rect bounds, {TextDirection? textDirection}) { | ||
final center = bounds.center; | ||
final dx = center.dx * (1 - scale.dx); | ||
final dy = center.dy * (1 - scale.dy); | ||
return Matrix4.identity() | ||
..translate(dx, dy) | ||
..scale(scale.dx, scale.dy) | ||
..translate(-dx, -dy); | ||
} | ||
} | ||
|
||
Rect _inflateRect(Rect rect, | ||
{double? left, double? top, double? right, double? bottom}) { | ||
return Rect.fromLTRB( | ||
rect.left - (left ?? 0), | ||
rect.top - (top ?? 0), | ||
rect.right + (right ?? 0), | ||
rect.bottom + (bottom ?? 0), | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.