1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-19 09:43:23 +00:00

[CL-390] - Spotlight Component (#14085)

* WIP spotlight and onboarding nudge

* finalize spotlight component

* finalize spotlight component

* revert changes

* re-add changes

* re-add frozen prop

* add documentation

* move to vault

* update to vault

* small css fixes to spotlight

* smaller button

* fix height for non-button

* remove unecessary class

* clean up styling

* more style cleanup

* favor gap instead of mt
This commit is contained in:
Jordan Aasen
2025-04-02 16:15:59 -07:00
committed by GitHub
parent e73a6fb16d
commit bd490e3af9
3 changed files with 146 additions and 0 deletions

View File

@@ -0,0 +1,34 @@
<div
class="tw-rounded-2xl tw-bg-primary-100 tw-border-primary-600 tw-border-solid tw-border tw-p-4 tw-pt-3 tw-flex tw-flex-col tw-gap-2"
>
<div class="tw-flex tw-justify-between tw-items-start tw-flex-grow">
<div>
<h2 bitTypography="h4" class="tw-font-semibold !tw-mb-1">{{ title }}</h2>
<p class="tw-text-main tw-mb-0" bitTypography="body2">
{{ subtitle }}
</p>
</div>
<button
type="button"
bitIconButton="bwi-close"
size="small"
*ngIf="!persistent"
(click)="handleDismiss()"
[attr.title]="'close' | i18n"
[attr.aria-label]="'close' | i18n"
></button>
</div>
<button
class="tw-w-full"
bitButton
type="button"
buttonType="primary"
*ngIf="buttonText"
(click)="handleButtonClick()"
>
{{ buttonText }}
</button>
<ng-content></ng-content>
</div>

View File

@@ -0,0 +1,32 @@
import { CommonModule } from "@angular/common";
import { Component, EventEmitter, Input, Output } from "@angular/core";
import { ButtonModule, IconButtonModule, TypographyModule } from "@bitwarden/components";
import { I18nPipe } from "@bitwarden/ui-common";
@Component({
selector: "bit-spotlight",
templateUrl: "spotlight.component.html",
standalone: true,
imports: [ButtonModule, CommonModule, IconButtonModule, I18nPipe, TypographyModule],
})
export class SpotlightComponent {
// The title of the component
@Input({ required: true }) title: string | null = null;
// The subtitle of the component
@Input({ required: true }) subtitle: string | null = null;
// The text to display on the button
@Input() buttonText?: string;
// Wheter the component can be dismissed, if true, the component will not show a close button
@Input() persistent = false;
@Output() onDismiss = new EventEmitter<void>();
@Output() onButtonClick = new EventEmitter<void>();
handleButtonClick(): void {
this.onButtonClick.emit();
}
handleDismiss(): void {
this.onDismiss.emit();
}
}

View File

@@ -0,0 +1,80 @@
import { moduleMetadata, Meta, StoryObj } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import {
ButtonModule,
I18nMockService,
IconButtonModule,
TypographyModule,
} from "@bitwarden/components";
import { SpotlightComponent } from "./spotlight.component";
const meta: Meta<SpotlightComponent> = {
title: "Vault/Spotlight",
component: SpotlightComponent,
decorators: [
moduleMetadata({
imports: [ButtonModule, IconButtonModule, TypographyModule],
providers: [
{
provide: I18nService,
useFactory: () => {
return new I18nMockService({
close: "Close",
});
},
},
],
}),
],
args: {
title: "Primary",
subtitle: "Callout Text",
buttonText: "Button",
},
};
export default meta;
type Story = StoryObj<SpotlightComponent>;
export const Default: Story = {};
export const WithoutButton: Story = {
args: {
buttonText: undefined,
},
};
export const Persistent: Story = {
args: {
persistent: true,
},
};
export const WithCustomButton: Story = {
args: {
buttonText: "Custom Button",
},
render: (args) => ({
props: args,
template: `
<bit-spotlight
[title]="title"
[subtitle]="subtitle"
>
<button
class="tw-w-full"
bit-item-content
bitButton
type="button"
buttonType="primary"
(click)="handleButtonClick()"
>
External Link
<i slot="end" class="bwi bwi-external-link ml-2" aria-hidden="true"></i>
</button>
</bit-spotlight>
`,
}),
};