Refactor button.css using nested CSS

This should help more easily maintain various button
variants. As a follow-up, I plan to reduce interleaving of sizing and visual variants so that each rule follows the same structure.

Bug: none
Change-Id: I7402e228b8109f79d83de5455e7d7abaf412cf02
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/5163634
Commit-Queue: Alex Rudenko <[email protected]>
Reviewed-by: Benedikt Meurer <[email protected]>
diff --git a/front_end/ui/components/buttons/button.css b/front_end/ui/components/buttons/button.css
index c664899..c579635 100644
--- a/front_end/ui/components/buttons/button.css
+++ b/front_end/ui/components/buttons/button.css
@@ -58,236 +58,205 @@
   justify-content: center;
   width: var(--button-width);
   white-space: nowrap;
+
+  devtools-icon {
+    width: calc(var(--button-width) - 4px);
+    height: calc(var(--button-height) - 4px);
+  }
+
+  &.small {
+    --button-height: 20px;
+
+    border-radius: 2px calc(var(--button-has-right-border-radius) * 2px) calc(var(--button-has-right-border-radius) * 2px) 2px;
+  }
+
+  &.toolbar,
+  &.round {
+    --button-height: 24px;
+    --button-width: 24px;
+
+    background: transparent;
+    border: none;
+    overflow: hidden;
+    padding: 0;
+    white-space: nowrap;
+
+    &.small {
+      --button-height: 20px;
+      --button-width: 20px;
+    }
+  }
+
+  &.toolbar {
+    border-radius: 2px calc(var(--button-has-right-border-radius) * 2px) calc(var(--button-has-right-border-radius) * 2px) 2px;
+  }
+
+  &.round {
+    border-radius: 100%;
+
+    &.tiny {
+      --button-height: 18px;
+      --button-width: 18px;
+    }
+  }
+
+  &.primary {
+    border: var(--button-border-size) solid var(--sys-color-primary);
+    background: var(--sys-color-primary);
+    color: var(--sys-color-on-primary);
+
+    devtools-icon {
+      color: var(--sys-color-cdt-base-container);
+    }
+  }
+
+  &.tonal {
+    border: var(--button-border-size) solid transparent;
+    background: var(--sys-color-tonal-container);
+    color: var(--sys-color-on-tonal-container);
+
+    devtools-icon {
+      color: var(--sys-color-on-tonal-container);
+    }
+  }
+
+  &.secondary {
+    border: var(--button-border-size) solid var(--sys-color-tonal-outline);
+    background: var(--sys-color-cdt-base-container);
+    color: var(--sys-color-primary);
+
+    devtools-icon {
+      color: var(--icon-primary);
+    }
+  }
+
+  &.primary-toolbar {
+    devtools-icon {
+      color: var(--icon-primary);
+    }
+  }
+
+  &.text-with-icon {
+    padding: 0 calc(12px - var(--button-border-size)) 0 calc(8px - var(--button-border-size));
+
+    devtools-icon {
+      width: 20px;
+      height: 20px;
+      margin-right: 4px;
+    }
+  }
+
+  &.only-icon {
+    padding: 0;
+  }
+
+  &:focus-visible {
+    outline: 2px solid var(--sys-color-state-focus-ring);
+    outline-offset: 2px;
+
+    &.toolbar,
+    &.round {
+      background-color: var(--sys-color-tonal-container);
+      outline: none;
+    }
+  }
+
+  &:disabled {
+    pointer-events: none;
+
+    &.primary {
+      border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
+      background: var(--sys-color-state-disabled-container);
+      color: var(--sys-color-state-disabled);
+    }
+
+    &.tonal {
+      border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
+      background: var(--sys-color-state-disabled-container);
+      color: var(--sys-color-state-disabled);
+    }
+
+    &.secondary {
+      border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
+      color: var(--sys-color-state-disabled);
+    }
+
+    &.toolbar,
+    &.round {
+      background: var(--sys-color-cdt-base-container);
+      color: var(--sys-color-state-disabled);
+    }
+
+    devtools-icon {
+      color: var(--icon-disabled);
+    }
+  }
+
+  &:hover {
+    &.primary {
+      background: color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-hover-on-prominent) 6%);
+      border: var(--button-border-size) solid color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-hover-on-prominent) 6%);
+    }
+
+    &.tonal {
+      background: color-mix(in sRGB, var(--sys-color-tonal-container), var(--sys-color-state-hover-on-subtle));
+    }
+
+    &.secondary {
+      background: var(--sys-color-state-hover-on-subtle);
+    }
+
+    &.toolbar,
+    &.round {
+      background-color: var(--sys-color-state-hover-on-subtle);
+    }
+
+    &.toobar {
+      devtools-icon {
+        color: var(--icon-default-hover);
+      }
+    }
+  }
+
+  &:active,
+  &.active {
+    &.primary {
+      background: color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-ripple-primary) 32%);
+      border: var(--button-border-size) solid color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-ripple-primary) 32%);
+    }
+
+    &.tonal {
+      background: color-mix(in sRGB, var(--sys-color-tonal-container), var(--sys-color-state-ripple-primary));
+    }
+
+    &.secondary {
+      background-color: var(--sys-color-surface-variant);
+    }
+
+    &.toolbar,
+    &.round {
+      background-color: var(--sys-color-state-ripple-neutral-on-subtle);
+    }
+
+    &.toolbar {
+      devtools-icon {
+        color: var(--icon-toggled);
+      }
+    }
+  }
+
+  &.text-with-icon.small {
+    padding: 0 calc(9px - var(--button-border-size)) 0 calc(3px - var(--button-border-size));
+
+    devtools-icon {
+      width: 16px;
+      height: 16px;
+      margin-right: 4px;
+    }
+  }
 }
 
-button.small {
-  --button-height: 20px;
-
-  border-radius: 2px calc(var(--button-has-right-border-radius) * 2px) calc(var(--button-has-right-border-radius) * 2px) 2px;
-}
-
-button:focus-visible {
-  outline: 2px solid var(--sys-color-state-focus-ring);
-  outline-offset: 2px;
-}
-
-button:disabled {
-  pointer-events: none;
-}
-
-button.toolbar,
-button.round {
-  --button-height: 24px;
-  --button-width: 24px;
-
-  background: transparent;
-  border: none;
-  overflow: hidden;
-  padding: 0;
-  white-space: nowrap;
-}
-
-button.toolbar {
-  border-radius: 2px calc(var(--button-has-right-border-radius) * 2px) calc(var(--button-has-right-border-radius) * 2px) 2px;
-}
-
-button.round {
-  border-radius: 100%;
-}
-
-button.round.small,
-button.toolbar.small {
-  --button-height: 20px;
-  --button-width: 20px;
-}
-
-button.round.tiny {
-  --button-height: 18px;
-  --button-width: 18px;
-}
-
-button.primary {
-  border: var(--button-border-size) solid var(--sys-color-primary);
-  background: var(--sys-color-primary);
-  color: var(--sys-color-on-primary);
-}
-
-button.primary:hover {
-  background: color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-hover-on-prominent) 6%);
-  border: var(--button-border-size) solid color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-hover-on-prominent) 6%);
-}
-
-button.primary.active,
-button.primary:active {
-  background: color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-ripple-primary) 32%);
-  border: var(--button-border-size) solid color-mix(in sRGB, var(--sys-color-primary), var(--sys-color-state-ripple-primary) 32%);
-}
-
-button.primary:disabled {
-  border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
-  background: var(--sys-color-state-disabled-container);
-  color: var(--sys-color-state-disabled);
-}
-
-button.tonal {
-  border: var(--button-border-size) solid transparent;
-  background: var(--sys-color-tonal-container);
-  color: var(--sys-color-on-tonal-container);
-}
-
-button.tonal:hover {
-  background: color-mix(in sRGB, var(--sys-color-tonal-container), var(--sys-color-state-hover-on-subtle));
-}
-
-button.tonal.active,
-button.tonal:active {
-  background: color-mix(in sRGB, var(--sys-color-tonal-container), var(--sys-color-state-ripple-primary));
-}
-
-button.tonal:disabled {
-  border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
-  background: var(--sys-color-state-disabled-container);
-  color: var(--sys-color-state-disabled);
-}
-
-button.secondary {
-  border: var(--button-border-size) solid var(--sys-color-tonal-outline);
-  background: var(--sys-color-cdt-base-container);
-  color: var(--sys-color-primary);
-}
-
-button.secondary:hover {
-  background: var(--sys-color-state-hover-on-subtle);
-}
-
-button.secondary.active,
-button.secondary:active {
-  background-color: var(--sys-color-surface-variant);
-}
-
-button.secondary:focus-visible {
-  outline: 2px solid var(--sys-color-state-focus-ring);
-  outline-offset: 2px;
-  box-shadow: none;
-}
-
-button.secondary:disabled {
-  border: var(--button-border-size) solid var(--sys-color-state-disabled-container);
-  color: var(--sys-color-state-disabled);
-}
-
-button.toolbar:hover,
-button.round:hover {
-  background-color: var(--sys-color-state-hover-on-subtle);
-}
-
-button.toolbar.active,
-button.toolbar:active,
-button.round.active,
-button.round:active {
-  background-color: var(--sys-color-state-ripple-neutral-on-subtle);
-}
-
-button.toolbar:focus-visible,
-button.round:focus-visible {
-  background-color: var(--sys-color-tonal-container);
-  outline: none;
-}
-
-button.toolbar:disabled,
-button.round:disabled {
-  background: var(--sys-color-cdt-base-container);
-  color: var(--sys-color-state-disabled);
-}
-
-button.text-with-icon {
-  padding: 0 calc(12px - var(--button-border-size)) 0 calc(8px - var(--button-border-size));
-}
-
-button.small.text-with-icon {
-  padding: 0 calc(9px - var(--button-border-size)) 0 calc(3px - var(--button-border-size));
-}
-
-button.only-icon {
-  padding: 0;
-}
-
-button devtools-icon {
-  width: calc(var(--button-width) - 4px);
-  height: calc(var(--button-height) - 4px);
-}
-
-.text-with-icon devtools-icon {
-  width: 20px;
-  height: 20px;
-  margin-right: 4px;
-}
-
-.primary-toolbar devtools-icon {
-  color: var(--icon-primary);
-}
-
-.primary devtools-icon {
-  color: var(--sys-color-cdt-base-container);
-}
-
-.tonal devtools-icon {
-  color: var(--sys-color-on-tonal-container);
-}
-
-.secondary devtools-icon {
-  color: var(--icon-primary);
-}
-
-.explicit-size devtools-icon {
-  width: unset;
-  height: unset;
-}
-
-button:disabled devtools-icon {
-  color: var(--icon-disabled);
-}
-
-.small.text-with-icon devtools-icon {
-  width: 16px;
-  height: 16px;
-  margin-right: 4px;
-}
-
-.toolbar.explicit-size devtools-icon,
-.round.explicit-size devtools-icon {
-  width: unset;
-  height: unset;
-}
-
-.toolbar.active devtools-icon,
-.toolbar:active devtools-icon {
-  color: var(--icon-toggled);
-}
-
-.primary-toolbar:active devtools-icon {
-  color: var(--icon-primary);
-}
-
-.toolbar:hover devtools-icon {
-  color: var(--icon-default-hover);
-}
-
-.primary-toolbar:hover devtools-icon {
-  color: var(--icon-primary);
-}
-
-.spinner-component.secondary {
-  border: 2px solid var(--sys-color-primary);
-  border-right-color: transparent;
-}
-
-.spinner-component.disabled {
-  border: 2px solid var(--sys-color-state-disabled);
-  border-right-color: transparent;
-}
-
-.spinner-component {
+.spinner {
   display: block;
   width: 12px;
   height: 12px;
@@ -296,6 +265,16 @@
   animation: spinner-animation 1s linear infinite;
   border-right-color: transparent;
   margin-right: 4px;
+
+  &.secondary {
+    border: 2px solid var(--sys-color-primary);
+    border-right-color: transparent;
+  }
+
+  &.disabled {
+    border: 2px solid var(--sys-color-state-disabled);
+    border-right-color: transparent;
+  }
 }
 
 @keyframes spinner-animation {