From 83f4aef85d2dd2bc24e2b328d559a016371a52fa Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 25 Feb 2026 15:32:57 +0100 Subject: [PATCH 01/43] okay lets go! --- .../fhi-table/fhi-table.component.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts diff --git a/packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts new file mode 100644 index 00000000..404f0db2 --- /dev/null +++ b/packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts @@ -0,0 +1,19 @@ +import { html, css, LitElement } from 'lit'; +import { customElement } from 'lit/decorators.js'; + +export const FhiTableSelector = 'fhi-table'; + +@customElement(FhiTableSelector) +export class FhiTable extends LitElement { + render() { + return html` +
+ + + +
+ `; + } + + static styles = css``; +} From a55e11495ac7c8e2e4b97450aa9099eb02f60db9 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 25 Feb 2026 15:46:40 +0100 Subject: [PATCH 02/43] wip --- .../src/components/{ => table}/fhi-table/fhi-table.component.ts | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/fhi-designsystem/src/components/{ => table}/fhi-table/fhi-table.component.ts (100%) diff --git a/packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts similarity index 100% rename from packages/fhi-designsystem/src/components/fhi-table/fhi-table.component.ts rename to packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts From b823ffdc1ce21013823d9e86cf65e08723f2089f Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Fri, 27 Feb 2026 15:19:49 +0100 Subject: [PATCH 03/43] wip using grid. missing rows --- .../fhi-table-cell.component.ts | 30 +++++++++++++++++++ .../table/fhi-table/fhi-table.component.ts | 23 +++++++++----- 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts new file mode 100644 index 00000000..385aa637 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -0,0 +1,30 @@ +import { html, css, LitElement, PropertyValues } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +export const FhiTableCellSelector = 'fhi-table-cell'; + +@customElement(FhiTableCellSelector) +export class FhiTableCell extends LitElement { + @property({ type: String, attribute: 'row-span' }) + rowSpan = 'span 1'; + + @property({ type: String, attribute: 'col-span' }) + colSpan = 'span 1'; + + protected update(changedProperties: PropertyValues): void { + super.update(changedProperties); + + this.style.gridRow = this.rowSpan; + this.style.gridColumn = this.colSpan; + } + + render() { + return html` `; + } + + static styles = css` + :host { + display: block; + } + `; +} diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 404f0db2..1b5e2fb6 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -1,19 +1,28 @@ import { html, css, LitElement } from 'lit'; -import { customElement } from 'lit/decorators.js'; +import { customElement, property } from 'lit/decorators.js'; + +import '../../fhi-grid/fhi-grid.component'; export const FhiTableSelector = 'fhi-table'; @customElement(FhiTableSelector) export class FhiTable extends LitElement { + @property({ type: Number }) + rows = 0; + + @property({ type: Number }) + colums = 0; + render() { return html` -
- - - -
+ + + `; } - static styles = css``; + static styles = css` + :host { + } + `; } From 3dc7acca9e5e0cf04866a51ca00fe6b2a19a25d7 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Fri, 27 Feb 2026 16:23:55 +0100 Subject: [PATCH 04/43] add rows functionality to grid --- .../components/fhi-grid/fhi-grid.component.ts | 10 ++ .../src/components/fhi-grid/fhi-grid.docs.mdx | 8 ++ .../components/fhi-grid/fhi-grid.stories.ts | 126 ++++++++---------- .../src/components/fhi-grid/fhi-grid.test.ts | 8 ++ 4 files changed, 84 insertions(+), 68 deletions(-) diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.component.ts b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.component.ts index 319f846a..9b4eca26 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.component.ts +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.component.ts @@ -36,6 +36,12 @@ export class FhiGrid extends LitElement { */ @property({ type: Number }) columns = 12; + /** + * Sets the number of rows in the grid layout. + * @type {number} + */ + @property({ type: Number }) rows = 1; + updated(changedProperties: PropertyValues) { super.updated(changedProperties); @@ -43,6 +49,10 @@ export class FhiGrid extends LitElement { this.style.gridTemplateColumns = `repeat( ${this.columns}, 1fr )`; } + if (changedProperties.has('rows')) { + this.style.gridTemplateRows = `repeat( ${this.rows}, 1fr )`; + } + if (changedProperties.has('gap')) { switch (this.gap) { case 'large': diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx index f7bf8c43..015ce40f 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx @@ -31,6 +31,14 @@ Hvis span ikke er definert på elementene i grid vil hvert element ta opp en kol +### Rader + +Grid har ingen forhåndsdefinerte rader, men det er mulig å sette et ønsket antall rader. + +Eksempel med satandard 12 colonner, og 8 rader. Elementene er plassert i i griddet med standard `grid-column` og `grid-row` css. + + + ### Gap Grid har noen forhåndsdefinerte avstander man kan sette: diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts index 7922c6e7..02164cc8 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts @@ -1,6 +1,6 @@ import type { Meta, StoryObj } from '@storybook/web-components-vite'; -import { html } from 'lit'; +import { html } from 'lit/html.js'; import { FhiGrid } from './fhi-grid.component'; @@ -16,7 +16,26 @@ const meta: Meta = { }, }, }, - decorators: [], + decorators: [ + Story => + html`
+ + ${Story()} +
`, + ], render: args => html``, argTypes: { gap: { @@ -30,6 +49,11 @@ const meta: Meta = { description: 'Bestemmer antall kolonner', defaultValue: { summary: '12' }, }, + rows: { + controls: 'number', + description: 'Bestemmer antall rader', + defaultValue: { summary: '1' }, + }, }, }; @@ -40,24 +64,13 @@ export const Preview: Story = { args: { gap: 'medium', columns: 12, + rows: 1, }, render: args => html` - -
- Slot -
-
- Slot -
-
- Slot -
+ +
Slot
+
Slot
+
Slot
`, }; @@ -70,41 +83,30 @@ export const LargeGrid: Story = { }, render: args => html` -
- Slot -
-
- Slot -
-
- Slot -
-
- Slot -
-
- Slot -
-
- Slot -
-
- Slot -
+
Slot
+
Slot
+
Slot
+
Slot
+
Slot
+
Slot
+
Slot
+
+ `, +}; + +export const GridWithRowsAndColumns: Story = { + tags: [], + args: { + gap: 'medium', + columns: 12, + rows: 8, + }, + render: args => html` + +
Slot
+
Slot
+
Slot
+
Slot
`, }; @@ -117,21 +119,9 @@ export const NoSpan: Story = { }, render: args => html` -
- Slot -
-
- Slot -
-
- Slot -
+
Slot
+
Slot
+
Slot
`, }; diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.test.ts b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.test.ts index 873319c2..c2fa2fe8 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.test.ts +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.test.ts @@ -32,6 +32,14 @@ describe('fhi-grid', () => { expect(component.columns).to.equal(8); }); + it('has an attribute to set rows', async () => { + const component = await fixture( + html``, + ); + expect(component.getAttribute('rows')).to.equal('4'); + expect(component.rows).to.equal(4); + }); + it('has an attribute to set gap', async () => { const component = await fixture( html``, From 3a54f979df666d3302ca280979555086556dc2fd Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Fri, 27 Feb 2026 16:28:20 +0100 Subject: [PATCH 05/43] edit the docs --- .../src/components/fhi-grid/fhi-grid.docs.mdx | 4 ++-- .../src/components/fhi-grid/fhi-grid.stories.ts | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx index 015ce40f..07bf0217 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx @@ -33,9 +33,9 @@ Hvis span ikke er definert på elementene i grid vil hvert element ta opp en kol ### Rader -Grid har ingen forhåndsdefinerte rader, men det er mulig å sette et ønsket antall rader. +Du kan bruke rader for å få mer kontroll over plasseringen av elementene i griddet. Rader er ikke nødvendig for å bruke grid, men kan være nyttig. -Eksempel med satandard 12 colonner, og 8 rader. Elementene er plassert i i griddet med standard `grid-column` og `grid-row` css. +Eksempel med standard medium gap, 12 colonner, og eksplisitt satte 8 rader. Elementene er plassert i griddet med standard `grid-column` og `grid-row` css. diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts index 02164cc8..5ae92afb 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.stories.ts @@ -98,11 +98,10 @@ export const GridWithRowsAndColumns: Story = { tags: [], args: { gap: 'medium', - columns: 12, rows: 8, }, render: args => html` - +
Slot
Slot
Slot
From 9871f69c9603e94572d1fac2c03df91891cb6a80 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Sat, 28 Feb 2026 13:25:28 +0100 Subject: [PATCH 06/43] change rows docs --- .../src/components/fhi-grid/fhi-grid.docs.mdx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx index 07bf0217..10e0ea48 100644 --- a/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx +++ b/packages/fhi-designsystem/src/components/fhi-grid/fhi-grid.docs.mdx @@ -33,7 +33,7 @@ Hvis span ikke er definert på elementene i grid vil hvert element ta opp en kol ### Rader -Du kan bruke rader for å få mer kontroll over plasseringen av elementene i griddet. Rader er ikke nødvendig for å bruke grid, men kan være nyttig. +Grid tar utgangspunkt i 1 rad, men er mulig å endre. Fler rader kan brukes for å få mer kontroll over plasseringen av elementene i griddet. Eksempel med standard medium gap, 12 colonner, og eksplisitt satte 8 rader. Elementene er plassert i griddet med standard `grid-column` og `grid-row` css. @@ -47,5 +47,3 @@ Grid har noen forhåndsdefinerte avstander man kan sette: - Large: 1.5rem (24px) I tillegg kan man sette egen verdi i tilfeller der standardene ikke er nok, for eksempel når man trenger ingen eller negativ avstand mellom elementene. - - From 4a21b19d843ad3d427e24489936b8b414bc2084c Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Mon, 2 Mar 2026 10:55:38 +0100 Subject: [PATCH 07/43] wip --- .../src/components/table/fhi-table/fhi-table.component.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 1b5e2fb6..6705e5e6 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -8,14 +8,14 @@ export const FhiTableSelector = 'fhi-table'; @customElement(FhiTableSelector) export class FhiTable extends LitElement { @property({ type: Number }) - rows = 0; + rows = 1; @property({ type: Number }) - colums = 0; + columns = 1; render() { return html` - + `; From f28524bc22a6eab0563826c0d6403d266c02d311 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Mon, 2 Mar 2026 20:52:26 +0100 Subject: [PATCH 08/43] try out some examples --- .../src/components/table/docs.mdx | 19 ++ .../fhi-table-cell.component.ts | 50 ++++- .../table/fhi-table/fhi-table.component.ts | 34 ++- .../table/fhi-table/fhi-table.stories.ts | 196 ++++++++++++++++++ 4 files changed, 284 insertions(+), 15 deletions(-) create mode 100644 packages/fhi-designsystem/src/components/table/docs.mdx create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx new file mode 100644 index 00000000..8b750a4c --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -0,0 +1,19 @@ +import { FhiTable } from './fhi-table/fhi-table.component.ts'; +import * as FhiTableStories from './fhi-table/fhi-table.stories.ts'; +import { Meta, Primary, Canvas, Controls } from '@storybook/addon-docs/blocks'; + + + +# Table + +Tabell brukes for å presentere data og informasjon på en ryddig måte. Brukeren kan raskt få oversikt og skanne innholdet effektivt. + +## Passer til + +- Å vise lister med større mengder strukturert data på en måte som er lett å lese og sammenligne + + + + + + diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 385aa637..ef11d382 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -5,26 +5,58 @@ export const FhiTableCellSelector = 'fhi-table-cell'; @customElement(FhiTableCellSelector) export class FhiTableCell extends LitElement { - @property({ type: String, attribute: 'row-span' }) - rowSpan = 'span 1'; + @property({ type: String }) + row = 'span 1'; - @property({ type: String, attribute: 'col-span' }) - colSpan = 'span 1'; + @property({ type: String }) + column = 'span 1'; + + @property({ type: String }) + variant: 'header' | 'body' = 'body'; protected update(changedProperties: PropertyValues): void { - super.update(changedProperties); + this.style.gridRow = this.row; + this.style.gridColumn = this.column; - this.style.gridRow = this.rowSpan; - this.style.gridColumn = this.colSpan; + if (changedProperties.has('variant')) { + if (this.variant != 'header' && this.variant != 'body') { + this.variant = 'body'; + } + } + + super.update(changedProperties); } render() { - return html` `; + return html`
+ +
`; } static styles = css` :host { - display: block; + --justify-content: start; + --align-items: center; + } + + :host { + div { + display: flex; + justify-content: var(--justify-content); + align-items: var(--align-items); + padding: 1rem; + height: -webkit-fill-available; + } + + div[role='cell'] { + border-bottom: 1px solid var(--fhi-color-neutral-border-subtle); + } + + div[role='columnheader'] { + border-bottom: 1px solid var(--fhi-color-neutral-border-default); + } } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 6705e5e6..8d6773ab 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -2,27 +2,49 @@ import { html, css, LitElement } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import '../../fhi-grid/fhi-grid.component'; +import '../../typography/fhi-body/fhi-body.component'; + +import { ifDefined } from 'lit/directives/if-defined.js'; export const FhiTableSelector = 'fhi-table'; @customElement(FhiTableSelector) export class FhiTable extends LitElement { - @property({ type: Number }) - rows = 1; + @property({ type: String }) + rows = '1'; + + @property({ type: String }) + columns = '1'; - @property({ type: Number }) - columns = 1; + @property({ type: String }) + caption?: string; render() { return html` - +
- +
+ ${this.caption + ? html`${this.caption}` + : null} `; } static styles = css` :host { + #caption { + display: block; + padding: 1rem; + } + + div { + display: grid; + } } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts new file mode 100644 index 00000000..e63fe7b6 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -0,0 +1,196 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from 'lit'; + +import { FhiTable } from './fhi-table.component'; +import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; +import { FhiCheckbox } from '../../fhi-checkbox/fhi-checkbox.component'; +import { FhiButton } from '../../fhi-button/fhi-button.component'; +import { FhiBody } from '../../typography/fhi-body/fhi-body.component'; +import { FhiLabel } from '../../typography/fhi-label/fhi-label.component'; + +import { FhiIconEye } from '../../icons/fhi-icon-eye.component'; +import { FhiIconDownload } from '../../icons/fhi-icon-download.component'; +import { FhiIconTrash } from '../../icons/fhi-icon-trash.component'; +import { ifDefined } from 'lit/directives/if-defined.js'; + +new FhiTable(); +new FhiTableCell(); +new FhiBody(); +new FhiLabel(); +new FhiCheckbox(); +new FhiButton(); +new FhiIconEye(); +new FhiIconDownload(); +new FhiIconTrash(); + +const meta: Meta = { + title: 'Komponenter/Table', + component: 'fhi-table', + parameters: {}, + decorators: [], + argTypes: { + columns: { + control: 'text', + description: + 'Definerer kolonnene i tabellen. Bruk CSS grid-syntaks, for eksempel "1fr 2fr 1fr" for tre kolonner med ulik bredde.', + defaultValue: { summary: '1' }, + }, + caption: { + control: 'text', + description: + 'Valgfri tekst som beskriver innholdet. Dette fungerer som tabellen sin tittel og er visuelt plassert under tabellen', + defaultValue: { summary: '1' }, + }, + }, +}; + +type Story = StoryObj; + +export const Preview: Story = { + tags: [], + args: {}, + render: () => html` + + + + 2021 + + + 2022 + + + 2023 + + + + Pasienter totalt + + + 374 964 + + + 383 347 + + + 392 106 + + + + Sykdommer i sirkulasjonssystemet (I00-I99) + + + 279 726 + + + 289 149 + + + 291 655 + + + `, +}; + +export const MoreComplex: Story = { + tags: [], + args: {}, + render: () => html` + + + Nr. + + + Tittel + + + Institusjon + + + Prosjektleder + + + Sluttdato + + + + + 3305 + + + VKM - inntak av energidrikker hos 13-åringer + + + Hesle Vest RHF + + + Pelle Parafin + + + 10.10.2027 + + + Gå til prosjekt + + + `, +}; + +export const WithCheckboxes: Story = { + tags: [], + args: { + columns: '1fr 6fr 3fr 3fr 4fr 3fr', + caption: 'Avkrysningsbokser.', + }, + render: args => html` + + + + Mal + + + Dimensjon + + + Opprettet + + + Opprettet av + + + + + + + + Geografi 2023 - norsk + + + GEO + + + 10.10.2027 + + + Pelle Parafin + + + + + Eksportèr + + + + Vis + + + + + + + `, +}; + +export default meta; From 6ca2dee83fe4dc3097324f8bb03145dc849e72e1 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 3 Mar 2026 10:49:28 +0100 Subject: [PATCH 09/43] add some tokens --- .../fhi-table-cell.component.ts | 20 +++++++++++-------- .../table/fhi-table/fhi-table.component.ts | 4 ++-- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index ef11d382..19387559 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -11,7 +11,7 @@ export class FhiTableCell extends LitElement { @property({ type: String }) column = 'span 1'; - @property({ type: String }) + @property({ type: String, reflect: true }) variant: 'header' | 'body' = 'body'; protected update(changedProperties: PropertyValues): void { @@ -39,6 +39,13 @@ export class FhiTableCell extends LitElement { :host { --justify-content: start; --align-items: center; + --padding: 1rem; + --border-bottom: 1px solid var(--fhi-color-neutral-border-subtle); + --height: -webkit-fill-available; + } + + :host([variant='header']) { + --border-bottom: 1px solid var(--fhi-color-neutral-border-default); } :host { @@ -46,16 +53,13 @@ export class FhiTableCell extends LitElement { display: flex; justify-content: var(--justify-content); align-items: var(--align-items); - padding: 1rem; - height: -webkit-fill-available; - } - - div[role='cell'] { - border-bottom: 1px solid var(--fhi-color-neutral-border-subtle); + padding: var(--padding); + height: var(--height); + border-bottom: var(--border-bottom); } div[role='columnheader'] { - border-bottom: 1px solid var(--fhi-color-neutral-border-default); + border-bottom: var(--border-bottom); } } `; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 8d6773ab..78b3661b 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -16,7 +16,7 @@ export class FhiTable extends LitElement { @property({ type: String }) columns = '1'; - @property({ type: String }) + @property({ type: String, reflect: true }) caption?: string; render() { @@ -42,7 +42,7 @@ export class FhiTable extends LitElement { padding: 1rem; } - div { + div[role='table'] { display: grid; } } From 2c91f6e1edad8ed84abf3a2fcd20302e2495620b Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 3 Mar 2026 12:38:36 +0100 Subject: [PATCH 10/43] add more tokens --- .../src/components/table/docs.mdx | 16 +++ .../fhi-table-cell.component.ts | 26 +++- .../table/fhi-table/fhi-table.component.ts | 18 ++- .../table/fhi-table/fhi-table.stories.ts | 133 +++++++----------- 4 files changed, 105 insertions(+), 88 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index 8b750a4c..e09fc0dc 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -8,6 +8,12 @@ import { Meta, Primary, Canvas, Controls } from '@storybook/addon-docs/blocks'; Tabell brukes for å presentere data og informasjon på en ryddig måte. Brukeren kan raskt få oversikt og skanne innholdet effektivt. +
+ På grunnet av en foreløpig begrensning i standard HTML `` sin interaksjon med shadow-DOM, har vi i steden implementert tabellen med CSS grid i bakgrunnen. + + +Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for både enkle og mer komplekse tabeller. Det er også mulig å legge til en caption som fungerer som en tittel for tabellen. + ## Passer til - Å vise lister med større mengder strukturert data på en måte som er lett å lese og sammenligne @@ -17,3 +23,13 @@ Tabell brukes for å presentere data og informasjon på en ryddig måte. Brukere + + \ No newline at end of file diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 19387559..eebc9b6b 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -39,13 +39,29 @@ export class FhiTableCell extends LitElement { :host { --justify-content: start; --align-items: center; - --padding: 1rem; - --border-bottom: 1px solid var(--fhi-color-neutral-border-subtle); + --padding: var(--fhi-spacing-200); --height: -webkit-fill-available; + + --color: var(--fhi-color-neutral-text-default); + --letter-spacing: var(--letter-spacing-medium); + + --border-bottom: var(--fhi-dimension-border-width) solid + var(--fhi-color-neutral-border-subtle); + + --font: var(--fhi-typography-body-medium-font-weight) + var(--fhi-typography-body-medium-font-size) / + var(--fhi-typography-body-medium-line-height) + var(--fhi-font-family-default); } :host([variant='header']) { - --border-bottom: 1px solid var(--fhi-color-neutral-border-default); + --border-bottom: var(--fhi-dimension-border-width) solid + var(--fhi-color-neutral-border-default); + + --font: var(--fhi-typography-label-medium-font-weight) + var(--fhi-typography-label-medium-font-size) / + var(--fhi-typography-label-medium-line-height) + var(--fhi-font-family-default); } :host { @@ -56,6 +72,10 @@ export class FhiTableCell extends LitElement { padding: var(--padding); height: var(--height); border-bottom: var(--border-bottom); + + font: var(--font); + color: var(--color); + letter-spacing: var(--letter-spacing); } div[role='columnheader'] { diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 78b3661b..8ebff2b1 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -1,4 +1,4 @@ -import { html, css, LitElement } from 'lit'; +import { html, css, LitElement, PropertyValues } from 'lit'; import { customElement, property } from 'lit/decorators.js'; import '../../fhi-grid/fhi-grid.component'; @@ -19,6 +19,22 @@ export class FhiTable extends LitElement { @property({ type: String, reflect: true }) caption?: string; + protected update(changedProperties: PropertyValues): void { + if (changedProperties.has('rows')) { + if (!this.rows) { + this.rows = '1'; + } + } + + if (changedProperties.has('columns')) { + if (!this.columns) { + this.columns = '1'; + } + } + + super.update(changedProperties); + } + render() { return html`
= { columns: { control: 'text', description: - 'Definerer kolonnene i tabellen. Bruk CSS grid-syntaks, for eksempel "1fr 2fr 1fr" for tre kolonner med ulik bredde.', + 'Definerer kolonnene i tabellen. Bruker CSS grid-template-columns i bakgrunnen. Bruke denne for å definere antall kolonner og deres bredder.', + defaultValue: { summary: '1' }, + }, + rows: { + control: 'text', + description: + 'Definerer radene i tabellen. Bruker CSS grid-template-rows i bakgrunnen. Rader vil automatisk legges til om antall elementer er mer enn antall definerte kolonner. Bruk denne om du ønsker mer kontroll over radstørrelsene.', defaultValue: { summary: '1' }, }, caption: { control: 'text', description: 'Valgfri tekst som beskriver innholdet. Dette fungerer som tabellen sin tittel og er visuelt plassert under tabellen', - defaultValue: { summary: '1' }, + defaultValue: { summary: undefined }, }, }, }; @@ -48,88 +50,63 @@ type Story = StoryObj; export const Preview: Story = { tags: [], - args: {}, - render: () => html` - + args: { + columns: '3fr 1fr 1fr 1fr', + caption: 'Total forekomst: Utvalgte diagnoser, antall', + }, + render: args => html` + - 2021 + 2021 - 2022 + 2022 - 2023 + 2023 - - Pasienter totalt - - - 374 964 - - - 383 347 - - - 392 106 - + Pasienter totalt + 374 964 + 383 347 + 392 106 - Sykdommer i sirkulasjonssystemet (I00-I99) - - - 279 726 - - - 289 149 - - - 291 655 + Sykdommer i sirkulasjonssystemet (I00-I99) + 279 726 + 289 149 + 291 655 `, }; export const MoreComplex: Story = { tags: [], - args: {}, - render: () => html` - - - Nr. - - - Tittel - - - Institusjon - - - Prosjektleder - + args: { + columns: '1fr 8fr 3fr 3fr 2fr 3fr', + caption: 'Tabell med flere kolonner og mer innhold.', + }, + render: args => html` + + Nr. + Tittel + Institusjon + Prosjektleder - Sluttdato + Sluttdato + 3305 - 3305 - - - VKM - inntak av energidrikker hos 13-åringer - - - Hesle Vest RHF - - - Pelle Parafin + VKM - inntak av energidrikker hos 13-åringer + Hesle Vest RHF + Pelle Parafin - 10.10.2027 + 10.10.2027 Gå til prosjekt @@ -147,35 +124,23 @@ export const WithCheckboxes: Story = { render: args => html` - - Mal - - - Dimensjon - + Mal + Dimensjon - Opprettet - - - Opprettet av + Opprettet + Opprettet av - - Geografi 2023 - norsk - - - GEO - + Geografi 2023 - norsk + GEO - 10.10.2027 - - - Pelle Parafin + 10.10.2027 + Pelle Parafin From 0907272a2e1502961c1a8c64b8d4bcc2d4c7c2d0 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 4 Mar 2026 16:55:13 +0100 Subject: [PATCH 11/43] better example --- .../src/components/table/docs.mdx | 3 +- .../table/fhi-table/fhi-table.stories.ts | 69 ++++++++++++++++--- 2 files changed, 62 insertions(+), 10 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index e09fc0dc..5a71a792 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -21,9 +21,10 @@ Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for b - + + \ No newline at end of file diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index eebc9b6b..6dccf633 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -5,82 +5,63 @@ export const FhiTableCellSelector = 'fhi-table-cell'; @customElement(FhiTableCellSelector) export class FhiTableCell extends LitElement { - @property({ type: String }) - row = 'span 1'; - - @property({ type: String }) - column = 'span 1'; - @property({ type: String, reflect: true }) variant: 'header' | 'body' = 'body'; protected update(changedProperties: PropertyValues): void { - this.style.gridRow = this.row; - this.style.gridColumn = this.column; - if (changedProperties.has('variant')) { - if (this.variant != 'header' && this.variant != 'body') { - this.variant = 'body'; - } + this.role = this.variant === 'header' ? 'columnheader' : 'cell'; } super.update(changedProperties); } render() { - return html`
- -
`; + return html``; } static styles = css` :host { - --justify-content: start; - --align-items: center; - --padding: var(--fhi-spacing-200); - --height: -webkit-fill-available; - - --color: var(--fhi-color-neutral-text-default); - --letter-spacing: var(--letter-spacing-medium); - - --border-bottom: var(--fhi-dimension-border-width) solid - var(--fhi-color-neutral-border-subtle); - - --font: var(--fhi-typography-body-medium-font-weight) + --fhi-table-cell-justify-content: end; + --fhi-table-cell-align-items: center; + --fhi-table-cell-padding: var(--fhi-spacing-200); + --fhi-table-cell-height: -webkit-fill-available; + --fhi-table-cell-background: initial; + + --fhi-table-cell-color: var(--fhi-color-neutral-text-default); + --fhi-table-cell-letter-spacing: var( + --fhi-typography-body-medium-letter-spacing + ); + --fhi-table-cell-font: var(--fhi-typography-body-medium-font-weight) var(--fhi-typography-body-medium-font-size) / var(--fhi-typography-body-medium-line-height) var(--fhi-font-family-default); } :host([variant='header']) { - --border-bottom: var(--fhi-dimension-border-width) solid - var(--fhi-color-neutral-border-default); - - --font: var(--fhi-typography-label-medium-font-weight) + --fhi-table-cell-letter-spacing: var( + --fhi-typography-label-medium-letter-spacing + ); + --fhi-table-cell-font: var(--fhi-typography-label-medium-font-weight) var(--fhi-typography-label-medium-font-size) / var(--fhi-typography-label-medium-line-height) var(--fhi-font-family-default); } :host { - div { - display: flex; - justify-content: var(--justify-content); - align-items: var(--align-items); - padding: var(--padding); - height: var(--height); - border-bottom: var(--border-bottom); - - font: var(--font); - color: var(--color); - letter-spacing: var(--letter-spacing); - } - - div[role='columnheader'] { - border-bottom: var(--border-bottom); - } + display: flex; + justify-content: var(--fhi-table-cell-justify-content); + align-items: var(--fhi-table-cell-align-items); + padding: var(--fhi-table-cell-padding); + height: var(--fhi-table-cell-height); + min-width: min-content; + overflow: hidden; + flex-wrap: wrap; + background: var(--fhi-table-cell-background); + + font: var(--fhi-table-cell-font); + color: var(--fhi-table-cell-color); + letter-spacing: var(--fhi-table-cell-letter-spacing); } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts new file mode 100644 index 00000000..1b10f1ed --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -0,0 +1,58 @@ +import { html, css, LitElement, PropertyValues } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +export const FhiTableRowSelector = 'fhi-table-row'; + +@customElement(FhiTableRowSelector) +export class FhiTableRow extends LitElement { + @property({ type: String, reflect: true, attribute: 'column-span' }) + columnSpan = 'span 1'; + + @property({ type: String, reflect: true }) + columns = '1fr'; + + @property({ type: String, reflect: true }) + variant: 'header' | 'body' = 'body'; + + connectedCallback(): void { + super.connectedCallback(); + + this.setAttribute('role', 'row'); + } + + protected update(changedProperties: PropertyValues): void { + if (changedProperties.has('columns')) { + this.style.gridTemplateColumns = this.columns; + } + + if (changedProperties.has('columnSpan')) { + this.style.gridColumn = this.columnSpan; + } + + super.update(changedProperties); + } + + render() { + return html``; + } + + static styles = css` + :host { + --fhi-table-row-background: initial; + + --fhi-table-row-border-bottom: var(--fhi-dimension-border-width) solid + var(--fhi-color-neutral-border-subtle); + } + + :host([variant='header']) { + --fhi-table-row-border-bottom: var(--fhi-dimension-border-width) solid + var(--fhi-color-neutral-border-default); + } + + :host { + display: grid; + border-bottom: var(--fhi-table-row-border-bottom); + background: var(--fhi-table-row-background); + } + `; +} diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 8ebff2b1..f28f2b86 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -4,32 +4,25 @@ import { customElement, property } from 'lit/decorators.js'; import '../../fhi-grid/fhi-grid.component'; import '../../typography/fhi-body/fhi-body.component'; -import { ifDefined } from 'lit/directives/if-defined.js'; - export const FhiTableSelector = 'fhi-table'; @customElement(FhiTableSelector) export class FhiTable extends LitElement { - @property({ type: String }) - rows = '1'; - - @property({ type: String }) - columns = '1'; + @property({ type: String, reflect: true }) + columns = '1fr'; @property({ type: String, reflect: true }) caption?: string; - protected update(changedProperties: PropertyValues): void { - if (changedProperties.has('rows')) { - if (!this.rows) { - this.rows = '1'; - } - } + connectedCallback(): void { + super.connectedCallback(); - if (changedProperties.has('columns')) { - if (!this.columns) { - this.columns = '1'; - } + this.setAttribute('role', 'table'); + } + + protected update(changedProperties: PropertyValues): void { + if (this.caption) { + this.setAttribute('aria-label', this.caption); } super.update(changedProperties); @@ -37,14 +30,8 @@ export class FhiTable extends LitElement { render() { return html` -
- -
+
+ ${this.caption ? html`${this.caption}` : null} @@ -57,10 +44,6 @@ export class FhiTable extends LitElement { display: block; padding: 1rem; } - - div[role='table'] { - display: grid; - } } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 46a9d50d..ddc7a69c 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -3,9 +3,15 @@ import { html } from 'lit'; import { FhiTable } from './fhi-table.component'; import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; +import { FhiTableRow } from '../fhi-table-row/fhi-table-row.component'; + import { FhiCheckbox } from '../../fhi-checkbox/fhi-checkbox.component'; import { FhiButton } from '../../fhi-button/fhi-button.component'; +import { FhiDisplay } from '../../typography/fhi-display/fhi-display.component'; +import { FhiTitle } from '../../typography/fhi-title/fhi-title.component'; +import { FhiBody } from '../../typography/fhi-body/fhi-body.component'; + import { FhiIconEye } from '../../icons/fhi-icon-eye.component'; import { FhiIconDownload } from '../../icons/fhi-icon-download.component'; import { FhiIconTrash } from '../../icons/fhi-icon-trash.component'; @@ -13,30 +19,23 @@ import { ifDefined } from 'lit/directives/if-defined.js'; new FhiTable(); new FhiTableCell(); +new FhiTableRow(); new FhiCheckbox(); new FhiButton(); new FhiIconEye(); new FhiIconDownload(); new FhiIconTrash(); +new FhiDisplay(); +new FhiTitle(); +new FhiBody(); + const meta: Meta = { title: 'Komponenter/Table', component: 'fhi-table', parameters: {}, decorators: [], argTypes: { - columns: { - control: 'text', - description: - 'Definerer kolonnene i tabellen. Bruker CSS grid-template-columns i bakgrunnen. Bruke denne for å definere antall kolonner og deres bredder.', - defaultValue: { summary: '1' }, - }, - rows: { - control: 'text', - description: - 'Definerer radene i tabellen. Bruker CSS grid-template-rows i bakgrunnen. Rader vil automatisk legges til om antall elementer er mer enn antall definerte kolonner. Bruk denne om du ønsker mer kontroll over radstørrelsene.', - defaultValue: { summary: '1' }, - }, caption: { control: 'text', description: @@ -51,117 +50,154 @@ type Story = StoryObj; export const Preview: Story = { tags: [], args: { - columns: '3fr 1fr 1fr 1fr', caption: 'Total forekomst: Utvalgte diagnoser, antall', }, render: args => html` - - - - 2021 - - - 2022 - - - 2023 - - - Pasienter totalt - 374 964 - 383 347 - 392 106 - - - Sykdommer i sirkulasjonssystemet (I00-I99) - - 279 726 - 289 149 - 291 655 + + + + 2021 + 2022 + 2023 + + + + + Pasienter totalt + + 374 964 + 383 347 + 392 106 + + + + + Sykdommer i sirkulasjonssystemet (I00-I99) + + 279 726 + 289 149 + 291 655 + `, }; -export const MoreComplex: Story = { +export const ComplexData: Story = { tags: [], - args: { - columns: 'repeat(7, 1fr)', - caption: 'Tabell med flere kolonner og mer innhold.', - }, + args: {}, render: args => html` - - - Nr. - Tittel - Institusjon - Prosjektleder - - - - - - - - 3305 - - VKM - inntak av energidrikker hos 13-åringer - - Hesle Vest RHF - Pelle Parafin - - - 3305 - - VKM - inntak av energidrikker hos 13-åringer - - Hesle Vest RHF - Pelle Parafin - - - - - - 3305 - - VKM - inntak av energidrikker hos 13-åringer - - Hesle Vest RHF - Pelle Parafin - - - 3305 - - VKM - inntak av energidrikker hos 13-åringer - - Hesle Vest RHF - Pelle Parafin + + + + P0a: Fødte per måned og mors bosted (med og uten fødselsmelding i MFR) + +
+ + Foreløpige tall kan endres ved senere oppdateringer. Tabellen inkluderer + fødte med fødselsmelding i MFR, som har fødselsvekt ≥ 500 gram og/eller + svangerskapet har vart ≥ 22 uker. Tabellen viser i tillegg fødte uten + fødselsmelding i MFR basert på informasjon fra Folkeregisteret¹. + +
+ + + + Oslo + + Januar + Februar + Mars + April + + + + + Alle fødte + + 685 + - + - + - + + + + + Med fødselsmelding + + 662 + - + - + - + + + + + Uten fødselsmelding + + 23 + - + - + - + + + +
+ + + + Østfold + + + + + + + + + + Alle fødte + + 230 + - + - + - + + + + + Med fødselsmelding + + 229 + - + - + - + + + + + Uten fødselsmelding + + 1 + - + - + - + `, }; @@ -169,42 +205,41 @@ export const MoreComplex: Story = { export const WithCheckboxes: Story = { tags: [], args: { - columns: '1fr 6fr 3fr 3fr 4fr 3fr', caption: 'Avkrysningsbokser.', }, render: args => html` - - - Mal - Dimensjon - - Opprettet - - Opprettet av - - - - - - Geografi 2023 - norsk - GEO - - 10.10.2027 - - Pelle Parafin - - - - Eksportèr - - - - Vis - - - - - + + + + Mal + Dimensjon + Opprettet + Opprettet av + + + + + + + + Geografi 2023 - norsk + GEO + 10.10.2027 + Pelle Parafin + + + + Eksportèr + + + + Vis + + + + + + `, }; From 796481d39f6ad1bc7633817188670130c15fe814 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 5 Mar 2026 11:30:51 +0100 Subject: [PATCH 13/43] fix some examples and remove unused apis --- .../fhi-table-row/fhi-table-row.component.ts | 7 ---- .../table/fhi-table/fhi-table.component.ts | 10 +++-- .../table/fhi-table/fhi-table.stories.ts | 41 ++++++++++++++----- 3 files changed, 37 insertions(+), 21 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 1b10f1ed..220fb74e 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -5,9 +5,6 @@ export const FhiTableRowSelector = 'fhi-table-row'; @customElement(FhiTableRowSelector) export class FhiTableRow extends LitElement { - @property({ type: String, reflect: true, attribute: 'column-span' }) - columnSpan = 'span 1'; - @property({ type: String, reflect: true }) columns = '1fr'; @@ -25,10 +22,6 @@ export class FhiTableRow extends LitElement { this.style.gridTemplateColumns = this.columns; } - if (changedProperties.has('columnSpan')) { - this.style.gridColumn = this.columnSpan; - } - super.update(changedProperties); } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index f28f2b86..a827159c 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -8,9 +8,6 @@ export const FhiTableSelector = 'fhi-table'; @customElement(FhiTableSelector) export class FhiTable extends LitElement { - @property({ type: String, reflect: true }) - columns = '1fr'; - @property({ type: String, reflect: true }) caption?: string; @@ -30,7 +27,6 @@ export class FhiTable extends LitElement { render() { return html` -
${this.caption ? html`${this.caption}` @@ -40,6 +36,12 @@ export class FhiTable extends LitElement { static styles = css` :host { + --fhi-table-width: auto; + } + + :host { + display: block; + width: var(--fhi-table-width); #caption { display: block; padding: 1rem; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index ddc7a69c..a3bcdc5c 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -209,23 +209,44 @@ export const WithCheckboxes: Story = { }, render: args => html` - + - Mal - Dimensjon + + Mal + + + Dimensjon + Opprettet - Opprettet av - + + Opprettet av + + - - + + - Geografi 2023 - norsk - GEO + + Geografi 2020 + + + ATC_Verdi + 10.10.2027 - Pelle Parafin + + Pelle Parafin + From 108c499601afeb3c4bd9ad350d0fdb80b16f64b4 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 11 Mar 2026 17:09:14 +0100 Subject: [PATCH 14/43] change defaulr width --- .../fhi-table-cell/fhi-table-cell.stories.ts | 34 +++++++++++++++++++ .../fhi-table-row/fhi-table-row.stories.ts | 23 +++++++++++++ .../table/fhi-table/fhi-table.component.ts | 2 +- .../table/fhi-table/fhi-table.stories.ts | 10 +++--- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts new file mode 100644 index 00000000..4a862904 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts @@ -0,0 +1,34 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from 'lit'; +import { FhiTableCell } from './fhi-table-cell.component'; +import { ifDefined } from 'lit/directives/if-defined.js'; + +new FhiTableCell(); + +const meta: Meta = { + title: 'Komponenter/Table/Cell', + component: 'fhi-table-cell', + parameters: {}, + decorators: [], + render: args => + html` + 374 964 + `, + argTypes: { + variant: { + control: 'select', + options: ['header', 'body'], + description: 'Definerer om cellen er en header eller body celle', + defaultValue: { summary: 'body' }, + }, + }, +}; + +type Story = StoryObj; + +export const Preview: Story = { + tags: [], + args: {}, +}; + +export default meta; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts new file mode 100644 index 00000000..272f8471 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts @@ -0,0 +1,23 @@ +import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import { html } from 'lit'; +import { FhiTableRow } from './fhi-table-row.component'; + +new FhiTableRow(); + +const meta: Meta = { + title: 'Komponenter/Table/Row', + component: 'fhi-table-row', + parameters: {}, + decorators: [], + render: () => html``, + argTypes: {}, +}; + +type Story = StoryObj; + +export const Preview: Story = { + tags: [], + args: {}, +}; + +export default meta; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index a827159c..a5be992d 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -36,7 +36,7 @@ export class FhiTable extends LitElement { static styles = css` :host { - --fhi-table-width: auto; + --fhi-table-width: max-content; } :host { diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index a3bcdc5c..0a848fdf 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -31,7 +31,7 @@ new FhiTitle(); new FhiBody(); const meta: Meta = { - title: 'Komponenter/Table', + title: 'Komponenter/Table/Table', component: 'fhi-table', parameters: {}, decorators: [], @@ -83,7 +83,7 @@ export const Preview: Story = { }; export const ComplexData: Story = { - tags: [], + tags: ['!dev'], args: {}, render: args => html` @@ -104,17 +112,15 @@ export const ComplexData: Story = {
- + - Oslo + + Oslo - Januar - Februar - Mars - April + Januar + Februar + Mars + April @@ -127,10 +133,7 @@ export const ComplexData: Story = { - - + Med fødselsmelding @@ -153,12 +156,10 @@ export const ComplexData: Story = {
- + - Østfold + + Østfold @@ -176,10 +177,7 @@ export const ComplexData: Story = { - - + Med fødselsmelding @@ -211,23 +209,14 @@ export const WithCheckboxes: Story = { - + Mal - + Dimensjon - Opprettet - + Opprettet + Opprettet av From 43ef619b1351034ae6f2c799d7af7cbfcae493ca Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 12 Mar 2026 13:05:33 +0100 Subject: [PATCH 17/43] only apply header variant to child cells --- .../fhi-designsystem/src/components/table/docs.mdx | 4 ++++ .../table/fhi-table-row/fhi-table-row.component.ts | 14 +++++++------- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index 7489cf2a..ad51dbac 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -2,6 +2,8 @@ import { FhiTable } from './fhi-table/fhi-table.component.ts'; import * as FhiTableStories from './fhi-table/fhi-table.stories.ts'; import { Meta, Primary, Canvas, Controls } from '@storybook/addon-docs/blocks'; +import { ApiDefinition } from '../../../.storybook/blocks/api-definition.jsx'; + # Table @@ -21,3 +23,5 @@ Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for b
+ + \ No newline at end of file diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index aea247cb..6775295e 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -31,13 +31,13 @@ export class FhiTableRow extends LitElement { } private handleSlotChange() { - console.log(this.slotElements); - - this.slotElements.forEach(element => { - if (element.tagName.toLowerCase() === 'fhi-table-cell') { - (element as FhiTableCell).variant = this.variant; - } - }); + if (this.variant === 'header') { + this.slotElements.forEach(element => { + if (element.tagName.toLowerCase() === 'fhi-table-cell') { + (element as FhiTableCell).variant = this.variant; + } + }); + } } render() { From 6e1431cc52de6948261bdbbb834dceac29c95d29 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 12 Mar 2026 13:05:57 +0100 Subject: [PATCH 18/43] add api definition for fhi-table --- .../fhi-table-cell/fhi-table-cell.stories.ts | 18 +++++++++++++---- .../fhi-table-row/fhi-table-row.stories.ts | 20 ++++++++++++++----- .../table/fhi-table/fhi-table.stories.ts | 16 ++++++++++++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts index 89586973..28740aef 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts @@ -1,14 +1,24 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import type { StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; import { FhiTableCell } from './fhi-table-cell.component'; import { ifDefined } from 'lit/directives/if-defined.js'; +import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; + new FhiTableCell(); -const meta: Meta = { +const meta: FhiStorybookMeta = { title: 'Komponenter/Table/Cell', component: 'fhi-table-cell', - parameters: {}, + parameters: { + slotTypes: [ + { + name: '-', + description: + 'Innholdet i cellen. Kan være tekst eller andre HTML-elementer.', + }, + ], + }, decorators: [], render: args => html` @@ -19,7 +29,7 @@ const meta: Meta = { control: 'select', options: ['header', 'body'], description: - 'Definerer om cellen er en header eller body celle. Når fhi-table-cell brukes i en fhi-table-row, vil variant automatisk arves fra fhi-table-row.', + 'Definerer om cellen er en header eller body celle. Når fhi-table-cell brukes i en header fhi-table-row, vil variant automatisk bli satt til header.', defaultValue: { summary: 'body' }, }, }, diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts index 1cd47ab7..a6e2c306 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts @@ -1,27 +1,37 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import type { StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; import { FhiTableRow } from './fhi-table-row.component'; +import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; + new FhiTableRow(); -const meta: Meta = { +const meta: FhiStorybookMeta = { title: 'Komponenter/Table/Row', component: 'fhi-table-row', - parameters: {}, + parameters: { + slotTypes: [ + { + name: '-', + description: + 'Alle celler i raden. Bruk fhi-table-cell for å definere celler i raden.', + }, + ], + }, decorators: [], render: () => html``, argTypes: { columns: { control: 'text', description: - 'Definerer kolonneoppsettet for raden. Bruk CSS grid-template-columns format, f.eks. "1fr 2fr 1fr".', + 'Definerer kolonneoppsettet for raden. Bruk CSS grid-template-columns format, f.eks. "3fr repeat(4, 1fr)".', defaultValue: { summary: '1fr' }, }, variant: { control: 'select', options: ['header', 'body'], description: - 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter.', + 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter. All fhi-table-cell elementer i en header fhi-table-row vil automatisk få variant satt til header.', defaultValue: { summary: 'body' }, }, }, diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 07a62bdb..de0802da 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -1,4 +1,4 @@ -import type { Meta, StoryObj } from '@storybook/web-components-vite'; +import type { StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; import { FhiTable } from './fhi-table.component'; @@ -17,6 +17,8 @@ import { FhiIconDownload } from '../../icons/fhi-icon-download.component'; import { FhiIconTrash } from '../../icons/fhi-icon-trash.component'; import { ifDefined } from 'lit/directives/if-defined.js'; +import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; + new FhiTable(); new FhiTableCell(); new FhiTableRow(); @@ -30,10 +32,18 @@ new FhiDisplay(); new FhiTitle(); new FhiBody(); -const meta: Meta = { +const meta: FhiStorybookMeta = { title: 'Komponenter/Table', component: 'fhi-table', - parameters: {}, + parameters: { + slotTypes: [ + { + name: '-', + description: + 'Alle rader i tabellen. Bruk fhi-table-row for å definere rader, og fhi-table-cell for å definere celler i radene.', + }, + ], + }, decorators: [], argTypes: { caption: { From 58ee3075a46c9d52c6a9b9542f05afb8abaae5e3 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 12 Mar 2026 13:33:07 +0100 Subject: [PATCH 19/43] add api definitions forsub-components --- packages/fhi-designsystem/src/components/table/docs.mdx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index ad51dbac..bd75f08d 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -1,5 +1,9 @@ import { FhiTable } from './fhi-table/fhi-table.component.ts'; + import * as FhiTableStories from './fhi-table/fhi-table.stories.ts'; +import * as FhiTableRowStories from './fhi-table-row/fhi-table-row.stories.ts'; +import * as FhiTableCellStories from './fhi-table-cell/fhi-table-cell.stories.ts'; + import { Meta, Primary, Canvas, Controls } from '@storybook/addon-docs/blocks'; import { ApiDefinition } from '../../../.storybook/blocks/api-definition.jsx'; @@ -24,4 +28,6 @@ Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for b
- \ No newline at end of file + + + \ No newline at end of file From 891e75c4a84356ea73f065a3be0dff0dab45a3e6 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 18 Mar 2026 16:44:53 +0100 Subject: [PATCH 20/43] work with new table component tokens --- .../fhi-table-cell.component.ts | 47 +++++++++++-------- .../fhi-table-row/fhi-table-row.component.ts | 26 ++++++---- .../table/fhi-table/fhi-table.component.ts | 5 +- .../table/fhi-table/fhi-table.stories.ts | 5 -- 4 files changed, 47 insertions(+), 36 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 6dccf633..9f3171c7 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -21,18 +21,40 @@ export class FhiTableCell extends LitElement { } static styles = css` + :host { + --fhi-table-cell-justify-content: unset; + --fhi-table-cell-align-items: unset; + --fhi-table-cell-padding: unset; + --fhi-table-cell-height: unset; + --fhi-table-cell-letter-spacing: unset; + --fhi-table-cell-font: unset; + } + :host { --fhi-table-cell-justify-content: end; --fhi-table-cell-align-items: center; --fhi-table-cell-padding: var(--fhi-spacing-200); --fhi-table-cell-height: -webkit-fill-available; - --fhi-table-cell-background: initial; - --fhi-table-cell-color: var(--fhi-color-neutral-text-default); + display: flex; + justify-content: var(--fhi-table-cell-justify-content); + align-items: var(--fhi-table-cell-align-items); + padding: var(--fhi-table-cell-padding); + height: var(--fhi-table-cell-height); + color: var(--fhi-color-neutral-text-default); + letter-spacing: var(--fhi-table-cell-letter-spacing); + min-width: min-content; + overflow: hidden; + flex-wrap: wrap; + background: initial; + } + + :host([variant='body']) { --fhi-table-cell-letter-spacing: var( --fhi-typography-body-medium-letter-spacing ); - --fhi-table-cell-font: var(--fhi-typography-body-medium-font-weight) + + font: var(--fhi-typography-body-medium-font-weight) var(--fhi-typography-body-medium-font-size) / var(--fhi-typography-body-medium-line-height) var(--fhi-font-family-default); @@ -42,26 +64,11 @@ export class FhiTableCell extends LitElement { --fhi-table-cell-letter-spacing: var( --fhi-typography-label-medium-letter-spacing ); - --fhi-table-cell-font: var(--fhi-typography-label-medium-font-weight) + + font: var(--fhi-typography-label-medium-font-weight) var(--fhi-typography-label-medium-font-size) / var(--fhi-typography-label-medium-line-height) var(--fhi-font-family-default); } - - :host { - display: flex; - justify-content: var(--fhi-table-cell-justify-content); - align-items: var(--fhi-table-cell-align-items); - padding: var(--fhi-table-cell-padding); - height: var(--fhi-table-cell-height); - min-width: min-content; - overflow: hidden; - flex-wrap: wrap; - background: var(--fhi-table-cell-background); - - font: var(--fhi-table-cell-font); - color: var(--fhi-table-cell-color); - letter-spacing: var(--fhi-table-cell-letter-spacing); - } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 6775295e..c153896f 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -46,21 +46,27 @@ export class FhiTableRow extends LitElement { static styles = css` :host { - --fhi-table-row-background: initial; + --fhi-table-row-border-style: unset; + --fhi-table-row-border-width: unset; + --fhi-table-row-border-color: unset; + } + + :host { + --fhi-table-row-border-style: none none solid none; + --fhi-table-row-border-width: var(--fhi-dimension-border-width); - --fhi-table-row-border-bottom: var(--fhi-dimension-border-width) solid - var(--fhi-color-neutral-border-subtle); + display: grid; + border-style: var(--fhi-table-row-border-style); + border-width: var(--fhi-table-row-border-width); + border-color: var(--fhi-table-row-border-color); } - :host([variant='header']) { - --fhi-table-row-border-bottom: var(--fhi-dimension-border-width) solid - var(--fhi-color-neutral-border-default); + :host([variant='body']) { + --fhi-table-row-border-color: var(--fhi-color-neutral-border-subtle); } - :host { - display: grid; - border-bottom: var(--fhi-table-row-border-bottom); - background: var(--fhi-table-row-background); + :host([variant='header']) { + --fhi-table-row-border-color: var(--fhi-color-neutral-border-default); } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index a5be992d..7f43ce79 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -36,12 +36,15 @@ export class FhiTable extends LitElement { static styles = css` :host { - --fhi-table-width: max-content; + --fhi-table-width: unset; } :host { + --fhi-table-width: max-content; + display: block; width: var(--fhi-table-width); + #caption { display: block; padding: 1rem; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index de0802da..32c162d7 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -99,11 +99,6 @@ export const ComplexData: Story = { - P0a: Fødte per måned og mors bosted (med og uten fødselsmelding i MFR) @@ -117,55 +108,84 @@ export const ComplexData: Story = {
- + - - Oslo + Oslo + + Januar + + + Februar + + + Mars + + + April - Januar - Februar - Mars - April - - Alle fødte + Alle fødte + + 685 + + + - + + + - + + + - - 685 - - - - - - - - Med fødselsmelding + Med fødselsmelding + + 662 + + + - + + + - + + + - - 662 - - - - - - - - Uten fødselsmelding + Uten fødselsmelding + + 23 + + + - + + + - + + + - - 23 - - - - - -
- + - - Østfold - + Østfold @@ -173,33 +193,51 @@ export const ComplexData: Story = { - - Alle fødte + Alle fødte + + 230 + + + - + + + - + + + - - 230 - - - - - - - - Med fødselsmelding + Med fødselsmelding + + 229 + + + - + + + - + + + - - 229 - - - - - - - - Uten fødselsmelding + Uten fødselsmelding + + 1 + + + - + + + - + + + - - 1 - - - - - - `, @@ -214,34 +252,22 @@ export const WithCheckboxes: Story = { - - Mal - - - Dimensjon - + Mal + Dimensjon Opprettet - - Opprettet av - + Opprettet av - + - - Geografi 2020 - - - ATC_Verdi - + Geografi 2020 + ATC_Verdi 10.10.2027 - - Pelle Parafin - - + Pelle Parafin + Eksportèr From 245ce015cc491c3b5e73c0c459714f1feef97660 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 13:14:40 +0200 Subject: [PATCH 22/43] add jsdocs --- .../fhi-table-cell.component.ts | 17 ++++++++++ .../fhi-table-row/fhi-table-row.component.ts | 23 +++++++++++++ .../table/fhi-table/fhi-table.component.ts | 33 +++++++++++++++++++ 3 files changed, 73 insertions(+) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index dcb327ea..2a604bc4 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -3,8 +3,25 @@ import { customElement, property } from 'lit/decorators.js'; export const FhiTableCellSelector = 'fhi-table-cell'; +/** + * ## FHI Table Cell + * + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table--docs} + * + * The `` component is an implementation of a table cell according to the FHI Design System guidelines. + * It allows users to properly display data within a ``. + * + * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * + * @tag fhi-table-row + * @element fhi-table-row + */ @customElement(FhiTableRowSelector) export class FhiTableRow extends LitElement { + /** + * Defines the column structure of the table row using CSS Grid syntax. This should be a string that specifies the width of each column, such as '1fr 2fr 1fr' for three columns with different widths. + * The number of columns defined here should match the number of `` elements within the row for proper alignment. + * @type {string} + */ @property({ type: String, reflect: true }) columns = '1fr'; + /** + * Defines the variant of the table row, which can be either 'header' or 'body'. This determines the styling and role of the row within the table. + * If the variant is set to 'header', all child `` elements will also be set to the 'header' variant to ensure consistent styling. + * @type {'header' | 'body'} + */ @property({ type: String, reflect: true }) variant: 'header' | 'body' = 'body'; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index ff130811..ea88ec26 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -6,8 +6,41 @@ import '../../typography/fhi-body/fhi-body.component'; export const FhiTableSelector = 'fhi-table'; +/** + * ## FHI Table + * + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table--docs} + * + * The `` component is an implementation of a table according to the FHI Design System guidelines. + * It allows users to display tabular data in a structured format using `` and `` components. + * + * For various reasons, the `` component does not use the native HTML `
` or `` elements. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * + * @tag fhi-table-cell + * @element fhi-table-cell + */ @customElement(FhiTableCellSelector) export class FhiTableCell extends LitElement { + /** + * Defines the variant of the table cell, which can be either 'header' or 'body'. This determines the styling and role of the cell within the table. + * @type {'header' | 'body'} + */ @property({ type: String, reflect: true }) variant: 'header' | 'body' = 'body'; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 6252fc47..9975e015 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -5,11 +5,34 @@ import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; export const FhiTableRowSelector = 'fhi-table-row'; +/** + * ## FHI Table Row + * + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table-row--docs} + * + * The `` component is an implementation of a table row according to the FHI Design System guidelines. + * It allows users to properly display data within a `` using `` components. + * + * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * + * Example usage: + * ```html + * + * + * Header 1 + * Header 2 + * Header 3 + * + * + * Data 1 + * Data 2 + * Data 3 + * + * + * ``` + * + * @tag fhi-table + * @element fhi-table + */ @customElement(FhiTableSelector) export class FhiTable extends LitElement { + /** + * The caption of the table. This should provide a brief description of the table's content. + * @type {string} + */ @property({ type: String, reflect: true }) caption?: string; From 921bc431b2d3a96413a0911965178f48acf52b1b Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 15:20:52 +0200 Subject: [PATCH 23/43] zebra -> striped --- .../components/table/fhi-table/fhi-table.component.ts | 9 ++++++++- .../src/components/table/fhi-table/fhi-table.stories.ts | 6 ++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index ea88ec26..7f58bf53 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -44,6 +44,13 @@ export class FhiTable extends LitElement { @property({ type: String, reflect: true }) caption?: string; + /** + * If set to true, the table will have alternating row colors (striped effect) for better readability. + * @type {boolean} + */ + @property({ type: Boolean, reflect: true }) + striped?: boolean; + connectedCallback(): void { super.connectedCallback(); this.role = 'table'; @@ -85,7 +92,7 @@ export class FhiTable extends LitElement { } } - :host([zebra]) { + :host([striped]) { ::slotted(fhi-table-row:nth-child(even)) { --fhi-table-row-background: var(--fhi-color-neutral-background-subtle); } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index ca377034..0669fd57 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -94,7 +94,9 @@ export const Preview: Story = { export const ComplexData: Story = { tags: ['!dev'], - args: {}, + args: { + striped: true, + }, render: args => html` P0a: Fødte per måned og mors bosted (med og uten fødselsmelding i MFR) @@ -111,7 +113,7 @@ export const ComplexData: Story = { Oslo From 56d0591f62a3e662cf43b1c44d70e84837195d9e Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 15:30:37 +0200 Subject: [PATCH 24/43] update story --- .../table/fhi-table-cell/fhi-table-cell.stories.ts | 2 +- .../table/fhi-table-row/fhi-table-row.stories.ts | 4 ++-- .../components/table/fhi-table/fhi-table.stories.ts | 13 ++++++++++--- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts index 28740aef..114ab189 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts @@ -29,7 +29,7 @@ const meta: FhiStorybookMeta = { control: 'select', options: ['header', 'body'], description: - 'Definerer om cellen er en header eller body celle. Når fhi-table-cell brukes i en header fhi-table-row, vil variant automatisk bli satt til header.', + 'Definerer om cellen er en header eller body celle. Når brukes i en header , vil variant automatisk bli satt til header.', defaultValue: { summary: 'body' }, }, }, diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts index a6e2c306..8e8ca6cf 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts @@ -14,7 +14,7 @@ const meta: FhiStorybookMeta = { { name: '-', description: - 'Alle celler i raden. Bruk fhi-table-cell for å definere celler i raden.', + 'Alle celler i raden. Bruk for å definere celler i raden.', }, ], }, @@ -31,7 +31,7 @@ const meta: FhiStorybookMeta = { control: 'select', options: ['header', 'body'], description: - 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter. All fhi-table-cell elementer i en header fhi-table-row vil automatisk få variant satt til header.', + 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter. Alle elementer i en header vil automatisk få variant satt til header.', defaultValue: { summary: 'body' }, }, }, diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 0669fd57..08d5ee47 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -40,7 +40,7 @@ const meta: FhiStorybookMeta = { { name: '-', description: - 'Alle rader i tabellen. Bruk fhi-table-row for å definere rader, og fhi-table-cell for å definere celler i radene.', + 'Alle rader i tabellen. Bruk for å definere rader, og for å definere celler i radene.', }, ], }, @@ -52,6 +52,11 @@ const meta: FhiStorybookMeta = { 'Valgfri tekst som beskriver innholdet. Dette fungerer som tabellen sin tittel og er visuelt plassert under tabellen', defaultValue: { summary: undefined }, }, + striped: { + control: 'boolean', + description: 'Om tabellen skal ha vekslende radfarger (stripete effekt).', + defaultValue: { summary: false }, + }, }, }; @@ -61,9 +66,10 @@ export const Preview: Story = { tags: [], args: { caption: 'Total forekomst: Utvalgte diagnoser, antall', + striped: false, }, render: args => html` - + 2021 @@ -249,9 +255,10 @@ export const WithCheckboxes: Story = { tags: ['!dev'], args: { caption: 'Avkrysningsbokser.', + striped: false, }, render: args => html` - + Mal From 4711fca4427d31b28bb37b1fa359e114e653fc09 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 15:58:02 +0200 Subject: [PATCH 25/43] clean up --- .../fhi-table-cell.component.ts | 1 - .../table/fhi-table/fhi-table.component.ts | 20 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 2a604bc4..18ee0cb0 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -51,7 +51,6 @@ export class FhiTableCell extends LitElement { justify-content: var(--fhi-table-cell-justify-content); align-items: var(--fhi-table-cell-align-items); padding: var(--fhi-spacing-150); - height: -webkit-fill-available; min-width: min-content; overflow: hidden; flex-wrap: wrap; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 7f58bf53..7b81a738 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -56,19 +56,25 @@ export class FhiTable extends LitElement { this.role = 'table'; } - protected update(changedProperties: PropertyValues): void { - if (this.caption) { - this.setAttribute('aria-label', this.caption); - } + protected updated(changedProperties: PropertyValues): void { + super.updated(changedProperties); - super.update(changedProperties); + if (changedProperties.has('caption')) { + if (this.caption) { + this.setAttribute('aria-label', this.caption); + } else { + this.removeAttribute('aria-label'); + } + } } render() { return html` ${this.caption - ? html`${this.caption}` + ? html`${this.caption}` : null} `; } @@ -85,7 +91,7 @@ export class FhiTable extends LitElement { width: var(--fhi-table-width); color: var(--fhi-color-neutral-text-default); - #caption { + .caption { display: block; padding: 1rem; color: var(--fhi-color-neutral-text-default); From 9b136f408932f3f3c20111f5b485d2eaca51b005 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 16:04:55 +0200 Subject: [PATCH 26/43] wip table border --- .../table/fhi-table-row/fhi-table-row.component.ts | 9 +-------- .../components/table/fhi-table/fhi-table.component.ts | 6 ++++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 9975e015..3bb081d7 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -79,6 +79,7 @@ export class FhiTableRow extends LitElement { :host { --fhi-table-row-border-style: none none solid none; --fhi-table-row-border-width: var(--fhi-dimension-border-width); + --fhi-table-row-border-color: var(--fhi-color-neutral-surface-active); display: grid; border-style: var(--fhi-table-row-border-style); @@ -86,13 +87,5 @@ export class FhiTableRow extends LitElement { border-color: var(--fhi-table-row-border-color); background: var(--fhi-table-row-background); } - - :host([variant='body']) { - --fhi-table-row-border-color: var(--fhi-color-neutral-border-subtle); - } - - :host([variant='header']) { - --fhi-table-row-border-color: var(--fhi-color-neutral-border-default); - } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 7b81a738..d0860d93 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -91,6 +91,12 @@ export class FhiTable extends LitElement { width: var(--fhi-table-width); color: var(--fhi-color-neutral-text-default); + slot { + display: block; + border: 1px solid var(--fhi-color-neutral-surface-active); + border-radius: var(--fhi-border-radius-100); + } + .caption { display: block; padding: 1rem; From 02886e75255cb61be8677860f221644a7ac2674f Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 16:15:17 +0200 Subject: [PATCH 27/43] adjust the final rows border style to fit with the table border --- .../table/fhi-table/fhi-table.component.ts | 43 +++++++++++++++++-- .../table/fhi-table/fhi-table.stories.ts | 1 + 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index d0860d93..1c7733e2 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -1,5 +1,9 @@ import { html, css, LitElement, PropertyValues } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; +import { + customElement, + property, + queryAssignedElements, +} from 'lit/decorators.js'; import '../../fhi-grid/fhi-grid.component'; import '../../typography/fhi-body/fhi-body.component'; @@ -51,6 +55,9 @@ export class FhiTable extends LitElement { @property({ type: Boolean, reflect: true }) striped?: boolean; + @queryAssignedElements() + slotElements!: Array; + connectedCallback(): void { super.connectedCallback(); this.role = 'table'; @@ -68,9 +75,25 @@ export class FhiTable extends LitElement { } } + private handleSlotChange() { + const rows = this.slotElements.filter( + el => el.tagName.toLowerCase() === 'fhi-table-row', + ); + + if (rows.length === 0) { + return; + } + + const finalRow = rows[rows.length - 1]; + + finalRow.style.borderBottom = 'none'; + finalRow.style.borderRadius = + '0 0 var(--fhi-table-row-border-radius) var(--fhi-table-row-border-radius)'; + } + render() { return html` - + ${this.caption ? html`${this.caption} Østfold From 72361f0198b5ef0157095bb2b1f6d8bb36889db0 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 9 Apr 2026 16:29:29 +0200 Subject: [PATCH 28/43] add border radius token to row and override tokens on last row in table --- .../fhi-table-row/fhi-table-row.component.ts | 2 + .../table/fhi-table/fhi-table.component.ts | 59 +++++++------------ 2 files changed, 24 insertions(+), 37 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 3bb081d7..eae8ce28 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -72,6 +72,7 @@ export class FhiTableRow extends LitElement { --fhi-table-row-border-style: unset; --fhi-table-row-border-width: unset; --fhi-table-row-border-color: unset; + --fhi-table-row-border-radius: unset; --fhi-table-row-background: unset; } @@ -85,6 +86,7 @@ export class FhiTableRow extends LitElement { border-style: var(--fhi-table-row-border-style); border-width: var(--fhi-table-row-border-width); border-color: var(--fhi-table-row-border-color); + border-radius: var(--fhi-table-row-border-radius); background: var(--fhi-table-row-background); } `; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 1c7733e2..884ed600 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -1,9 +1,5 @@ import { html, css, LitElement, PropertyValues } from 'lit'; -import { - customElement, - property, - queryAssignedElements, -} from 'lit/decorators.js'; +import { customElement, property } from 'lit/decorators.js'; import '../../fhi-grid/fhi-grid.component'; import '../../typography/fhi-body/fhi-body.component'; @@ -55,9 +51,6 @@ export class FhiTable extends LitElement { @property({ type: Boolean, reflect: true }) striped?: boolean; - @queryAssignedElements() - slotElements!: Array; - connectedCallback(): void { super.connectedCallback(); this.role = 'table'; @@ -75,25 +68,9 @@ export class FhiTable extends LitElement { } } - private handleSlotChange() { - const rows = this.slotElements.filter( - el => el.tagName.toLowerCase() === 'fhi-table-row', - ); - - if (rows.length === 0) { - return; - } - - const finalRow = rows[rows.length - 1]; - - finalRow.style.borderBottom = 'none'; - finalRow.style.borderRadius = - '0 0 var(--fhi-table-row-border-radius) var(--fhi-table-row-border-radius)'; - } - render() { return html` - + ${this.caption ? html`${this.caption} Date: Fri, 10 Apr 2026 14:35:43 +0200 Subject: [PATCH 29/43] refine fhi-table --- .../src/components/table/docs.mdx | 2 +- .../table/fhi-table/fhi-table.component.ts | 13 +++--- .../table/fhi-table/fhi-table.stories.ts | 40 +++++++++++++------ 3 files changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index bd75f08d..63c9b9e1 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -18,7 +18,7 @@ Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for b ## Passer til -- Å vise lister med større mengder strukturert data på en måte som er lett å lese og sammenligne +- Å vise lister med større mengder strukturert data på en måte som er lett å lese og sammenligne. diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 884ed600..27b880fc 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -51,10 +51,7 @@ export class FhiTable extends LitElement { @property({ type: Boolean, reflect: true }) striped?: boolean; - connectedCallback(): void { - super.connectedCallback(); - this.role = 'table'; - } + public role = 'table'; protected updated(changedProperties: PropertyValues): void { super.updated(changedProperties); @@ -83,6 +80,8 @@ export class FhiTable extends LitElement { :host { --fhi-table-width: unset; + --fhi-table-caption-width: unset; + --fhi-table-border-style: unset; --fhi-table-border-width: unset; --fhi-table-border-color: unset; @@ -98,11 +97,11 @@ export class FhiTable extends LitElement { --fhi-table-border-radius: var(--fhi-border-radius-100); display: block; - width: var(--fhi-table-width); color: var(--fhi-color-neutral-text-default); slot { display: block; + width: var(--fhi-table-width); border-style: var(--fhi-table-border-style); border-width: var(--fhi-table-border-width); border-color: var(--fhi-table-border-color); @@ -111,8 +110,8 @@ export class FhiTable extends LitElement { .caption { display: block; - padding: 1rem; - color: var(--fhi-color-neutral-text-default); + padding: var(--fhi-spacing-150); + width: var(--fhi-table-caption-width); } ::slotted(fhi-table-row:last-child) { diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 888da858..9bf21af5 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -72,27 +72,43 @@ export const Preview: Story = { - 2021 - 2022 - 2023 + + 2021 + + + 2022 + + + 2023 + - - Pasienter totalt + Pasienter totalt + + 374 964 + + + 383 347 + + + 392 106 - 374 964 - 383 347 - 392 106 - + Sykdommer i sirkulasjonssystemet (I00-I99) - 279 726 - 289 149 - 291 655 + + 279 726 + + + 289 149 + + + 291 655 + `, From 210b5abe40bd925ea6f8e9b6ccc51a5b5a3618fa Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Fri, 10 Apr 2026 17:01:15 +0200 Subject: [PATCH 30/43] move column definition to fhi-table and add some guards --- .../fhi-table-row/fhi-table-row.component.ts | 47 +++++++++++------- .../fhi-table-row/fhi-table-row.stories.ts | 6 --- .../table/fhi-table/fhi-table.component.ts | 26 +++++++++- .../table/fhi-table/fhi-table.stories.ts | 49 +++++++++++++------ 4 files changed, 88 insertions(+), 40 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index eae8ce28..c1be4528 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -20,14 +20,6 @@ export const FhiTableRowSelector = 'fhi-table-row'; */ @customElement(FhiTableRowSelector) export class FhiTableRow extends LitElement { - /** - * Defines the column structure of the table row using CSS Grid syntax. This should be a string that specifies the width of each column, such as '1fr 2fr 1fr' for three columns with different widths. - * The number of columns defined here should match the number of `` elements within the row for proper alignment. - * @type {string} - */ - @property({ type: String, reflect: true }) - columns = '1fr'; - /** * Defines the variant of the table row, which can be either 'header' or 'body'. This determines the styling and role of the row within the table. * If the variant is set to 'header', all child `` elements will also be set to the 'header' variant to ensure consistent styling. @@ -41,26 +33,41 @@ export class FhiTableRow extends LitElement { connectedCallback(): void { super.connectedCallback(); - - this.setAttribute('role', 'row'); + this.role = 'row'; } protected update(changedProperties: PropertyValues): void { - if (changedProperties.has('columns')) { - this.style.gridTemplateColumns = this.columns; + if (changedProperties.has('variant')) { + if (this.variant !== 'body' && this.variant !== 'header') { + this.variant = 'body'; + } } super.update(changedProperties); } + protected updated(changedProperties: PropertyValues): void { + if (changedProperties.has('variant')) { + this.setCellVariants(); + } + + super.updated(changedProperties); + } + private handleSlotChange() { - if (this.variant === 'header') { - this.slotElements.forEach(element => { - if (element.tagName.toLowerCase() === 'fhi-table-cell') { - (element as FhiTableCell).variant = this.variant; + this.setCellVariants(); + } + + private setCellVariants() { + this.slotElements.forEach(element => { + if (element.tagName.toLowerCase() === 'fhi-table-cell') { + const tableCell = element as FhiTableCell; + + if (tableCell.variant !== this.variant) { + tableCell.variant = this.variant; } - }); - } + } + }); } render() { @@ -75,6 +82,8 @@ export class FhiTableRow extends LitElement { --fhi-table-row-border-radius: unset; --fhi-table-row-background: unset; + + --fhi-table-row-grid-template-columns: unset; } :host { @@ -83,6 +92,8 @@ export class FhiTableRow extends LitElement { --fhi-table-row-border-color: var(--fhi-color-neutral-surface-active); display: grid; + grid-template-columns: var(--fhi-table-row-grid-template-columns); + border-style: var(--fhi-table-row-border-style); border-width: var(--fhi-table-row-border-width); border-color: var(--fhi-table-row-border-color); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts index 8e8ca6cf..9310e8ae 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts @@ -21,12 +21,6 @@ const meta: FhiStorybookMeta = { decorators: [], render: () => html``, argTypes: { - columns: { - control: 'text', - description: - 'Definerer kolonneoppsettet for raden. Bruk CSS grid-template-columns format, f.eks. "3fr repeat(4, 1fr)".', - defaultValue: { summary: '1fr' }, - }, variant: { control: 'select', options: ['header', 'body'], diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 27b880fc..4e371f8d 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -51,7 +51,19 @@ export class FhiTable extends LitElement { @property({ type: Boolean, reflect: true }) striped?: boolean; - public role = 'table'; + /** + * Defines the column structure of the table using CSS Grid syntax. This should be a string that specifies the width of each column, such as '1fr 2fr 1fr' for three columns with different widths. + * All `` elements within the table will inherit this column structure. + * The number of columns defined here should match the number of `` elements within a `` for proper alignment. + * @type {string} + */ + @property({ type: String, reflect: true }) + columns = '1fr'; + + connectedCallback(): void { + super.connectedCallback(); + this.role = 'table'; + } protected updated(changedProperties: PropertyValues): void { super.updated(changedProperties); @@ -63,6 +75,10 @@ export class FhiTable extends LitElement { this.removeAttribute('aria-label'); } } + + if (changedProperties.has('columns')) { + this.style.setProperty('--fhi-table-grid-template-columns', this.columns); + } } render() { @@ -82,6 +98,8 @@ export class FhiTable extends LitElement { --fhi-table-caption-width: unset; + --fhi-table-grid-template-columns: unset; + --fhi-table-border-style: unset; --fhi-table-border-width: unset; --fhi-table-border-color: unset; @@ -114,6 +132,12 @@ export class FhiTable extends LitElement { width: var(--fhi-table-caption-width); } + ::slotted(fhi-table-row) { + --fhi-table-row-grid-template-columns: var( + --fhi-table-grid-template-columns + ); + } + ::slotted(fhi-table-row:last-child) { --fhi-table-row-border-style: none none none none; --fhi-table-row-border-width: unset; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 9bf21af5..cd3d25fc 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -57,6 +57,12 @@ const meta: FhiStorybookMeta = { description: 'Om tabellen skal ha vekslende radfarger (stripete effekt).', defaultValue: { summary: false }, }, + columns: { + control: 'text', + description: + 'Definerer kolonnene i tabellen ved hjelp av CSS Grid-syntaks. Dette bør være en streng som spesifiserer antall kolonner og bredden på hver kolonne, for eksempel "1fr 2fr 1fr" for tre kolonner med forskjellige bredder. Alle -elementer i tabellen vil arve denne kolonnedefinisjonen. Antallet kolonner definert her bør samsvare med antallet -elementer i en for riktig justering.', + defaultValue: { summary: '1fr' }, + }, }, }; @@ -67,10 +73,15 @@ export const Preview: Story = { args: { caption: 'Total forekomst: Utvalgte diagnoser, antall', striped: false, + columns: '3fr 1fr 1fr 1fr', }, render: args => html` - - + + 2021 @@ -83,7 +94,7 @@ export const Preview: Story = { - + Pasienter totalt 374 964 @@ -96,7 +107,7 @@ export const Preview: Story = { - + Sykdommer i sirkulasjonssystemet (I00-I99) @@ -118,6 +129,7 @@ export const ComplexData: Story = { tags: ['!dev'], args: { striped: true, + columns: '2fr repeat(4, 1fr)', }, render: args => html` @@ -136,8 +148,9 @@ export const ComplexData: Story = { caption="${ifDefined(args.caption)}" style="--fhi-table-width: auto" ?striped="${args.striped}" + columns="${args.columns}" > - + Oslo Januar @@ -153,7 +166,7 @@ export const ComplexData: Story = { - + Alle fødte 685 @@ -169,7 +182,7 @@ export const ComplexData: Story = { - + Med fødselsmelding 662 @@ -185,7 +198,7 @@ export const ComplexData: Story = { - + Uten fødselsmelding 23 @@ -208,8 +221,9 @@ export const ComplexData: Story = { caption="${ifDefined(args.caption)}" style="--fhi-table-width: auto" ?striped="${args.striped}" + columns="${args.columns}" > - + Østfold @@ -217,7 +231,7 @@ export const ComplexData: Story = { - + Alle fødte 230 @@ -233,7 +247,7 @@ export const ComplexData: Story = { - + Med fødselsmelding 229 @@ -249,7 +263,7 @@ export const ComplexData: Story = { - + Uten fødselsmelding 1 @@ -273,10 +287,15 @@ export const WithCheckboxes: Story = { args: { caption: 'Avkrysningsbokser.', striped: false, + columns: '2.5rem 4fr 3fr 2fr 2fr 6fr', }, render: args => html` - - + + Mal Dimensjon @@ -285,7 +304,7 @@ export const WithCheckboxes: Story = { - + From 4b81fb04eed7e4bd5a22b3bfc21e9a413ae36cd6 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 14 Apr 2026 12:52:30 +0200 Subject: [PATCH 31/43] add tests --- .../fhi-table-cell/fhi-table-cell.test.ts | 58 +++++++++ .../table/fhi-table-row/fhi-table-row.test.ts | 119 ++++++++++++++++++ .../table/fhi-table/fhi-table.component.ts | 3 +- .../table/fhi-table/fhi-table.test.ts | 57 +++++++++ 4 files changed, 236 insertions(+), 1 deletion(-) create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts create mode 100644 packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts new file mode 100644 index 00000000..243f9dce --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts @@ -0,0 +1,58 @@ +import { fixture, expect } from '@open-wc/testing'; +import { html } from 'lit/static-html.js'; +import { FhiTableCell } from './fhi-table-cell.component'; +import { FhiTableRow } from '../fhi-table-row/fhi-table-row.component'; +import { FhiTable } from '../fhi-table/fhi-table.component'; + +describe('fhi-table-cell', () => { + new FhiTableCell(); + new FhiTableRow(); + new FhiTable(); + + let component: FhiTableCell; + + describe('accessibility', () => { + beforeEach(async () => { + component = await fixture(html``); + }); + + it('is accessible when it has a correct parent structure', async () => { + const table = await fixture( + html` + + + + `, + ); + + const cell = table.querySelector('fhi-table-cell'); + await expect(cell).to.be.accessible(); + }); + + it('is not accessible when it does not have a correct parent', async () => { + await expect(component).not.to.be.accessible(); + }); + + it('should have the role "cell" by default', async () => { + expect(component.getAttribute('role')).to.equal('cell'); + }); + + it('should have the role "columnheader" when variant is set to "header"', async () => { + component.variant = 'header'; + await component.updateComplete; + + expect(component.getAttribute('role')).to.equal('columnheader'); + }); + }); + + describe('setting attributes', () => { + it('has an attribute to set the variant', async () => { + component = await fixture( + html``, + ); + + expect(component.getAttribute('variant')).to.equal('header'); + expect(component.variant).to.equal('header'); + }); + }); +}); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts new file mode 100644 index 00000000..ce1ceaa1 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts @@ -0,0 +1,119 @@ +import { fixture, expect } from '@open-wc/testing'; +import { html } from 'lit/static-html.js'; +import { FhiTable } from '../fhi-table/fhi-table.component'; +import { FhiTableRow } from './fhi-table-row.component'; +import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; + +describe('fhi-table-row', () => { + new FhiTable(); + new FhiTableRow(); + new FhiTableCell(); + + let component: FhiTableRow; + + describe('accessibility', () => { + beforeEach(async () => { + component = await fixture(html``); + }); + + it("should have the 'row' role", async () => { + expect(component.getAttribute('role')).to.equal('row'); + }); + + it('is accessible when it has a correct parent and child structure', async () => { + component = await fixture( + html` + + + + `, + ); + + const row = component.querySelector('fhi-table-row'); + await expect(row).to.be.accessible(); + }); + + it('is not accessible when it does not have a correct parent', async () => { + component = await fixture( + html` + + `, + ); + + await expect(component).not.to.be.accessible(); + }); + + it('is not accessible when it does not have a correct child', async () => { + component = await fixture( + html` + + `, + ); + + const row = component.querySelector('fhi-table-row'); + await expect(row).not.to.be.accessible(); + }); + }); + + describe('setting attributes', () => { + it('has an attribute to set the variant', async () => { + component = await fixture( + html``, + ); + + expect(component.getAttribute('variant')).to.equal('header'); + expect(component.variant).to.equal('header'); + }); + }); + + describe('propagation of properties', () => { + it('should set the variant of child fhi-table-cell elements to match its own variant', async () => { + component = await fixture( + html` + + + + + `, + ); + + const cells = component.querySelectorAll( + 'fhi-table-row fhi-table-cell', + ); + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('header'); + expect(cell.variant).to.equal('header'); + }); + }); + + it('should update the variant of child fhi-table-cell elements when its own variant changes', async () => { + component = await fixture( + html` + + + + + `, + ); + + const row = component.querySelector('fhi-table-row') as FhiTableRow; + const cells = component.querySelectorAll( + 'fhi-table-row fhi-table-cell', + ); + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('header'); + expect(cell.variant).to.equal('header'); + }); + + row.variant = 'body'; + await row.updateComplete; + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('body'); + expect(cell.variant).to.equal('body'); + }); + }); + }); +}); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 4e371f8d..405bdb66 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -58,10 +58,11 @@ export class FhiTable extends LitElement { * @type {string} */ @property({ type: String, reflect: true }) - columns = '1fr'; + columns?: string = '1fr'; connectedCallback(): void { super.connectedCallback(); + this.role = 'table'; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts new file mode 100644 index 00000000..1d6fa3ef --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts @@ -0,0 +1,57 @@ +import { fixture, expect } from '@open-wc/testing'; +import { html } from 'lit/static-html.js'; +import { FhiTable } from './fhi-table.component'; + +describe('fhi-table', () => { + new FhiTable(); + + let component: FhiTable; + + describe('accessibility', () => { + beforeEach(async () => { + component = await fixture(html``); + }); + + it('is accessible', async () => { + await expect(component).to.be.accessible(); + }); + + it('should have the role "table"', async () => { + expect(component.getAttribute('role')).to.equal('table'); + }); + + it('should have an aria-label if caption attribute is set', async () => { + component.caption = 'Table Caption'; + await component.updateComplete; + + expect(component.getAttribute('aria-label')).to.equal('Table Caption'); + }); + }); + + describe('setting attributes', () => { + it('has an attribute to set the caption', async () => { + component = await fixture( + html``, + ); + + expect(component.getAttribute('caption')).to.equal('Table Caption'); + expect(component.caption).to.equal('Table Caption'); + }); + + it('has an attribute to set striped', async () => { + component = await fixture(html``); + + expect(component.hasAttribute('striped')).to.equal(true); + expect(component.striped).to.equal(true); + }); + + it('has an attribute to set columns', async () => { + component = await fixture( + html``, + ); + + expect(component.getAttribute('columns')).to.equal('1fr 2fr 1fr'); + expect(component.columns).to.equal('1fr 2fr 1fr'); + }); + }); +}); From 8cba267d31b1db225fe3b74cf1a547fedaa71f4e Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 14 Apr 2026 12:58:03 +0200 Subject: [PATCH 32/43] add guard for table columns --- .../components/table/fhi-table/fhi-table.component.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 405bdb66..5ad4e687 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -58,7 +58,7 @@ export class FhiTable extends LitElement { * @type {string} */ @property({ type: String, reflect: true }) - columns?: string = '1fr'; + columns: string = '1fr'; connectedCallback(): void { super.connectedCallback(); @@ -66,6 +66,14 @@ export class FhiTable extends LitElement { this.role = 'table'; } + protected update(changedProperties: PropertyValues): void { + if (!this.columns) { + this.columns = '1fr'; + } + + super.update(changedProperties); + } + protected updated(changedProperties: PropertyValues): void { super.updated(changedProperties); From a985568737cc38cb46aa19568e92586874c06abf Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 14 Apr 2026 13:32:02 +0200 Subject: [PATCH 33/43] adjustments --- .../table/fhi-table-cell/fhi-table-cell.component.ts | 7 ++++++- .../src/components/table/fhi-table/fhi-table.stories.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 18ee0cb0..bdf31bcd 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -51,10 +51,13 @@ export class FhiTableCell extends LitElement { justify-content: var(--fhi-table-cell-justify-content); align-items: var(--fhi-table-cell-align-items); padding: var(--fhi-spacing-150); + color: var(--fhi-color-neutral-text-default); min-width: min-content; overflow: hidden; - flex-wrap: wrap; background: initial; + flex-wrap: wrap; + text-overflow: ellipsis; + font-variant-numeric: lining-nums proportional-nums; } :host([variant='body']) { @@ -67,6 +70,8 @@ export class FhiTableCell extends LitElement { } :host([variant='header']) { + white-space: nowrap; + letter-spacing: var(--fhi-typography-label-medium-letter-spacing); font: var(--fhi-typography-label-medium-font-weight) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index cd3d25fc..d51b2d82 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -299,7 +299,9 @@ export const WithCheckboxes: Story = { Mal Dimensjon - Opprettet + + Opprettet + Opprettet av @@ -310,7 +312,9 @@ export const WithCheckboxes: Story = { Geografi 2020 ATC_Verdi - 10.10.2027 + + 10.10.2027 + Pelle Parafin From 83aff3c67c2372f1e4504527175bc6dbcbb93e53 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 15 Apr 2026 10:22:30 +0200 Subject: [PATCH 34/43] update example in JSDoc --- .../table/fhi-table/fhi-table.component.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 5ad4e687..9e9ea2e4 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -18,13 +18,13 @@ export const FhiTableSelector = 'fhi-table'; * * Example usage: * ```html - * - * - * Header 1 - * Header 2 - * Header 3 + * + * + * Header 1 + * Header 2 + * Header 3 * - * + * * Data 1 * Data 2 * Data 3 From 358d66fe3b2e01ceadeae1049be2f4e3eab7f8e8 Mon Sep 17 00:00:00 2001 From: Daniel Alexander Fermin Nilsen Date: Thu, 16 Apr 2026 17:14:19 +0200 Subject: [PATCH 35/43] Update packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts Co-authored-by: Trygve Bernhardt <51702336+trybern@users.noreply.github.com> --- .../src/components/table/fhi-table/fhi-table.stories.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index d51b2d82..351c9aba 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -299,7 +299,7 @@ export const WithCheckboxes: Story = { Mal Dimensjon - + Opprettet Opprettet av @@ -312,7 +312,7 @@ export const WithCheckboxes: Story = { Geografi 2020 ATC_Verdi - + 10.10.2027 Pelle Parafin From 1a22e50dd6dbca93e20c1c8fe46d140e49bee93d Mon Sep 17 00:00:00 2001 From: Daniel Alexander Fermin Nilsen Date: Thu, 16 Apr 2026 17:16:03 +0200 Subject: [PATCH 36/43] Update packages/fhi-designsystem/src/components/table/docs.mdx Co-authored-by: Trygve Bernhardt <51702336+trybern@users.noreply.github.com> --- packages/fhi-designsystem/src/components/table/docs.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index 63c9b9e1..72f7880e 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -14,7 +14,7 @@ import { ApiDefinition } from '../../../.storybook/blocks/api-definition.jsx'; Tabell brukes for å presentere data og informasjon på en ryddig måte. Brukeren kan raskt få oversikt og skanne innholdet effektivt. -Tabellen bruker CSS grid for å definere rader og kolonner, og har støtte for både enkle og mer komplekse tabeller. Det er også mulig å legge til en caption som fungerer som en tittel for tabellen. +Tabellen bruker CSS Grid for å definere rader og kolonner, og har støtte for både enkle og mer komplekse tabeller. Det er også mulig å legge til `caption` som fungerer som en tittel for tabellen. ## Passer til From 53d16d72b62aec2c14ca8a38db0daf52cf1f8d6c Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 16 Apr 2026 20:12:28 +0200 Subject: [PATCH 37/43] remove unnecessary text --- .../src/components/table/fhi-table/fhi-table.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 9e9ea2e4..93fc44a0 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -14,7 +14,7 @@ export const FhiTableSelector = 'fhi-table'; * The `` component is an implementation of a table according to the FHI Design System guidelines. * It allows users to display tabular data in a structured format using `` and `` components. * - * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * The `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. * * Example usage: * ```html From a49a308ac57f5dd565c342094d9f3e7006d89298 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Thu, 16 Apr 2026 20:16:36 +0200 Subject: [PATCH 38/43] add white background for odd rows when striped --- .../components/table/fhi-table/fhi-table.component.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 93fc44a0..bde46d69 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -147,6 +147,11 @@ export class FhiTable extends LitElement { ); } + ::slotted(fhi-table-row:first-child) { + --fhi-table-row-border-radius: var(--fhi-table-border-radius) + var(--fhi-table-border-radius) 0 0; + } + ::slotted(fhi-table-row:last-child) { --fhi-table-row-border-style: none none none none; --fhi-table-row-border-width: unset; @@ -160,6 +165,10 @@ export class FhiTable extends LitElement { ::slotted(fhi-table-row:nth-child(even)) { --fhi-table-row-background: var(--fhi-color-neutral-background-subtle); } + + ::slotted(fhi-table-row:nth-child(odd)) { + --fhi-table-row-background: var(--fhi-color-neutral-background-default); + } } `; } From 82043dc9f34a8d83f99c5969f3b12ab1dd7d2083 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Fri, 17 Apr 2026 09:54:54 +0200 Subject: [PATCH 39/43] change confisung sizeing --- .../table/fhi-table-cell/fhi-table-cell.component.ts | 1 - .../components/table/fhi-table/fhi-table.component.ts | 2 +- .../src/components/table/fhi-table/fhi-table.stories.ts | 9 ++------- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index bdf31bcd..00900289 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -52,7 +52,6 @@ export class FhiTableCell extends LitElement { align-items: var(--fhi-table-cell-align-items); padding: var(--fhi-spacing-150); color: var(--fhi-color-neutral-text-default); - min-width: min-content; overflow: hidden; background: initial; flex-wrap: wrap; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index bde46d69..6ba6aea3 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -116,7 +116,7 @@ export class FhiTable extends LitElement { } :host { - --fhi-table-width: max-content; + --fhi-table-width: unset; --fhi-table-border-style: solid; --fhi-table-border-width: var(--fhi-dimension-border-width); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts index 351c9aba..202f7fd0 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts @@ -146,7 +146,6 @@ export const ComplexData: Story = { @@ -299,9 +298,7 @@ export const WithCheckboxes: Story = { Mal Dimensjon - - Opprettet - + Opprettet Opprettet av @@ -312,9 +309,7 @@ export const WithCheckboxes: Story = { Geografi 2020 ATC_Verdi - - 10.10.2027 - + 10.10.2027 Pelle Parafin From de04c952c24e462f02997e4bd2bdf2ee545c68f6 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 21 Apr 2026 09:54:33 +0200 Subject: [PATCH 40/43] add ellipsis to cells --- .../table/fhi-table-cell/fhi-table-cell.component.ts | 10 ++++++---- .../components/table/fhi-table/fhi-table.component.ts | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 00900289..4484281d 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -52,11 +52,13 @@ export class FhiTableCell extends LitElement { align-items: var(--fhi-table-cell-align-items); padding: var(--fhi-spacing-150); color: var(--fhi-color-neutral-text-default); - overflow: hidden; background: initial; - flex-wrap: wrap; - text-overflow: ellipsis; - font-variant-numeric: lining-nums proportional-nums; + + slot { + display: block; + overflow: hidden; + text-overflow: ellipsis; + } } :host([variant='body']) { diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 6ba6aea3..26ac6011 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -129,6 +129,7 @@ export class FhiTable extends LitElement { slot { display: block; width: var(--fhi-table-width); + min-width: min-content; border-style: var(--fhi-table-border-style); border-width: var(--fhi-table-border-width); border-color: var(--fhi-table-border-color); From 067167aaed26c174e4ac6f03a0e6c75ce5ac41a5 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Wed, 22 Apr 2026 11:28:02 +0200 Subject: [PATCH 41/43] try out display: table --- .../fhi-table-cell.component.ts | 30 +++++++--- .../fhi-table-row/fhi-table-row.component.ts | 20 +++---- .../table/fhi-table/fhi-table.component.ts | 57 ++++--------------- .../table/fhi-table/fhi-table.stories.ts | 28 +-------- 4 files changed, 44 insertions(+), 91 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index 4484281d..c5f91596 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -34,30 +34,42 @@ export class FhiTableCell extends LitElement { } render() { - return html``; + return html` +
+ +
+ `; } static styles = css` :host { --fhi-table-cell-justify-content: unset; --fhi-table-cell-align-items: unset; + + --fhi-table-cell-border-style: unset; + --fhi-table-cell-border-width: unset; + --fhi-table-cell-border-color: unset; + + --fhi-table-cell-background: unset; } :host { --fhi-table-cell-justify-content: start; --fhi-table-cell-align-items: center; - display: flex; - justify-content: var(--fhi-table-cell-justify-content); - align-items: var(--fhi-table-cell-align-items); + display: table-cell; + padding: var(--fhi-spacing-150); color: var(--fhi-color-neutral-text-default); - background: initial; - slot { - display: block; - overflow: hidden; - text-overflow: ellipsis; + border-style: var(--fhi-table-cell-border-style); + border-width: var(--fhi-table-cell-border-width); + border-color: var(--fhi-table-cell-border-color); + + .cell-content { + display: flex; + justify-content: var(--fhi-table-cell-justify-content); + align-items: var(--fhi-table-cell-align-items); } } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index c1be4528..0c5cb653 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -79,26 +79,24 @@ export class FhiTableRow extends LitElement { --fhi-table-row-border-style: unset; --fhi-table-row-border-width: unset; --fhi-table-row-border-color: unset; - --fhi-table-row-border-radius: unset; --fhi-table-row-background: unset; - - --fhi-table-row-grid-template-columns: unset; } :host { + display: table-row; + background: var(--fhi-table-row-background); + --fhi-table-row-border-style: none none solid none; --fhi-table-row-border-width: var(--fhi-dimension-border-width); --fhi-table-row-border-color: var(--fhi-color-neutral-surface-active); - display: grid; - grid-template-columns: var(--fhi-table-row-grid-template-columns); - - border-style: var(--fhi-table-row-border-style); - border-width: var(--fhi-table-row-border-width); - border-color: var(--fhi-table-row-border-color); - border-radius: var(--fhi-table-row-border-radius); - background: var(--fhi-table-row-background); + ::slotted(fhi-table-cell) { + --fhi-table-cell-background: var(--fhi-table-row-background); + --fhi-table-cell-border-style: var(--fhi-table-row-border-style); + --fhi-table-cell-border-width: var(--fhi-table-row-border-width); + --fhi-table-cell-border-color: var(--fhi-table-row-border-color); + } } `; } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts index 26ac6011..373be388 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts @@ -51,15 +51,6 @@ export class FhiTable extends LitElement { @property({ type: Boolean, reflect: true }) striped?: boolean; - /** - * Defines the column structure of the table using CSS Grid syntax. This should be a string that specifies the width of each column, such as '1fr 2fr 1fr' for three columns with different widths. - * All `` elements within the table will inherit this column structure. - * The number of columns defined here should match the number of `` elements within a `` for proper alignment. - * @type {string} - */ - @property({ type: String, reflect: true }) - columns: string = '1fr'; - connectedCallback(): void { super.connectedCallback(); @@ -67,10 +58,6 @@ export class FhiTable extends LitElement { } protected update(changedProperties: PropertyValues): void { - if (!this.columns) { - this.columns = '1fr'; - } - super.update(changedProperties); } @@ -84,15 +71,13 @@ export class FhiTable extends LitElement { this.removeAttribute('aria-label'); } } - - if (changedProperties.has('columns')) { - this.style.setProperty('--fhi-table-grid-template-columns', this.columns); - } } render() { return html` - +
+ +
${this.caption ? html`${this.caption} = { description: 'Om tabellen skal ha vekslende radfarger (stripete effekt).', defaultValue: { summary: false }, }, - columns: { - control: 'text', - description: - 'Definerer kolonnene i tabellen ved hjelp av CSS Grid-syntaks. Dette bør være en streng som spesifiserer antall kolonner og bredden på hver kolonne, for eksempel "1fr 2fr 1fr" for tre kolonner med forskjellige bredder. Alle -elementer i tabellen vil arve denne kolonnedefinisjonen. Antallet kolonner definert her bør samsvare med antallet -elementer i en for riktig justering.', - defaultValue: { summary: '1fr' }, - }, }, }; @@ -73,14 +67,9 @@ export const Preview: Story = { args: { caption: 'Total forekomst: Utvalgte diagnoser, antall', striped: false, - columns: '3fr 1fr 1fr 1fr', }, render: args => html` - + @@ -129,7 +118,6 @@ export const ComplexData: Story = { tags: ['!dev'], args: { striped: true, - columns: '2fr repeat(4, 1fr)', }, render: args => html` @@ -144,11 +132,7 @@ export const ComplexData: Story = {
- + Oslo @@ -220,7 +204,6 @@ export const ComplexData: Story = { caption="${ifDefined(args.caption)}" style="--fhi-table-width: auto" ?striped="${args.striped}" - columns="${args.columns}" > Østfold @@ -286,14 +269,9 @@ export const WithCheckboxes: Story = { args: { caption: 'Avkrysningsbokser.', striped: false, - columns: '2.5rem 4fr 3fr 2fr 2fr 6fr', }, render: args => html` - + Mal From a7bb661de25af245705052f711d48ee716b867d5 Mon Sep 17 00:00:00 2001 From: Daniel Alexander Fermin Nilsen Date: Tue, 28 Apr 2026 11:40:58 +0200 Subject: [PATCH 42/43] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Marthe Søvdsnes <99345946+Masuso@users.noreply.github.com> --- .../components/table/fhi-table-cell/fhi-table-cell.component.ts | 2 +- .../components/table/fhi-table-row/fhi-table-row.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts index c5f91596..19cdccdf 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts @@ -11,7 +11,7 @@ export const FhiTableCellSelector = 'fhi-table-cell'; * The `` component is an implementation of a table cell according to the FHI Design System guidelines. * It allows users to properly display data within a ``. * - * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * The `` component does not use the native HTML `` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. * * @tag fhi-table-row * @element fhi-table-row From 39e7c27d8804336adda884bf2cd3d734c45dd461 Mon Sep 17 00:00:00 2001 From: Daniel Nilsen Date: Tue, 28 Apr 2026 12:07:33 +0200 Subject: [PATCH 43/43] rename to data table and adjust docs --- .../src/components/table/docs.mdx | 30 +- .../fhi-data-table-cell.component.ts} | 44 ++- .../fhi-data-table-cell.stories.ts} | 16 +- .../fhi-data-table-cell.test.ts} | 34 +- .../fhi-data-table-row.component.ts | 110 +++++++ .../fhi-data-table-row.stories.ts} | 16 +- .../fhi-data-table-row.test.ts | 123 +++++++ .../fhi-data-table.component.ts | 144 ++++++++ .../fhi-data-table/fhi-data-table.stories.ts | 255 ++++++++++++++ .../fhi-data-table.test.ts} | 25 +- .../fhi-table-row/fhi-table-row.component.ts | 102 ------ .../table/fhi-table-row/fhi-table-row.test.ts | 119 ------- .../table/fhi-table/fhi-table.component.ts | 140 -------- .../table/fhi-table/fhi-table.stories.ts | 310 ------------------ 14 files changed, 711 insertions(+), 757 deletions(-) rename packages/fhi-designsystem/src/components/table/{fhi-table-cell/fhi-table-cell.component.ts => fhi-data-table-cell/fhi-data-table-cell.component.ts} (55%) rename packages/fhi-designsystem/src/components/table/{fhi-table-cell/fhi-table-cell.stories.ts => fhi-data-table-cell/fhi-data-table-cell.stories.ts} (65%) rename packages/fhi-designsystem/src/components/table/{fhi-table-cell/fhi-table-cell.test.ts => fhi-data-table-cell/fhi-data-table-cell.test.ts} (59%) create mode 100644 packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.component.ts rename packages/fhi-designsystem/src/components/table/{fhi-table-row/fhi-table-row.stories.ts => fhi-data-table-row/fhi-data-table-row.stories.ts} (58%) create mode 100644 packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.test.ts create mode 100644 packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.component.ts create mode 100644 packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.stories.ts rename packages/fhi-designsystem/src/components/table/{fhi-table/fhi-table.test.ts => fhi-data-table/fhi-data-table.test.ts} (66%) delete mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts delete mode 100644 packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts delete mode 100644 packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts delete mode 100644 packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts diff --git a/packages/fhi-designsystem/src/components/table/docs.mdx b/packages/fhi-designsystem/src/components/table/docs.mdx index 72f7880e..83c97ce9 100644 --- a/packages/fhi-designsystem/src/components/table/docs.mdx +++ b/packages/fhi-designsystem/src/components/table/docs.mdx @@ -1,33 +1,33 @@ -import { FhiTable } from './fhi-table/fhi-table.component.ts'; +import { FhiDataTable } from './fhi-data-table/fhi-data-table.component.ts'; -import * as FhiTableStories from './fhi-table/fhi-table.stories.ts'; -import * as FhiTableRowStories from './fhi-table-row/fhi-table-row.stories.ts'; -import * as FhiTableCellStories from './fhi-table-cell/fhi-table-cell.stories.ts'; +import * as FhiDataTableStories from './fhi-data-table/fhi-data-table.stories.ts'; +import * as FhiDataTableRowStories from './fhi-data-table-row/fhi-data-table-row.stories.ts'; +import * as FhiDataTableCellStories from './fhi-data-table-cell/fhi-data-table-cell.stories.ts'; import { Meta, Primary, Canvas, Controls } from '@storybook/addon-docs/blocks'; import { ApiDefinition } from '../../../.storybook/blocks/api-definition.jsx'; - + -# Table +# Data Table -Tabell brukes for å presentere data og informasjon på en ryddig måte. Brukeren kan raskt få oversikt og skanne innholdet effektivt. +Data babell brukes for å presentere data og informasjon på en ryddig måte. Brukeren kan raskt få oversikt og skanne innholdet effektivt. -Tabellen bruker CSS Grid for å definere rader og kolonner, og har støtte for både enkle og mer komplekse tabeller. Det er også mulig å legge til `caption` som fungerer som en tittel for tabellen. +Tabellen består av rader med celler som inneholder data. Rader defineres med ``, og celler med ``. ## Passer til - Å vise lister med større mengder strukturert data på en måte som er lett å lese og sammenligne. - - + + ## Eksempler - +
- + - - - \ No newline at end of file + + + \ No newline at end of file diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.component.ts similarity index 55% rename from packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts rename to packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.component.ts index c5f91596..ae9d73fe 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.component.ts @@ -1,23 +1,23 @@ import { html, css, LitElement, PropertyValues } from 'lit'; import { customElement, property } from 'lit/decorators.js'; -export const FhiTableCellSelector = 'fhi-table-cell'; +export const FhiDataTableCellSelector = 'fhi-data-table-cell'; /** * ## FHI Table Cell * - * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table--docs} + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-data-table--docs} * - * The `` component is an implementation of a table cell according to the FHI Design System guidelines. - * It allows users to properly display data within a ``. + * The `` component is an implementation of a table cell according to the FHI Design System guidelines. + * It allows users to properly display data within a ``. * - * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * + * @tag fhi-data-table-row + * @element fhi-data-table-row + */ +@customElement(FhiDataTableRowSelector) +export class FhiDataTableRow extends LitElement { + /** + * Defines the variant of the table row, which can be either 'header' or 'body'. This determines the styling and role of the row within the table. + * If the variant is set to 'header', all child `` elements will also be set to the 'header' variant to ensure consistent styling. + * @type {'header' | 'body'} + */ + @property({ type: String, reflect: true }) + variant: 'header' | 'body' = 'body'; + + @queryAssignedElements() + slotElements!: Array; + + connectedCallback(): void { + super.connectedCallback(); + this.role = 'row'; + } + + protected update(changedProperties: PropertyValues): void { + if (changedProperties.has('variant')) { + if (this.variant !== 'body' && this.variant !== 'header') { + this.variant = 'body'; + } + } + + super.update(changedProperties); + } + + protected updated(changedProperties: PropertyValues): void { + if (changedProperties.has('variant')) { + this.setCellVariants(); + } + + super.updated(changedProperties); + } + + private handleSlotChange() { + this.setCellVariants(); + } + + private setCellVariants() { + this.slotElements.forEach(element => { + if (element.tagName.toLowerCase() === 'fhi-data-table-cell') { + const tableCell = element as FhiDataTableCell; + + if (tableCell.variant !== this.variant) { + tableCell.variant = this.variant; + } + } + }); + } + + render() { + return html``; + } + + static styles = css` + :host { + --fhi-data-table-row-border-style: unset; + --fhi-data-table-row-border-width: unset; + --fhi-data-table-row-border-color: unset; + + --fhi-data-table-row-background: unset; + } + + :host { + display: table-row; + background: var(--fhi-data-table-row-background); + + --fhi-data-table-row-border-style: none none solid none; + --fhi-data-table-row-border-width: var(--fhi-dimension-border-width); + --fhi-data-table-row-border-color: var( + --fhi-color-neutral-surface-active + ); + + ::slotted(fhi-data-table-cell) { + --fhi-data-table-cell-background: var(--fhi-data-table-row-background); + --fhi-data-table-cell-border-style: var( + --fhi-data-table-row-border-style + ); + --fhi-data-table-cell-border-width: var( + --fhi-data-table-row-border-width + ); + --fhi-data-table-cell-border-color: var( + --fhi-data-table-row-border-color + ); + } + } + `; +} diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.stories.ts similarity index 58% rename from packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts rename to packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.stories.ts index 9310e8ae..acf795ed 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.stories.ts @@ -1,37 +1,37 @@ import type { StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; -import { FhiTableRow } from './fhi-table-row.component'; +import { FhiDataTableRow } from './fhi-data-table-row.component'; import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; -new FhiTableRow(); +new FhiDataTableRow(); -const meta: FhiStorybookMeta = { +const meta: FhiStorybookMeta = { title: 'Komponenter/Table/Row', - component: 'fhi-table-row', + component: 'fhi-data-table-row', parameters: { slotTypes: [ { name: '-', description: - 'Alle celler i raden. Bruk for å definere celler i raden.', + 'Alle celler i raden. Bruk for å definere celler i raden.', }, ], }, decorators: [], - render: () => html``, + render: () => html``, argTypes: { variant: { control: 'select', options: ['header', 'body'], description: - 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter. Alle elementer i en header vil automatisk få variant satt til header.', + 'Definerer om raden er en header-rad eller en vanlig rad. Header-rader har en annen stil og brukes for å definere kolonneoverskrifter. Alle elementer i en header vil automatisk få variant satt til header.', defaultValue: { summary: 'body' }, }, }, }; -type Story = StoryObj; +type Story = StoryObj; export const Preview: Story = { tags: ['!dev'], diff --git a/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.test.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.test.ts new file mode 100644 index 00000000..9b321e93 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.test.ts @@ -0,0 +1,123 @@ +import { fixture, expect } from '@open-wc/testing'; +import { html } from 'lit/static-html.js'; +import { FhiDataTable } from '../fhi-data-table/fhi-data-table.component'; +import { FhiDataTableRow } from './fhi-data-table-row.component'; +import { FhiDataTableCell } from '../fhi-data-table-cell/fhi-data-table-cell.component'; + +describe('fhi-data-table-row', () => { + new FhiDataTable(); + new FhiDataTableRow(); + new FhiDataTableCell(); + + let component: FhiDataTableRow; + + describe('accessibility', () => { + beforeEach(async () => { + component = await fixture( + html``, + ); + }); + + it("should have the 'row' role", async () => { + expect(component.getAttribute('role')).to.equal('row'); + }); + + it('is accessible when it has a correct parent and child structure', async () => { + component = await fixture( + html` + + + + `, + ); + + const row = component.querySelector('fhi-data-table-row'); + await expect(row).to.be.accessible(); + }); + + it('is not accessible when it does not have a correct parent', async () => { + component = await fixture( + html` + + `, + ); + + await expect(component).not.to.be.accessible(); + }); + + it('is not accessible when it does not have a correct child', async () => { + component = await fixture( + html` + + `, + ); + + const row = component.querySelector('fhi-data-table-row'); + await expect(row).not.to.be.accessible(); + }); + }); + + describe('setting attributes', () => { + it('has an attribute to set the variant', async () => { + component = await fixture( + html``, + ); + + expect(component.getAttribute('variant')).to.equal('header'); + expect(component.variant).to.equal('header'); + }); + }); + + describe('propagation of properties', () => { + it('should set the variant of child fhi-data-table-cell elements to match its own variant', async () => { + component = await fixture( + html` + + + + + `, + ); + + const cells = component.querySelectorAll( + 'fhi-data-table-row fhi-data-table-cell', + ); + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('header'); + expect(cell.variant).to.equal('header'); + }); + }); + + it('should update the variant of child fhi-data-table-cell elements when its own variant changes', async () => { + component = await fixture( + html` + + + + + `, + ); + + const row = component.querySelector( + 'fhi-data-table-row', + ) as FhiDataTableRow; + const cells = component.querySelectorAll( + 'fhi-data-table-row fhi-data-table-cell', + ); + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('header'); + expect(cell.variant).to.equal('header'); + }); + + row.variant = 'body'; + await row.updateComplete; + + cells.forEach(cell => { + expect(cell.getAttribute('variant')).to.equal('body'); + expect(cell.variant).to.equal('body'); + }); + }); + }); +}); diff --git a/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.component.ts new file mode 100644 index 00000000..9e10484f --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.component.ts @@ -0,0 +1,144 @@ +import { html, css, LitElement, PropertyValues } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; + +import '../../fhi-grid/fhi-grid.component'; +import '../../typography/fhi-body/fhi-body.component'; + +export const FhiDataTableSelector = 'fhi-data-table'; + +/** + * ## FHI Table + * + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-data-table--docs} + * + * The `` component is an implementation of a table according to the FHI Design System guidelines. + * It allows users to display tabular data in a structured format using `` and `` components. + * + * The `` component does not use the native HTML `
` or `` elements. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * The `` component does not use the native HTML `` or `` elements. Instead, it relies on CSS Grid to achieve the desired layout and styling. * * @tag fhi-table-cell * @element fhi-table-cell diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts index 0c5cb653..608c412a 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts @@ -13,7 +13,7 @@ export const FhiTableRowSelector = 'fhi-table-row'; * The `` component is an implementation of a table row according to the FHI Design System guidelines. * It allows users to properly display data within a `` using `` components. * - * For various reasons, the `` component does not use the native HTML `
` or `` elements. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * For various reasons, the `` component does not use the native HTML `` or `` elements. Instead, it relies on CSS Grid to achieve the desired layout and styling. * - * @tag fhi-table-cell - * @element fhi-table-cell + * @tag fhi-data-table-cell + * @element fhi-data-table-cell */ -@customElement(FhiTableCellSelector) -export class FhiTableCell extends LitElement { +@customElement(FhiDataTableCellSelector) +export class FhiDataTableCell extends LitElement { /** * Defines the variant of the table cell, which can be either 'header' or 'body'. This determines the styling and role of the cell within the table. * @type {'header' | 'body'} @@ -43,33 +43,31 @@ export class FhiTableCell extends LitElement { static styles = css` :host { - --fhi-table-cell-justify-content: unset; - --fhi-table-cell-align-items: unset; + --fhi-data-table-cell-justify-content: unset; + --fhi-data-table-cell-align-items: unset; - --fhi-table-cell-border-style: unset; - --fhi-table-cell-border-width: unset; - --fhi-table-cell-border-color: unset; - - --fhi-table-cell-background: unset; + --fhi-data-table-cell-border-style: unset; + --fhi-data-table-cell-border-width: unset; + --fhi-data-table-cell-border-color: unset; } :host { - --fhi-table-cell-justify-content: start; - --fhi-table-cell-align-items: center; + --fhi-data-table-cell-justify-content: start; + --fhi-data-table-cell-align-items: center; display: table-cell; padding: var(--fhi-spacing-150); color: var(--fhi-color-neutral-text-default); - border-style: var(--fhi-table-cell-border-style); - border-width: var(--fhi-table-cell-border-width); - border-color: var(--fhi-table-cell-border-color); + border-style: var(--fhi-data-table-cell-border-style); + border-width: var(--fhi-data-table-cell-border-width); + border-color: var(--fhi-data-table-cell-border-color); .cell-content { display: flex; - justify-content: var(--fhi-table-cell-justify-content); - align-items: var(--fhi-table-cell-align-items); + justify-content: var(--fhi-data-table-cell-justify-content); + align-items: var(--fhi-data-table-cell-align-items); } } diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.stories.ts similarity index 65% rename from packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts rename to packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.stories.ts index 114ab189..50b51e10 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.stories.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.stories.ts @@ -1,15 +1,15 @@ import type { StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; -import { FhiTableCell } from './fhi-table-cell.component'; +import { FhiDataTableCell } from './fhi-data-table-cell.component'; import { ifDefined } from 'lit/directives/if-defined.js'; import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; -new FhiTableCell(); +new FhiDataTableCell(); -const meta: FhiStorybookMeta = { +const meta: FhiStorybookMeta = { title: 'Komponenter/Table/Cell', - component: 'fhi-table-cell', + component: 'fhi-data-table-cell', parameters: { slotTypes: [ { @@ -21,21 +21,21 @@ const meta: FhiStorybookMeta = { }, decorators: [], render: args => - html` + html` 374 964 - `, + `, argTypes: { variant: { control: 'select', options: ['header', 'body'], description: - 'Definerer om cellen er en header eller body celle. Når brukes i en header , vil variant automatisk bli satt til header.', + 'Definerer om cellen er en header eller body celle. Når brukes i en header , vil variant automatisk bli satt til header.', defaultValue: { summary: 'body' }, }, }, }; -type Story = StoryObj; +type Story = StoryObj; export const Preview: Story = { tags: ['!dev'], diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.test.ts similarity index 59% rename from packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts rename to packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.test.ts index 243f9dce..27f6ffc9 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table-cell/fhi-table-cell.test.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-cell/fhi-data-table-cell.test.ts @@ -1,31 +1,33 @@ import { fixture, expect } from '@open-wc/testing'; import { html } from 'lit/static-html.js'; -import { FhiTableCell } from './fhi-table-cell.component'; -import { FhiTableRow } from '../fhi-table-row/fhi-table-row.component'; -import { FhiTable } from '../fhi-table/fhi-table.component'; +import { FhiDataTableCell } from './fhi-data-table-cell.component'; +import { FhiDataTableRow } from '../fhi-data-table-row/fhi-data-table-row.component'; +import { FhiDataTable } from '../fhi-data-table/fhi-data-table.component'; -describe('fhi-table-cell', () => { - new FhiTableCell(); - new FhiTableRow(); - new FhiTable(); +describe('fhi-data-table-cell', () => { + new FhiDataTableCell(); + new FhiDataTableRow(); + new FhiDataTable(); - let component: FhiTableCell; + let component: FhiDataTableCell; describe('accessibility', () => { beforeEach(async () => { - component = await fixture(html``); + component = await fixture( + html``, + ); }); it('is accessible when it has a correct parent structure', async () => { const table = await fixture( - html` - - - - `, + html` + + + + `, ); - const cell = table.querySelector('fhi-table-cell'); + const cell = table.querySelector('fhi-data-table-cell'); await expect(cell).to.be.accessible(); }); @@ -48,7 +50,7 @@ describe('fhi-table-cell', () => { describe('setting attributes', () => { it('has an attribute to set the variant', async () => { component = await fixture( - html``, + html``, ); expect(component.getAttribute('variant')).to.equal('header'); diff --git a/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.component.ts new file mode 100644 index 00000000..c34c56a7 --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table-row/fhi-data-table-row.component.ts @@ -0,0 +1,110 @@ +import { html, css, LitElement, PropertyValues } from 'lit'; +import { customElement, property } from 'lit/decorators.js'; +import { queryAssignedElements } from 'lit/decorators.js'; +import { FhiDataTableCell } from '../fhi-data-table-cell/fhi-data-table-cell.component'; + +export const FhiDataTableRowSelector = 'fhi-data-table-row'; + +/** + * ## FHI Table Row + * + * {@link https://designsystem.fhi.no/?path=/docs/komponenter-data-table-row--docs} + * + * The `` component is an implementation of a table row according to the FHI Design System guidelines. + * It allows users to properly display data within a `` using `` components. + * + * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. + * + * Example usage: + * ```html + * + * + * Header 1 + * Header 2 + * Header 3 + * + * + * Data 1 + * Data 2 + * Data 3 + * + * + * ``` + * + * @tag fhi-data-table + * @element fhi-data-table + */ +@customElement(FhiDataTableSelector) +export class FhiDataTable extends LitElement { + /** + * The caption of the table. This should provide a brief description of the table's content. + * @type {string} + */ + @property({ type: String, reflect: true }) + caption?: string; + + /** + * If set to true, the table will have alternating row colors (striped effect) for better readability. + * @type {boolean} + */ + @property({ type: Boolean, reflect: true }) + striped?: boolean; + + connectedCallback(): void { + super.connectedCallback(); + + this.role = 'table'; + } + + protected update(changedProperties: PropertyValues): void { + super.update(changedProperties); + } + + protected updated(changedProperties: PropertyValues): void { + super.updated(changedProperties); + + if (changedProperties.has('caption')) { + if (this.caption) { + this.setAttribute('aria-label', this.caption); + } else { + this.removeAttribute('aria-label'); + } + } + } + + render() { + return html` +
+ +
+ ${this.caption + ? html`${this.caption}` + : null} + `; + } + + static styles = css` + :host { + --fhi-data-table-caption-width: unset; + + --fhi-data-table-border-style: unset; + --fhi-data-table-border-width: unset; + --fhi-data-table-border-color: unset; + --fhi-data-table-border-radius: unset; + } + + :host { + --fhi-data-table-border-style: solid; + --fhi-data-table-border-width: var(--fhi-dimension-border-width); + --fhi-data-table-border-color: var(--fhi-color-neutral-surface-active); + --fhi-data-table-border-radius: var(--fhi-border-radius-100); + + color: var(--fhi-color-neutral-text-default); + + .caption { + display: block; + padding: var(--fhi-spacing-150); + width: var(--fhi-data-table-caption-width); + } + + .table-content { + display: table; + width: 100%; + overflow: hidden; + border-style: var(--fhi-data-table-border-style); + border-width: var(--fhi-data-table-border-width); + border-color: var(--fhi-data-table-border-color); + border-radius: var(--fhi-data-table-border-radius); + } + + ::slotted(fhi-data-table-row:last-child) { + --fhi-data-table-row-border-style: none none none none; + --fhi-data-table-row-border-width: unset; + --fhi-data-table-row-border-color: unset; + } + } + + :host([striped]) { + ::slotted(fhi-data-table-row:nth-child(even)) { + --fhi-data-table-row-background: var( + --fhi-color-neutral-background-subtle + ); + } + + ::slotted(fhi-data-table-row:nth-child(odd)) { + --fhi-data-table-row-background: var( + --fhi-color-neutral-background-default + ); + } + } + `; +} diff --git a/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.stories.ts new file mode 100644 index 00000000..c73a9b3e --- /dev/null +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.stories.ts @@ -0,0 +1,255 @@ +import type { StoryObj } from '@storybook/web-components-vite'; +import { html } from 'lit'; + +import { FhiDataTable } from './fhi-data-table.component'; +import { FhiDataTableCell } from '../fhi-data-table-cell/fhi-data-table-cell.component'; +import { FhiDataTableRow } from '../fhi-data-table-row/fhi-data-table-row.component'; + +import { FhiCheckbox } from '../../fhi-checkbox/fhi-checkbox.component'; +import { FhiButton } from '../../fhi-button/fhi-button.component'; + +import { FhiDisplay } from '../../typography/fhi-display/fhi-display.component'; +import { FhiTitle } from '../../typography/fhi-title/fhi-title.component'; +import { FhiBody } from '../../typography/fhi-body/fhi-body.component'; + +import { FhiIconEye } from '../../icons/fhi-icon-eye.component'; +import { FhiIconDownload } from '../../icons/fhi-icon-download.component'; +import { FhiIconTrash } from '../../icons/fhi-icon-trash.component'; +import { ifDefined } from 'lit/directives/if-defined.js'; + +import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; + +new FhiDataTable(); +new FhiDataTableCell(); +new FhiDataTableRow(); +new FhiCheckbox(); +new FhiButton(); +new FhiIconEye(); +new FhiIconDownload(); +new FhiIconTrash(); + +new FhiDisplay(); +new FhiTitle(); +new FhiBody(); + +const meta: FhiStorybookMeta = { + title: 'Komponenter/Data Table', + component: 'fhi-data-table', + parameters: { + slotTypes: [ + { + name: '-', + description: + 'Alle rader i tabellen. Bruk for å definere rader, og for å definere celler i radene.', + }, + ], + }, + decorators: [], + argTypes: { + caption: { + control: 'text', + description: + 'Valgfri tekst som beskriver innholdet. Dette fungerer som tabellen sin tittel og er visuelt plassert under tabellen', + defaultValue: { summary: undefined }, + }, + striped: { + control: 'boolean', + description: 'Om tabellen skal ha vekslende radfarger (stripete effekt).', + defaultValue: { summary: false }, + }, + }, +}; + +type Story = StoryObj; + +export const Preview: Story = { + tags: [], + args: { + caption: 'Total forekomst: Utvalgte diagnoser, antall', + striped: false, + }, + render: args => html` + + + + + 2021 + + + 2022 + + + 2023 + + + + + Pasienter totalt + + 374 964 + + + 383 347 + + + 392 106 + + + + + + Sykdommer i sirkulasjonssystemet (I00-I99) + + + 279 726 + + + 289 149 + + + 291 655 + + + + `, +}; + +export const ComplexData: Story = { + tags: ['!dev'], + args: { + striped: true, + }, + render: args => html` + + P0a: Fødte per måned og mors bosted (med og uten fødselsmelding i MFR) + +
+ + Foreløpige tall kan endres ved senere oppdateringer. Tabellen inkluderer + fødte med fødselsmelding i MFR, som har fødselsvekt ≥ 500 gram og/eller + svangerskapet har vart ≥ 22 uker. Tabellen viser i tillegg fødte uten + fødselsmelding i MFR basert på informasjon fra Folkeregisteret¹. + +
+ + + + Oslo + + Januar + + + Februar + + + Mars + + + April + + + + + Alle fødte + + 685 + + + - + + + - + + + - + + + + + Med fødselsmelding + + 662 + + + - + + + - + + + - + + + + + Uten fødselsmelding + + 23 + + + - + + + - + + + - + + + + `, +}; + +export const WithCheckboxes: Story = { + tags: ['!dev'], + args: { + caption: 'Avkrysningsbokser.', + striped: false, + }, + render: args => html` + + + + Mal + Dimensjon + Opprettet + Opprettet av + + + + + + + + Geografi 2020 + ATC_Verdi + 10.10.2027 + Pelle Parafin + + + + Eksportèr + + + + Vis + + + + + + + + `, +}; + +export default meta; diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.test.ts similarity index 66% rename from packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts rename to packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.test.ts index 1d6fa3ef..82d450c5 100644 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.test.ts +++ b/packages/fhi-designsystem/src/components/table/fhi-data-table/fhi-data-table.test.ts @@ -1,15 +1,15 @@ import { fixture, expect } from '@open-wc/testing'; import { html } from 'lit/static-html.js'; -import { FhiTable } from './fhi-table.component'; +import { FhiDataTable } from './fhi-data-table.component'; -describe('fhi-table', () => { - new FhiTable(); +describe('fhi-data-table', () => { + new FhiDataTable(); - let component: FhiTable; + let component: FhiDataTable; describe('accessibility', () => { beforeEach(async () => { - component = await fixture(html``); + component = await fixture(html``); }); it('is accessible', async () => { @@ -31,7 +31,7 @@ describe('fhi-table', () => { describe('setting attributes', () => { it('has an attribute to set the caption', async () => { component = await fixture( - html``, + html``, ); expect(component.getAttribute('caption')).to.equal('Table Caption'); @@ -39,19 +39,12 @@ describe('fhi-table', () => { }); it('has an attribute to set striped', async () => { - component = await fixture(html``); - - expect(component.hasAttribute('striped')).to.equal(true); - expect(component.striped).to.equal(true); - }); - - it('has an attribute to set columns', async () => { component = await fixture( - html``, + html``, ); - expect(component.getAttribute('columns')).to.equal('1fr 2fr 1fr'); - expect(component.columns).to.equal('1fr 2fr 1fr'); + expect(component.hasAttribute('striped')).to.equal(true); + expect(component.striped).to.equal(true); }); }); }); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts deleted file mode 100644 index 0c5cb653..00000000 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.component.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { html, css, LitElement, PropertyValues } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; -import { queryAssignedElements } from 'lit/decorators.js'; -import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; - -export const FhiTableRowSelector = 'fhi-table-row'; - -/** - * ## FHI Table Row - * - * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table-row--docs} - * - * The `` component is an implementation of a table row according to the FHI Design System guidelines. - * It allows users to properly display data within a `` using `` components. - * - * For various reasons, the `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. - * - * @tag fhi-table-row - * @element fhi-table-row - */ -@customElement(FhiTableRowSelector) -export class FhiTableRow extends LitElement { - /** - * Defines the variant of the table row, which can be either 'header' or 'body'. This determines the styling and role of the row within the table. - * If the variant is set to 'header', all child `` elements will also be set to the 'header' variant to ensure consistent styling. - * @type {'header' | 'body'} - */ - @property({ type: String, reflect: true }) - variant: 'header' | 'body' = 'body'; - - @queryAssignedElements() - slotElements!: Array; - - connectedCallback(): void { - super.connectedCallback(); - this.role = 'row'; - } - - protected update(changedProperties: PropertyValues): void { - if (changedProperties.has('variant')) { - if (this.variant !== 'body' && this.variant !== 'header') { - this.variant = 'body'; - } - } - - super.update(changedProperties); - } - - protected updated(changedProperties: PropertyValues): void { - if (changedProperties.has('variant')) { - this.setCellVariants(); - } - - super.updated(changedProperties); - } - - private handleSlotChange() { - this.setCellVariants(); - } - - private setCellVariants() { - this.slotElements.forEach(element => { - if (element.tagName.toLowerCase() === 'fhi-table-cell') { - const tableCell = element as FhiTableCell; - - if (tableCell.variant !== this.variant) { - tableCell.variant = this.variant; - } - } - }); - } - - render() { - return html``; - } - - static styles = css` - :host { - --fhi-table-row-border-style: unset; - --fhi-table-row-border-width: unset; - --fhi-table-row-border-color: unset; - - --fhi-table-row-background: unset; - } - - :host { - display: table-row; - background: var(--fhi-table-row-background); - - --fhi-table-row-border-style: none none solid none; - --fhi-table-row-border-width: var(--fhi-dimension-border-width); - --fhi-table-row-border-color: var(--fhi-color-neutral-surface-active); - - ::slotted(fhi-table-cell) { - --fhi-table-cell-background: var(--fhi-table-row-background); - --fhi-table-cell-border-style: var(--fhi-table-row-border-style); - --fhi-table-cell-border-width: var(--fhi-table-row-border-width); - --fhi-table-cell-border-color: var(--fhi-table-row-border-color); - } - } - `; -} diff --git a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts b/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts deleted file mode 100644 index ce1ceaa1..00000000 --- a/packages/fhi-designsystem/src/components/table/fhi-table-row/fhi-table-row.test.ts +++ /dev/null @@ -1,119 +0,0 @@ -import { fixture, expect } from '@open-wc/testing'; -import { html } from 'lit/static-html.js'; -import { FhiTable } from '../fhi-table/fhi-table.component'; -import { FhiTableRow } from './fhi-table-row.component'; -import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; - -describe('fhi-table-row', () => { - new FhiTable(); - new FhiTableRow(); - new FhiTableCell(); - - let component: FhiTableRow; - - describe('accessibility', () => { - beforeEach(async () => { - component = await fixture(html``); - }); - - it("should have the 'row' role", async () => { - expect(component.getAttribute('role')).to.equal('row'); - }); - - it('is accessible when it has a correct parent and child structure', async () => { - component = await fixture( - html` - - - - `, - ); - - const row = component.querySelector('fhi-table-row'); - await expect(row).to.be.accessible(); - }); - - it('is not accessible when it does not have a correct parent', async () => { - component = await fixture( - html` - - `, - ); - - await expect(component).not.to.be.accessible(); - }); - - it('is not accessible when it does not have a correct child', async () => { - component = await fixture( - html` - - `, - ); - - const row = component.querySelector('fhi-table-row'); - await expect(row).not.to.be.accessible(); - }); - }); - - describe('setting attributes', () => { - it('has an attribute to set the variant', async () => { - component = await fixture( - html``, - ); - - expect(component.getAttribute('variant')).to.equal('header'); - expect(component.variant).to.equal('header'); - }); - }); - - describe('propagation of properties', () => { - it('should set the variant of child fhi-table-cell elements to match its own variant', async () => { - component = await fixture( - html` - - - - - `, - ); - - const cells = component.querySelectorAll( - 'fhi-table-row fhi-table-cell', - ); - - cells.forEach(cell => { - expect(cell.getAttribute('variant')).to.equal('header'); - expect(cell.variant).to.equal('header'); - }); - }); - - it('should update the variant of child fhi-table-cell elements when its own variant changes', async () => { - component = await fixture( - html` - - - - - `, - ); - - const row = component.querySelector('fhi-table-row') as FhiTableRow; - const cells = component.querySelectorAll( - 'fhi-table-row fhi-table-cell', - ); - - cells.forEach(cell => { - expect(cell.getAttribute('variant')).to.equal('header'); - expect(cell.variant).to.equal('header'); - }); - - row.variant = 'body'; - await row.updateComplete; - - cells.forEach(cell => { - expect(cell.getAttribute('variant')).to.equal('body'); - expect(cell.variant).to.equal('body'); - }); - }); - }); -}); diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts deleted file mode 100644 index 373be388..00000000 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.component.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { html, css, LitElement, PropertyValues } from 'lit'; -import { customElement, property } from 'lit/decorators.js'; - -import '../../fhi-grid/fhi-grid.component'; -import '../../typography/fhi-body/fhi-body.component'; - -export const FhiTableSelector = 'fhi-table'; - -/** - * ## FHI Table - * - * {@link https://designsystem.fhi.no/?path=/docs/komponenter-table--docs} - * - * The `` component is an implementation of a table according to the FHI Design System guidelines. - * It allows users to display tabular data in a structured format using `` and `` components. - * - * The `` component does not use the native HTML `
` element. Instead, it relies on CSS Grid to achieve the desired layout and styling. - * - * Example usage: - * ```html - * - * - * Header 1 - * Header 2 - * Header 3 - * - * - * Data 1 - * Data 2 - * Data 3 - * - * - * ``` - * - * @tag fhi-table - * @element fhi-table - */ -@customElement(FhiTableSelector) -export class FhiTable extends LitElement { - /** - * The caption of the table. This should provide a brief description of the table's content. - * @type {string} - */ - @property({ type: String, reflect: true }) - caption?: string; - - /** - * If set to true, the table will have alternating row colors (striped effect) for better readability. - * @type {boolean} - */ - @property({ type: Boolean, reflect: true }) - striped?: boolean; - - connectedCallback(): void { - super.connectedCallback(); - - this.role = 'table'; - } - - protected update(changedProperties: PropertyValues): void { - super.update(changedProperties); - } - - protected updated(changedProperties: PropertyValues): void { - super.updated(changedProperties); - - if (changedProperties.has('caption')) { - if (this.caption) { - this.setAttribute('aria-label', this.caption); - } else { - this.removeAttribute('aria-label'); - } - } - } - - render() { - return html` -
- -
- ${this.caption - ? html`${this.caption}` - : null} - `; - } - - static styles = css` - :host { - --fhi-table-caption-width: unset; - - --fhi-table-border-style: unset; - --fhi-table-border-width: unset; - --fhi-table-border-color: unset; - --fhi-table-border-radius: unset; - } - - :host { - --fhi-table-border-style: solid; - --fhi-table-border-width: var(--fhi-dimension-border-width); - --fhi-table-border-color: var(--fhi-color-neutral-surface-active); - --fhi-table-border-radius: var(--fhi-border-radius-100); - - color: var(--fhi-color-neutral-text-default); - - .caption { - display: block; - padding: var(--fhi-spacing-150); - width: var(--fhi-table-caption-width); - } - - .table-content { - display: table; - width: 100%; - overflow: hidden; - border-style: var(--fhi-table-border-style); - border-width: var(--fhi-table-border-width); - border-color: var(--fhi-table-border-color); - border-radius: var(--fhi-table-border-radius); - } - - ::slotted(fhi-table-row:last-child) { - --fhi-table-row-border-style: none none none none; - --fhi-table-row-border-width: unset; - --fhi-table-row-border-color: unset; - } - } - - :host([striped]) { - ::slotted(fhi-table-row:nth-child(even)) { - --fhi-table-row-background: var(--fhi-color-neutral-background-subtle); - } - - ::slotted(fhi-table-row:nth-child(odd)) { - --fhi-table-row-background: var(--fhi-color-neutral-background-default); - } - } - `; -} diff --git a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts b/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts deleted file mode 100644 index f6987c6f..00000000 --- a/packages/fhi-designsystem/src/components/table/fhi-table/fhi-table.stories.ts +++ /dev/null @@ -1,310 +0,0 @@ -import type { StoryObj } from '@storybook/web-components-vite'; -import { html } from 'lit'; - -import { FhiTable } from './fhi-table.component'; -import { FhiTableCell } from '../fhi-table-cell/fhi-table-cell.component'; -import { FhiTableRow } from '../fhi-table-row/fhi-table-row.component'; - -import { FhiCheckbox } from '../../fhi-checkbox/fhi-checkbox.component'; -import { FhiButton } from '../../fhi-button/fhi-button.component'; - -import { FhiDisplay } from '../../typography/fhi-display/fhi-display.component'; -import { FhiTitle } from '../../typography/fhi-title/fhi-title.component'; -import { FhiBody } from '../../typography/fhi-body/fhi-body.component'; - -import { FhiIconEye } from '../../icons/fhi-icon-eye.component'; -import { FhiIconDownload } from '../../icons/fhi-icon-download.component'; -import { FhiIconTrash } from '../../icons/fhi-icon-trash.component'; -import { ifDefined } from 'lit/directives/if-defined.js'; - -import { FhiStorybookMeta } from '../../../../.storybook/fhi-meta'; - -new FhiTable(); -new FhiTableCell(); -new FhiTableRow(); -new FhiCheckbox(); -new FhiButton(); -new FhiIconEye(); -new FhiIconDownload(); -new FhiIconTrash(); - -new FhiDisplay(); -new FhiTitle(); -new FhiBody(); - -const meta: FhiStorybookMeta = { - title: 'Komponenter/Table', - component: 'fhi-table', - parameters: { - slotTypes: [ - { - name: '-', - description: - 'Alle rader i tabellen. Bruk for å definere rader, og for å definere celler i radene.', - }, - ], - }, - decorators: [], - argTypes: { - caption: { - control: 'text', - description: - 'Valgfri tekst som beskriver innholdet. Dette fungerer som tabellen sin tittel og er visuelt plassert under tabellen', - defaultValue: { summary: undefined }, - }, - striped: { - control: 'boolean', - description: 'Om tabellen skal ha vekslende radfarger (stripete effekt).', - defaultValue: { summary: false }, - }, - }, -}; - -type Story = StoryObj; - -export const Preview: Story = { - tags: [], - args: { - caption: 'Total forekomst: Utvalgte diagnoser, antall', - striped: false, - }, - render: args => html` - - - - - 2021 - - - 2022 - - - 2023 - - - - - Pasienter totalt - - 374 964 - - - 383 347 - - - 392 106 - - - - - - Sykdommer i sirkulasjonssystemet (I00-I99) - - - 279 726 - - - 289 149 - - - 291 655 - - - - `, -}; - -export const ComplexData: Story = { - tags: ['!dev'], - args: { - striped: true, - }, - render: args => html` - - P0a: Fødte per måned og mors bosted (med og uten fødselsmelding i MFR) - -
- - Foreløpige tall kan endres ved senere oppdateringer. Tabellen inkluderer - fødte med fødselsmelding i MFR, som har fødselsvekt ≥ 500 gram og/eller - svangerskapet har vart ≥ 22 uker. Tabellen viser i tillegg fødte uten - fødselsmelding i MFR basert på informasjon fra Folkeregisteret¹. - -
- - - - Oslo - - Januar - - - Februar - - - Mars - - - April - - - - - Alle fødte - - 685 - - - - - - - - - - - - - - - - - Med fødselsmelding - - 662 - - - - - - - - - - - - - - - - - Uten fødselsmelding - - 23 - - - - - - - - - - - - - - - - -
- - - - Østfold - - - - - - - - Alle fødte - - 230 - - - - - - - - - - - - - - - - - Med fødselsmelding - - 229 - - - - - - - - - - - - - - - - - Uten fødselsmelding - - 1 - - - - - - - - - - - - - - - - `, -}; - -export const WithCheckboxes: Story = { - tags: ['!dev'], - args: { - caption: 'Avkrysningsbokser.', - striped: false, - }, - render: args => html` - - - - Mal - Dimensjon - Opprettet - Opprettet av - - - - - - - - Geografi 2020 - ATC_Verdi - 10.10.2027 - Pelle Parafin - - - - Eksportèr - - - - Vis - - - - - - - - `, -}; - -export default meta;