Details

    • Type: Feature Request
    • Status: Resolved (View Workflow)
    • Priority: Major
    • Resolution: Done
    • Component/s: bootstrap
    • Labels:
      None

      Description

      Recently, during a conversation over a GitHub pull request, a problem has been found: the way to handle Bootstrap color designs for each component is broken. Why? Because they all use the same enum (BootstrapSeverity) but they don't all support all values (only the button has a "primary" severity and there is no "inverse" alert for example), so it is not good for IDE autocomplete since the suggestions should be based on the enum values. In the same time, it is not good also for the code to allow values that should never be used.

      One solution would be to do one enum per component (ButtonSeverity, AlertSeverity, ...). Simple and easy, it allows only supported values and will throws exceptions in other cases. IDE would only suggest those right values. Quite good.

      But to be honnest, after thinking about it some time, I don't really like bloking the user to only a determined set of values. What if a user want to add new severities like "Debug" and "Fatal" to be more compliant with JSF severities? Those don't exist at all in Bootstrap. But using LESS syntax, it's really easy to create a new design for new severities and apply them. We should provide a generic way to handle any severity (for buttons, it would be to add a CSS class named "btn-[severity name]") and suggest values supported out-of-box but still allow users to create their own severity ("btn-debug") and use the "severity" attribute to handle it (severity="debug") instead of using a workaround (styleClass="btn-debug").

      In order to do that, the easiest way would be to drop enums and use only strings. If the "severity" attribute is present, then add a CSS class based on its value and use the @Attribute CDK annotation to provide suggested values by IDE for each component. What's the problem? It's not really type safe and you have to write the business rule in the template/renderer since you can no longer write them in the enum. I would prefer for the rendered to only ask the enum "Hey, what should I add?" and the enum answer "a CSS class named 'btn-primary'" without the component worrying about how to generate the CSS class name based on the value of the attribute.

      So, even if I would be totally fine with plain old strings, I would like to suggest another idea to have both enums and an open world where users can create their own values. Let's take a concrete example with the severity for the button component:

      public enum ButtonSeverity {
          PRIMARY("btn-primary"),
          ERROR("btn-error"),
          ...;
      
          private String value;
          private boolean custom;
      
          private ButtonSeverity(String value) {
              this.value = value;
              this.custom = false;
          }
      
          private ButtonSeverity(String value, boolean custom) {
              this.value = value;
              this.custom = custom;
          }
      
          public String getStyleClass() {
              if(custom) {
                  return "btn-"+value;
              } else {
                  return value;
              }
          }
      }
      

      What is important here is the "custom" attribute. The idea is that if the user a value supported out-of-the box, then "custom" will be set to false and the enum can handle it its own way as complex as you want it to be. But if the user try to put a new value in the JSF component attribute, like severity="debug", then, inside the Java code, it will be one of our enums (for example the PRIMARY one) but with "custom" set to true. If "custom" is true, then the enum has the duty to no longer rely in anything except the "value" attribute which is the value provided by the user.

      It's like having one more value for the enum, a generic one which can rely only to its name. I was thinking about adding it to the enum, like "GENERIC", but since we don't want the IDE to suggest it, the "custom" boolean is a workaround to do that. The previous example is a bit trivial, so it doesn't show the real benefit of having such a complex stuff but the idea is to be more type safe and supporting both potential complex business rules for our values and a generic way to handle other values submitted by users.

      Since it's a bit complex, and would mean to intercept the JSF attribute value to test if the value is inside the enum or not in order to set "custom" to true or not, and also because it's a bit dirty to have a concrete enum (like PRIMARY) but using it in a way that have nothing to do with the "primary" notion (since it's custom), I don't know if it worth it... but still, I wanted to think of a way to have both of two worlds: type-safe enums and plain old strings allowing anything. If someone has another way to achieve it, feel free to propose it. In any case, strings are always good at the end.

      In the same time, all components are currently using the "severity" attribute but we can also think or renaming it for some of them. I like thise name right now but maybe for some components like the progress bar, people would prefer something like "design" or "color" or "colorScheme" since there is no real "severity" for a progress bar...

      Regards,

        Gliffy Diagrams

          Attachments

            Activity

              People

              • Assignee:
                paul.dijou Paul Dijou
                Reporter:
                paul.dijou Paul Dijou
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: