Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 32 additions & 22 deletions doc-site/components/nve-link-card.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ Bruk `size` for å endre størrelse. `medium` er standard.

Du kan legge til en ekstra tekst under hovedlenkens overskrift ved å bruke `additionalText`-egenskapen. Både overskriften og den tilhørende teksten blir lest opp av skjermlesere, så sørg for at teksten er kortfattet og lett å forstå.

**Merk:**
`additionalText` vises kun på én linje. Hvis teksten er for lang, blir den automatisk avkortet med `...`.

<CodeExamplePreview>

```html
Expand Down Expand Up @@ -134,12 +137,39 @@ Se anbefalinger for e-postlenker i seksjonen [Tilgjengelighet](#tilgjengelighet)

</CodeExamplePreview>

## Ikon til venstre

Du kan legge til et ikon helt til venstre i kortet ved å bruke slot med `slot="icon"`. Dette gir deg fleksibilitet til å vise hvilket som helst ikon først i kortet, uavhengig av hvilket ikon som vises til høyre (styrt av `clickAction`). Ikonet du setter med slot plasseres alltid ytterst til venstre, og får automatisk en størrelse på 24px. Du skal ikke endre størrelsen på dette ikonet med egne props eller CSS – kortet sørger for riktig størrelse og plassering.

<CodeExamplePreview>

```html
<nve-link-card
label="Last ned høringsdokument"
variant="secondary"
size="large"
href="/assets/mardalsfossen.jpg"
clickAction="download"
>
<nve-icon name="docs" slot="icon"></nve-icon>
</nve-link-card>
<nve-link-card
label="Varsom – vær og snøskred"
variant="secondary"
clickAction="external"
size="large"
href="https://www.varsom.no/"
>
<nve-icon name="warning" slot="icon"></nve-icon>
</nve-link-card>
```

</CodeExamplePreview>

## Bruk med klient side-routing i SPA-applikasjoner

Når man benytter klientside-routing, for eksempel med `routerLink`, genereres et eget `<a>`-element av rammeverket. I disse tilfellene blir `nve-link-card` pakket inn i en `<a>`. For å unngå ugyldig HTML-struktur med `<a>`-elementer inni hverandre, sjekker `nve-link-card` derfor om dets direkte forelder er et `<a>`. Hvis dette er tilfelle, rendres kortet som et `<div>` i stedet for et `<a>`.

SKRIV HER AT NOEN RAMMEVERKER STØTTER VISITED!!! ser ut at next js og vue støtter det i spa applikasjoner. verdt å teste i safari tenker jeg

På denne måten beholdes mest funksjonalitet og styling fra `nve-link-card`, samtidig som man unngår semantiske og tekniske problemer med nestede lenker.

Bruk av nve-link-card i Vue:
Expand Down Expand Up @@ -167,26 +197,6 @@ Bruk av nve-link-card i React:
</Link>
```

## Besøkt lenke

I henhold til krav for universell utforming skal besøkte lenker ha `besøkt`-tilstand. De fleste nettlesere håndterer dette automatisk ved å bruke CSS-pseudoklassen `:visited` på lenker som er besøkt. Vi definerer egen styling for besøkte lenker i `global.css`, som hentes inn via tema-filer (for eksempel `varsom.css` eller `nve.css`) som bruker denne pseudoklassen.

Ved bruk av lenkekomponenter fra JS-rammeverk, kan det i enkelte tilfeller forekomme at `:visited`-tilstanden ikke fungerer som forventet i noen nettlesere. Dersom du opplever dette, kan du aktivere `visited`-egenskapen på `nve-link-card` når den er pakket inn i en rammeverkslenke. ( Denne egenskapen har ingen effekt dersom `nve-link-card` brukes som en selvstendig lenke, ettersom den da støtter `:visited`-tilstanden direkte gjennom nettleseren.).

For å bruke `visited`-egenskapen må du selv håndtere logikken for besøkte lenker — for eksempel ved å lagre besøkte URL-er i lokal lagring (localStorage).

Dette er likevel en sjelden problemstilling. Lenkekomponentene i Vue, React og Next.js støtter `:visited` som forventet, og du trenger som regel ikke gjøre noe spesielt. Bruker du et annet rammeverk, anbefaler vi å teste om `:visited`-tilstanden settes korrekt i DevTools før du tar i bruk `visited`-egenskapen.

<CodeExamplePreview>

```html
<a class="rammeverk-sin-lenke-komponent" href="/components/Komponentoversikt">
<nve-link-card label="Gå til komponentoversikt" variant="contrast" clickAction="internal" visited> </nve-link-card>
</a>
```

</CodeExamplePreview>

## Tilgjengelighet

### Retningslinjer
Expand Down
3 changes: 3 additions & 0 deletions src/components/nve-icon/offline-icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
* velg aktuelt ikon, velg 24px størrelse og svart farge og "copy icon to clipboard"
*/
export const offlineIcons: { [key: string]: string } = {
arrow_forward: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M647-440H160v-80h487L423-744l57-56 320 320-320 320-57-56 224-224Z"/></svg>`,
check_circle:
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="m424-296 282-282-56-56-226 226-114-114-56 56 170 170Zm56 216q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>',
chevron_backward: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M560-240 320-480l240-240 56 56-184 184 184 184-56 56Z"/></svg>`,
chevron_forward: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M504-480 320-664l56-56 240 240-240 240-56-56 184-184Z"/></svg>`,
close: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="m256-200-56-56 224-224-224-224 56-56 224 224 224-224 56 56-224 224 224 224-56 56-224-224-224 224Z"/></svg>`,
download: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M480-320 280-520l56-58 104 104v-326h80v326l104-104 56 58-200 200ZM160-160v-200h80v120h480v-120h80v200H160Z"/></svg>`,
error: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M480-280q17 0 28.5-11.5T520-320q0-17-11.5-28.5T480-360q-17 0-28.5 11.5T440-320q0 17 11.5 28.5T480-280Zm-40-160h80v-240h-80v240Zm40 360q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>`,
info: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M440-280h80v-240h-80v240Zm40-320q17 0 28.5-11.5T520-640q0-17-11.5-28.5T480-680q-17 0-28.5 11.5T440-640q0 17 11.5 28.5T480-600Zm0 520q-83 0-156-31.5T197-197q-54-54-85.5-127T80-480q0-83 31.5-156T197-763q54-54 127-85.5T480-880q83 0 156 31.5T763-763q54 54 85.5 127T880-480q0 83-31.5 156T763-197q-54 54-127 85.5T480-80Zm0-80q134 0 227-93t93-227q0-134-93-227t-227-93q-134 0-227 93t-93 227q0 134 93 227t227 93Zm0-320Z"/></svg>`,
lock: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M240-80q-33 0-56.5-23.5T160-160v-400q0-33 23.5-56.5T240-640h40v-80q0-83 58.5-141.5T480-920q83 0 141.5 58.5T680-720v80h40q33 0 56.5 23.5T800-560v400q0 33-23.5 56.5T720-80H240Zm0-80h480v-400H240v400Zm240-120q33 0 56.5-23.5T560-360q0-33-23.5-56.5T480-440q-33 0-56.5 23.5T400-360q0 33 23.5 56.5T480-280ZM360-640h240v-80q0-50-35-85t-85-35q-50 0-85 35t-35 85v80ZM240-160v-400 400Z"/></svg>`,
mail: `<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#000000"><path d="M80-160v-640h800v640H80Zm400-280L160-640v400h640v-400L480-440Zm0-80 320-200H160l320 200ZM160-640v-80 480-400Z"/></svg>`,
open_in_new: `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="M200-120q-33 0-56.5-23.5T120-200v-560q0-33 23.5-56.5T200-840h280v80H200v560h560v-280h80v280q0 33-23.5 56.5T760-120H200Zm188-212-56-56 372-372H560v-80h280v280h-80v-144L388-332Z"/></svg>`,
warning:
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -960 960 960" fill="#000000"><path d="m40-120 440-760 440 760H40Zm138-80h604L480-720 178-200Zm302-40q17 0 28.5-11.5T520-280q0-17-11.5-28.5T480-320q-17 0-28.5 11.5T440-280q0 17 11.5 28.5T480-240Zm-40-120h80v-200h-80v200Zm40-100Z"/></svg>',
Expand Down
9 changes: 6 additions & 3 deletions src/components/nve-link-card/nve-link-card.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ import '../nve-icon/nve-icon.component';
* Komponent som brukes til å navigere til interne, eksterne sider, laste ned filer, eller sende e-post.
* For å bruke komponenten på best og tilgjengelig måte les mer i tilgjengelighet seksjonen.
*
* Ikonet lengst til venstre i kortet kan settes med <slot name="icon"> og kan være hvilket som helst element.
* Ikonet til høyre styres av clickAction-propen og vises automatisk.
*
* @csspart link-card Topp-element
* @csspart label Overskriften
* @csspart additional-text Tilleggsbeskrivelse under overskriften
* @slot icon Ikon til venstre i kortet (valgfritt)
*/
@customElement('nve-link-card')
export default class NveLinkCard extends LitElement implements INveComponent {
Expand All @@ -35,8 +40,6 @@ export default class NveLinkCard extends LitElement implements INveComponent {
/** Lenken som brukes for handlinger som intern/ekstern navigering eller e-post */
@property() href: string | undefined = undefined;

/** Brukes for å legge :visited style når lenken kommer fra eksternt rammeverk som f.eks RouterLink i Vue */
@property({ type: Boolean }) visited: boolean = false;
static styles = [styles];

/**
Expand All @@ -59,6 +62,7 @@ export default class NveLinkCard extends LitElement implements INveComponent {

private renderContent() {
return html`
<slot name="icon"></slot>
<div class="link-card__content">
<div part="label" class="link-card__label">${this.label}</div>
${this.additionalText
Expand All @@ -81,7 +85,6 @@ export default class NveLinkCard extends LitElement implements INveComponent {
testId="${ifDefined(this.testId)}"
class=${classMap({
'link-card': true,
'link-card--visited': this.visited,
[`link-card--${this.size}`]: true,
[`link-card--${this.variant}`]: true,
})}
Expand Down
129 changes: 68 additions & 61 deletions src/components/nve-link-card/nve-link-card.styles.ts
Original file line number Diff line number Diff line change
@@ -1,124 +1,131 @@
import { css } from 'lit';
export default css`
.link-card {
border-radius: var(--border-radius-small);
padding: var(--spacing-medium, 16px) var(--spacing-large, 24px);
transition: background 0.3s ease;
border: 2px solid transparent;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
width: 100%;
padding: var(--spacing-medium) var(--spacing-large);
gap: var(--spacing-medium);
border-radius: var(--border-radius-small);
border: var(--border-width-stronger) solid transparent;
background: var(--color-neutrals-background-primary);
cursor: pointer;
text-decoration: none;
transition:
background 0.3s ease,
border-color 0.3s ease;
}

/*bruker color på a, ikke på link-card fordi link-card overskriver standard lenke farge i remmeverker som next js som har sin egen
wrappar rundt lenke og som støtter :visited*/
/* Setter farge på <a> for å sikre riktig lenkefarge uansett rammeverk eller browser */
a {
color: var(--color-neutrals-foreground-primary, #0d0d0e);
color: var(--color-neutrals-foreground-primary);
}

.link-card--visited,
a:visited {
color: var(--color-interactive-links-visited);
.link-card:hover {
border-color: var(--color-neutrals-border-subtle);
background: var(--color-neutrals-background-primary);
}

.link-card:focus {
outline: var(--color-interactive-primary-foreground-border-focus, #008ffb) solid 2px;
.link-card:active {
border-color: var(--color-neutrals-border-mute);
}

.link-card:hover .link-card__label {
text-decoration: underline;
}

.link-card:active {
outline: var(--color-interactive-primary-foreground-border-focus, #008ffb) solid 2px;
.link-card:focus-visible {
outline: var(--color-interactive-primary-border-focus) solid 2px;
}

.link-card--small {
padding: var(--spacing-small) var(--spacing-medium) var(--spacing-small) var(--spacing-medium);
padding: var(--spacing-small) var(--spacing-medium);
gap: var(--spacing-x-small);
min-height: var(--sizing-2x-small);
}

.link-card--medium {
padding: var(--spacing-medium) var(--spacing-medium) var(--spacing-medium) var(--spacing-large);
padding: var(--spacing-medium) var(--spacing-large);
min-height: var(--sizing-2x-small);
}

.link-card--large {
padding: var(--spacing-medium) var(--spacing-medium) var(--spacing-medium) var(--spacing-large);
padding: var(--spacing-large);
min-height: var(--sizing-x-small);
}

.link-card__label {
font-size: 1rem;
font-family: 'Source Sans 3';
font-style: normal;
font-weight: 400;
line-height: 150%;
}

.link-card--visited .link-card__label,
.link-card:visited .link-card__label {
color: var(--color-interactive-links-visited);
.link-card--primary {
background: var(--color-neutrals-background-primary);
}

.link-card__label--small {
font-size: 0.875rem;
.link-card--contrast {
background: var(--color-neutrals-background-primary-contrast);
}

.link-card__label--large {
font-size: 1.125rem;
.link-card--secondary {
background: var(--color-neutrals-background-secondary);
}

.link-card__content {
display: flex;
flex-direction: column;
justify-content: space-between;
justify-content: center;
flex: 1;
}

.link-card__additional-text {
color: inherit;
font-family: 'Source Sans 3';
font-style: normal;
font-weight: 400;
line-height: 120%;
padding-top: 4px;
font-size: 0.875rem;
.link-card__label {
font: var(--typography-heading-x-small);
color: var(--color-neutrals-foreground-primary);
transition:
color 0.3s ease,
text-decoration-thickness 0.3s,
text-underline-offset 0.3s;
}

.link-card--visited .link-card__additional-text,
a:visited .link-card__additional-text {
color: var(--color-interactive-links-visited);
.link-card:hover .link-card__label {
color: var(--color-brand-foreground-primary);
text-decoration: underline;
text-decoration-style: solid;
text-decoration-thickness: 5%;
text-underline-offset: 16%;
}

.link-card--primary {
background: var(--color-neutrals-background-primary, #fff);
.link-card:active .link-card__label {
text-decoration-thickness: 10%;
text-underline-offset: 16%;
}

.link-card--primary:hover {
background: var(--color-neutrals-background-secondary, #e4e5e7);
.link-card--small .link-card__label {
font: var(--typography-label-small);
}

.link-card--contrast {
background: var(--color-neutrals-background-primary-contrast, #f7f7f8);
.link-card--large .link-card__label {
font: var(--typography-heading-x-small);
}

.link-card--contrast:hover {
background: var(--color-neutrals-background-secondary, #e4e5e7);
.link-card__additional-text {
color: var(--color-neutrals-foreground-subtle);
font: var(--typography-body-compact-x-small-compact);
overflow: hidden;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
text-overflow: ellipsis;
}

.link-card--secondary {
background: var(--color-neutrals-background-secondary, #e4e5e7);
.link-card--small .link-card__additional-text {
font: var(--typography-body-compact-x-small-compact);
}

.link-card--secondary:hover {
border: 2px solid var(--color-neutrals-foreground-primary, #0d0d0e);
.link-card--large .link-card__additional-text {
font: var(--typography-body-compact-small-compact);
}

.link-card ::slotted([slot='icon']) {
--icon-size: 24px;
}

nve-icon {
--icon-size: 24px;
color: var(--color-neutrals-foreground-primary);
color: var(--color-brand-foreground-primary);
}
`;
Loading
Loading