mirror of
https://github.com/bitwarden/browser
synced 2025-12-11 13:53:34 +00:00
add small button variant (#14326)
* adds small button size variant * makes small icon button same size as small button * testing small button for extension header * remove extension changes * update popout layout story * revert change to small icon button padding * add whitespace to see if error resolves * default buttonType to primary * default buttonType to secondary * add comment around why nonNullButtonSize value exists * add comment to property about using the non null version * Update apps/browser/src/platform/popup/layout/popup-layout.stories.ts Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com> * updated input syntax when using static values * remove nonNull value coersion * allow changing of size input in Story --------- Co-authored-by: Oscar Hinton <Hinton@users.noreply.github.com>
This commit is contained in:
@@ -80,7 +80,7 @@ class VaultComponent {
|
|||||||
@Component({
|
@Component({
|
||||||
selector: "mock-add-button",
|
selector: "mock-add-button",
|
||||||
template: `
|
template: `
|
||||||
<button bitButton buttonType="primary" type="button">
|
<button bitButton size="small" buttonType="primary" type="button">
|
||||||
<i class="bwi bwi-plus-f" aria-hidden="true"></i>
|
<i class="bwi bwi-plus-f" aria-hidden="true"></i>
|
||||||
Add
|
Add
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
// FIXME: Update this file to be type safe and remove this and next line
|
|
||||||
// @ts-strict-ignore
|
|
||||||
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
import { coerceBooleanProperty } from "@angular/cdk/coercion";
|
||||||
import { NgClass } from "@angular/common";
|
import { NgClass } from "@angular/common";
|
||||||
import { Input, HostBinding, Component, model, computed } from "@angular/core";
|
import { Input, HostBinding, Component, model, computed, input } from "@angular/core";
|
||||||
import { toObservable, toSignal } from "@angular/core/rxjs-interop";
|
import { toObservable, toSignal } from "@angular/core/rxjs-interop";
|
||||||
import { debounce, interval } from "rxjs";
|
import { debounce, interval } from "rxjs";
|
||||||
|
|
||||||
import { ButtonLikeAbstraction, ButtonType } from "../shared/button-like.abstraction";
|
import { ButtonLikeAbstraction, ButtonType, ButtonSize } from "../shared/button-like.abstraction";
|
||||||
|
|
||||||
const focusRing = [
|
const focusRing = [
|
||||||
"focus-visible:tw-ring-2",
|
"focus-visible:tw-ring-2",
|
||||||
@@ -15,6 +13,11 @@ const focusRing = [
|
|||||||
"focus-visible:tw-z-10",
|
"focus-visible:tw-z-10",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const buttonSizeStyles: Record<ButtonSize, string[]> = {
|
||||||
|
small: ["tw-py-1", "tw-px-3", "tw-text-sm"],
|
||||||
|
default: ["tw-py-1.5", "tw-px-3"],
|
||||||
|
};
|
||||||
|
|
||||||
const buttonStyles: Record<ButtonType, string[]> = {
|
const buttonStyles: Record<ButtonType, string[]> = {
|
||||||
primary: [
|
primary: [
|
||||||
"tw-border-primary-600",
|
"tw-border-primary-600",
|
||||||
@@ -59,8 +62,6 @@ export class ButtonComponent implements ButtonLikeAbstraction {
|
|||||||
@HostBinding("class") get classList() {
|
@HostBinding("class") get classList() {
|
||||||
return [
|
return [
|
||||||
"tw-font-semibold",
|
"tw-font-semibold",
|
||||||
"tw-py-1.5",
|
|
||||||
"tw-px-3",
|
|
||||||
"tw-rounded-full",
|
"tw-rounded-full",
|
||||||
"tw-transition",
|
"tw-transition",
|
||||||
"tw-border-2",
|
"tw-border-2",
|
||||||
@@ -85,7 +86,8 @@ export class ButtonComponent implements ButtonLikeAbstraction {
|
|||||||
"disabled:hover:tw-no-underline",
|
"disabled:hover:tw-no-underline",
|
||||||
]
|
]
|
||||||
: [],
|
: [],
|
||||||
);
|
)
|
||||||
|
.concat(buttonSizeStyles[this.size() || "default"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected disabledAttr = computed(() => {
|
protected disabledAttr = computed(() => {
|
||||||
@@ -105,7 +107,9 @@ export class ButtonComponent implements ButtonLikeAbstraction {
|
|||||||
return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false);
|
return this.showLoadingStyle() || (this.disabledAttr() && this.loading() === false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@Input() buttonType: ButtonType;
|
@Input() buttonType: ButtonType = "secondary";
|
||||||
|
|
||||||
|
size = input<ButtonSize>("default");
|
||||||
|
|
||||||
private _block = false;
|
private _block = false;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ export default {
|
|||||||
buttonType: "primary",
|
buttonType: "primary",
|
||||||
disabled: false,
|
disabled: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
size: {
|
||||||
|
options: ["small", "default"],
|
||||||
|
control: { type: "radio" },
|
||||||
|
},
|
||||||
},
|
},
|
||||||
parameters: {
|
parameters: {
|
||||||
design: {
|
design: {
|
||||||
@@ -24,19 +31,19 @@ export const Primary: Story = {
|
|||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
props: args,
|
props: args,
|
||||||
template: /*html*/ `
|
template: /*html*/ `
|
||||||
<div class="tw-flex tw-gap-4 tw-mb-6">
|
<div class="tw-flex tw-gap-4 tw-mb-6 tw-items-center">
|
||||||
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block">Button</button>
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [size]="size" [block]="block">Button</button>
|
||||||
<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" [size]="size" [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" [size]="size" [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" [size]="size" [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>
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [size]="size" [block]="block" class="tw-test-active">Button:active</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="tw-flex tw-gap-4">
|
<div class="tw-flex tw-gap-4 tw-items-center">
|
||||||
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [block]="block">Anchor</a>
|
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [size]="size" [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" [size]="size" [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" [size]="size" [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" [size]="size" [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>
|
<a href="#" bitButton [disabled]="disabled" [loading]="loading" [buttonType]="buttonType" [size]="size" [block]="block" class="tw-test-active">Anchor:active</a>
|
||||||
</div>
|
</div>
|
||||||
`,
|
`,
|
||||||
}),
|
}),
|
||||||
@@ -59,6 +66,22 @@ export const Danger: Story = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const Small: Story = {
|
||||||
|
render: (args) => ({
|
||||||
|
props: args,
|
||||||
|
template: /*html*/ `
|
||||||
|
<div class="tw-flex tw-gap-4 tw-mb-6 tw-items-center">
|
||||||
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="'primary'" [size]="size" [block]="block">Primary small</button>
|
||||||
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="'secondary'" [size]="size" [block]="block">Secondary small</button>
|
||||||
|
<button bitButton [disabled]="disabled" [loading]="loading" [buttonType]="'danger'" [size]="size" [block]="block">Danger small</button>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
}),
|
||||||
|
args: {
|
||||||
|
size: "small",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
export const Loading: Story = {
|
export const Loading: Story = {
|
||||||
render: (args) => ({
|
render: (args) => ({
|
||||||
props: args,
|
props: args,
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import { ModelSignal } from "@angular/core";
|
|||||||
// @ts-strict-ignore
|
// @ts-strict-ignore
|
||||||
export type ButtonType = "primary" | "secondary" | "danger" | "unstyled";
|
export type ButtonType = "primary" | "secondary" | "danger" | "unstyled";
|
||||||
|
|
||||||
|
export type ButtonSize = "default" | "small";
|
||||||
|
|
||||||
export abstract class ButtonLikeAbstraction {
|
export abstract class ButtonLikeAbstraction {
|
||||||
loading: ModelSignal<boolean>;
|
loading: ModelSignal<boolean>;
|
||||||
disabled: ModelSignal<boolean>;
|
disabled: ModelSignal<boolean>;
|
||||||
|
|||||||
Reference in New Issue
Block a user