mirror of
https://github.com/bitwarden/browser
synced 2026-02-21 11:54:02 +00:00
update fully to spec
This commit is contained in:
@@ -17,6 +17,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import {
|
||||
AvatarDefaultColors,
|
||||
DIALOG_DATA,
|
||||
DialogConfig,
|
||||
DialogRef,
|
||||
@@ -48,18 +49,13 @@ export class ChangeAvatarDialogComponent implements OnInit, OnDestroy {
|
||||
|
||||
loading = false;
|
||||
|
||||
// change palette to new colors
|
||||
defaultColorPalette: NamedAvatarColor[] = [
|
||||
{ name: "brightBlue", color: "#16cbfc" },
|
||||
{ name: "green", color: "#94cc4b" },
|
||||
{ name: "orange", color: "#ffb520" },
|
||||
{ name: "lavender", color: "#e5beed" },
|
||||
{ name: "yellow", color: "#fcff41" },
|
||||
{ name: "indigo", color: "#acbdf7" },
|
||||
{ name: "teal", color: "#8ecdc5" },
|
||||
{ name: "salmon", color: "#ffa3a3" },
|
||||
{ name: "pink", color: "#ffa2d4" },
|
||||
];
|
||||
defaultColorPalette: NamedAvatarColor[] = AvatarDefaultColors.map((color) => {
|
||||
return {
|
||||
color,
|
||||
name: this.i18nService.t(color === "brand" ? "blue" : color),
|
||||
};
|
||||
});
|
||||
|
||||
customColorSelected = false;
|
||||
currentSelection: string;
|
||||
|
||||
@@ -79,9 +75,6 @@ export class ChangeAvatarDialogComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
//localize the default colors
|
||||
this.defaultColorPalette.forEach((c) => (c.name = this.i18nService.t(c.name)));
|
||||
|
||||
this.customColor$
|
||||
.pipe(debounceTime(200), takeUntil(this.destroy$))
|
||||
.subscribe((color: string | null) => {
|
||||
@@ -104,13 +97,12 @@ export class ChangeAvatarDialogComponent implements OnInit, OnDestroy {
|
||||
this.setSelection(this.customColor$.value);
|
||||
}
|
||||
|
||||
// does this get used anywhere?
|
||||
async generateAvatarColor() {
|
||||
Utils.stringToColor(this.profile.name.toString());
|
||||
}
|
||||
|
||||
submit = async () => {
|
||||
if (Utils.validateHexColor(this.currentSelection) || this.currentSelection == null) {
|
||||
const defaultColorSelected = AvatarDefaultColors.includes(this.currentSelection);
|
||||
const isValidHex = Utils.validateHexColor(this.currentSelection);
|
||||
const isValidSelection = this.currentSelection == null || defaultColorSelected || isValidHex;
|
||||
|
||||
if (isValidSelection) {
|
||||
await this.avatarService.setAvatarColor(this.currentSelection);
|
||||
this.dialogRef.close();
|
||||
this.toastService.showToast({
|
||||
|
||||
@@ -8221,6 +8221,15 @@
|
||||
"pink": {
|
||||
"message": "Pink"
|
||||
},
|
||||
"coral": {
|
||||
"message": "Coral"
|
||||
},
|
||||
"purple": {
|
||||
"message": "Purple"
|
||||
},
|
||||
"blue": {
|
||||
"message": "Blue"
|
||||
},
|
||||
"customColor": {
|
||||
"message": "Custom Color"
|
||||
},
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</bit-form-field>
|
||||
</div>
|
||||
<div class="tw-col-span-6">
|
||||
<bit-avatar [text]="provider.name" [id]="provider.id" size="2xlarge"></bit-avatar> // aaa
|
||||
<bit-avatar [text]="provider.name" [id]="provider.id" size="2xlarge"></bit-avatar>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" bitFormButton bitButton buttonType="primary">
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
x="50%"
|
||||
dy="0.35em"
|
||||
pointer-events="auto"
|
||||
[attr.fill]="textColor()"
|
||||
[class]="textColor()"
|
||||
[style.fontWeight]="svgFontWeight"
|
||||
[style.fontSize.px]="svgFontSize"
|
||||
[style.lineHeight.px]="16"
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { NgClass } from "@angular/common";
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
@@ -6,13 +5,18 @@ import {
|
||||
ElementRef,
|
||||
inject,
|
||||
input,
|
||||
signal,
|
||||
} from "@angular/core";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
import { AriaDisableDirective } from "../a11y";
|
||||
import { ariaDisableElement } from "../utils";
|
||||
|
||||
export type AvatarSizes = "2xlarge" | "xlarge" | "large" | "base" | "small";
|
||||
|
||||
export type AvatarColors = "teal" | "coral" | "brand" | "green" | "purple";
|
||||
export const AvatarDefaultColors = ["teal", "coral", "brand", "green", "purple"];
|
||||
export type AvatarColors = (typeof AvatarDefaultColors)[number];
|
||||
|
||||
const SizeClasses: Record<AvatarSizes, string[]> = {
|
||||
"2xlarge": ["tw-h-16", "tw-w-16", "tw-min-w-16"],
|
||||
@@ -42,15 +46,16 @@ export const DefaultAvatarColors: Record<AvatarColors, string> = {
|
||||
* dark mode.
|
||||
*/
|
||||
const DefaultAvatarHoverColors: Record<AvatarColors, string> = {
|
||||
teal: "group-hover/avatar:tw-bg-bg-avatar-teal-hover",
|
||||
coral: "group-hover/avatar:tw-bg-bg-avatar-coral-hover",
|
||||
brand: "group-hover/avatar:tw-bg-bg-avatar-brand-hover",
|
||||
green: "group-hover/avatar:tw-bg-bg-avatar-green-hover",
|
||||
purple: "group-hover/avatar:tw-bg-bg-avatar-purple-hover",
|
||||
teal: "tw-bg-bg-avatar-teal-hover",
|
||||
coral: "tw-bg-bg-avatar-coral-hover",
|
||||
brand: "tw-bg-bg-avatar-brand-hover",
|
||||
green: "tw-bg-bg-avatar-green-hover",
|
||||
purple: "tw-bg-bg-avatar-purple-hover",
|
||||
};
|
||||
|
||||
/**
|
||||
* Avatars display a background color that helps a user visually recognize their logged in account.
|
||||
* The avatar component is a visual representation of a user profile. Color variations help users
|
||||
* quickly identify the active account and differentiate between multiple accounts in a list.
|
||||
*
|
||||
* Color options include a pre-defined set of palette-approved colors, or users can select a
|
||||
* custom color. A variance in color across the avatar component is important as it is used in
|
||||
@@ -60,17 +65,19 @@ const DefaultAvatarHoverColors: Record<AvatarColors, string> = {
|
||||
* Avatars can be static or interactive.
|
||||
*/
|
||||
@Component({
|
||||
selector: "bit-avatar, button[bit-avatar], a[bit-avatar]",
|
||||
selector: "bit-avatar, button[bit-avatar]",
|
||||
templateUrl: "avatar.component.html",
|
||||
imports: [NgClass],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
host: {
|
||||
class: "tw-group/avatar",
|
||||
"(mouseenter)": "isHovering.set(true)",
|
||||
"(mouseleave)": "isHovering.set(false)",
|
||||
"[class]": "avatarClass()",
|
||||
},
|
||||
// host directive for aria disabled states? check figma for disabled styles
|
||||
hostDirectives: [AriaDisableDirective],
|
||||
})
|
||||
export class AvatarComponent {
|
||||
private el = inject(ElementRef);
|
||||
|
||||
/**
|
||||
* Background color for the avatar. Provide one of the AvatarColors, or a custom hex code.
|
||||
*
|
||||
@@ -100,21 +107,60 @@ export class AvatarComponent {
|
||||
*/
|
||||
readonly size = input<AvatarSizes>("base");
|
||||
|
||||
/**
|
||||
* For button element avatars, whether the button is disabled. No effect for non-button avatars
|
||||
*/
|
||||
readonly disabled = input<boolean>(false);
|
||||
|
||||
constructor() {
|
||||
ariaDisableElement(this.el.nativeElement, this.disabled);
|
||||
}
|
||||
|
||||
readonly showDisabledStyles = computed(() => {
|
||||
return this.isInteractive() && this.disabled();
|
||||
});
|
||||
|
||||
protected readonly svgCharCount = 2;
|
||||
protected readonly svgFontSize = 12;
|
||||
protected readonly svgFontWeight = 400;
|
||||
protected readonly svgSize = 32;
|
||||
|
||||
protected readonly svgClass = computed(() => {
|
||||
return ["tw-rounded-full", "tw-border-solid", this.backgroundColorClass()]
|
||||
.concat(SizeClasses[this.size()] ?? [])
|
||||
.concat(this.hasHoverEffects() ? this.interactiveSvgClasses() : []);
|
||||
protected readonly isInteractive = computed(() => {
|
||||
return this.el.nativeElement.nodeName === "BUTTON";
|
||||
});
|
||||
|
||||
protected readonly hasHoverEffects = computed(() => {
|
||||
return this.el.nativeElement.nodeName === "BUTTON" || this.el.nativeElement.nodeName === "A";
|
||||
protected readonly avatarClass = computed(() => {
|
||||
const classes = [
|
||||
"tw-leading-[0px]",
|
||||
"focus-visible:tw-outline-none",
|
||||
"tw-rounded-full",
|
||||
"focus-visible:tw-ring-2",
|
||||
"focus-visible:tw-ring-offset-1",
|
||||
"focus-visible:tw-ring-border-focus",
|
||||
"!focus-visible:tw-border-[transparent]",
|
||||
"focus-visible:tw-z-10",
|
||||
].concat(this.showDisabledStyles() ? ["tw-cursor-not-allowed"] : []);
|
||||
return classes;
|
||||
});
|
||||
|
||||
protected readonly svgClass = computed(() => {
|
||||
return ["tw-rounded-full"]
|
||||
.concat(SizeClasses[this.size()] ?? [])
|
||||
.concat(this.showDisabledStyles() ? ["tw-bg-bg-disabled"] : this.avatarBackgroundColor());
|
||||
});
|
||||
|
||||
/**
|
||||
* Manually track the hover state.
|
||||
*
|
||||
* We're doing this instead of using tailwind's hover helper selectors because we need to be able
|
||||
* to apply a darker color on hover for custom background colors, and we can't use tailwind for
|
||||
* the dynamic custom background colors due to limitations with how it generates styles at build
|
||||
* time
|
||||
*/
|
||||
protected readonly isHovering = signal(false);
|
||||
|
||||
protected readonly showHoverColor = computed(() => this.isInteractive() && this.isHovering());
|
||||
|
||||
protected readonly usingCustomColor = computed(() => {
|
||||
if (Utils.isNullOrWhitespace(this.color())) {
|
||||
return false;
|
||||
@@ -124,41 +170,70 @@ export class AvatarComponent {
|
||||
return !defaultColorKeys.includes(this.color() as AvatarColors);
|
||||
});
|
||||
|
||||
protected readonly customBackgroundColor = computed(() => {
|
||||
/**
|
||||
* Background color tailwind class
|
||||
*
|
||||
* Returns the appropriate class if using default avatar colors
|
||||
* Returns an empty string (a "blank" tailwind class) if using custom color
|
||||
*/
|
||||
protected readonly avatarBackgroundColor = computed(() => {
|
||||
// If using custom color instead of default avatar color, early exit
|
||||
if (this.usingCustomColor()) {
|
||||
return this.color()!;
|
||||
return "";
|
||||
}
|
||||
|
||||
return undefined;
|
||||
});
|
||||
|
||||
protected readonly backgroundColorClass = computed(() => {
|
||||
if (!this.usingCustomColor()) {
|
||||
return DefaultAvatarColors[(this.color() as AvatarColors) ?? this.avatarDefaultColorKey()];
|
||||
}
|
||||
|
||||
return "";
|
||||
});
|
||||
|
||||
protected readonly interactiveSvgClasses = computed(() => {
|
||||
if (!this.usingCustomColor()) {
|
||||
return [
|
||||
DefaultAvatarHoverColors[(this.color() as AvatarColors) ?? this.avatarDefaultColorKey()],
|
||||
if (this.showHoverColor()) {
|
||||
return DefaultAvatarHoverColors[
|
||||
(this.color() as AvatarColors) ?? this.avatarDefaultColorKey()
|
||||
];
|
||||
}
|
||||
|
||||
// awaiting design choice for custom color hover state
|
||||
return "";
|
||||
return DefaultAvatarColors[(this.color() as AvatarColors) ?? this.avatarDefaultColorKey()];
|
||||
});
|
||||
|
||||
/**
|
||||
* Background color hex code
|
||||
*
|
||||
* Returns the custom color if using a custom background color
|
||||
* Returns `undefined` if using a default avatar color
|
||||
*
|
||||
* Custom hexes need to be applied as a style property, because dynamic values can't be used in
|
||||
* tailwind arbitrary values due to limitations with how it generates tailwind styles at build
|
||||
* time
|
||||
*/
|
||||
protected readonly customBackgroundColor = computed(() => {
|
||||
/**
|
||||
* If using a default avatar color instead of custom color, early exit.
|
||||
* If button is disabled, we want to use a tailwind class instead, so also early exit
|
||||
*/
|
||||
if (!this.usingCustomColor() || this.showDisabledStyles()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (this.showHoverColor()) {
|
||||
// Drop the color's saturation and lightness by 10% when hovering
|
||||
return `hsl(from ${this.color()} h calc(s - 10) calc(l - 10))`;
|
||||
}
|
||||
|
||||
return this.color();
|
||||
});
|
||||
|
||||
/**
|
||||
* Text color class that satisfies accessible contrast requirements
|
||||
*/
|
||||
protected readonly textColor = computed(() => {
|
||||
if (this.showDisabledStyles()) {
|
||||
return "tw-fill-fg-disabled";
|
||||
}
|
||||
|
||||
const customBg = this.customBackgroundColor();
|
||||
let textColor = "white";
|
||||
|
||||
if (customBg) {
|
||||
return Utils.pickTextColorBasedOnBgColor(customBg, 135, true);
|
||||
} else {
|
||||
return "white";
|
||||
textColor = Utils.pickTextColorBasedOnBgColor(customBg, 135, true);
|
||||
}
|
||||
|
||||
return textColor === "white" ? "tw-fill-fg-white" : "tw-fill-fg-black";
|
||||
});
|
||||
|
||||
protected readonly displayChars = computed(() => {
|
||||
@@ -195,6 +270,12 @@ export class AvatarComponent {
|
||||
return characters != null ? characters.slice(0, count).join("") : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Deterministically chosen default avatar color
|
||||
*
|
||||
* Based on the id first and the text second, choose a color from AvatarColors. This ensures that
|
||||
* the user sees the same color for the same avatar input every time.
|
||||
*/
|
||||
readonly avatarDefaultColorKey = computed(() => {
|
||||
let magicString = "";
|
||||
const id = this.id();
|
||||
|
||||
@@ -14,52 +14,61 @@ import { AvatarModule } from "@bitwarden/components";
|
||||
<Primary />
|
||||
<Controls />
|
||||
|
||||
## Size
|
||||
## Static
|
||||
|
||||
### 2XLarge
|
||||
By default, the avatar component is non-interactive. Use the avatar component as an atom in a larger
|
||||
molecule like a list item, table, or card to help users differentiate between multiple accounts in a
|
||||
list.
|
||||
|
||||
<Canvas of={stories.XXLarge} />
|
||||
If the avatar is not a clickable element, there are no hover or focus states.
|
||||
|
||||
### XLarge
|
||||
## Interactive
|
||||
|
||||
<Canvas of={stories.XLarge} />
|
||||
The Avatar can be used as a button. Use the avatar component as a button to open a secondary menu
|
||||
like an account switcher or dropdown.
|
||||
|
||||
### Large
|
||||
When the avatar is used as a button, there are hover and focus states for accessibility. Although it
|
||||
is rare for an avatar button to be inactive, this state is supported as well.
|
||||
|
||||
<Canvas of={stories.Large} />
|
||||
<Canvas of={stories.Interactive} />
|
||||
|
||||
### Base
|
||||
### Inactive
|
||||
|
||||
<Canvas of={stories.Default} />
|
||||
<Canvas of={stories.Inactive} />
|
||||
|
||||
### Small
|
||||
## Sizes
|
||||
|
||||
<Canvas of={stories.Small} />
|
||||
There are multiple sizes available for the Avatar:
|
||||
`"2xlarge" | "xlarge" | "large" | "base" | "small"`
|
||||
|
||||
## Background color
|
||||
<Canvas of={stories.Sizes} />
|
||||
|
||||
The Background color can be set 3 ways. The color is generated using the following order of
|
||||
priority:
|
||||
## Color
|
||||
|
||||
- Color
|
||||
- ID
|
||||
- Text, usually set to the user's Name field
|
||||
The avatar color can be set 3 ways. The color is generated using the following order of priority:
|
||||
|
||||
| Method | Input | Accepted inputs |
|
||||
| -------------- | ------- | ----------------------------------------------------------------------------------- |
|
||||
| Default colors | `color` | `"teal" \| "coral" \| "brand" \| "green" \| "purple"` |
|
||||
| Custom color | `color` | Css colors like a hex code |
|
||||
| ID | `id` | Unique string identifier |
|
||||
| Text | `text` | String whose first letters are displayed inside the avatar, usually the user's name |
|
||||
|
||||
### Default colors
|
||||
|
||||
<Canvas of={stories.DefaultColors} />
|
||||
|
||||
### Custom color
|
||||
|
||||
<Canvas of={stories.CustomColor} />
|
||||
|
||||
### Color by ID
|
||||
|
||||
<Canvas of={stories.ColorByText} />
|
||||
Use the user 'ID' field if `Name` is not defined.
|
||||
<Canvas of={stories.ColorByID} />
|
||||
|
||||
## Avatar as a button
|
||||
### Color by Text
|
||||
|
||||
The Avatar can be used as a button.
|
||||
|
||||
Typically this is only in the navigation on client apps where account switching is used and in the
|
||||
web app for the account menu indicator.
|
||||
|
||||
When the avatar is used as a button, the following states should be used:
|
||||
|
||||
`TODO:` [Jira add stories](https://bitwarden.atlassian.net/browse/CL-101) for button avatars.
|
||||
[See Figma](https://www.figma.com/file/Zt3YSeb6E6lebAffrNLa0h/Tailwind-Component-Library?type=design&node-id=9730-31746&mode=design&t=IjDIHDb6FZl6bUQW-4)
|
||||
<Canvas of={stories.ColorByText} />
|
||||
|
||||
## Accessibility
|
||||
|
||||
|
||||
@@ -36,56 +36,7 @@ export const Default: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const XXLarge: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
size: "2xlarge",
|
||||
},
|
||||
};
|
||||
|
||||
export const XLarge: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
size: "xlarge",
|
||||
},
|
||||
};
|
||||
|
||||
export const Large: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
size: "large",
|
||||
},
|
||||
};
|
||||
|
||||
export const Small: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
size: "small",
|
||||
},
|
||||
};
|
||||
|
||||
export const ColorByID: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
id: "236478",
|
||||
},
|
||||
};
|
||||
|
||||
export const ColorByText: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
text: "Jason Doe",
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomColor: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
color: "#fbd9ff",
|
||||
},
|
||||
};
|
||||
|
||||
export const Button: Story = {
|
||||
export const Interactive: Story = {
|
||||
render: (args) => {
|
||||
return {
|
||||
props: args,
|
||||
@@ -99,9 +50,129 @@ export const Button: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
// color by text or id button story?
|
||||
export const Sizes: Story = {
|
||||
render: (args) => {
|
||||
return {
|
||||
props: args,
|
||||
template: `
|
||||
<span class="tw-font-bold">Static</span>
|
||||
<div class="tw-flex tw-gap-4 tw-mb-10">
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> small </span>
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'small'"></bit-avatar>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> base </span>
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> large </span>
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'large'"></bit-avatar>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> xlarge </span>
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'xlarge'"></bit-avatar>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> 2xlarge </span>
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'2xlarge'"></bit-avatar>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
export const CustomColorButton: Story = {
|
||||
<span class="tw-font-bold">Interactive</span>
|
||||
<div class="tw-flex tw-gap-4 tw-mb-10">
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> small </span>
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'small'"></button>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> base </span>
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'"></button>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> large </span>
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'large'"></button>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> xlarge </span>
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'xlarge'"></button>
|
||||
</div>
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span> 2xlarge </span>
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'" [size]="'2xlarge'"></button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const DefaultColors: Story = {
|
||||
render: (args) => {
|
||||
return {
|
||||
props: args,
|
||||
template: `
|
||||
<span class="tw-font-bold">Static</span>
|
||||
<div class="tw-flex tw-gap-2 tw-mb-10">
|
||||
<bit-avatar [color]="'brand'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
<bit-avatar [color]="'teal'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
<bit-avatar [color]="'coral'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
<bit-avatar [color]="'green'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
<bit-avatar [color]="'purple'" [text]="'Walt Walterson'"></bit-avatar>
|
||||
</div>
|
||||
|
||||
<span class="tw-font-bold">Interactive</span>
|
||||
<div class="tw-flex tw-gap-2">
|
||||
<button bit-avatar [color]="'brand'" [text]="'Walt Walterson'"></button>
|
||||
<button bit-avatar [color]="'teal'" [text]="'Walt Walterson'"></button>
|
||||
<button bit-avatar [color]="'coral'" [text]="'Walt Walterson'"></button>
|
||||
<button bit-avatar [color]="'green'" [text]="'Walt Walterson'"></button>
|
||||
<button bit-avatar [color]="'purple'" [text]="'Walt Walterson'"></button>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
},
|
||||
};
|
||||
|
||||
export const ColorByID: Story = {
|
||||
render: (args) => {
|
||||
return {
|
||||
props: args,
|
||||
template: `
|
||||
<div class="tw-flex tw-gap-4">
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span class="tw-font-bold"> Static </span>
|
||||
<bit-avatar ${formatArgsForCodeSnippet<AvatarComponent>(args)}></bit-avatar>
|
||||
</div>
|
||||
|
||||
<div class="tw-flex tw-flex-col tw-gap-2 tw-items-center">
|
||||
<span class="tw-font-bold"> Interactive </span>
|
||||
<button bit-avatar ${formatArgsForCodeSnippet<AvatarComponent>(args)}></button>
|
||||
</div>
|
||||
</div>
|
||||
`,
|
||||
};
|
||||
},
|
||||
args: {
|
||||
id: "236478",
|
||||
},
|
||||
};
|
||||
|
||||
export const ColorByText: Story = {
|
||||
...ColorByID,
|
||||
args: {
|
||||
text: "Jason Doe",
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomColor: Story = {
|
||||
...ColorByID,
|
||||
args: {
|
||||
color: "#fbd9fe",
|
||||
},
|
||||
};
|
||||
|
||||
export const Inactive: Story = {
|
||||
render: (args) => {
|
||||
return {
|
||||
props: args,
|
||||
@@ -111,6 +182,6 @@ export const CustomColorButton: Story = {
|
||||
};
|
||||
},
|
||||
args: {
|
||||
color: "#fbd9ff",
|
||||
disabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user