Repository: Energinet-DataHub/greenforce-frontend
Pull request #4177: Watt Segmented Buttons!
Author: login: Sejruppen
Created: 2025-04-09T08:38:27Z | Merged: 2025-04-11T11:15:14Z

## Description

This is a watt version of the Angular Material component "Button toggle". 
I have styled it, made it a "ControlValueAccessor", to enable usage with a formControl and made a way to disable the component based of the formControl.

I also export an interface for the list of buttons, to ease the use, called "WattSegmentedButton"

Stories were made too 😄 

![segmentedButtons](https://github.com/user-attachments/assets/acffc629-be8d-46ed-96db-bb426f1d3e60)


Diff:
diff --git a/libs/watt/package/package.json b/libs/watt/package/package.json
index 7ffa6e808ff..f68e89b47b0 100644
--- a/libs/watt/package/package.json
+++ b/libs/watt/package/package.json
@@ -1,7 +1,7 @@
 {
   "type": "module",
   "name": "@energinet/watt",
-  "version": "1.3.0",
+  "version": "1.4.0",
   "license": "Apache-2.0",
   "exports": {
     ".": {
diff --git a/libs/watt/package/segmented-buttons/+storybook/watt-segmented-buttons.component.stories.ts b/libs/watt/package/segmented-buttons/+storybook/watt-segmented-buttons.component.stories.ts
new file mode 100644
index 00000000000..c04547d796f
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/+storybook/watt-segmented-buttons.component.stories.ts
@@ -0,0 +1,73 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { Meta, moduleMetadata, StoryFn } from '@storybook/angular';
+
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { WattSegmentedButtonsComponent } from '../watt-segmented-buttons.component';
+import { WattButtonComponent } from '@energinet/watt/button';
+import { WattSegmentedButtonComponent } from '../watt-segmented-button.component';
+
+const meta: Meta<WattSegmentedButtonsComponent> = {
+  title: 'Components/Segmented buttons',
+  component: WattSegmentedButtonsComponent,
+  decorators: [
+    moduleMetadata({
+      imports: [
+        ReactiveFormsModule,
+        WattSegmentedButtonsComponent,
+        WattSegmentedButtonComponent,
+        WattButtonComponent,
+      ],
+    }),
+  ],
+};
+export default meta;
+
+export const WithFormControl: StoryFn<WattSegmentedButtonsComponent> = () => ({
+  props: {
+    exampleFormControl: new FormControl('year'),
+  },
+  template: `
+    <watt-segmented-buttons [formControl]="exampleFormControl">
+      <watt-segmented-button value="day">Day</watt-segmented-button>
+      <watt-segmented-button value="month">Month</watt-segmented-button>
+      <watt-segmented-button value="year">Year</watt-segmented-button>
+      <watt-segmented-button value="all years">All Years</watt-segmented-button>
+    </watt-segmented-buttons>
+    <h5>Form value: {{exampleFormControl.value}}</h5>
+  `,
+});
+export const Disable: StoryFn<WattSegmentedButtonsComponent> = () => ({
+  props: {
+    exampleFormControl: new FormControl('year'),
+  },
+  template: `
+    <watt-segmented-buttons [formControl]="exampleFormControl">
+      <watt-segmented-button value="day">Day</watt-segmented-button>
+      <watt-segmented-button value="month">Month</watt-segmented-button>
+      <watt-segmented-button value="year">Year</watt-segmented-button>
+      <watt-segmented-button value="all years">All Years</watt-segmented-button>
+    </watt-segmented-buttons>
+    <h5>Form value: {{exampleFormControl.value}}</h5>
+    <div style="display: flex; grid-gap: 10px; margin-top: 20px;">
+      <watt-button (click)="exampleFormControl.disable()">disable</watt-button>
+      <watt-button (click)="exampleFormControl.enable()">enable</watt-button>
+    </div>
+  `,
+});
diff --git a/libs/watt/package/segmented-buttons/index.ts b/libs/watt/package/segmented-buttons/index.ts
new file mode 100644
index 00000000000..60c31a5c302
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/index.ts
@@ -0,0 +1,20 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+export { WattSegmentedButtonsComponent } from './watt-segmented-buttons.component';
+export { WattSegmentedButtonComponent } from './watt-segmented-button.component';
diff --git a/libs/watt/package/segmented-buttons/ng-package.json b/libs/watt/package/segmented-buttons/ng-package.json
new file mode 100644
index 00000000000..4ce0e7e0fa1
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/ng-package.json
@@ -0,0 +1,6 @@
+{
+  "lib": {
+    "entryFile": "index.ts",
+    "styleIncludePaths": ["../core/styles"]
+  }
+}
diff --git a/libs/watt/package/segmented-buttons/watt-segmented-button.component.ts b/libs/watt/package/segmented-buttons/watt-segmented-button.component.ts
new file mode 100644
index 00000000000..4c624561e74
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/watt-segmented-button.component.ts
@@ -0,0 +1,30 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { Component, input, TemplateRef, viewChild } from '@angular/core';
+
+@Component({
+  selector: 'watt-segmented-button',
+  template: ` <ng-template>
+    <ng-content />
+  </ng-template>`,
+})
+export class WattSegmentedButtonComponent {
+  templateRef = viewChild.required<TemplateRef<unknown>>(TemplateRef);
+  value = input.required<string>();
+}
diff --git a/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.scss b/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.scss
new file mode 100644
index 00000000000..c133781c9da
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.scss
@@ -0,0 +1,41 @@
+// Copyright 2020 Energinet DataHub A/S
+//
+// Licensed under the Apache License, Version 2.0 (the "License2");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+@use "@energinet-datahub/watt/utils" as watt;
+@use "@angular/material" as mat;
+
+:root {
+  @include mat.button-toggle-overrides(
+    (
+      selected-state-text-color: white,
+      selected-state-background-color: var(--watt-color-primary),
+      height: 2.5rem,
+    )
+  );
+
+  mat-button-toggle-group {
+    border-color: var(--watt-color-neutral-grey-700);
+
+    mat-button-toggle {
+      border-color: var(--watt-color-neutral-grey-700) !important;
+
+      button {
+        width: 6.5rem;
+
+        span {
+          font-size: 0.8rem;
+        }
+      }
+    }
+  }
+}
diff --git a/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts b/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
new file mode 100644
index 00000000000..f242a868ba6
--- /dev/null
+++ b/libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
@@ -0,0 +1,85 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  contentChildren,
+  ElementRef,
+  forwardRef,
+  inject,
+  model,
+  signal,
+  ViewEncapsulation,
+} from '@angular/core';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+import { NgTemplateOutlet } from '@angular/common';
+import { WattSegmentedButtonComponent } from './watt-segmented-button.component';
+
+/**
+ * Segmented buttons.
+ */
+@Component({
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  encapsulation: ViewEncapsulation.None,
+  imports: [MatButtonToggleModule, FormsModule, NgTemplateOutlet],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => WattSegmentedButtonsComponent),
+      multi: true,
+    },
+  ],
+  selector: 'watt-segmented-buttons',
+  styleUrls: ['./watt-segmented-buttons.component.scss'],
+  template: ` <mat-button-toggle-group
+    [(ngModel)]="selected"
+    [multiple]="false"
+    [hideSingleSelectionIndicator]="true"
+    [disabled]="disabled()"
+  >
+    @for (segmentedButton of segmentedButtonElements(); track segmentedButton) {
+      <mat-button-toggle [value]="segmentedButton.value()">
+        <ng-container *ngTemplateOutlet="segmentedButton.templateRef()" />
+      </mat-button-toggle>
+    }
+  </mat-button-toggle-group>`,
+})
+export class WattSegmentedButtonsComponent implements ControlValueAccessor {
+  segmentedButtonElements = contentChildren(WattSegmentedButtonComponent);
+  selected = model<string>('');
+  disabled = signal(false);
+  private element = inject(ElementRef);
+
+  writeValue(selected: string): void {
+    this.selected.set(selected);
+  }
+
+  registerOnChange(fn: (value: string) => void): void {
+    this.selected.subscribe(fn);
+  }
+
+  registerOnTouched(fn: (value: boolean) => void): void {
+    this.element.nativeElement.addEventListener('focusout', fn);
+  }
+
+  setDisabledState?(isDisabled: boolean): void {
+    this.disabled.set(isDisabled);
+  }
+}


Reviews:
user: login: ManBearTM
body: Nice work! Undo the `bun.lock` changes, then update to bun 1.2.4 and try to run `bun install` again - hopefully that should result in no changes to the lock file.

Also I agree with @mimse that child components are the way to go. We have tried the array-based approach before, but it quickly becomes too limiting. But giving the time constraints, I'm also okay with this solution for now if it is sufficient for our use case.
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:26:14Z
user: login: ManBearTM
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:29:43Z
user: login: mimse
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-09T10:44:33Z
user: login: Sejruppen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T06:20:25Z
user: login: Sejruppen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T08:57:09Z
user: login: Sejruppen
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T09:01:02Z
user: login: ManBearTM
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:40:32Z
user: login: ManBearTM
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:41:07Z
user: login: ManBearTM
body: lgtm!
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T10:45:16Z
user: login: ManBearTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-11T11:02:26Z

Review comments:
diff_hunk: @@ -0,0 +1,88 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  ElementRef,
+  forwardRef,
+  inject,
+  input,
+  model,
+  signal,
+  ViewEncapsulation,
+} from '@angular/core';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+
+export interface WattSegmentedButton {
+  label: string;
+  value: string;
+}
+
+/**
+ * Segmented buttons.
+ */
+@Component({
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  encapsulation: ViewEncapsulation.None,
+  imports: [MatButtonToggleModule, FormsModule],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => WattSegmentedButtonsComponent),
+      multi: true,
+    },
+  ],
+  selector: 'watt-segmented-buttons',
+  styleUrls: ['./watt-segmented-buttons.component.scss'],
+  template: ` <mat-button-toggle-group
+    [(ngModel)]="selected"
+    [multiple]="false"
+    [hideSingleSelectionIndicator]="true"
+    [disabled]="isDisabled()"
+  >
+    @for (button of buttons(); track button.value) {
+      <mat-button-toggle [value]="button.value">
+        {{ button.label }}
+      </mat-button-toggle>
+    }
+  </mat-button-toggle-group>`,
+})
+export class WattSegmentedButtonsComponent implements ControlValueAccessor {
+  buttons = input<WattSegmentedButton[]>([]);
+  selected = model<string>('');
+  isDisabled = signal(false);
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
user: login: ManBearTM
body: nitpick: rename to `disabled` for consistency with other components 🙂 
created_at: 2025-04-09T09:17:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -1,7 +1,7 @@
 {
   "type": "module",
   "name": "@energinet/watt",
-  "version": "1.2.3",
+  "version": "1.2.4",
path: libs/watt/package/package.json
user: login: ManBearTM
body: nitpick: bump to 1.3.0 🎉 
created_at: 2025-04-09T09:20:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { render, screen } from '@testing-library/angular';
+import { WattSegmentedButtonsComponent } from './watt-segmented-buttons.component';
+
+describe.skip(WattSegmentedButtonsComponent, () => {
+  it('renders', async () => {
+    await render(WattSegmentedButtonsComponent);
+
+    expect(screen.queryAllByRole('slider')).toHaveLength(2);
+  });
+});
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.spec.ts
user: login: ManBearTM
body: i don't believe this test is executed (it has `.skip`). also the `slider` assertion seems wrong, unless the `MatButtonToogle` is somehow set up like that. either fix the test or remove it if it doesn't provide any value.
created_at: 2025-04-09T10:29:43Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,88 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  ElementRef,
+  forwardRef,
+  inject,
+  input,
+  model,
+  signal,
+  ViewEncapsulation,
+} from '@angular/core';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+
+export interface WattSegmentedButton {
+  label: string;
+  value: string;
+}
+
+/**
+ * Segmented buttons.
+ */
+@Component({
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  encapsulation: ViewEncapsulation.None,
+  imports: [MatButtonToggleModule, FormsModule],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => WattSegmentedButtonsComponent),
+      multi: true,
+    },
+  ],
+  selector: 'watt-segmented-buttons',
+  styleUrls: ['./watt-segmented-buttons.component.scss'],
+  template: ` <mat-button-toggle-group
+    [(ngModel)]="selected"
+    [multiple]="false"
+    [hideSingleSelectionIndicator]="true"
+    [disabled]="isDisabled()"
+  >
+    @for (button of buttons(); track button.value) {
+      <mat-button-toggle [value]="button.value">
+        {{ button.label }}
+      </mat-button-toggle>
+    }
+  </mat-button-toggle-group>`,
+})
+export class WattSegmentedButtonsComponent implements ControlValueAccessor {
+  buttons = input<WattSegmentedButton[]>([]);
+  selected = model<string>('');
+  isDisabled = signal(false);
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
user: login: mimse
body: I think disable will give a lint error, because its a native html element property
created_at: 2025-04-09T10:44:33Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { render, screen } from '@testing-library/angular';
+import { WattSegmentedButtonsComponent } from './watt-segmented-buttons.component';
+
+describe.skip(WattSegmentedButtonsComponent, () => {
+  it('renders', async () => {
+    await render(WattSegmentedButtonsComponent);
+
+    expect(screen.queryAllByRole('slider')).toHaveLength(2);
+  });
+});
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.spec.ts
user: login: Sejruppen
body: Sorry - det var da vidst en copy paste fejl - kigger på det!
created_at: 2025-04-11T06:20:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,88 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  ElementRef,
+  forwardRef,
+  inject,
+  input,
+  model,
+  signal,
+  ViewEncapsulation,
+} from '@angular/core';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+
+export interface WattSegmentedButton {
+  label: string;
+  value: string;
+}
+
+/**
+ * Segmented buttons.
+ */
+@Component({
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  encapsulation: ViewEncapsulation.None,
+  imports: [MatButtonToggleModule, FormsModule],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => WattSegmentedButtonsComponent),
+      multi: true,
+    },
+  ],
+  selector: 'watt-segmented-buttons',
+  styleUrls: ['./watt-segmented-buttons.component.scss'],
+  template: ` <mat-button-toggle-group
+    [(ngModel)]="selected"
+    [multiple]="false"
+    [hideSingleSelectionIndicator]="true"
+    [disabled]="isDisabled()"
+  >
+    @for (button of buttons(); track button.value) {
+      <mat-button-toggle [value]="button.value">
+        {{ button.label }}
+      </mat-button-toggle>
+    }
+  </mat-button-toggle-group>`,
+})
+export class WattSegmentedButtonsComponent implements ControlValueAccessor {
+  buttons = input<WattSegmentedButton[]>([]);
+  selected = model<string>('');
+  isDisabled = signal(false);
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
user: login: Sejruppen
body: The bun thing worked! 👍 Thanks !!
created_at: 2025-04-11T08:57:09Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,88 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR } from '@angular/forms';
+import {
+  ChangeDetectionStrategy,
+  Component,
+  ElementRef,
+  forwardRef,
+  inject,
+  input,
+  model,
+  signal,
+  ViewEncapsulation,
+} from '@angular/core';
+import { MatButtonToggleModule } from '@angular/material/button-toggle';
+
+export interface WattSegmentedButton {
+  label: string;
+  value: string;
+}
+
+/**
+ * Segmented buttons.
+ */
+@Component({
+  changeDetection: ChangeDetectionStrategy.OnPush,
+  encapsulation: ViewEncapsulation.None,
+  imports: [MatButtonToggleModule, FormsModule],
+  providers: [
+    {
+      provide: NG_VALUE_ACCESSOR,
+      useExisting: forwardRef(() => WattSegmentedButtonsComponent),
+      multi: true,
+    },
+  ],
+  selector: 'watt-segmented-buttons',
+  styleUrls: ['./watt-segmented-buttons.component.scss'],
+  template: ` <mat-button-toggle-group
+    [(ngModel)]="selected"
+    [multiple]="false"
+    [hideSingleSelectionIndicator]="true"
+    [disabled]="isDisabled()"
+  >
+    @for (button of buttons(); track button.value) {
+      <mat-button-toggle [value]="button.value">
+        {{ button.label }}
+      </mat-button-toggle>
+    }
+  </mat-button-toggle-group>`,
+})
+export class WattSegmentedButtonsComponent implements ControlValueAccessor {
+  buttons = input<WattSegmentedButton[]>([]);
+  selected = model<string>('');
+  isDisabled = signal(false);
path: libs/watt/package/segmented-buttons/watt-segmented-buttons.component.ts
user: login: Sejruppen
body: about the isDisabled - I tried to change it to disabled and there did not seem to be any lint error or anything else - I have copy pasted @mimse 's work, which is why the naming is as it is 😝 
created_at: 2025-04-11T09:01:02Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,75 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { Meta, moduleMetadata, StoryFn } from '@storybook/angular';
+
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { WattSegmentedButtonsComponent } from '../watt-segmented-buttons.component';
+import { WattButtonComponent } from '@energinet/watt/button';
+import { WattSegmentedButtonComponent } from '../watt-segmented-button.component';
+
+const meta: Meta<WattSegmentedButtonsComponent> = {
+  title: 'Components/Segmented buttons',
+  component: WattSegmentedButtonsComponent,
+  decorators: [
+    moduleMetadata({
+      imports: [
+        ReactiveFormsModule,
+        WattSegmentedButtonsComponent,
+        WattSegmentedButtonComponent,
+        WattButtonComponent,
+      ],
+    }),
+  ],
+};
+export default meta;
+
+export const WithFormControl: StoryFn<WattSegmentedButtonsComponent> = () => ({
+  props: {
+    exampleFormControl: new FormControl('year'),
+  },
+  template: `
+    <watt-segmented-buttons [formControl]="exampleFormControl">
+      <watt-segmented-button [value]="'day'">Day</watt-segmented-button>
+      <watt-segmented-button [value]="'month'">Month</watt-segmented-button>
+      <watt-segmented-button [value]="'year'">Year</watt-segmented-button>
+      <watt-segmented-button [value]="'all years'">All Years</watt-segmented-button>
path: libs/watt/package/segmented-buttons/+storybook/watt-segmented-buttons.component.stories.ts
user: login: ManBearTM
body: nitpick: readability
```suggestion
      <watt-segmented-button value="day">Day</watt-segmented-button>
      <watt-segmented-button value="month">Month</watt-segmented-button>
      <watt-segmented-button value="year">Year</watt-segmented-button>
      <watt-segmented-button value="all years">All Years</watt-segmented-button>
```
created_at: 2025-04-11T10:40:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,75 @@
+//#region License
+/**
+ * @license
+ * Copyright 2020 Energinet DataHub A/S
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License2");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+//#endregion
+import { Meta, moduleMetadata, StoryFn } from '@storybook/angular';
+
+import { FormControl, ReactiveFormsModule } from '@angular/forms';
+import { WattSegmentedButtonsComponent } from '../watt-segmented-buttons.component';
+import { WattButtonComponent } from '@energinet/watt/button';
+import { WattSegmentedButtonComponent } from '../watt-segmented-button.component';
+
+const meta: Meta<WattSegmentedButtonsComponent> = {
+  title: 'Components/Segmented buttons',
+  component: WattSegmentedButtonsComponent,
+  decorators: [
+    moduleMetadata({
+      imports: [
+        ReactiveFormsModule,
+        WattSegmentedButtonsComponent,
+        WattSegmentedButtonComponent,
+        WattButtonComponent,
+      ],
+    }),
+  ],
+};
+export default meta;
+
+export const WithFormControl: StoryFn<WattSegmentedButtonsComponent> = () => ({
+  props: {
+    exampleFormControl: new FormControl('year'),
+  },
+  template: `
+    <watt-segmented-buttons [formControl]="exampleFormControl">
+      <watt-segmented-button [value]="'day'">Day</watt-segmented-button>
+      <watt-segmented-button [value]="'month'">Month</watt-segmented-button>
+      <watt-segmented-button [value]="'year'">Year</watt-segmented-button>
+      <watt-segmented-button [value]="'all years'">All Years</watt-segmented-button>
+    </watt-segmented-buttons>
+    <h5>Form value: {{exampleFormControl.value}}</h5>
+  `,
+});
+
+export const Disable: StoryFn<WattSegmentedButtonsComponent> = () => ({
+  props: {
+    exampleFormControl: new FormControl('year'),
+  },
+  template: `
+    <watt-segmented-buttons [formControl]="exampleFormControl">
+      <watt-segmented-button [value]="'day'">Day</watt-segmented-button>
+      <watt-segmented-button [value]="'month'">Month</watt-segmented-button>
+      <watt-segmented-button [value]="'year'">Year</watt-segmented-button>
+      <watt-segmented-button [value]="'all years'">All Years</watt-segmented-button>
path: libs/watt/package/segmented-buttons/+storybook/watt-segmented-buttons.component.stories.ts
user: login: ManBearTM
body: nitpick: readability
```suggestion
      <watt-segmented-button value="day">Day</watt-segmented-button>
      <watt-segmented-button value="month">Month</watt-segmented-button>
      <watt-segmented-button value="year">Year</watt-segmented-button>
      <watt-segmented-button value="all years">All Years</watt-segmented-button>
```
created_at: 2025-04-11T10:41:07Z
author_association: CONTRIBUTOR

PR comments:
user: login: nx-cloud[bot]
created_at: 2025-04-09T08:41:58Z
body: 
View your [CI Pipeline Execution ↗](https://cloud.nx.app/cipes/67f8f70f19e50a29715b9481?utm_source=pull-request&utm_medium=comment) for commit 61bb8fb4faf9b34bcb392877afef4155ddf391da.

| Command | Status | Duration | Result |
|---------|--------|----------:|--------|
| `nx build app-dh` | ✅ Succeeded | 1m 14s | [View ↗](https://cloud.nx.app/runs/GKfjLKee5a?utm_source=pull-request&utm_medium=comment) |
| `nx run watt:package` | ✅ Succeeded | 19s | [View ↗](https://cloud.nx.app/runs/j30AcKouYD?utm_source=pull-request&utm_medium=comment) |
| `nx run watt:build-storybook` | ✅ Succeeded | 27s | [View ↗](https://cloud.nx.app/runs/SUPTmqAGEw?utm_source=pull-request&utm_medium=comment) |

---

☁️ [Nx Cloud](https://cloud.nx.app?utm_source=pull-request&utm_medium=comment) last updated this comment at `2025-04-11 11:10:28` UTC

<!-- NX_CLOUD_APP_COMMENT_END -->
author_association: NONE
user: login: mimse
created_at: 2025-04-09T09:57:43Z
body: Praise: nice work 👍🏻 

Suggestions:
I think we need to rethink providing an array of buttons to the component in favor of using child components instead.
This will align it with the other components that we have (look at watt-tab(s)) it will also make it possible to add @if logic and permissions directives the children components.
This will be harder to do when providing an array.
author_association: CONTRIBUTOR