mirror of
https://github.com/bitwarden/browser
synced 2026-02-11 22:13:32 +00:00
Merge branch 'master' into PM-2014-passkey-registration
This commit is contained in:
@@ -5,9 +5,9 @@ import { Directive, HostBinding, HostListener, Input, Optional } from "@angular/
|
||||
selector: "[bitDialogClose]",
|
||||
})
|
||||
export class DialogCloseDirective {
|
||||
@Input("bit-dialog-close") dialogResult: any;
|
||||
@Input("bitDialogClose") dialogResult: any;
|
||||
|
||||
constructor(@Optional() public dialogRef: DialogRef<any>) {}
|
||||
constructor(@Optional() public dialogRef: DialogRef) {}
|
||||
|
||||
@HostBinding("attr.disabled")
|
||||
get disableClose() {
|
||||
|
||||
@@ -24,7 +24,7 @@ export default {
|
||||
required: "required",
|
||||
inputRequired: "Input is required.",
|
||||
inputEmail: "Input is not an email-address.",
|
||||
fieldsNeedAttention: "$COUNT$ field(s) above need your attention.",
|
||||
fieldsNeedAttention: "__$1__ field(s) above need your attention.",
|
||||
});
|
||||
},
|
||||
},
|
||||
@@ -63,12 +63,12 @@ export const Default: StoryObj<BitFormFieldComponent> = {
|
||||
<bit-label>Name</bit-label>
|
||||
<input bitInput formControlName="name" />
|
||||
</bit-form-field>
|
||||
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>Email</bit-label>
|
||||
<input bitInput formControlName="email" />
|
||||
</bit-form-field>
|
||||
|
||||
|
||||
<button type="submit" bitButton buttonType="primary">Submit</button>
|
||||
<bit-error-summary [formGroup]="formObj"></bit-error-summary>
|
||||
</form>
|
||||
|
||||
@@ -6,7 +6,9 @@ export type InputTypes =
|
||||
| "email"
|
||||
| "checkbox"
|
||||
| "search"
|
||||
| "file";
|
||||
| "file"
|
||||
| "date"
|
||||
| "time";
|
||||
|
||||
export abstract class BitFormFieldControl {
|
||||
ariaDescribedBy: string;
|
||||
|
||||
@@ -157,6 +157,24 @@ export const Disabled: Story = {
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const Readonly: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: `
|
||||
<bit-form-field>
|
||||
<bit-label>Input</bit-label>
|
||||
<input bitInput value="Foobar" readonly />
|
||||
</bit-form-field>
|
||||
|
||||
<bit-form-field>
|
||||
<bit-label>Textarea</bit-label>
|
||||
<textarea bitInput rows="4" readonly>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</textarea>
|
||||
</bit-form-field>
|
||||
`,
|
||||
}),
|
||||
args: {},
|
||||
};
|
||||
|
||||
export const InputGroup: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
|
||||
@@ -13,6 +13,7 @@ export * from "./form-field";
|
||||
export * from "./icon-button";
|
||||
export * from "./icon";
|
||||
export * from "./input";
|
||||
export * from "./layout";
|
||||
export * from "./link";
|
||||
export * from "./menu";
|
||||
export * from "./multi-select";
|
||||
|
||||
@@ -44,6 +44,7 @@ export class BitInputDirective implements BitFormFieldControl {
|
||||
"focus:tw-ring-primary-700",
|
||||
"focus:tw-z-10",
|
||||
"disabled:tw-bg-secondary-100",
|
||||
"[&:is(input,textarea):read-only]:tw-bg-secondary-100",
|
||||
].filter((s) => s != "");
|
||||
}
|
||||
|
||||
|
||||
1
libs/components/src/layout/index.ts
Normal file
1
libs/components/src/layout/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from "./layout.component";
|
||||
10
libs/components/src/layout/layout.component.html
Normal file
10
libs/components/src/layout/layout.component.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="tw-flex tw-w-full">
|
||||
<aside
|
||||
class="tw-fixed tw-inset-y-0 tw-left-0 tw-h-screen tw-w-60 tw-overflow-auto tw-bg-background-alt3"
|
||||
>
|
||||
<ng-content select="[slot=sidebar]"></ng-content>
|
||||
</aside>
|
||||
<main class="tw-ml-60 tw-min-h-screen tw-min-w-0 tw-flex-1 tw-bg-background tw-p-6">
|
||||
<ng-content></ng-content>
|
||||
</main>
|
||||
</div>
|
||||
9
libs/components/src/layout/layout.component.ts
Normal file
9
libs/components/src/layout/layout.component.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "bit-layout",
|
||||
templateUrl: "layout.component.html",
|
||||
standalone: true,
|
||||
imports: [],
|
||||
})
|
||||
export class LayoutComponent {}
|
||||
64
libs/components/src/layout/layout.stories.ts
Normal file
64
libs/components/src/layout/layout.stories.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import { RouterTestingModule } from "@angular/router/testing";
|
||||
import { Meta, StoryObj, componentWrapperDecorator, moduleMetadata } from "@storybook/angular";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
|
||||
import { CalloutModule } from "../callout";
|
||||
import { NavigationModule } from "../navigation";
|
||||
import { I18nMockService } from "../utils/i18n-mock.service";
|
||||
|
||||
import { LayoutComponent } from "./layout.component";
|
||||
|
||||
export default {
|
||||
title: "Component Library/Layout",
|
||||
component: LayoutComponent,
|
||||
decorators: [
|
||||
componentWrapperDecorator(
|
||||
/**
|
||||
* Applying a CSS transform makes a `position: fixed` element act like it is `position: relative`
|
||||
* https://github.com/storybookjs/storybook/issues/8011#issue-490251969
|
||||
*/
|
||||
(story) => /* HTML */ `<div class="tw-scale-100 tw-border-2 tw-border-solid tw-border-[red]">
|
||||
${story}
|
||||
</div>`
|
||||
),
|
||||
moduleMetadata({
|
||||
imports: [NavigationModule, RouterTestingModule, CalloutModule],
|
||||
providers: [
|
||||
{
|
||||
provide: I18nService,
|
||||
useFactory: () => {
|
||||
return new I18nMockService({});
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
],
|
||||
} as Meta;
|
||||
|
||||
type Story = StoryObj<LayoutComponent>;
|
||||
|
||||
export const Empty: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: /* HTML */ `<bit-layout></bit-layout>`,
|
||||
}),
|
||||
};
|
||||
|
||||
export const WithContent: Story = {
|
||||
render: (args) => ({
|
||||
props: args,
|
||||
template: /* HTML */ `
|
||||
<bit-layout>
|
||||
<nav slot="sidebar">
|
||||
<bit-nav-item text="Item A" icon="bwi-collection"></bit-nav-item>
|
||||
<bit-nav-item text="Item B" icon="bwi-collection"></bit-nav-item>
|
||||
<bit-nav-divider></bit-nav-divider>
|
||||
<bit-nav-item text="Item C" icon="bwi-collection"></bit-nav-item>
|
||||
<bit-nav-item text="Item D" icon="bwi-collection"></bit-nav-item>
|
||||
</nav>
|
||||
<bit-callout title="Foobar"> Hello world! </bit-callout>
|
||||
</bit-layout>
|
||||
`,
|
||||
}),
|
||||
};
|
||||
@@ -58,7 +58,6 @@ const commonStyles = [
|
||||
"before:tw-rounded-md",
|
||||
"before:tw-transition",
|
||||
"focus-visible:before:tw-ring-2",
|
||||
"focus-visible:before:tw-ring-text-contrast",
|
||||
"focus-visible:tw-z-10",
|
||||
];
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
notFoundText="{{ 'multiSelectNotFound' | i18n }}"
|
||||
clearAllText="{{ 'multiSelectClearAll' | i18n }}"
|
||||
[multiple]="true"
|
||||
[selectOnTab]="true"
|
||||
[closeOnSelect]="false"
|
||||
(close)="onDropdownClosed()"
|
||||
[disabled]="disabled"
|
||||
|
||||
@@ -75,12 +75,6 @@ export class MultiSelectComponent implements OnInit, BitFormFieldControl, Contro
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.select.isOpen && event.key === "Enter" && !hasModifierKey(event)) {
|
||||
this.select.close();
|
||||
event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.select.isOpen && event.key === "Escape" && !hasModifierKey(event)) {
|
||||
this.selectedItems = [];
|
||||
this.select.close();
|
||||
|
||||
@@ -6,6 +6,6 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
body {
|
||||
html {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
|
||||
--color-text-main: 253 246 227;
|
||||
--color-text-muted: 147 161 161;
|
||||
--color-text-contrast: 0 43 54;
|
||||
--color-text-contrast: 0 0 0;
|
||||
--color-text-alt2: 255 255 255;
|
||||
--color-text-code: 240 141 199;
|
||||
|
||||
|
||||
@@ -12,8 +12,20 @@ export class I18nMockService implements I18nService {
|
||||
constructor(private lookupTable: Record<string, string | ((...args: string[]) => string)>) {}
|
||||
|
||||
t(id: string, p1?: string, p2?: string, p3?: string) {
|
||||
const value = this.lookupTable[id];
|
||||
let value = this.lookupTable[id];
|
||||
if (typeof value == "string") {
|
||||
if (value !== "") {
|
||||
if (p1 != null) {
|
||||
value = value.split("__$1__").join(p1.toString());
|
||||
}
|
||||
if (p2 != null) {
|
||||
value = value.split("__$2__").join(p2.toString());
|
||||
}
|
||||
if (p3 != null) {
|
||||
value = value.split("__$3__").join(p3.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
return value(p1, p2, p3);
|
||||
|
||||
@@ -4,10 +4,10 @@ $primary: #175ddc;
|
||||
$primary-accent: #1252a3;
|
||||
$secondary: #ced4da;
|
||||
$secondary-alt: #1a3b66;
|
||||
$success: #00a65a;
|
||||
$success: #017e45;
|
||||
$info: #555555;
|
||||
$warning: #bf7e16;
|
||||
$danger: #dd4b39;
|
||||
$warning: #8b6609;
|
||||
$danger: #c83522;
|
||||
$white: #ffffff;
|
||||
|
||||
// Bootstrap Variable Overrides
|
||||
@@ -85,7 +85,7 @@ $mfaTypes: 0, 2, 3, 4, 6;
|
||||
// Theme Variables
|
||||
// Light
|
||||
|
||||
$lightDangerHover: #c43421;
|
||||
$lightDangerHover: #c83522;
|
||||
$lightInputColor: #465057;
|
||||
$lightInputPlaceholderColor: #b6b8b8;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user