maxence-charriere / go-app

A package to build progressive web apps with Go programming language and WebAssembly.
https://go-app.dev
MIT License
7.94k stars 365 forks source link

CSS framework support #478

Closed kheadjr-rv closed 3 years ago

kheadjr-rv commented 3 years ago

First thank you so much for all the work that you have done.

Your most recent update to the go-app docs made it much more clearer and gave me an idea to create components utilizing UIkit. As a first pass I started the repo below.

https://github.com/niveklabs/go-uikit

I am not sure how much interest there is for something like this but in my case I found myself spending a lot of time creating components. Having no design skills I rely on simple to use frontend CSS frameworks like Bulma, Tailwind or in this case UIkit. With that said I see you have done similar in shell, stack, flow etc... Am I correct in assuming that there might be theming support later on?

maxence-charriere commented 3 years ago

Hello @kheadjr-rv , Awesome work on this!

Yes, I started to create this kind of thing but I target only layout-related components within the main package. Now that someone did it too, I guess I should find a plug and play solution to load external libraries like yours (with its css and js).

I had a bunch of ideas like providing a Plugin field in the app handler where styles and script URLs could be specified or directly embedded within the page. Something like:

// Plugin represents a descriptor to load resources required by an external plugin based on the go-app package.
type Plugin struct{
    // URLs of your CSS files. Must be remote URL like 
    // https://raw.githubusercontent.com/niveklabs/go-uikit/main/docs/web/css/uikit.min.css
    Styles []string

    // CSS styles generated within a Go string that will be embedded directly in the page.
    InlineStyles string

    // URLs of your js files. Must be a remote URL too.
    Scripts []string
}
app.Hander{
    Plugins: []app.Plugin{
        uikit.Plugin(),
       // other plugin,
       // ...
    }
}

You would have to provide a function or global field that returns a plugin descriptor:

func Plugin() app.Plugin{
    Styles: []string{
        "https://raw.githubusercontent.com/niveklabs/go-uikit/main/docs/web/css/uikit.min.css",
    },
}

Let me know what you think or if you have some ideas too. And thanks for this work! It really makes me happy to see that some people start to build libraries on the top of this package :).

kheadjr-rv commented 3 years ago

@maxence-charriere, thank you and I definitely have some ideas that I will be glad to share. I will post them after the holidays in better detail.

Today did some work on code generation. This was definitely heavily inspired by how you handled HTML code generation.

For now happy new year and talk to you soon.

kheadjr-rv commented 3 years ago

@maxence-charriere, would it be simpler for the plugin to just provide a Styles() and Scripts() function?

package uikit

func Styles() []string {
    return []string{
        "https://cdn.jsdelivr.net/npm/uikit@3.6.5/dist/css/uikit.min.css",
    }
}

func Scripts() []string {
    return []string{
        "https://cdn.jsdelivr.net/npm/uikit@3.6.5/dist/js/uikit.min.js",
        "https://cdn.jsdelivr.net/npm/uikit@3.6.5/dist/js/uikit-icons.min.js",
    }
}

Then the user of the plugin could simply add something like this in the handler?

h := app.Handler{
// ...
    Scripts: append(
        uikit.Scripts(),
        "/web/js/prism.js",
    ),
    Styles: append(
        uikit.Styles(),
        "https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;700&family=Montserrat:wght@300;400;700&display=swap",
        "/web/css/prism.css",
        "/web/css/app.css",
    ),
// ...
}
maxence-charriere commented 3 years ago

That is 2 places to add what is required to use your kit vs 1.

maxence-charriere commented 3 years ago

Have to think about it, right now nothing is stopping you to document your package to make it work the way you suggest :)

kheadjr-rv commented 3 years ago

Sorry about the delay. Yep, I will continue to work on the uikit. Unless you are already working on it I will be glad to help contribute here. Let me know if there is anything I can do. Otherwise we can close this. Thank you again for your work.

maxence-charriere commented 3 years ago

Thank you so much for this work and the sponsor.

The components I add in the main package are just about simple layout disposition. UI kit is more advanced. Let me know when it is ready for prime and if you want to be featured in the Built with go-app section.

By the way, I just pushed a release that may help pour doing responsive components => https://github.com/maxence-charriere/go-app/releases/tag/v7.2.0

maxence-charriere commented 3 years ago

I will think more about the right way to bring a one line of code solution to install dependencies for a package like yours.

bika-c commented 2 years ago

Hi, is there any update on this? I am doing a css framework using tailwind as well. go-app needs to have support of css framework just like react or vue. So if we could have a one line solution to include ui component plugins, it would be awesome.

oderwat commented 2 years ago

I am not sure if I understand this right (using Tailwindcss and scripts as resources in offline mode without problems).

You can add scripts/css anything using:

type Handler struct {
 ...
    // The paths or urls of the CSS files to use with the page.
    //
    // eg:
    //  app.Handler{
    //      Styles: []string{
    //          "/web/test.css",            // Static resource
    //          "https://foo.com/test.css", // External resource
    //      },
    //  },
    Styles [][string](https://go-app.dev/pkg/builtin/#string)

    // The paths or urls of the JavaScript files to use with the page.
    //
    // eg:
    //  app.Handler{
    //      Scripts: []string{
    //          "/web/test.js",            // Static resource
    //          "https://foo.com/test.js", // External resource
    //      },
    //  },
    Scripts [][string](https://go-app.dev/pkg/builtin/#string)

    // The path of the static resources that the browser is caching in order to
    // provide offline mode.
    //
    // Note that Icon, Styles and Scripts are already cached by default.
    //
    // Paths are relative to the root directory.
    CacheableResources [][string](https://go-app.dev/pkg/builtin/#string)
...
    // The static resources that are accessible from custom paths. Files that
    // are proxied by default are /robots.txt, /sitemap.xml and /ads.txt.
    [ProxyResource](https://go-app.dev/reference#ProxyResource)s []ProxyResource

    // The resource provider that provides static resources. Static resources
    // are always accessed from a path that starts with "/web/".
    //
    // eg:
    //  "/web/main.css"
    //
    // Default: LocalDir("")
    Resources [ResourceProvider](https://go-app.dev/reference#ResourceProvider)
...
}

But, maybe I did not understand what is being asked.

bika-c commented 2 years ago

Ah, yes, this is the way I am currently using, but I think if I can pull the ui components out as a package and export it as a plugin like @maxence-charriere mentioned above:

Hello @kheadjr-rv , Awesome work on this!

Yes, I started to create this kind of thing but I target only layout-related components within the main package. Now that someone did it too, I guess I should find a plug and play solution to load external libraries like yours (with its css and js).

I had a bunch of ideas like providing a Plugin field in the app handler where styles and script URLs could be specified or directly embedded within the page. Something like:

// Plugin represents a descriptor to load resources required by an external plugin based on the go-app package.
type Plugin struct{
    // URLs of your CSS files. Must be remote URL like 
    // https://raw.githubusercontent.com/niveklabs/go-uikit/main/docs/web/css/uikit.min.css
    Styles []string

    // CSS styles generated within a Go string that will be embedded directly in the page.
    InlineStyles string

    // URLs of your js files. Must be a remote URL too.
    Scripts []string
}
app.Hander{
    Plugins: []app.Plugin{
        uikit.Plugin(),
       // other plugin,
       // ...
    }
}

You would have to provide a function or global field that returns a plugin descriptor:

func Plugin() app.Plugin{
    Styles: []string{
        "https://raw.githubusercontent.com/niveklabs/go-uikit/main/docs/web/css/uikit.min.css",
    },
}

Let me know what you think or if you have some ideas too. And thanks for this work! It really makes me happy to see that some people start to build libraries on the top of this package :).

oderwat commented 2 years ago

But can't you just do this yourself and populate the handler fields with the sum of all the plugin calls? Or call something like myPlugin.Register(*app.Handler) that adds its own requirements to the handler before it is used?

bika-c commented 2 years ago

Yeah this would work, thx!

Edit: I still think having a field in the handler to add plugins is better. I will look into it later.

Thanks for all the work you have done. I just discovered this repo recently and I am amazed