Skip to content

First steps of bootstrap replacement#19946

Merged
dannon merged 19 commits intogalaxyproject:devfrom
ElectronicBlueberry:g-button-and-color-system
Apr 9, 2025
Merged

First steps of bootstrap replacement#19946
dannon merged 19 commits intogalaxyproject:devfrom
ElectronicBlueberry:g-button-and-color-system

Conversation

@ElectronicBlueberry
Copy link
Copy Markdown
Member

This PR is mostly to gather feedback on the discussed bootstrap replacement, as it will heavily shape on how the replacement will look and work moving forward. It includes a base implementation of the button component, which is our most heavily used component from the bootstrap vue library, to illustrate the direction I plan on taking this refactor.

The look of the button component is nearly identical, and the primary goal here to collect feedback on the code structure and direction.

My design goal with this refactor is not achieving a 100% drop in replacement, but still have the components easy to replace while adjusting their interfaces to our use-cases.

Tooltips

This PR also includes a re-implementation of the bootstrap vue tooltip, which is fully accessible. It can be activated and dismissed via keyboard and works on disabled components.

Color system

The color system is inspired by tailwind. Each color has a pre-defined set of handpicked gradients, to ensure sufficient contrast and color-uniformity. Additionally partially transparent colors have been removed, as they further reduce contrast, and lead to new, non-palettized colors. Each color has a gradient from 100, lightest, to 900, darkest. example usage: var(--color-blue-500).

Spacing

Spacing also follows tailwinds example. Instead of defining a arbitrary set of space sizes, all sizes are a multiple of a base size. example usage: var(--spacing-4) is 4 times the base spacing.

Next steps

The next step for the replacement will be replacing all uses of plain (non-grouped) boostrap buttons with this component, and adding additional features required to do so. Mainly an icon-only variant of the button is still missing.

After that further components will be converted, starting with button groups.

Additionally I would like to add a GLink component, as we heavily make use of custom, button-like links.

How to test the changes?

(Select all options that apply)

  • I've included appropriate automated tests.
  • This is a refactoring of components with existing test coverage.
  • Instructions for manual testing are as follows:
    1. [add testing steps and prerequisites here if you didn't write automated tests covering all your changes]

License

  • I agree to license these and all my past contributions to the core galaxy codebase under the MIT license.

@ElectronicBlueberry ElectronicBlueberry marked this pull request as ready for review April 3, 2025 13:17
@github-actions github-actions Bot added this to the 25.0 milestone Apr 3, 2025
@dannon
Copy link
Copy Markdown
Member

dannon commented Apr 3, 2025

I love the direction this is taking, thank you for working on it. I know this is probably what you are already doing, but we should definitely take these components incrementally -- following up on the link component, etc. separately and focus just on button (and I guess tooltip) here.

My one concern is using raw color vars directly in each component. I think we might want to go ahead and take the plunge to use semantic design tokens that then use the color system. This is future-proofing easier theme support and changes, more clarity in naming (i.e., you don't pick a shade of grey in fancy-new-component-x, you just use widget-primary-bg, etc), and I think it's a small investment we can make now that will pay off down the road.

i.e. --

// tokens.scss
:root {
    --widget-primary-bg: var(--color-grey-200);
    --widget-default-border: var(--color-grey-300);
    --widget-default-text: var(--color-grey-800);

That then gets used in the component as:

.g-button {
  // Default variant uses grey tokens
  background-color: var(--widget-default-bg);
  ...

?

One more thought (not really a concern, but something to think about as you build more of these) - we may want to move some of the more repetitive boilerplate blocks to use mixins, for consistency, reuse, and just easier reading.

(Again, THANK YOU for working on this :) )

@ElectronicBlueberry
Copy link
Copy Markdown
Member Author

Thank you for having a look at this and your feedback!

following up on the link component, etc. separately and focus just on button (and I guess tooltip) here.

Yes, I agree, and it is on what I plan to do. I also plan to have the PRs which replace this component separately, save from some example use-cases, so it makes the implementation easier to review. This PR only includes 3 components, because the button component heavily depends on the other two components included.

One more thought (not really a concern, but something to think about as you build more of these) - we may want to move some of the more repetitive boilerplate blocks to use mixins, for consistency, reuse, and just easier reading.

I plan on doing this, if I sport overlap in future components. However, I will try to prioritize nesting components over styles duplicated via mixins.

Regarding raw colors vs semantic colors:

I have though a lot about semantic colors vs raw color tokens before deciding on raw color tokens. My reasoning is as follows:

  1. Semantic abstractions restrict you into a further limited set of options. While this is usually a good thing in coding, with colors this can make different components look too alike. While components should always visually fit to one another, them looking too alike can make them way harder to tell apart and spot at a glance. The colors asthetically fitting to one another is already achieved by the raw color tokens, as the colors were chosen with this criteria in mind. It is also possible to back oneself into a corner with this further restricted set of colors, for example needing to choose a low contrast, semantically correct, option over a better fitting high contrast one.

  2. It can be very difficult to consistently use the correct semantic abstractions in user interfaces. We already have this problem in a bunch of places. Think about links vs buttons. It is much simpler and clearer to choose an ui abstraction based on what you want it to look like, rather than on semantics. For some components it can also be on the edge, between one semantic abstraction or another and one may choose one over the other on a whim. This can quickly become messy. With raw color tokens it is much easier to use them at any place in the code, without needing to put too much effort into figuring out the correct semantic token.

  3. It makes it easier to adjust and theme to colors, as it is instantly visually clear which parts of the UI will be affected in what way by just looking at the interface, unlike semantic colors.

    3.a. This can also be seen as a point for semantic colors, as they could allow easier adjusting for one type of component, separately from another type of component. I do however not think this is a frequent use case, as it makes swapping color pallets much more of a laborious effort than it already is, and it would require a very consistent use of semantics as outlined in point 2. to be possible, adding to development complexity.

    3.b. Dark mode. Swapping the 100 to 900 ordering can achieve dark more rather easily, without having to hand pick a new set of semantic colors for every component type.

  4. A point for semantic colors is that it makes them easier to swap out in the future. For example if we ever would want to replace blue for purple down the road. However, due to the long unique names of the tokens, this can be achieved rather trivially with a search and replace.

So in total I think that the raw color tokens actually scale better, and offer a better developer experience, despite not seeming like they do on the surface. There may be some special component for which we still want separate definitions, like the masthead, but I do not think that this should be generally done for all types of components.

@dannon
Copy link
Copy Markdown
Member

dannon commented Apr 4, 2025

Thanks for your thoughtful and detailed response on the color system approach -- I appreciate how much consideration you've put into this.

The points about maintaining visual distinctiveness between components and the challenges of consistent semantic abstraction are well-taken, and it's easy to acknowledge that raw color tokens provide more flexibility and direct visual mapping when implementing new components, but, I do think there might be value in a lightweight hybrid approach as the system evolves. Maybe as this goes we can identify a small set of heavily reused and stable concepts could be pulled out to address future maintenance without creating the rigidity you're concerned about.

In any case, I'm comfortable with moving forward with the raw color token approach for now. We can always iterate on this as the component library grows and patterns emerge. The most important thing is making progress on the Bootstrap replacement, and your implementation looks excellent.

Looking forward to seeing how this evolves, and thanks again for your work on this!

@ElectronicBlueberry ElectronicBlueberry force-pushed the g-button-and-color-system branch from 3b019c7 to 282ec87 Compare April 7, 2025 11:09
@dannon dannon merged commit a77ea5e into galaxyproject:dev Apr 9, 2025
29 of 30 checks passed
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2025

This PR was merged without a "kind/" label, please correct.

dannon added a commit to dannon/galaxy that referenced this pull request Apr 28, 2026
Drops the @import of @/style/scss/theme/blue.scss and switches to the
--color-* tokens from custom_theme_variables.scss (PR galaxyproject#19946, Laila
Los): --color-blue-600 for info, --color-orange-600/200 for warning,
--color-green-600/200 for success, --color-red-600/200 for danger, and
--color-grey-100 for neutral background.

GTip was the only G-component with an explicit theme SCSS import, so
removing it cleans up the last bit of mandatory theme coupling in
BaseComponents. The SCSS scale-color() calls for warning/success/danger
backgrounds map to the 200-shade of each hue, which is the closest
pre-defined match and avoids the partial-transparency pattern the color
system intentionally moved away from.

Prep work for the @galaxyproject/galaxy-ui workspace package: the
package can't depend on Galaxy's SCSS theme, so it consumes CSS custom
properties injected by the app at :root.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants