mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 10:33:31 +00:00
merge in main
This commit is contained in:
@@ -3,6 +3,7 @@ import { Component } from "@angular/core";
|
||||
@Component({
|
||||
selector: "app-root",
|
||||
template: "",
|
||||
standalone: false,
|
||||
})
|
||||
export class AppComponent {
|
||||
title = "components";
|
||||
|
||||
@@ -123,7 +123,7 @@ export class AvatarComponent implements OnChanges {
|
||||
textTag.setAttribute("fill", Utils.pickTextColorBasedOnBgColor(color, 135, true));
|
||||
textTag.setAttribute(
|
||||
"font-family",
|
||||
'"DM Sans","Helvetica Neue",Helvetica,Arial,' +
|
||||
'Roboto,"Helvetica Neue",Helvetica,Arial,' +
|
||||
'sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"',
|
||||
);
|
||||
// Warning do not use innerHTML here, characters are user provided
|
||||
|
||||
@@ -14,7 +14,8 @@
|
||||
<!-- Primary button -->
|
||||
<button
|
||||
type="button"
|
||||
class="fvw-target tw-inline-flex tw-gap-1.5 tw-items-center tw-justify-between tw-bg-transparent hover:tw-bg-transparent tw-border-none tw-outline-none tw-w-full tw-py-1 tw-pl-3 last:tw-pr-3 [&:not(:last-child)]:tw-pr-0 tw-truncate tw-text-[color:inherit] tw-text-[length:inherit]"
|
||||
class="tw-inline-flex tw-gap-1.5 tw-items-center tw-justify-between tw-bg-transparent hover:tw-bg-transparent tw-border-none tw-outline-none tw-w-full tw-py-1 tw-pl-3 last:tw-pr-3 [&:not(:last-child)]:tw-pr-0 tw-truncate tw-text-[color:inherit] tw-text-[length:inherit]"
|
||||
data-fvw-target
|
||||
[ngClass]="{
|
||||
'tw-cursor-not-allowed': disabled,
|
||||
'group-hover/chip-select:tw-text-secondary-700': !selectedOption && !disabled,
|
||||
|
||||
@@ -80,7 +80,7 @@ export class ChipSelectComponent<T = unknown> implements ControlValueAccessor, A
|
||||
protected focusVisibleWithin = signal(false);
|
||||
@HostListener("focusin", ["$event.target"])
|
||||
onFocusIn(target: HTMLElement) {
|
||||
this.focusVisibleWithin.set(target.matches(".fvw-target:focus-visible"));
|
||||
this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible"));
|
||||
}
|
||||
@HostListener("focusout")
|
||||
onFocusOut() {
|
||||
|
||||
@@ -2,6 +2,8 @@ import { Component, computed, HostBinding, input } from "@angular/core";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
|
||||
// FIXME: update to use a const object instead of a typescript enum
|
||||
// eslint-disable-next-line @bitwarden/platform/no-enums
|
||||
enum CharacterType {
|
||||
Letter,
|
||||
Emoji,
|
||||
|
||||
@@ -56,7 +56,8 @@
|
||||
<ng-container *ngTemplateOutlet="prefixContent"></ng-container>
|
||||
</div>
|
||||
<div
|
||||
class="default-content tw-w-full tw-relative tw-py-2 has-[bit-select]:tw-p-0 has-[bit-multi-select]:tw-p-0 has-[input:read-only:not([hidden])]:tw-bg-secondary-100 has-[textarea:read-only:not([hidden])]:tw-bg-secondary-100"
|
||||
class="tw-w-full tw-relative tw-py-2 has-[bit-select]:tw-p-0 has-[bit-multi-select]:tw-p-0 has-[input:read-only:not([hidden])]:tw-bg-secondary-100 has-[textarea:read-only:not([hidden])]:tw-bg-secondary-100"
|
||||
data-default-content
|
||||
[ngClass]="[
|
||||
prefixHasChildren() ? '' : 'tw-rounded-l-lg tw-pl-3',
|
||||
suffixHasChildren() ? '' : 'tw-rounded-r-lg tw-pr-3',
|
||||
@@ -96,7 +97,8 @@
|
||||
<ng-container *ngTemplateOutlet="prefixContent"></ng-container>
|
||||
</div>
|
||||
<div
|
||||
class="default-content tw-w-full tw-pb-0 tw-relative [&>*]:tw-p-0 [&>*::selection]:tw-bg-primary-700 [&>*::selection]:tw-text-contrast"
|
||||
class="tw-w-full tw-pb-0 tw-relative [&>*]:tw-p-0 [&>*::selection]:tw-bg-primary-700 [&>*::selection]:tw-text-contrast"
|
||||
data-default-content
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="defaultContent"></ng-container>
|
||||
</div>
|
||||
|
||||
@@ -91,7 +91,7 @@ export class BitFormFieldComponent implements AfterContentChecked {
|
||||
protected defaultContentIsFocused = signal(false);
|
||||
@HostListener("focusin", ["$event.target"])
|
||||
onFocusIn(target: HTMLElement) {
|
||||
this.defaultContentIsFocused.set(target.matches(".default-content *:focus-visible"));
|
||||
this.defaultContentIsFocused.set(target.matches("[data-default-content] *:focus-visible"));
|
||||
}
|
||||
@HostListener("focusout")
|
||||
onFocusOut() {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { FocusableElement } from "../shared/focusable-element";
|
||||
*/
|
||||
@Directive({
|
||||
selector: "[appAutofocus], [bitAutofocus]",
|
||||
standalone: false,
|
||||
})
|
||||
export class AutofocusDirective implements AfterContentChecked {
|
||||
@Input() set appAutofocus(condition: boolean | string) {
|
||||
|
||||
@@ -25,7 +25,8 @@ import { TypographyModule } from "../typography";
|
||||
* y-axis padding should be kept in sync with `item-action.component.ts`'s `top` and `bottom` units.
|
||||
* we want this to be the same height as the `item-action`'s `:after` element
|
||||
*/
|
||||
"fvw-target tw-outline-none tw-text-main hover:tw-text-main tw-no-underline hover:tw-no-underline tw-text-base tw-py-2 tw-px-4 bit-compact:tw-py-1.5 bit-compact:tw-px-2 tw-bg-transparent tw-w-full tw-border-none tw-flex tw-gap-4 tw-items-center tw-justify-between",
|
||||
"tw-outline-none tw-text-main hover:tw-text-main tw-no-underline hover:tw-no-underline tw-text-base tw-py-2 tw-px-4 bit-compact:tw-py-1.5 bit-compact:tw-px-2 tw-bg-transparent tw-w-full tw-border-none tw-flex tw-gap-4 tw-items-center tw-justify-between",
|
||||
"data-fvw-target": "",
|
||||
},
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<bit-item-action class="item-main-content tw-flex tw-flex-1 tw-overflow-hidden">
|
||||
<bit-item-action class="tw-flex tw-flex-1 tw-overflow-hidden" data-item-main-content>
|
||||
<ng-content></ng-content>
|
||||
</bit-item-action>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import { ItemActionComponent } from "./item-action.component";
|
||||
providers: [{ provide: A11yRowDirective, useExisting: ItemComponent }],
|
||||
host: {
|
||||
class:
|
||||
"tw-block tw-box-border tw-overflow-hidden tw-flex tw-bg-background [&:has(.item-main-content_button:hover,.item-main-content_a:hover)]:tw-cursor-pointer [&:has(.item-main-content_button:hover,.item-main-content_a:hover)]:tw-bg-primary-100 tw-text-main tw-border-solid tw-border-b tw-border-0 [&:not(bit-layout_*)]:tw-rounded-lg bit-compact:[&:not(bit-layout_*)]:tw-rounded-none bit-compact:[&:not(bit-layout_*)]:last-of-type:tw-rounded-b-lg bit-compact:[&:not(bit-layout_*)]:first-of-type:tw-rounded-t-lg tw-min-h-9 tw-mb-1.5 bit-compact:tw-mb-0",
|
||||
"tw-block tw-box-border tw-overflow-hidden tw-flex tw-bg-background [&:has([data-item-main-content]_button:hover,[data-item-main-content]_a:hover)]:tw-cursor-pointer [&:has([data-item-main-content]_button:hover,[data-item-main-content]_a:hover)]:tw-bg-primary-100 tw-text-main tw-border-solid tw-border-b tw-border-0 [&:not(bit-layout_*)]:tw-rounded-lg bit-compact:[&:not(bit-layout_*)]:tw-rounded-none bit-compact:[&:not(bit-layout_*)]:last-of-type:tw-rounded-b-lg bit-compact:[&:not(bit-layout_*)]:first-of-type:tw-rounded-t-lg tw-min-h-9 tw-mb-1.5 bit-compact:tw-mb-0",
|
||||
},
|
||||
})
|
||||
export class ItemComponent extends A11yRowDirective {
|
||||
@@ -33,7 +33,7 @@ export class ItemComponent extends A11yRowDirective {
|
||||
protected focusVisibleWithin = signal(false);
|
||||
@HostListener("focusin", ["$event.target"])
|
||||
onFocusIn(target: HTMLElement) {
|
||||
this.focusVisibleWithin.set(target.matches(".fvw-target:focus-visible"));
|
||||
this.focusVisibleWithin.set(target.matches("[data-fvw-target]:focus-visible"));
|
||||
}
|
||||
@HostListener("focusout")
|
||||
onFocusOut() {
|
||||
|
||||
@@ -16,11 +16,7 @@ import { filter, mergeWith } from "rxjs/operators";
|
||||
|
||||
import { MenuComponent } from "./menu.component";
|
||||
|
||||
@Directive({
|
||||
selector: "[bitMenuTriggerFor]",
|
||||
exportAs: "menuTrigger",
|
||||
standalone: true,
|
||||
})
|
||||
@Directive({ selector: "[bitMenuTriggerFor]", exportAs: "menuTrigger", standalone: true })
|
||||
export class MenuTriggerForDirective implements OnDestroy {
|
||||
@HostBinding("attr.aria-expanded") isOpen = false;
|
||||
@HostBinding("attr.aria-haspopup") get hasPopup(): "menu" | "dialog" {
|
||||
@@ -42,18 +38,10 @@ export class MenuTriggerForDirective implements OnDestroy {
|
||||
.position()
|
||||
.flexibleConnectedTo(this.elementRef)
|
||||
.withPositions([
|
||||
{
|
||||
originX: "start",
|
||||
originY: "bottom",
|
||||
overlayX: "start",
|
||||
overlayY: "top",
|
||||
},
|
||||
{
|
||||
originX: "end",
|
||||
originY: "bottom",
|
||||
overlayX: "end",
|
||||
overlayY: "top",
|
||||
},
|
||||
{ originX: "start", originY: "bottom", overlayX: "start", overlayY: "top" },
|
||||
{ originX: "end", originY: "bottom", overlayX: "end", overlayY: "top" },
|
||||
{ originX: "start", originY: "top", overlayX: "start", overlayY: "bottom" },
|
||||
{ originX: "end", originY: "top", overlayX: "end", overlayY: "bottom" },
|
||||
])
|
||||
.withLockedPosition(true)
|
||||
.withFlexibleDimensions(false)
|
||||
|
||||
@@ -70,10 +70,11 @@
|
||||
|
||||
<!-- Show if a value was passed to `this.to` -->
|
||||
<ng-template #isAnchor>
|
||||
<!-- The `fvw` class passes focus to `this.focusVisibleWithin$` -->
|
||||
<!-- The `data-fvw` attribute passes focus to `this.focusVisibleWithin$` -->
|
||||
<!-- The following `class` field should match the `#isButton` class field below -->
|
||||
<a
|
||||
class="fvw tw-w-full tw-truncate tw-border-none tw-bg-transparent tw-p-0 tw-text-start !tw-text-alt2 hover:tw-text-alt2 hover:tw-no-underline focus:tw-outline-none"
|
||||
class="tw-w-full tw-truncate tw-border-none tw-bg-transparent tw-p-0 tw-text-start !tw-text-alt2 hover:tw-text-alt2 hover:tw-no-underline focus:tw-outline-none"
|
||||
data-fvw
|
||||
[routerLink]="route"
|
||||
[relativeTo]="relativeTo"
|
||||
[attr.aria-label]="ariaLabel || text"
|
||||
@@ -92,7 +93,8 @@
|
||||
<!-- Class field should match `#isAnchor` class field above -->
|
||||
<button
|
||||
type="button"
|
||||
class="fvw tw-w-full tw-truncate tw-border-none tw-bg-transparent tw-p-0 tw-text-start !tw-text-alt2 hover:tw-text-alt2 hover:tw-no-underline focus:tw-outline-none"
|
||||
class="tw-w-full tw-truncate tw-border-none tw-bg-transparent tw-p-0 tw-text-start !tw-text-alt2 hover:tw-text-alt2 hover:tw-no-underline focus:tw-outline-none"
|
||||
data-fvw
|
||||
(click)="mainContentClicked.emit()"
|
||||
>
|
||||
<ng-container *ngTemplateOutlet="anchorAndButtonContent"></ng-container>
|
||||
|
||||
@@ -39,11 +39,15 @@ export class NavItemComponent extends NavBaseComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* The design spec calls for the an outline to wrap the entire element when the template's anchor/button has :focus-visible.
|
||||
* Usually, we would use :focus-within for this. However, that matches when a child element has :focus instead of :focus-visible.
|
||||
* The design spec calls for the an outline to wrap the entire element when the template's
|
||||
* anchor/button has :focus-visible. Usually, we would use :focus-within for this. However, that
|
||||
* matches when a child element has :focus instead of :focus-visible.
|
||||
*
|
||||
* Currently, the browser does not have a pseudo selector that combines these two, e.g. :focus-visible-within (WICG/focus-visible#151)
|
||||
* To make our own :focus-visible-within functionality, we use event delegation on the host and manually check if the focus target (denoted with the .fvw class) matches :focus-visible. We then map that state to some styles, so the entire component can have an outline.
|
||||
* Currently, the browser does not have a pseudo selector that combines these two, e.g.
|
||||
* :focus-visible-within (WICG/focus-visible#151). To make our own :focus-visible-within
|
||||
* functionality, we use event delegation on the host and manually check if the focus target
|
||||
* (denoted with the data-fvw attribute) matches :focus-visible. We then map that state to some
|
||||
* styles, so the entire component can have an outline.
|
||||
*/
|
||||
protected focusVisibleWithin$ = new BehaviorSubject(false);
|
||||
protected fvwStyles$ = this.focusVisibleWithin$.pipe(
|
||||
@@ -53,7 +57,7 @@ export class NavItemComponent extends NavBaseComponent {
|
||||
);
|
||||
@HostListener("focusin", ["$event.target"])
|
||||
onFocusIn(target: HTMLElement) {
|
||||
this.focusVisibleWithin$.next(target.matches(".fvw:focus-visible"));
|
||||
this.focusVisibleWithin$.next(target.matches("[data-fvw]:focus-visible"));
|
||||
}
|
||||
@HostListener("focusout")
|
||||
onFocusOut() {
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// @ts-strict-ignore
|
||||
import {
|
||||
CdkVirtualScrollViewport,
|
||||
CdkVirtualScrollableWindow,
|
||||
CdkFixedSizeVirtualScroll,
|
||||
CdkVirtualForOf,
|
||||
CdkVirtualScrollableWindow,
|
||||
} from "@angular/cdk/scrolling";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import {
|
||||
|
||||
@@ -21,7 +21,7 @@ $body-bg: $white;
|
||||
$body-color: #333333;
|
||||
|
||||
$font-family-sans-serif:
|
||||
"DM Sans", "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
|
||||
"Segoe UI Symbol";
|
||||
|
||||
$h1-font-size: 1.7rem;
|
||||
|
||||
Reference in New Issue
Block a user