├── .gitignore ├── .metadata ├── CHANGELOG.md ├── LICENSE ├── README.md ├── example └── example.dart ├── lib └── vertical_tabs.dart ├── pubspec.lock ├── pubspec.yaml ├── vertical-tab-intro.gif ├── vertical-tab-rtl.gif ├── vertical-tab-verhor.gif └── vertical_tabs.iml /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .dart_tool/ 3 | .idea/ 4 | 5 | .packages 6 | .pub/ 7 | 8 | build/ 9 | ios/.generated/ 10 | ios/Flutter/Generated.xcconfig 11 | ios/Runner/GeneratedPluginRegistrant.* 12 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b 8 | channel: beta 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [0.1.4] - 02/15/2019. 2 | 3 | * bug fix 4 | 5 | ## [0.2.0] - 01/30/2020. 6 | 7 | * onSelect method added 8 | * canvas backgroundColor property added 9 | * indicatorSide property added 10 | * initialIndex property added 11 | * tabs fixed height removed 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 XinoSoft 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Vertical Tabs 2 | 3 | A vertical tabs package for flutter framework. 4 | 5 | ## Getting Started 6 | 7 | A simple example of usage. to get more examples see `Examples` directory. 8 | To see all settings please visit API reference of this package 9 | 10 | ```dart 11 | ... 12 | 13 | VerticalTabs( 14 | tabsWidth: 150, 15 | tabs: [ 16 | Tab(child: Text('Flutter'), icon: Icon(Icons.phone)), 17 | Tab(child: Text('Dart')), 18 | Tab(child: Text('NodeJS')), 19 | Tab(child: Text('PHP')), 20 | Tab(child: Text('HTML 5')), 21 | ], 22 | contents: [ 23 | Container(child: Text('Flutter'), padding: EdgeInsets.all(20)), 24 | Container(child: Text('Dart'), padding: EdgeInsets.all(20)), 25 | Container(child: Text('NodeJS'), padding: EdgeInsets.all(20)), 26 | Container(child: Text('PHP'), padding: EdgeInsets.all(20)), 27 | Container(child: Text('HTML 5'), padding: EdgeInsets.all(20)) 28 | ], 29 | ), 30 | 31 | 32 | ``` 33 | 34 |
35 | 36 | 37 | ![](vertical-tab-intro.gif) 38 | 39 | 40 |


41 | 42 | 43 | Scroll direction of content 44 | 45 | ![](vertical-tab-verhor.gif) 46 | 47 |


48 | 49 | RTL 50 | 51 | ![](vertical-tab-rtl.gif) -------------------------------------------------------------------------------- /example/example.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | import 'package:vertical_tabs/vertical_tabs.dart'; 3 | 4 | void main() => runApp(Home()); 5 | 6 | class Home extends StatelessWidget { 7 | @override 8 | Widget build(BuildContext context) { 9 | return MaterialApp( 10 | title: 'Title', 11 | home: Scaffold( 12 | body: SafeArea( 13 | 14 | child: Column( 15 | children: [ 16 | Expanded( 17 | child: Container( 18 | 19 | 20 | 21 | child: VerticalTabs( 22 | tabsWidth: 150, 23 | tabs: [ 24 | Tab(child: Text('Flutter'), icon: Icon(Icons.phone)), 25 | Tab(child: Text('Dart')), 26 | Tab( 27 | child: Container( 28 | margin: EdgeInsets.only(bottom: 1), 29 | child: Row( 30 | children: [ 31 | Icon(Icons.favorite), 32 | SizedBox(width: 25), 33 | Text('Javascript'), 34 | ], 35 | ), 36 | ), 37 | ), 38 | Tab(child: Text('NodeJS')), 39 | Tab(child: Text('PHP')), 40 | Tab(child: Text('HTML 5')), 41 | Tab(child: Text('CSS 3')), 42 | ], 43 | contents: [ 44 | tabsContent('Flutter', 'Change page by scrolling content is disabled in settings. Changing contents pages is only available via tapping on tabs'), 45 | tabsContent('Dart'), 46 | tabsContent('Javascript'), 47 | tabsContent('NodeJS'), 48 | Container( 49 | color: Colors.black12, 50 | child: ListView.builder( 51 | itemCount: 10, 52 | itemExtent: 100, 53 | itemBuilder: (context, index){ 54 | return Container( 55 | margin: EdgeInsets.all(10), 56 | color: Colors.white30, 57 | ); 58 | }) 59 | ), 60 | tabsContent('HTML 5'), 61 | Container( 62 | color: Colors.black12, 63 | child: ListView.builder( 64 | scrollDirection: Axis.horizontal, 65 | itemCount: 10, 66 | itemExtent: 100, 67 | itemBuilder: (context, index){ 68 | return Container( 69 | margin: EdgeInsets.all(10), 70 | color: Colors.white30, 71 | ); 72 | }) 73 | ), 74 | ], 75 | ), 76 | 77 | 78 | 79 | ), 80 | ), 81 | 82 | ], 83 | ), 84 | 85 | 86 | 87 | /*child: Column( 88 | children: [ 89 | Container( 90 | height: 300, 91 | child: VerticalTabs( 92 | tabsWidth: 150, 93 | direction: TextDirection.ltr, 94 | contentScrollAxis: Axis.vertical, 95 | changePageDuration: Duration(milliseconds: 500), 96 | tabs: [ 97 | Tab(child: Text('Flutter'), icon: Icon(Icons.phone)), 98 | Tab(child: Text('Dart')), 99 | Tab( 100 | child: Container( 101 | margin: EdgeInsets.only(bottom: 1), 102 | child: Row( 103 | children: [ 104 | Icon(Icons.favorite), 105 | SizedBox(width: 25), 106 | Text('Javascript'), 107 | ], 108 | ), 109 | ), 110 | ), 111 | Tab(child: Text('NodeJS')), 112 | Tab(child: Text('PHP')), 113 | ], 114 | contents: [ 115 | tabsContent('Flutter', 'You can change page by scrolling content vertically'), 116 | tabsContent('Dart'), 117 | tabsContent('Javascript'), 118 | tabsContent('NodeJS'), 119 | Container( 120 | color: Colors.black12, 121 | child: ListView.builder( 122 | itemCount: 10, 123 | itemExtent: 100, 124 | scrollDirection: Axis.horizontal, 125 | itemBuilder: (context, index){ 126 | return Container( 127 | margin: EdgeInsets.all(10), 128 | color: Colors.white30, 129 | ); 130 | }) 131 | ), 132 | ], 133 | ), 134 | ), 135 | Divider(height: 20, color: Colors.black87,), 136 | Container( 137 | height: 300, 138 | child: VerticalTabs( 139 | tabsWidth: 150, 140 | direction: TextDirection.ltr, 141 | changePageDuration: Duration(milliseconds: 500), 142 | tabs: [ 143 | Tab(child: Text('Flutter'), icon: Icon(Icons.phone)), 144 | Tab(child: Text('Dart')), 145 | Tab( 146 | child: Container( 147 | margin: EdgeInsets.only(bottom: 1), 148 | child: Row( 149 | children: [ 150 | Icon(Icons.favorite), 151 | SizedBox(width: 25), 152 | Text('Javascript'), 153 | ], 154 | ), 155 | ), 156 | ), 157 | Tab(child: Text('NodeJS')), 158 | Tab(child: Text('PHP')), 159 | ], 160 | contents: [ 161 | tabsContent('Flutter', 'You can change page by scrolling content horizontally'), 162 | tabsContent('Dart'), 163 | tabsContent('Javascript'), 164 | tabsContent('NodeJS'), 165 | Container( 166 | color: Colors.black12, 167 | child: ListView.builder( 168 | itemCount: 10, 169 | itemExtent: 100, 170 | scrollDirection: Axis.vertical, 171 | itemBuilder: (context, index){ 172 | return Container( 173 | margin: EdgeInsets.all(10), 174 | color: Colors.white30, 175 | ); 176 | }) 177 | ), 178 | ], 179 | ), 180 | ), 181 | ], 182 | ),*/ 183 | ), 184 | ), 185 | ); 186 | } 187 | 188 | Widget tabsContent(String caption, [ String description = '' ] ) { 189 | return Container( 190 | margin: EdgeInsets.all(10), 191 | padding: EdgeInsets.all(20), 192 | color: Colors.black12, 193 | child: Column( 194 | children: [ 195 | Text( 196 | caption, 197 | style: TextStyle(fontSize: 25), 198 | ), 199 | Divider(height: 20, color: Colors.black45,), 200 | Text( 201 | description, 202 | style: TextStyle(fontSize: 15, color: Colors.black87), 203 | ), 204 | ], 205 | ), 206 | ); 207 | } 208 | } -------------------------------------------------------------------------------- /lib/vertical_tabs.dart: -------------------------------------------------------------------------------- 1 | import 'package:flutter/material.dart'; 2 | 3 | enum IndicatorSide { start, end } 4 | 5 | /// A vertical tab widget for flutter 6 | class VerticalTabs extends StatefulWidget { 7 | final Key key; 8 | final int initialIndex; 9 | final double tabsWidth; 10 | final double indicatorWidth; 11 | final IndicatorSide indicatorSide; 12 | final List tabs; 13 | final List contents; 14 | final TextDirection direction; 15 | final Color indicatorColor; 16 | final bool disabledChangePageFromContentView; 17 | final Axis contentScrollAxis; 18 | final Color selectedTabBackgroundColor; 19 | final Color tabBackgroundColor; 20 | final TextStyle selectedTabTextStyle; 21 | final TextStyle tabTextStyle; 22 | final Duration changePageDuration; 23 | final Curve changePageCurve; 24 | final Color tabsShadowColor; 25 | final double tabsElevation; 26 | final Function(int tabIndex) onSelect; 27 | final Color backgroundColor; 28 | 29 | VerticalTabs( 30 | {this.key, 31 | @required this.tabs, 32 | @required this.contents, 33 | this.tabsWidth = 200, 34 | this.indicatorWidth = 3, 35 | this.indicatorSide, 36 | this.initialIndex = 0, 37 | this.direction = TextDirection.ltr, 38 | this.indicatorColor = Colors.green, 39 | this.disabledChangePageFromContentView = false, 40 | this.contentScrollAxis = Axis.horizontal, 41 | this.selectedTabBackgroundColor = const Color(0x1100ff00), 42 | this.tabBackgroundColor = const Color(0xfff8f8f8), 43 | this.selectedTabTextStyle = const TextStyle(color: Colors.black), 44 | this.tabTextStyle = const TextStyle(color: Colors.black38), 45 | this.changePageCurve = Curves.easeInOut, 46 | this.changePageDuration = const Duration(milliseconds: 300), 47 | this.tabsShadowColor = Colors.black54, 48 | this.tabsElevation = 2.0, 49 | this.onSelect, 50 | this.backgroundColor}) 51 | : assert( 52 | tabs != null && contents != null && tabs.length == contents.length), 53 | super(key: key); 54 | 55 | @override 56 | _VerticalTabsState createState() => _VerticalTabsState(); 57 | } 58 | 59 | class _VerticalTabsState extends State 60 | with TickerProviderStateMixin { 61 | int _selectedIndex; 62 | bool _changePageByTapView; 63 | 64 | AnimationController animationController; 65 | Animation animation; 66 | Animation rectAnimation; 67 | 68 | PageController pageController = PageController(); 69 | 70 | List animationControllers = []; 71 | 72 | ScrollPhysics pageScrollPhysics = AlwaysScrollableScrollPhysics(); 73 | 74 | @override 75 | void initState() { 76 | _selectedIndex = widget.initialIndex; 77 | for (int i = 0; i < widget.tabs.length; i++) { 78 | animationControllers.add(AnimationController( 79 | duration: const Duration(milliseconds: 400), 80 | vsync: this, 81 | )); 82 | } 83 | _selectTab(widget.initialIndex); 84 | 85 | if (widget.disabledChangePageFromContentView == true) 86 | pageScrollPhysics = NeverScrollableScrollPhysics(); 87 | 88 | super.initState(); 89 | WidgetsBinding.instance.addPostFrameCallback((_) { 90 | pageController.jumpToPage(widget.initialIndex); 91 | setState(() {}); 92 | }); 93 | } 94 | 95 | @override 96 | Widget build(BuildContext context) { 97 | // Border border = Border( 98 | // right: BorderSide( 99 | // width: 0.5, color: widget.dividerColor)); 100 | // if (widget.direction == TextDirection.rtl) { 101 | // border = Border( 102 | // left: BorderSide( 103 | // width: 0.5, color: widget.dividerColor)); 104 | // } 105 | 106 | return Directionality( 107 | textDirection: widget.direction, 108 | child: Container( 109 | color: widget.backgroundColor ?? Theme.of(context).canvasColor, 110 | child: Column( 111 | mainAxisSize: MainAxisSize.min, 112 | children: [ 113 | Expanded( 114 | child: Row( 115 | children: [ 116 | Material( 117 | child: Container( 118 | width: widget.tabsWidth, 119 | child: ListView.builder( 120 | itemCount: widget.tabs.length, 121 | itemBuilder: (context, index) { 122 | Tab tab = widget.tabs[index]; 123 | 124 | Alignment alignment = Alignment.centerLeft; 125 | if (widget.direction == TextDirection.rtl) { 126 | alignment = Alignment.centerRight; 127 | } 128 | 129 | Widget child; 130 | if (tab.child != null) { 131 | child = tab.child; 132 | } else { 133 | child = Container( 134 | padding: EdgeInsets.all(10), 135 | child: Row( 136 | children: [ 137 | (tab.icon != null) 138 | ? Row( 139 | children: [ 140 | tab.icon, 141 | SizedBox( 142 | width: 5, 143 | ) 144 | ], 145 | ) 146 | : Container(), 147 | (tab.text != null) 148 | ? Container( 149 | width: widget.tabsWidth - 50, 150 | child: Text( 151 | tab.text, 152 | softWrap: true, 153 | style: _selectedIndex == index 154 | ? widget.selectedTabTextStyle 155 | : widget.tabTextStyle, 156 | )) 157 | : Container(), 158 | ], 159 | )); 160 | } 161 | 162 | Color itemBGColor = widget.tabBackgroundColor; 163 | if (_selectedIndex == index) 164 | itemBGColor = widget.selectedTabBackgroundColor; 165 | 166 | double left, right; 167 | if (widget.direction == TextDirection.rtl) { 168 | left = (widget.indicatorSide == IndicatorSide.end) 169 | ? 0 170 | : null; 171 | right = 172 | (widget.indicatorSide == IndicatorSide.start) 173 | ? 0 174 | : null; 175 | } else { 176 | left = (widget.indicatorSide == IndicatorSide.start) 177 | ? 0 178 | : null; 179 | right = (widget.indicatorSide == IndicatorSide.end) 180 | ? 0 181 | : null; 182 | } 183 | 184 | return Stack( 185 | children: [ 186 | Positioned( 187 | top: 2, 188 | bottom: 2, 189 | width: widget.indicatorWidth, 190 | left: left, 191 | right: right, 192 | child: ScaleTransition( 193 | child: Container( 194 | color: widget.indicatorColor, 195 | ), 196 | scale: Tween(begin: 0.0, end: 1.0).animate( 197 | new CurvedAnimation( 198 | parent: animationControllers[index], 199 | curve: Curves.elasticOut, 200 | ), 201 | ), 202 | ), 203 | ), 204 | GestureDetector( 205 | onTap: () { 206 | _changePageByTapView = true; 207 | setState(() { 208 | _selectTab(index); 209 | }); 210 | 211 | pageController.animateToPage(index, 212 | duration: widget.changePageDuration, 213 | curve: widget.changePageCurve); 214 | }, 215 | child: Container( 216 | decoration: BoxDecoration( 217 | color: itemBGColor, 218 | ), 219 | alignment: alignment, 220 | padding: EdgeInsets.all(5), 221 | child: child, 222 | ), 223 | ), 224 | ], 225 | ); 226 | }, 227 | ), 228 | ), 229 | elevation: widget.tabsElevation, 230 | shadowColor: widget.tabsShadowColor, 231 | shape: BeveledRectangleBorder(), 232 | ), 233 | Expanded( 234 | child: PageView.builder( 235 | scrollDirection: widget.contentScrollAxis, 236 | physics: pageScrollPhysics, 237 | onPageChanged: (index) { 238 | if (_changePageByTapView == false || 239 | _changePageByTapView == null) { 240 | _selectTab(index); 241 | } 242 | if (_selectedIndex == index) { 243 | _changePageByTapView = null; 244 | } 245 | setState(() {}); 246 | }, 247 | controller: pageController, 248 | 249 | // the number of pages 250 | itemCount: widget.contents.length, 251 | 252 | // building pages 253 | itemBuilder: (BuildContext context, int index) { 254 | return widget.contents[index]; 255 | }, 256 | ), 257 | ), 258 | ], 259 | ), 260 | ), 261 | ], 262 | ), 263 | ), 264 | ); 265 | } 266 | 267 | void _selectTab(index) { 268 | _selectedIndex = index; 269 | for (AnimationController animationController in animationControllers) { 270 | animationController.reset(); 271 | } 272 | animationControllers[index].forward(); 273 | 274 | if (widget.onSelect != null) { 275 | widget.onSelect(_selectedIndex); 276 | } 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /pubspec.lock: -------------------------------------------------------------------------------- 1 | # Generated by pub 2 | # See https://www.dartlang.org/tools/pub/glossary#lockfile 3 | packages: 4 | async: 5 | dependency: transitive 6 | description: 7 | name: async 8 | url: "https://pub.dartlang.org" 9 | source: hosted 10 | version: "2.0.8" 11 | boolean_selector: 12 | dependency: transitive 13 | description: 14 | name: boolean_selector 15 | url: "https://pub.dartlang.org" 16 | source: hosted 17 | version: "1.0.4" 18 | charcode: 19 | dependency: transitive 20 | description: 21 | name: charcode 22 | url: "https://pub.dartlang.org" 23 | source: hosted 24 | version: "1.1.2" 25 | collection: 26 | dependency: transitive 27 | description: 28 | name: collection 29 | url: "https://pub.dartlang.org" 30 | source: hosted 31 | version: "1.14.11" 32 | flutter: 33 | dependency: "direct main" 34 | description: flutter 35 | source: sdk 36 | version: "0.0.0" 37 | flutter_test: 38 | dependency: "direct dev" 39 | description: flutter 40 | source: sdk 41 | version: "0.0.0" 42 | matcher: 43 | dependency: transitive 44 | description: 45 | name: matcher 46 | url: "https://pub.dartlang.org" 47 | source: hosted 48 | version: "0.12.3+1" 49 | meta: 50 | dependency: transitive 51 | description: 52 | name: meta 53 | url: "https://pub.dartlang.org" 54 | source: hosted 55 | version: "1.1.6" 56 | path: 57 | dependency: transitive 58 | description: 59 | name: path 60 | url: "https://pub.dartlang.org" 61 | source: hosted 62 | version: "1.6.2" 63 | quiver: 64 | dependency: transitive 65 | description: 66 | name: quiver 67 | url: "https://pub.dartlang.org" 68 | source: hosted 69 | version: "2.0.1" 70 | sky_engine: 71 | dependency: transitive 72 | description: flutter 73 | source: sdk 74 | version: "0.0.99" 75 | source_span: 76 | dependency: transitive 77 | description: 78 | name: source_span 79 | url: "https://pub.dartlang.org" 80 | source: hosted 81 | version: "1.4.1" 82 | stack_trace: 83 | dependency: transitive 84 | description: 85 | name: stack_trace 86 | url: "https://pub.dartlang.org" 87 | source: hosted 88 | version: "1.9.3" 89 | stream_channel: 90 | dependency: transitive 91 | description: 92 | name: stream_channel 93 | url: "https://pub.dartlang.org" 94 | source: hosted 95 | version: "1.6.8" 96 | string_scanner: 97 | dependency: transitive 98 | description: 99 | name: string_scanner 100 | url: "https://pub.dartlang.org" 101 | source: hosted 102 | version: "1.0.4" 103 | term_glyph: 104 | dependency: transitive 105 | description: 106 | name: term_glyph 107 | url: "https://pub.dartlang.org" 108 | source: hosted 109 | version: "1.0.1" 110 | test_api: 111 | dependency: transitive 112 | description: 113 | name: test_api 114 | url: "https://pub.dartlang.org" 115 | source: hosted 116 | version: "0.2.1" 117 | typed_data: 118 | dependency: transitive 119 | description: 120 | name: typed_data 121 | url: "https://pub.dartlang.org" 122 | source: hosted 123 | version: "1.1.6" 124 | vector_math: 125 | dependency: transitive 126 | description: 127 | name: vector_math 128 | url: "https://pub.dartlang.org" 129 | source: hosted 130 | version: "2.0.8" 131 | sdks: 132 | dart: ">=2.0.0 <3.0.0" 133 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: vertical_tabs 2 | description: A vertical tabs package with some handy settings for flutter framework. 3 | version: 0.2.0 4 | author: Ali Azmoude 5 | homepage: https://github.com/Ali-Azmoud/vertical_tabs 6 | 7 | environment: 8 | sdk: ">=2.0.0-dev.68.0 <3.0.0" 9 | 10 | dependencies: 11 | flutter: 12 | sdk: flutter 13 | 14 | dev_dependencies: 15 | flutter_test: 16 | sdk: flutter 17 | 18 | # For information on the generic Dart part of this file, see the 19 | # following page: https://www.dartlang.org/tools/pub/pubspec 20 | 21 | # The following section is specific to Flutter. 22 | flutter: 23 | 24 | # To add assets to your package, add an assets section, like this: 25 | # assets: 26 | # - images/a_dot_burr.jpeg 27 | # - images/a_dot_ham.jpeg 28 | # 29 | # For details regarding assets in packages, see 30 | # https://flutter.io/assets-and-images/#from-packages 31 | # 32 | # An image asset can refer to one or more resolution-specific "variants", see 33 | # https://flutter.io/assets-and-images/#resolution-aware. 34 | 35 | # To add custom fonts to your package, add a fonts section here, 36 | # in this "flutter" section. Each entry in this list should have a 37 | # "family" key with the font family name, and a "fonts" key with a 38 | # list giving the asset and other descriptors for the font. For 39 | # example: 40 | # fonts: 41 | # - family: Schyler 42 | # fonts: 43 | # - asset: fonts/Schyler-Regular.ttf 44 | # - asset: fonts/Schyler-Italic.ttf 45 | # style: italic 46 | # - family: Trajan Pro 47 | # fonts: 48 | # - asset: fonts/TrajanPro.ttf 49 | # - asset: fonts/TrajanPro_Bold.ttf 50 | # weight: 700 51 | # 52 | # For details regarding fonts in packages, see 53 | # https://flutter.io/custom-fonts/#from-packages 54 | -------------------------------------------------------------------------------- /vertical-tab-intro.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ali-Azmoud/vertical_tabs/ccfee0aad550303c621920666c081e31ba003614/vertical-tab-intro.gif -------------------------------------------------------------------------------- /vertical-tab-rtl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ali-Azmoud/vertical_tabs/ccfee0aad550303c621920666c081e31ba003614/vertical-tab-rtl.gif -------------------------------------------------------------------------------- /vertical-tab-verhor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Ali-Azmoud/vertical_tabs/ccfee0aad550303c621920666c081e31ba003614/vertical-tab-verhor.gif -------------------------------------------------------------------------------- /vertical_tabs.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | --------------------------------------------------------------------------------