1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-14 07:13:32 +00:00

[PM-2195] Adjust radio groups margin (#5410)

* Adjust radio groups margin

* Move hint margin to input field

* Tweak field spacing

* Add story for hint, and fix hint display

* Fix label ssue

* Revert input margin

* Re-add margin to hint

* Change font weight

* Fix required placement

* Add support for required

* Change margin of radio group

* Remove unnecessary div

* Fix long inputs cutting off

* Fix radio story

* Remove newline

---------

Co-authored-by: Will Martin <contact@willmartian.com>
This commit is contained in:
Oscar Hinton
2023-11-21 04:59:03 +01:00
committed by GitHub
parent 651593bcd2
commit 50493ab6f7
12 changed files with 168 additions and 23 deletions

View File

@@ -1,15 +1,15 @@
<bit-form-control inline>
<bit-form-control [inline]="!block" disableMargin>
<input
type="radio"
bitRadio
[id]="inputId"
[name]="name"
[disabled]="groupDisabled || disabled"
[value]="value"
[checked]="selected"
(change)="onInputChange()"
(blur)="onBlur()"
/>
<ng-content select="bit-label" ngProjectAs="bit-label"></ng-content>
<ng-content select="bit-hint" ngProjectAs="bit-hint"></ng-content>
</bit-form-control>

View File

@@ -10,6 +10,10 @@ let nextId = 0;
})
export class RadioButtonComponent {
@HostBinding("attr.id") @Input() id = `bit-radio-button-${nextId++}`;
@HostBinding("class") get classList() {
return [this.block ? "tw-block" : "tw-inline-block", "tw-mb-2"];
}
@Input() value: unknown;
@Input() disabled = false;
@@ -31,6 +35,10 @@ export class RadioButtonComponent {
return this.groupComponent.disabled;
}
get block() {
return this.groupComponent.block;
}
protected onInputChange() {
this.groupComponent.onInputChange(this.value);
}

View File

@@ -2,13 +2,14 @@ import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { FormControlModule } from "../form-control";
import { SharedModule } from "../shared";
import { RadioButtonComponent } from "./radio-button.component";
import { RadioGroupComponent } from "./radio-group.component";
import { RadioInputComponent } from "./radio-input.component";
@NgModule({
imports: [CommonModule, FormControlModule],
imports: [CommonModule, SharedModule, FormControlModule],
declarations: [RadioInputComponent, RadioButtonComponent, RadioGroupComponent],
exports: [FormControlModule, RadioInputComponent, RadioButtonComponent, RadioGroupComponent],
})

View File

@@ -1,5 +1,5 @@
import { FormsModule, ReactiveFormsModule, FormControl, FormGroup } from "@angular/forms";
import { Meta, StoryObj, moduleMetadata } from "@storybook/angular";
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -67,6 +67,37 @@ export const Inline: Story = {
}),
};
export const InlineHint: Story = {
render: () => ({
props: {
formObj: new FormGroup({
radio: new FormControl(0),
}),
},
template: `
<form [formGroup]="formObj">
<bit-radio-group formControlName="radio" aria-label="Example radio group">
<bit-label>Group of radio buttons</bit-label>
<bit-radio-button id="radio-first" [value]="0">
<bit-label>First</bit-label>
</bit-radio-button>
<bit-radio-button id="radio-second" [value]="1">
<bit-label>Second</bit-label>
</bit-radio-button>
<bit-radio-button id="radio-third" [value]="2">
<bit-label>Third</bit-label>
</bit-radio-button>
<bit-hint>This is a hint for the radio group</bit-hint>
</bit-radio-group>
</form>
`,
}),
};
export const Block: Story = {
render: () => ({
props: {
@@ -76,20 +107,20 @@ export const Block: Story = {
},
template: `
<form [formGroup]="formObj">
<bit-radio-group formControlName="radio" aria-label="Example radio group">
<bit-radio-group formControlName="radio" aria-label="Example radio group" [block]="true">
<bit-label>Group of radio buttons</bit-label>
<bit-radio-button id="radio-first" class="tw-block" [value]="0">
<bit-radio-button id="radio-first" [value]="0">
<bit-label>First</bit-label>
<bit-hint>This is a hint for the first option</bit-hint>
</bit-radio-button>
<bit-radio-button id="radio-second" class="tw-block" [value]="1">
<bit-radio-button id="radio-second" [value]="1">
<bit-label>Second</bit-label>
<bit-hint>This is a hint for the second option</bit-hint>
</bit-radio-button>
<bit-radio-button id="radio-third" class="tw-block" [value]="2">
<bit-radio-button id="radio-third" [value]="2">
<bit-label>Third</bit-label>
<bit-hint>This is a hint for the third option</bit-hint>
</bit-radio-button>
@@ -98,3 +129,37 @@ export const Block: Story = {
`,
}),
};
export const BlockHint: Story = {
render: () => ({
props: {
formObj: new FormGroup({
radio: new FormControl(0),
}),
},
template: `
<form [formGroup]="formObj">
<bit-radio-group formControlName="radio" aria-label="Example radio group" [block]="true">
<bit-label>Group of radio buttons</bit-label>
<bit-radio-button id="radio-first" [value]="0">
<bit-label>First</bit-label>
<bit-hint>This is a hint for the first option</bit-hint>
</bit-radio-button>
<bit-radio-button id="radio-second" [value]="1">
<bit-label>Second</bit-label>
<bit-hint>This is a hint for the second option</bit-hint>
</bit-radio-button>
<bit-radio-button id="radio-third" [value]="2">
<bit-label>Third</bit-label>
<bit-hint>This is a hint for the third option</bit-hint>
</bit-radio-button>
<bit-hint>This is a hint for the radio group</bit-hint>
</bit-radio-group>
</form>
`,
}),
};

View File

@@ -2,6 +2,7 @@
<fieldset>
<legend class="tw-mb-1 tw-block tw-text-sm tw-font-semibold tw-text-main">
<ng-content select="bit-label"></ng-content>
<span *ngIf="required" class="tw-text-xs tw-font-normal"> ({{ "required" | i18n }})</span>
</legend>
<ng-container *ngTemplateOutlet="content"></ng-container>
</fieldset>
@@ -11,4 +12,9 @@
<ng-container *ngTemplateOutlet="content"></ng-container>
</ng-container>
<ng-template #content><ng-content></ng-content></ng-template>
<ng-template #content>
<div>
<ng-content></ng-content>
</div>
<ng-content select="bit-hint" ngProjectAs="bit-hint"></ng-content>
</ng-template>

View File

@@ -1,5 +1,5 @@
import { Component, ContentChild, HostBinding, Input, Optional, Self } from "@angular/core";
import { ControlValueAccessor, NgControl } from "@angular/forms";
import { ControlValueAccessor, NgControl, Validators } from "@angular/forms";
import { BitLabel } from "../form-control/label.directive";
@@ -21,8 +21,11 @@ export class RadioGroupComponent implements ControlValueAccessor {
this._name = value;
}
@Input() block = false;
@HostBinding("attr.role") role = "radiogroup";
@HostBinding("attr.id") @Input() id = `bit-radio-group-${nextId++}`;
@HostBinding("class") classList = ["tw-block", "tw-mb-4"];
@ContentChild(BitLabel) protected label: BitLabel;
@@ -32,6 +35,10 @@ export class RadioGroupComponent implements ControlValueAccessor {
}
}
get required() {
return this.ngControl?.control?.hasValidator(Validators.required) ?? false;
}
// ControlValueAccessor
onChange: (value: unknown) => void;
onTouched: () => void;

View File

@@ -29,6 +29,7 @@ export class RadioInputComponent implements BitFormControlAbstraction {
"tw-h-3.5",
"tw-mr-1.5",
"tw-bottom-[-1px]", // Fix checkbox looking off-center
"tw-flex-none", // Flexbox fix for bit-form-control
"hover:tw-border-2",
"[&>label:hover]:tw-border-2",