Skip to content
This repository has been archived by the owner on Mar 17, 2024. It is now read-only.

xsoulspace/vuefer

Repository files navigation

Vuefer just a way to write Vue3 styled like Flutter with Tailwind CSS

Support me on Patreon

Archive reason

Since I moved to FLutter & Dart ecosystem, I found awesome package Jaspr which syntax and approach very similar to what I was trying to achieve in this package. So because of that it makes no sense to maintain or develop this project - and now it's archived:) Hope you find something useful or inspiration in this package:)

Old docs

Please notice: this project was renamed from vuefer to independent name: vuefer

Please notice: this project is a work in progress and completely experimental!

Please notice: vue-provider now is maintained as standalone package. Please see it in packages/vue-provider

The reason & motivation why this project have been started is a question: Flutter & Dart awesome! Vue3 & Typescript awesome too!

But...

html+css or jsx are not providing a strong enough typing way to write widgets/components.

So, what if we will write Vue3 TS in style of Flutter, because it's just simplier and faster?

Purpose: fast prototyping and fast MVP development

Please notice:

  • It is not a Flutter at all and even close, but hopefully will be use its style of components & methods writing.
  • It is not properly written at all and cannot be used in production until release 1.
  • It is not aligned to any standard yet and do not have any styling at all and it looks bad:) as primary focus now is to write basic widgets.
  • All is subject to change until release 1.
  • If you like this project - contributing &|| star is very welcome and appreciated and will keep development running Open Source and free:)

Awesome tools used and many thanks to:

Installation

Add this package to your package.json file:

"dependencies": {
  "@xsoulspace/vuefer": "next"
}

add styling to your main.ts

import '@xsoulspace/vuefer/dist/vft.css'

add styling to app div (temporary and will be removed during Scaffold widget refactoring)

<div id="app" class="absolute left-0 right-0 top-0 bottom-0"></div>

Usage

export const wrapperApp = () => {
  const text = ref('Hello world!')
  const text2 = ref(2)
  const padding = EdgeInsets.all(EdgeInsetsStep.s3)

  const textCard = Padding({
    child: Text({
      text,
    }),
    padding,
  })

  const btn = ElevatedButton({
    child: Text({ text: ref('Hello Button') }),
    onPressed: () => {
      text2.value++
      text.value = `Hello Wolrd! Counter: ${text2.value}`
    },
  })

  return Scaffold({
    body: Align({
      overlay: true,
      alignment: Alignment.bottom,
      child: Container({
        padding,
        decoration: new BoxDecoration({
          boxShadow: BoxShadow.xl,
          borderRadius: BorderRadius.vertical({ bottom: BorderRadiusStep.xxl }),
        }),
        child: Row({
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            MouseRegion({
              child: btn,
              cursor: SystemMouseCursor.use({
                cursor: SystemMouseCursors.click,
              }),
            }),
            textCard,
          ],
        }),
      }),
    }),
  })
}

Roadmap

Ready to test and possible to use

  • [] Provider

Usage:

Let's suppose we have a model:

export class Hero {
  constructor(public name: string) {}
}
export class HeroesModel {
  heroes = reactive<Maybe<Hero>[]>([])
  add(hero: Hero) {
    this.heroes.push(hero)
  }
  get count() {
    return this.heroes.length
  }
}

Create Provider on top of tree

MultiProvider.create({
  models: [HeroesModel],
  child: wrapperApp(),
})

And somewhere in tree just call

const heroModel = MultiProvider.get<HeroesModel>(HeroesModel)
  • Text Widget, FontWeight, TextDecoration, TextStyle, TextAlign, TextOverflow
  • Alignment, Align, Center
  • Padding
  • Margin
  • ButtonStyleButton
  • Flex
  • Row (Flex -> row)
  • Column (Flex -> column)
  • DividerDecoration (only for Row, Column)
  • MouseRegion
  • TextButton
  • Elevated Button
  • ListView.builder made with vue3-virtual-scroller - must be placed inside SizedBox to have defined size
  • ConstrainedBox
  • SizedBox
  • Opacity [x] widget [x] Text
  • ColoredBox
  • CheckboxListTile
  • ListTile
  • Grid, GridTile with awesome vue-grid-layout - temporary deprecated as it is broken
  • Wrap (Flex - flex-wrap)
  • Dialog

Usage

First - get NavigationController in setup

Be sure that you have Navigation widget on top of tree

const navigationController =
  MultiProvider.get<NavigationController>(NavigationController)

Second call a function from for example Button.onTap:

ElevatedButton({
  child: Text({
    text: ref('Show dialog'),
  }),
  onTap: () => {
    showDialog({
      builder: Dialog({
        child: Text({ text: ref('Hello World') }),
      }),
      navigationController,
    })
  },
}),

To close, just use navigationController.pop()

  • MultiDropdown Button

Usage:

Create controller in setup or anywehere and give generic type to use

const IndexedText {
  id: string
  text: string
}


const multiDropdownController = new MultiDropdownFieldController<IndexedText>(
  { keyofValue: 'id' }
)

Then use MultiDropdownButton with DropdownMenuItem in items to make it work

MultiDropdownButton({
  controller: multiDropdownController,
  items: dropdownItems.map((el) =>
    DropdownMenuItem({
      child: Text({
        text: ref(el.text),
      }),
      value: el,
      key: el.id,
      title: el.text,
    })
  ),
}),

To get or change selected values use: controller.value

  • Navigation & NavigationController

    • Popup (with background) functionality
    • Fullscreen functionality

Usage:

Add controller into MultiPorvider and Navigation widget below:

MultiProvider.create({
  models: [NavigationController, ...],
  child: Navigation({
    child: ...,
  }),
})
  • DropdownButton, DropdownButtonItem [x] functionality [] decoration

  • [] Visibility [x] functionality [] animation

  • [] TextField [x] Basic properties [x] TextEditingController [] InputDecoration (partially) [] TextStyle

  • Checkbox [x] Basic [] Style

  • ReordableListView

WIP

  • [] GestureDetecture [x] click [] tap [] swipes [] hover

  • [] Container [x] Border [x] BorderRadius [x] Color [x] Shadow [] Margin [x] Padding [] Color Opacity ? Border Color Opacity [] Shape [] Gradient [] Alignment [] Image [x] Height [x] Width

  • [] Material

  • [] InkWell

  • [] Colors [x] White, black [] Color palette

  • [] Scaffold [x] Drawer [x] AppBar

  • [] Drawer [x] basic [] animation

  • [] AppBar [x] basic

Next

  • [] Flexible
  • [] OutlinedButton
  • [] Ripple
  • [] Progress
  • [] Card
  • [] Icon
  • [] IconButton
  • [] Bar
  • [] ButtonBar
  • [] ListView, ListView.separeted
  • [] Object Fit - FitBox?, FittedBox?

Current Problems:

  • [] Tailwind included as package, but needs to be included to main.ts(js) when this package added. Maybe it's a wrong way..
  • [] Sizes cannot be set as numbers.

Changelog

Changelog can be found in Releases

Setup with Vue 3 + Typescript + Vite

Recommended IDE Setup

VSCode + Vetur. Make sure to enable vetur.experimental.templateInterpolationService in settings!

If Using <script setup>

<script setup> is a feature that is currently in RFC stage. To get proper IDE support for the syntax, use Volar instead of Vetur (and disable Vetur).

Type Support For .vue Imports in TS

Since TypeScript cannot handle type information for .vue imports, they are shimmed to be a generic Vue component type by default. In most cases this is fine if you don't really care about component prop types outside of templates. However, if you wish to get actual prop types in .vue imports (for example to get props validation when using manual h(...) calls), you can use the following:

If Using Volar

Run Volar: Switch TS Plugin on/off from VSCode command palette.

If Using Vetur

  1. Install and add @vuedx/typescript-plugin-vue to the plugins section in tsconfig.json
  2. Delete src/shims-vue.d.ts as it is no longer needed to provide module info to Typescript
  3. Open src/main.ts in VSCode
  4. Open the VSCode command palette 5. Search and run "Select TypeScript version" -> "Use workspace version"