Skip to content
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

Add unique classes to components #1361

Closed
wants to merge 13 commits into from
Closed

Add unique classes to components #1361

wants to merge 13 commits into from

Conversation

djvs
Copy link
Contributor

@djvs djvs commented Jun 17, 2023

See #1319. Want to add a lot of classes to allow proper contextualization of CSS.

This should mostly create a migration path away from styles being tied directly to React (well, Inferno) components, which is a big anti-pattern for something that should be themeable.

These are mostly just picked as I went, with a couple small naming conventions that should be apparent. I'm not married to any particular change here besides the general gist of it, so if you want to edit the PR or anything like that let me know.

@jsit
Copy link
Contributor

jsit commented Jun 17, 2023

@djvs Disclaimer: I'm very new to this project, so I can't speak for the code maintainers (@dessalines and @SleeplessOne1917), but here's my read on the situation:

Because the project is moving so fast and because there will be so many different people working on it, I think sticking with Bootstrap classes is an intentional decision to (a) reduce overhead for pitching in (no learning curve on class naming conventions or an extra layer in the stack) and (b) prevent inconsistencies in approach or naming.

(I have a general distaste for Bootstrap, too, but I think its use may be warranted in this case.)

Regarding the issue of elements not being easily targetable for custom styling, I think the general approach right now is, "If it can't be done with Bootstrap, don't do it (for now)." Much of Bootstrap can be customized with theming (there are other efforts going on there AFAIK).

See the conversation in #863


It might be a good idea to update the Contributing guide to discuss this.

@Zetaphor
Copy link
Contributor

I think there's a worthwhile middle ground to explore here. I understand the point that @dessalines is making in that he doesn't want to bind the base themes to custom classes because the core of lemmy-ui should be able to painlessly adopt any Bootstrap theme.

However I also agree with everyone else in the community who says that doing custom theming, which is a valid and clearly highly desirable goal, is made unnecessarily difficult by the current lack of semantics in the markup.

I don't see why it would not be a viable path forward to insist that the base Lemmy themes be only based on Bootstrap standard classes, and that any markup added or changed adhere to the Bootstrap structure and styling, while also providing hooks for users who want to go beyond Bootstrap. This includes far more than just theme developers, but also people making userscripts and browser extensions.

If the goal here is to support user choice first (be it end-user or instance host), while also keeping the codebase clean and accessible, I think there's a fairly easy to reach line that accomplishes both of those goals.

We can have our stock experience that can seamlessly slot in a Bootstrap theme for those who just want to ship the defaults with maybe some light color swaps, while also enabling an ecosystem of users adding increased value and customization to either their individual or hosted experience.

@ayan4m1
Copy link
Contributor

ayan4m1 commented Jun 17, 2023

Agreed, I have no idea where the naming conventions for these classes lives/came from but it needs to be much better documented if it's going to be merged in imho. The class names in this PR are confusing, sometimes abbreviated sometimes not, undocumented suffixes, does not seem to adhere to BEM or any other naming convention I'm familiar with.

@Zetaphor
Copy link
Contributor

Agreed, I have no idea where the naming conventions for these classes lives/came from but it needs to be much better documented if it's going to be merged in imho. The class names in this PR are confusing, sometimes abbreviated sometimes not, undocumented suffixes, does not seem to adhere to BEM or any other naming convention I'm familiar with.

You wrote this seconds after I posted my response. I also completely agree with this post. If we are going to extend courtesy to customization it should be through sane and sensible naming conventions that align well with the existing Bootstrap standards.

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

Well, in general I would advise against using Bootstrap in the first place. That creates a baked-in opinionated approach to layout which limits themes' ability to handle responsive design.

That aside, the current reliance on Bootstrap classes, with virtually no other classes anywhere else in the codebase, as Klobenda mentions in the other thread, is completely hostile to any third party themes. People inevitably are forced to create 6-element-deep selectors to target specific elements which will break suddenly and non-debuggably with any change to the components. I have literally already had to do this a few dozens of times for my user-styles CSS (linked via the issue linked above). The rule of thumb after my PR here is to try to limit necessary selectors to 2-3 levels deep if possible. There is also a serious issue with lack of contextualization - I noticed I had a hard requirement to actually reference "comments on a post page", "comments on a user page", etc. to create reusable styles, but this was impossible, and had to be constructed using a basically random sequence like "#app > div > ul > li > div.mr-3 > li".

The naming convention I used is basically just "create unique names and try to namespace them". BEM tends to be extremely verbose and unpleasant to work with, and unnecessarily confines elements to contexts that may be more harmful than useful. All I did was basically namespace particular elements with something close to the name of the wrapping component, detail rows, buttons, li's etc per name to make them individually addressable in importance places, and the outermost component (or something very likely to be branched off) is prefaced with "cnt-". "-w" is a similar suffix for wrapping components inside one of the containing/component-level ones. I'm happy to change those, I imagine the "cnt-" one is least palatable. Keep in mind that the length of class names increases payload size in general, so there's a balance here between specificity/verbosity and conciseness. But, in general, the classes/IDs just refer to "specific things on whatever it is your web app does", so you can generally get away with "just use alphanumeric + hyphens, and maybe underscores, and don't create names that are so vague you accidentally reuse them". I wouldn't really overthink it past there.

edit: To walk that back slightly, BEM is fairly workable if the block scope isn't overly broad, which is the approach I went with for the later implementation here (mostly the same as component-level scope).

@Zetaphor
Copy link
Contributor

Well, in general I would advise against using Bootstrap in the first place. That creates a baked-in opinionated approach to layout which limits themes' ability to handle responsive design.

I also agree with this, but it's not my place to drive that large of a change.

That aside, the current reliance on Bootstrap classes, with virtually no other classes anywhere else in the codebase, as Klobenda mentions in the other thread, is completely hostile to any third party themes. People inevitably are forced to create 6-element-deep selectors to target specific elements which will break suddenly and non-debuggably with any change to the components.

This is something I tried to help with with the changes I made in #1327, but I went for a much sparser approach trying to only focus on major areas rather than tagging as thoroughly. I do hope we can reach a consensus on this with the maintainers.

I'm happy to change those, I imagine the "cnt-" one is least palatable.

I did read this in my head as c*nt 😅

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

Well, I mean more that cnt- is a prefix, although it is done that way to make it explicit it's denoting a section. It's short for "container". "w" for wrap, "err" for error, etc..

@jsit
Copy link
Contributor

jsit commented Jun 17, 2023

Well, in general I would advise against using Bootstrap in the first place. That creates a baked-in opinionated approach to layout which limits themes' ability to handle responsive design.

The project is already heavily using Bootstrap, so dropping it will require quite a bit of planning. I agree that relying on Bootstrap can be problematic but it's what we've got.

BEM tends to be extremely verbose and unpleasant to work with, and unnecessarily confines elements to contexts that may be more harmful than useful.

Personally I think BEM can be hugely advantageous, especially in a codebase with a lot of people working on it.

Probably a conversation to be had elsewhere. Would it be useful to have GitHub Discussions set up on this project? @dessalines @SleeplessOne1917

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

Well, I would use BEM here if it would get this merged. This was quite a bit of typing and hopefully not in vain.

@jsit
Copy link
Contributor

jsit commented Jun 17, 2023

Well, I would use BEM here if it would get this merged. This was quite a bit of typing and hopefully not in vain.

I think more is needed than just converting these classes to BEM. A clear plan would probably have to be laid out.

@jsit
Copy link
Contributor

jsit commented Jun 17, 2023

This was quite a bit of typing and hopefully not in vain.

I think it would be a good idea to check with the maintainers to make sure something like this is desired before putting this much work into it.

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

Resubmitted as BEM in the interest of conforming to some actual existing standard

@jsit
Copy link
Contributor

jsit commented Jun 17, 2023

@djvs You seem to be using double dashes for both modifier syntax and child syntax? There are several BEM naming conventions but I'm not familiar with this one.

https://en.bem.info/methodology/naming-convention/

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

Whoops, yeah I don't use BEM much these days. Fixing.

@djvs
Copy link
Contributor Author

djvs commented Jun 17, 2023

👍

@jsit
Copy link
Contributor

jsit commented Jun 18, 2023

@djvs So, for something like this:

Screenshot 2023-06-17 at 8 00 40 PM

It looks like these three elements are probably styled very similar, meaning their classes should be modifiers of the same class.

So instead of:

<label
  className="listing-type-select__label-subscribed"
  className="listing-type-select__label-local"
  className="listing-type-select__label-show-all"
/>
<label
  className="listing-type-select__label listing-type-select__label--subscribed"
  className="listing-type-select__label listing-type-select__label--local"
  className="listing-type-select__label listing-type-select__label--show-all"
/>

@jsit
Copy link
Contributor

jsit commented Jun 18, 2023

It's these kinds of things that make me think any efforts here need to be part of some larger planning, not hashed out in the comments of a big PR.

@djvs
Copy link
Contributor Author

djvs commented Jun 18, 2023

That's a fair point, I'll address that now.

@jsit
Copy link
Contributor

jsit commented Jun 18, 2023

I think if and when this project switches to semantic class names, it should be done on a component-by-component basis, not as one big PR that adds a ton of classes that aren't getting styled yet.

@djvs
Copy link
Contributor Author

djvs commented Jun 18, 2023

I don't think being explicitly styled is a prerequisite to adding classes to a FE that's intended to support themes? Even if so, it'd be better to at least get something down for themers to work off of. Especially with Lemmy userbase taking off right now.

@djvs
Copy link
Contributor Author

djvs commented Jun 18, 2023

Anyway, probably gonna quit making changes for the moment until maintainers chime in, I feel like this approach is pretty reasonable atm.

@jsit
Copy link
Contributor

jsit commented Jun 18, 2023

it'd be better to at least get something down for themers to work off of.

I may be wrong but I don’t think user themes is a high priority right now. The UI needs a lot more work than just the way it looks. Ultimately the main benefit of using semantic class names is maintainability, not for user stylesheets to latch onto.

@alectrocute
Copy link
Contributor

I applaud the effort but unfortunately I think it may be a bit misguided. I’m not a fan of it. My two cents: If we want to do something like this, we should be using id’s. That way, our classNames can be separate and it can also be user style friendly.

@djvs
Copy link
Contributor Author

djvs commented Jun 18, 2023

IDs only for unique elements (getElementById vs getElementsByClassName), keeping it broadly generic allows element reuse. There may be a few exceptions worth isolating (e.g. #app that's already there), but generally very little benefit from confining them. CSS allows both to be referenced for selectors of course.

@jsit
Copy link
Contributor

jsit commented Jun 18, 2023

@djvs @alectrocute @Zetaphor I've written some more about a possible CSS plan in #1371

@jsit
Copy link
Contributor

jsit commented Jun 19, 2023

Something else I kind of worry about with this is that PRs might start coming in with modifications to main.css that modify the styles on these classes.

@@ -1153,20 +1153,20 @@ export class PostListing extends Component<PostListingProps, PostListingState> {
) : (
<>
<button
className="d-inline-block mr-1 btn btn-link btn-animate text-muted py-0"
className="post-listing__btn post-listing__btn--transfc-confirm d-inline-block mr-1 btn btn-link btn-animate text-muted py-0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transfc = transfer community? The class name's already so long, I see no reason to not just write the rest of the words.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I mean about planning. Will this specific button really be styled much differently from other buttons? Does it need a modifier?

All these names are chosen with no intention other than making sure everything has a class name on it. These are extremely likely to change, breaking whatever user themes are created in the meantime. Then you have a bunch of user themers getting upset at the project for "breaking" their themes.

This is not what CSS is for.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alectrocute It's extremely messy and doesn't serve the larger goals of the project, these are only serving as sledgehammer hooks for custom theming. Obviously this isn't my project, but I just think this whole thing is greatly misguided.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with you on all counts, @jsit.

Copy link
Member

@dessalines dessalines Jun 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@djvs It seems like the consensus is that this is not a good idea, and that users are going to come complaining to us every time their themes break when we change things around.

Is it so bad to generate bootstrap-compatible themes for site customization?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the product of two constraints:

  • Somebody wanting to style that particular button
  • Using BEM

And sort of additionally:

  • jsit's earlier request to have generic and then modifier substrings for stuff like buttons - `post-listing__btn post-listing__btn--transfc-confirm". Specifically, it's:

Block: post-listing

Element: btn

Modifier: transfc-confirm

The verbosity is my problem with BEM, but without it you are indeed stuck with "confirm-transfc" or whatever. That was basically my initial approach with slightly more namespacing.

Copy link
Contributor

@alectrocute alectrocute left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Objectively looked through it and called out any potential issues. I think we need to have further discussion about this.

Mixing BEM and Bootstrap is kinda an abomination. I've never seen anything like it. This will have consequences on the project. As @jsit aptly put, contributors and maintainers will have to follow this practice for every new element we add/change, and will be responsible for it in perpetuity.

@djvs
Copy link
Contributor Author

djvs commented Jun 19, 2023

Well, not my decision to make, but classes/IDs are basically the only way for user styles/scripts to work, and BEM happens to be the prevailing standard for class/ID naming (I'm not a huge fan of it either - you could commit to some modified BEM without double dashes/underscores, but that might be even more trouble). And interest was expressed by 2+ of you in abandoning Bootstrap long-term, in which case this is basically just a step towards that.

@djvs
Copy link
Contributor Author

djvs commented Jun 19, 2023

P.S. - the kind of bare minimum for people abiding by this standard is "just add a meaningful class name at the root of a component". The additional ones I added were just in the interest of being thorough.

@SleeplessOne1917
Copy link
Member

Sorry for taking awhile to review this. I agree with @jsit saying this is a lot of premature optimization. I would be more for it if it wasn't for the fact that contributors will have to come up with these sorts of class names whenever something is added.

@jsit
Copy link
Contributor

jsit commented Jun 20, 2023

In other words, these class names have no actual relationship to how they’re actually going to be used. They’re just there to be there.

it’s not “a start” because they’ll likely be abandoned when the codebase switches to Tailwind anyway.

AND they will be hard to remove. There are hundreds of new class names here, and none of them has any styling applied to them. To get rid of any one of them, you’d have to know that no styles depend on their being there.

@jsit
Copy link
Contributor

jsit commented Jun 20, 2023

Adding class names without associated styles, just so that they might be custom-styled, is a really good way to pollute your codebase with all kinds of unnecessary markup. It’s asking for trouble.

@jsit
Copy link
Contributor

jsit commented Jun 20, 2023

“Does this class do anything” shouldn’t be a hard question to answer when looking at a codebase. Here, that will be unclear in hundreds of new instances.

@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

OK - can we reach a compromise like "one unique class name per actual component"? I could go either way on BEM, you guys seem split on that.

@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

You can use grep to check if/when a CSS class is used btw.

@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

There might be a bit of "missing the forest for the trees" going on here. At the end of the day the goal is for Lemmy to be something lots of people want to use. For it to be that, it has to look good and be intuitive. That won't be one-size-fits-all in the first place - different visual preferences, devices, browsers, disabilities, you name it. The goal of CSS classes in a context like that isn't simply for the convenience of the developers, it's to allow the UI to support customization. Reddit handled this correctly for years - old.reddit.com was well marked up and styleable (allowing subreddit/community-level styling as well!), and the RES extension took full advantage of this as well. IMO the cost of "having a few classes lying around that don't have associated styles in the main source tree" isn't even on the same order of magnitude.

It's actually a bit surprising to encounter this attitude. My reaction to the first opening of Lemmy with F11 inspector was basically "WTF?" - typically sites have at least 25% class coverage for elements. E.g. on this very page - "edit-comment-hide", "timeline-comment-header", "timeline-comment", "unminimized-comment", etc. just in a comment box, along with quite a few others. Paired with utility classes I would add. Sometimes that's minified along with the JS, but not anywhere they expect user customization.

I phrase it as "a start" because you could absolutely use my classes as a jumping off point for styling. There's quite a bit of UI markup and logic already - you might want to rethink the class components that Inferno uses if you move to React proper - but no point in rewriting things that are already fine.

@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

Github apparently lets me merge this but no idea what maintainer hierarchy is. I would not like to maintain this indefinitely as a downstream branch, I'm already past the third set of merge conflict resolves. If there's a workable solution here please let me know, I have a lot on my plate right now.

(...er, Github does not let me merge it, I'm just used to the "All green checks" display meaning "you can merge")

@djvs djvs changed the title Add a lot of classes Add unique classes to components Jun 20, 2023
Copy link
Member

@dessalines dessalines left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should hold off on this one for now, because its a highly contentious issue. Racing to put class names on everything, conflicts with the existing UI frameworks preferred way to do custom styling, and is likely to put a ton more work on us devs.

@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

OK, I won't be able to maintain this branch separately long-term. Can we do a middle of the road compromise like "one meaningful class name per component"?

@djvs djvs mentioned this pull request Jun 20, 2023
@djvs
Copy link
Contributor Author

djvs commented Jun 20, 2023

Simpler version here:

#1421

@dessalines
Copy link
Member

Closing in favor of #1421

@dessalines dessalines closed this Jun 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants