-
Notifications
You must be signed in to change notification settings - Fork 245
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: a class map for easy class manipulation. #66
Comments
I think the
I think you're right, that should help for 90% of cases and then people can use scoped slots if they want to go deeper. |
Correct, the |
Dropping the map may help beginners a bit more. It's a bit more succinct I guess. |
There is no need for this way to work |
This comment has been minimized.
This comment has been minimized.
Giving that portals will be a built in feature for vue, the approach could be: <div class="form-group">
<label for="exampleInputEmail1">Email address</label>
<input type="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp">
<small id="emailHelp" class="form-text text-muted">We'll never share your email with anyone else.</small>
</div> Using portals, the label, input and messages/errors should be wrapped by a portal and the widget should be written like: <div class="form-group">
<label for="exampleInputEmail1"><PortalTarget name="label"></PortalTarget></label>
<PortalTarget name="input"></PortalTarget>
<small id="emailHelp" class="form-text text-muted"><PortalTarget name="msg"></PortalTarget></small>
</div> The only part that will need some attributes will be the input Would be more simple and better for this library if we could focus on the specifics of managing forms and not how they should look (seems that is the whole point of vue-portal: separation between the layout and the functionality) |
This comment has been minimized.
This comment has been minimized.
Perhaps your are the confused one but, ok, I will mind my business |
According with Linus Borg's portal-vue: Bye |
This comment has been minimized.
This comment has been minimized.
Thanks for making this plugin, Very nice. Unfortunately, I can't easily add Bootstrap classes to it. |
Simple solution, use tailwind ;) |
I'm waiting on this been talking about vue-formulate for a long time, just want to throw my own classes in it and dev quicker and not have any bs. |
@narwy Vue Formulate does not want to take strong stances on layout (https://vueformulate.com/guide/#what-it-isn-t). The base theme is currently provided mainly for the sake of having good-looking examples. Whether your CSS approach of choice is to roll your own styles, use a full UI framework such as Bootstrap, or leverage a utility-based class system such as Tailwind we’re seeking to make the library work for you. Rather than “just use Tailwind” we’d prefer to solve the hard problem of creating an API that allows Tailwind users to get just as much value out of Vue Formulate as any other CSS aficionado. We’re not there yet though, so as a Tailwind user your input would be invaluable to us (we are not users of Tailwind ourselves). We need feedback on any proposed class-map system to ensure it’ll be robust enough to handle whatever CSS system is currently in vogue. |
@andrew-boyd I'd just create the correct props/api "config" as such to handle for passing classes. This day and age people make classes regardless, seen as tailwindcss is a utility driven css framework which is classes only this is a good thing. Other frameworks like BS4, Bulma etc as long as you can pass a class to the style a component you want i think that would cover it all. Something to take into account in tailwind we have pseudo class variants an example would be a I think covering each element is a must. I'll be honest when It comes to forms I'd rather have a package like formulate that just is generic where I have any input in my app.. I'd have some form of config that I can change in one place instead of on each element, and maybe if i pass a custom style on that component, it will override the config? I don't know spit-balling ideas here where I could see it benefiting. This is the only thing that's been putting me off using formulate more is the styling, i want to have ease when it comes to throwing something together vs manually doing everything, especially when an app maybe form input heavy. Don't know if this helps or if I'm rambling on, but please add a way to style items in a easier way/format vs each element manually styling. |
Thanks for the input. The proposed system (and the one that’s also in the works) allows for setting custom classes on each level of hierarchy that Vue Formulate outputs. You’d be able to set both global “these classes should be on every Vue Formulate element” defaults as well as per-input overrides when you need exceptions. If you have a form-heavy project then even with class maps it may be worth it to create your own abstraction components that output specific input lock-ups that are common in your project’s UI — but that is something we would leave up to the individual project author to complete. Keep an eye on this issue and we’d love to get your reaction to class maps when they ship. Current target is for release in version 2.4.0. |
Super excited about this 🙌 I up vote for First time using Tailwind (coming from Bulma) and Vue Formulate was my first "can't do" so far, as detailed here.
@narwy Are you able to use Tailwind on Vue Formulate with inline classes? What is your workaround? (withou @apply etc) |
@hmaesta No work around for me, have to use |
Hey @narwy @hmaesta and @gilesbutler — this feature is almost finished now. I've got an early preview of the docs here: https://vueformulatecom-git-feature-classmaps.braid.now.sh/guide/theming/#customizing-classes I think this should handle almost every use case, and like @narwy mentioned you can just configure your tailwind classes once at the global level and be done — then when you need a little more customization on a particular input extend those globals. Would love feedback though! |
also @bbugh somehow I missed your helpful conversation on here. I've considered including renderless too. It would be pretty easy to implement, but I'm slightly concerned about it undermining the main the goals of this project: to make form authoring really easy, fast, and high quality (best practices, accessibility out of the box, etc) so markup is actually a pretty important part of what we're trying to do here — and getting people to conform to a system that allows those features to be improved over time is really valuable for the community at large. For example, if we get some good accessibility feedback an update could help hundreds of sites improve accessibility at the same time. That said, I understand that occasionally people need to deviate from that or their use case really doesn't need those features. I was hoping slots, and slot components would suffice. |
That's really nice, @justin-schroeder 🤩 I read the doc and everything looks great. But since you are already working on this... shouldn't Vue Formulate support pseudo-classes on input elements? For example:
Thinking about Tailwind specific, if @tailwind/ui plugin is present it shouldn't be any problem, since Since this is a project that handles forms, at least I have some fears about performance, but I think it should be supported. Tailwind UI is a paid plugin for Tailwind CSS. Right now everyone is using (including me) because it's early stage (and free), but it's not so clear if this plugin will continue free after the public release. What I understand so far is that they will charge for the "example codes", but since the plugin doesn't have a public repository I feel that it maybe won't be free. Anyway, Tailwind is just an argument. I really think pseudo-class support would be great for advanced CSS styling. Just to illustrate, this is my Tailwind code so far – without using Tailwind UI: .formulate-input {
.formulate-input-label {
@apply block text-sm leading-5 text-gray-700;
}
.formulate-input-element {
@apply mt-1 relative rounded-md shadow-sm;
&.formulate-input-element--text {
input {
@apply block w-full px-3 py-2 border-gray-100 border-solid border rounded-md transition duration-100 ease-in-out;
&:hover {
@apply border-gray-200;
}
&:focus {
@apply border-blue-400 outline-none shadow-outline;
}
}
}
}
} Ps: |
Also thinking about status classes... I am not happy about adding more complexity for this, but I believe it's best to bring all cases to discussion. 🤐
|
@hmaesta So if you want to conditionally add classes you could always use functions and then change things based on the context, but are you sure that you need separate class keys for each of these? I'm not much of a tailwind user, only dabbled, but since psuedo's are just classes in tailwind would it work something like this? Standard HTML: <input class="bg-gray-200 hover:bg-white hover:border-gray-300 focus:outline-none focus:bg-white focus:shadow-outline focus:border-gray-300"> Vue Formulate: <FormulateInput
input-class="bg-gray-200 hover:bg-white hover:border-gray-300 focus:outline-none focus:bg-white focus:shadow-outline focus:border-gray-300"
/> Am I way off on that @hmaesta |
Oh god 🙉 Today I was so immersed with the For that scenario you are totally right. No need for specific "pseudo-keys" on Vue Formulate. |
@hmaesta you're correct, bootstrap doesn't have hover psuedo-classes like Tailwind. Generally, the class map idea seems like it will work great with Tailwind and not so well for non-utility frameworks. To get a global styling for Bootstrap, we'd likely have to shadow/extend the built-in formulate classes with custom CSS and/or create a custom wrapper component for |
Yeah, with non-utilities we'll never have enough options. There are so many combinations of things out there. The current approach gives people an escape hatch to implement their own functions to apply as needed, for example to add Vue.use(VueFormulate, {
classes: {
input: (context, baseClasses) => {
if (context.visibleValidationErrors.length) {
baseClasses.push('input-error-class')
}
return baseClasses
}
}
}) |
In my mind I can imagine 4 levels for this:
To be honest I think we should go at least with Level 2 – simply because we should be responsible for UX. Here's an example: We can't deny what input is way easier to recognise that has wrong data. Looking both inputs side by side it's clear that the second one is better. For the average user, on a form full of filled inputs, this makes a lot of difference. It's 100% don't make me think. I know we can offer a nice sample code of "how to do it yourself", but we have to be honest with ourselves: on a cheap project with a near deadline, no developer will care about this kind of detail. So, again, we have to be responsible for UX and the "average user". It's not a huge change for us, but can benefit a lot of people. I don't feel like I am in a position of telling what should be done – since I can't even help with coding and I am not paying for this great work – but every one of these states significant improves user experience. So, if you guys have the time and it's possible to go with Level 4 without perfomance issues, I would go for it – but if you are looking for the best balance, I think it is the Level 2. Why don't we start with Level 2 and them, based on community feedback (aka issues "how to do this?"), we add support for other levels? 🙂 |
@hmaesta strong argument, and I cant disagree that we should give a better UX to more end users by embracing sensible defaults. Great feedback. I'll try and implement 1-3. I'm concerned that Level 4 is a “bridge too far” since we'd need to tracking cursors/touch start etc. However your Level 4 would make for a compelling little plugin if someone wants to write one. |
Phew — ok everyone. This is finally merged and live in |
That's the fastest open source project team on GitHub 😆 For the error classes, that's how I am doing: let error_class = '';
Vue.use(VueFormulate, {
classes: {
input: (context) => {
if (context.hasErrors) {
error_class = 'border-red-400 hover:border-red-400';
} else {
error_class = '';
}
switch (context.classification) {
case "select":
return 'form-select ' + error_class;
default:
return 'form-input ' + error_class;
}
}, I am a designer... Not sure if that's the best approach – if you have suggestions, let me know. Thank you for the fast implementation 👍 |
Props on the 2.4 release! We're in the process of adding VueFormulate to our codebase and the newly introduced classes functionality has saved us from needing to create custom inputs that override the defaults, which had been necessary due to our Boostrap css setup. |
That’s awesome @mwojtul! So glad that saved some pain! @hmaesta Thanks for the kind words! I think the way you're doing it looks great. Also, we did implement your suggestion for states like Vue.use(VueFormulate, {
classes: {
input: (context) => {
switch (context.classification) {
case "select":
return 'form-select ' + error_class;
default:
return 'form-input ' + error_class;
}
},
inputHasErrors: 'border-red-400 hover:border-red-400'
} These are "state keys" and are always additive (they wont override). They're your idea :) and totally a helpful shortcut! https://vueformulate.com/guide/theming/customizing-classes/#state-keys |
Congrats on the 2.4 release @justin-schroeder and the rest of the Braid team. Awesome work and amazing results! |
Oh, I don't why I thought that just Thanks, guys. |
Describe the new feature you'd like
Proposed solution for allowing classes to be overriden on any sub-element of vue-formulate:
The default would be something like:
The idea is that classMap function would be defined globally for all inputs, and then each sub-type could override it, and then as granular as individual input fields could also override each:
The idea is that the above solution would allow a developer to setup their own fields using a class-based ui framework and handle 90% of a project's form styles globally for all
FormulateInput
elements, and then on a case by case basis easily override the styles on a per-element basis, and lastly scoped slots as a nuclear option.I'll reiterate the goal of Vue Formulate is to make high quality form building fast and easy, so I we want to provide that 90% solution as painlessly as possible. 90% of inputs shouldn't require any additional configuration, scoped slot usage, etc.
What percentage of vue-formulate users would benefit?
Probably about 20%
I'm looking for feedback from users of frameworks like Tailwind, Tachyons, or Bootstrap.
The text was updated successfully, but these errors were encountered: