mirror of
https://github.com/bitwarden/browser
synced 2026-02-13 06:54:07 +00:00
[CL-230] [CL-296] Update button styles (#9345)
Co-authored-by: Will Martin <contact@willmartian.com>
This commit is contained in:
@@ -27,57 +27,6 @@ describe("Button", () => {
|
||||
linkDebugElement = fixture.debugElement.query(By.css("a"));
|
||||
}));
|
||||
|
||||
it("should apply classes based on type", () => {
|
||||
testAppComponent.buttonType = "primary";
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-bg-primary-600")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-bg-primary-600")).toBe(true);
|
||||
|
||||
testAppComponent.buttonType = "secondary";
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true);
|
||||
|
||||
testAppComponent.buttonType = "danger";
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-border-danger-600")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-border-danger-600")).toBe(true);
|
||||
|
||||
testAppComponent.buttonType = "unstyled";
|
||||
fixture.detectChanges();
|
||||
expect(
|
||||
Array.from(buttonDebugElement.nativeElement.classList).some((klass: string) =>
|
||||
klass.startsWith("tw-bg"),
|
||||
),
|
||||
).toBe(false);
|
||||
expect(
|
||||
Array.from(linkDebugElement.nativeElement.classList).some((klass: string) =>
|
||||
klass.startsWith("tw-bg"),
|
||||
),
|
||||
).toBe(false);
|
||||
|
||||
testAppComponent.buttonType = null;
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-border-text-muted")).toBe(true);
|
||||
});
|
||||
|
||||
it("should apply block when true and inline-block when false", () => {
|
||||
testAppComponent.block = true;
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(true);
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(false);
|
||||
|
||||
testAppComponent.block = false;
|
||||
fixture.detectChanges();
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-inline-block")).toBe(true);
|
||||
expect(buttonDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
|
||||
expect(linkDebugElement.nativeElement.classList.contains("tw-block")).toBe(false);
|
||||
});
|
||||
|
||||
it("should not be disabled when loading and disabled are false", () => {
|
||||
testAppComponent.loading = false;
|
||||
testAppComponent.disabled = false;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstrac
|
||||
const focusRing = [
|
||||
"focus-visible:tw-ring",
|
||||
"focus-visible:tw-ring-offset-2",
|
||||
"focus-visible:tw-ring-primary-700",
|
||||
"focus-visible:tw-ring-primary-500",
|
||||
"focus-visible:tw-z-10",
|
||||
];
|
||||
|
||||
@@ -17,37 +17,24 @@ const buttonStyles: Record<ButtonType, string[]> = {
|
||||
"!tw-text-contrast",
|
||||
"hover:tw-bg-primary-700",
|
||||
"hover:tw-border-primary-700",
|
||||
"disabled:tw-bg-primary-600/60",
|
||||
"disabled:tw-border-primary-600/60",
|
||||
"disabled:!tw-text-contrast/60",
|
||||
"disabled:tw-bg-clip-padding",
|
||||
"disabled:tw-cursor-not-allowed",
|
||||
...focusRing,
|
||||
],
|
||||
secondary: [
|
||||
"tw-bg-transparent",
|
||||
"tw-border-text-muted",
|
||||
"!tw-text-muted",
|
||||
"hover:tw-bg-text-muted",
|
||||
"hover:tw-border-text-muted",
|
||||
"hover:!tw-text-contrast",
|
||||
"disabled:tw-bg-transparent",
|
||||
"disabled:tw-border-text-muted/60",
|
||||
"disabled:!tw-text-muted/60",
|
||||
"disabled:tw-cursor-not-allowed",
|
||||
"tw-border-primary-600",
|
||||
"!tw-text-primary-600",
|
||||
"hover:tw-bg-transparent",
|
||||
"hover:tw-border-primary-700",
|
||||
"hover:!tw-text-primary-700",
|
||||
...focusRing,
|
||||
],
|
||||
danger: [
|
||||
"tw-bg-transparent",
|
||||
"tw-border-danger-600",
|
||||
"!tw-text-danger",
|
||||
"hover:tw-bg-danger-600",
|
||||
"hover:tw-border-danger-600",
|
||||
"hover:!tw-text-contrast",
|
||||
"disabled:tw-bg-transparent",
|
||||
"disabled:tw-border-danger-600/60",
|
||||
"disabled:!tw-text-danger/60",
|
||||
"disabled:tw-cursor-not-allowed",
|
||||
"hover:tw-bg-transparent",
|
||||
"hover:tw-border-danger-700",
|
||||
"hover:!tw-text-danger-700",
|
||||
...focusRing,
|
||||
],
|
||||
unstyled: [],
|
||||
@@ -64,14 +51,22 @@ export class ButtonComponent implements ButtonLikeAbstraction {
|
||||
"tw-font-semibold",
|
||||
"tw-py-1.5",
|
||||
"tw-px-3",
|
||||
"tw-rounded",
|
||||
"tw-rounded-full",
|
||||
"tw-transition",
|
||||
"tw-border",
|
||||
"tw-border-2",
|
||||
"tw-border-solid",
|
||||
"tw-text-center",
|
||||
"tw-no-underline",
|
||||
"hover:tw-no-underline",
|
||||
"hover:tw-underline",
|
||||
"focus:tw-outline-none",
|
||||
"disabled:tw-bg-secondary-300",
|
||||
"disabled:hover:tw-bg-secondary-300",
|
||||
"disabled:tw-border-secondary-300",
|
||||
"disabled:hover:tw-border-secondary-300",
|
||||
"disabled:!tw-text-muted",
|
||||
"disabled:hover:!tw-text-muted",
|
||||
"disabled:tw-cursor-not-allowed",
|
||||
"disabled:hover:tw-no-underline",
|
||||
]
|
||||
.concat(this.block ? ["tw-w-full", "tw-block"] : ["tw-inline-block"])
|
||||
.concat(buttonStyles[this.buttonType ?? "secondary"]);
|
||||
|
||||
@@ -60,9 +60,6 @@ Use the danger styling only in settings when the user may preform a permanent ac
|
||||
|
||||
## Disabled UI
|
||||
|
||||
Both the disabled and loading states use the default state’s color with a 60% opacity or
|
||||
`tw-opacity-60`.
|
||||
|
||||
<Story of={stories.Disabled} />
|
||||
|
||||
## Block
|
||||
|
||||
@@ -23,9 +23,21 @@ type Story = StoryObj<ButtonComponent>;
|
||||
export const Primary: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `
|
||||
template: /*html*/ `
|
||||
<div class="tw-flex tw-gap-4 tw-mb-6">
|
||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block">Button</button>
|
||||
<a bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" href="#" class="tw-ml-2">Link</a>
|
||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-hover">Button:hover</button>
|
||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-focus-visible">Button:focus-visible</button>
|
||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-hover tw-test-focus-visible">Button:hover:focus-visible</button>
|
||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-active">Button:active</button>
|
||||
</div>
|
||||
<div class="tw-flex tw-gap-4">
|
||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block">Anchor</a>
|
||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-hover">Anchor:hover</a>
|
||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-focus-visible">Anchor:focus-visible</a>
|
||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-hover tw-test-focus-visible">Anchor:hover:focus-visible</a>
|
||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block" class="tw-test-active">Anchor:active</a>
|
||||
</div>
|
||||
`,
|
||||
}),
|
||||
args: {
|
||||
|
||||
@@ -77,7 +77,11 @@ module.exports = {
|
||||
alt2: rgba("--color-text-alt2"),
|
||||
code: rgba("--color-text-code"),
|
||||
success: rgba("--color-success-600"),
|
||||
danger: rgba("--color-danger-600"),
|
||||
danger: {
|
||||
DEFAULT: rgba("--color-danger-600"),
|
||||
600: rgba("--color-danger-600"),
|
||||
700: rgba("--color-danger-700"),
|
||||
},
|
||||
warning: rgba("--color-warning-600"),
|
||||
info: rgba("--color-info-600"),
|
||||
primary: {
|
||||
@@ -124,5 +128,18 @@ module.exports = {
|
||||
{},
|
||||
);
|
||||
}),
|
||||
plugin(function ({ addVariant }) {
|
||||
for (const state of [
|
||||
"active",
|
||||
"hover",
|
||||
"focus",
|
||||
"focus-within",
|
||||
"focus-visible",
|
||||
"target",
|
||||
"visited",
|
||||
]) {
|
||||
addVariant(state, [`&:${state}`, `&.test-${state}`]);
|
||||
}
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user