@oslokommune/punkt-elements 18.4.0 → 18.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{accordion-4eAsO-Sr.js → accordion-D814csFx.js} +6 -6
  3. package/dist/{accordion-DOa5vubf.cjs → accordion-E0-pLzBq.cjs} +6 -6
  4. package/dist/{alert-BUpd4yWu.js → alert-DNZtr3gd.js} +39 -31
  5. package/dist/alert-DqM9l5as.cjs +40 -0
  6. package/dist/{backlink-CA5R69FX.cjs → backlink-DYO8qA9C.cjs} +1 -1
  7. package/dist/{button-Dk6ued7E.js → button-Drwt7Qe5.js} +28 -25
  8. package/dist/button-jJfzE9C7.cjs +32 -0
  9. package/dist/{card-DgRvtnnk.js → card-BhmJZOGh.js} +90 -70
  10. package/dist/card-D-1JMn_h.cjs +64 -0
  11. package/dist/{combobox-DuTrCV1l.js → combobox-BNstYIC5.js} +20 -20
  12. package/dist/{combobox-DQ0yPhEy.cjs → combobox-CRdBlMz1.cjs} +17 -17
  13. package/dist/components/alert/alert.d.ts +2 -0
  14. package/dist/components/card/card.d.ts +12 -3
  15. package/dist/components/linkcard/linkcard.d.ts +1 -1
  16. package/dist/components/loader/loader.d.ts +2 -2
  17. package/dist/components/messagebox/messagebox.d.ts +1 -1
  18. package/dist/components/progressbar/progressbar.d.ts +2 -6
  19. package/dist/{consent-agJtEZHc.cjs → consent-DaOFbopy.cjs} +1 -1
  20. package/dist/{consent-yXeRsyAl.js → consent-Yvw7gZI_.js} +1 -1
  21. package/dist/{datepicker-CYndy_BG.cjs → datepicker-DjvL_Nb8.cjs} +16 -16
  22. package/dist/{datepicker-C7KtgfDs.js → datepicker-DzTdWHkX.js} +3 -3
  23. package/dist/{fileupload-BcJSBp9e.js → fileupload-B8Uhfx2d.js} +24 -24
  24. package/dist/{fileupload-CmxozEde.cjs → fileupload-BJVYPl8u.cjs} +15 -15
  25. package/dist/{footer-J-fOEOj5.cjs → footer-BGC5PkLa.cjs} +1 -1
  26. package/dist/{footer-DSrWdWxm.js → footer-BPxKLaut.js} +2 -2
  27. package/dist/{header-EtPWdXaI.js → header-BPzlBRhY.js} +30 -30
  28. package/dist/{header-DmJiygel.cjs → header-CAqegPzW.cjs} +34 -34
  29. package/dist/{header-menu-DpQbRKcm.cjs → header-menu-DBy7Yrd_.cjs} +1 -1
  30. package/dist/{header-menu-Dgem4HO9.js → header-menu-DWiPoQ58.js} +1 -1
  31. package/dist/{helptext-Ds8Q9IGV.cjs → helptext-BwDhf6VB.cjs} +2 -2
  32. package/dist/{helptext-BzLJKMMO.js → helptext-mf-67-fv.js} +2 -2
  33. package/dist/{input-wrapper-DZhzHSxD.js → input-wrapper-BetB7OLQ.js} +16 -15
  34. package/dist/{input-wrapper-B9wREHHW.cjs → input-wrapper-CS0qrYcm.cjs} +8 -7
  35. package/dist/{link-CpwR3BLX.cjs → link-DXnoMJIo.cjs} +3 -3
  36. package/dist/{link-C9xAIILf.js → link-DkO7a3Fs.js} +3 -3
  37. package/dist/{linkcard-Bzv3CEw5.cjs → linkcard-2l6z1M2U.cjs} +3 -3
  38. package/dist/{linkcard-C6ljKc0B.js → linkcard-aVKL5JPP.js} +8 -8
  39. package/dist/{loader-D6dau_7w.js → loader-CRVUJ-HU.js} +1 -1
  40. package/dist/{loader-Bv-1vwju.cjs → loader-D23kzlaR.cjs} +1 -1
  41. package/dist/{messagebox-CmhjIh0n.js → messagebox-CqI6_Ah7.js} +2 -2
  42. package/dist/{messagebox-DNUfv2FN.cjs → messagebox-DP06cyqc.cjs} +1 -1
  43. package/dist/pkt-accordion.cjs +1 -1
  44. package/dist/pkt-accordion.js +1 -1
  45. package/dist/pkt-alert.cjs +1 -1
  46. package/dist/pkt-alert.js +1 -1
  47. package/dist/pkt-backlink.cjs +1 -1
  48. package/dist/pkt-backlink.js +1 -1
  49. package/dist/pkt-button.cjs +1 -1
  50. package/dist/pkt-button.js +1 -1
  51. package/dist/pkt-card.cjs +1 -1
  52. package/dist/pkt-card.js +1 -1
  53. package/dist/pkt-combobox.cjs +1 -1
  54. package/dist/pkt-combobox.js +1 -1
  55. package/dist/pkt-consent.cjs +1 -1
  56. package/dist/pkt-consent.js +1 -1
  57. package/dist/pkt-datepicker.cjs +1 -1
  58. package/dist/pkt-datepicker.js +1 -1
  59. package/dist/pkt-fileupload.cjs +1 -1
  60. package/dist/pkt-fileupload.js +1 -1
  61. package/dist/pkt-footer.cjs +1 -1
  62. package/dist/pkt-footer.js +1 -1
  63. package/dist/pkt-header-menu.cjs +1 -1
  64. package/dist/pkt-header-menu.js +1 -1
  65. package/dist/pkt-header.cjs +1 -1
  66. package/dist/pkt-header.js +1 -1
  67. package/dist/pkt-helptext.cjs +1 -1
  68. package/dist/pkt-helptext.js +1 -1
  69. package/dist/pkt-index.cjs +1 -1
  70. package/dist/pkt-index.js +31 -31
  71. package/dist/pkt-input-wrapper.cjs +1 -1
  72. package/dist/pkt-input-wrapper.js +1 -1
  73. package/dist/pkt-link.cjs +1 -1
  74. package/dist/pkt-link.js +1 -1
  75. package/dist/pkt-linkcard.cjs +1 -1
  76. package/dist/pkt-linkcard.js +1 -1
  77. package/dist/pkt-loader.cjs +1 -1
  78. package/dist/pkt-loader.js +1 -1
  79. package/dist/pkt-messagebox.cjs +1 -1
  80. package/dist/pkt-messagebox.js +1 -1
  81. package/dist/pkt-progressbar.cjs +1 -1
  82. package/dist/pkt-progressbar.js +1 -1
  83. package/dist/pkt-radiobutton.cjs +1 -1
  84. package/dist/pkt-radiobutton.js +1 -1
  85. package/dist/pkt-searchinput.cjs +1 -1
  86. package/dist/pkt-searchinput.js +1 -1
  87. package/dist/pkt-select.cjs +1 -1
  88. package/dist/pkt-select.js +1 -1
  89. package/dist/pkt-tabs.cjs +1 -1
  90. package/dist/pkt-tabs.js +1 -1
  91. package/dist/pkt-tag.cjs +1 -1
  92. package/dist/pkt-tag.js +1 -1
  93. package/dist/pkt-textarea.cjs +1 -1
  94. package/dist/pkt-textarea.js +1 -1
  95. package/dist/pkt-textinput.cjs +1 -1
  96. package/dist/pkt-textinput.js +1 -1
  97. package/dist/pkt-timepicker.cjs +1 -1
  98. package/dist/pkt-timepicker.js +1 -1
  99. package/dist/progressbar-BPHLC7ce.js +117 -0
  100. package/dist/progressbar-BpcsDCnG.cjs +31 -0
  101. package/dist/{radiobutton-B_j_nYCC.js → radiobutton-B2e9Vyp8.js} +0 -1
  102. package/dist/{radiobutton-DsL-FNDd.cjs → radiobutton-C3nmL9rA.cjs} +0 -1
  103. package/dist/{searchinput-Dm3T0tGS.cjs → searchinput-CiPB8xvh.cjs} +3 -2
  104. package/dist/{searchinput-D7Dd2W2z.js → searchinput-DrUcPajl.js} +14 -12
  105. package/dist/{select-CIGYIrl3.js → select-B7TvZGIL.js} +15 -16
  106. package/dist/{select-DA5ZBqbg.cjs → select-qxjHJ8bu.cjs} +13 -14
  107. package/dist/{tabs-DPdDkHSk.js → tabs-C_tCCdBK.js} +18 -18
  108. package/dist/{tabs-nvIpMwHK.cjs → tabs-DBanbSG1.cjs} +15 -15
  109. package/dist/tag-BDlwKjgT.cjs +27 -0
  110. package/dist/{tag-DBCzfbPE.js → tag-CdiDs9zb.js} +10 -10
  111. package/dist/{textarea-CST8hYg2.cjs → textarea-DgFwd2LY.cjs} +10 -10
  112. package/dist/{textarea-BqK3V7uZ.js → textarea-YL6JYsB5.js} +14 -14
  113. package/dist/{textinput-DByVORsj.cjs → textinput-CIxMtaIo.cjs} +10 -10
  114. package/dist/{textinput-B3xYwLt3.js → textinput-CrJYDOHb.js} +12 -12
  115. package/dist/{timepicker-DZwmwpWM.js → timepicker-BHWOqlr8.js} +11 -11
  116. package/dist/{timepicker-Boj-9I40.cjs → timepicker-avaMu1hN.cjs} +8 -8
  117. package/package.json +2 -2
  118. package/src/components/accordion/accordion.ts +2 -1
  119. package/src/components/alert/alert.test.ts +2 -1
  120. package/src/components/alert/alert.ts +21 -3
  121. package/src/components/button/button.test.ts +0 -2
  122. package/src/components/button/button.ts +32 -23
  123. package/src/components/card/card.test.ts +7 -7
  124. package/src/components/card/card.ts +99 -80
  125. package/src/components/helptext/helptext.ts +2 -2
  126. package/src/components/input-wrapper/input-wrapper.ts +1 -0
  127. package/src/components/link/link.ts +4 -2
  128. package/src/components/linkcard/linkcard.test.ts +3 -3
  129. package/src/components/linkcard/linkcard.ts +1 -1
  130. package/src/components/loader/loader.test.ts +1 -1
  131. package/src/components/loader/loader.ts +3 -3
  132. package/src/components/messagebox/messagebox.test.ts +1 -1
  133. package/src/components/messagebox/messagebox.ts +2 -2
  134. package/src/components/progressbar/progressbar.test.ts +10 -8
  135. package/src/components/progressbar/progressbar.ts +63 -84
  136. package/src/components/radiobutton/radiobutton.ts +0 -1
  137. package/src/components/searchinput/searchinput.ts +3 -1
  138. package/src/components/select/select.test.ts +2 -1
  139. package/src/components/select/select.ts +0 -1
  140. package/dist/alert-BYDWYgyL.cjs +0 -35
  141. package/dist/button-C5BYwmoo.cjs +0 -30
  142. package/dist/card-DMKvuvNv.cjs +0 -87
  143. package/dist/progressbar-Bk_RsEjW.js +0 -112
  144. package/dist/progressbar-T5_MpZGN.cjs +0 -17
  145. package/dist/tag-Bp9gJnYh.cjs +0 -27
  146. package/dist/{backlink-BYUtL8cO.js → backlink-BHtxOlTw.js} +1 -1
@@ -58,7 +58,7 @@ export class PktButton extends PktElementWithSlot<IPktButton> implements IPktBut
58
58
  @property({ type: String }) color?: TPktButtonColor
59
59
  @property({ type: String }) skin: TPktButtonSkin = 'primary'
60
60
  @property({ type: String }) variant: TPktButtonVariant = 'label-only'
61
- @property({ type: String, reflect: true }) state?: TPktButtonState = 'normal'
61
+ @property({ type: String, reflect: true }) state?: TPktButtonState = undefined
62
62
  @property({ type: String, reflect: true }) type: THTMLButtonType = 'button'
63
63
  @property({ type: String }) form: string | undefined = undefined
64
64
  @property({ type: Boolean, reflect: true }) isLoading: Booleanish = false
@@ -109,6 +109,8 @@ export class PktButton extends PktElementWithSlot<IPktButton> implements IPktBut
109
109
  'aria-haspopup',
110
110
  'aria-expanded',
111
111
  'aria-controls',
112
+ 'aria-label',
113
+ 'tabindex',
112
114
  ] as const
113
115
 
114
116
  @state() private relocatedAria: Record<string, string> = {}
@@ -153,7 +155,6 @@ export class PktButton extends PktElementWithSlot<IPktButton> implements IPktBut
153
155
  [`pkt-btn--${this.state}`]: !!this.state,
154
156
  'pkt-btn--full': !!this.fullWidth,
155
157
  'pkt-btn--full-small': !!this.fullWidthOnMobile,
156
- 'pkt-btn--disabled': !!this.disabled,
157
158
  'pkt-btn--isLoading': !!this.isLoading,
158
159
  }
159
160
 
@@ -167,30 +168,38 @@ export class PktButton extends PktElementWithSlot<IPktButton> implements IPktBut
167
168
  aria-haspopup=${ifDefined(this.relocatedAria['aria-haspopup'])}
168
169
  aria-expanded=${ifDefined(this.relocatedAria['aria-expanded'])}
169
170
  aria-controls=${ifDefined(this.relocatedAria['aria-controls'])}
171
+ aria-label=${ifDefined(this.relocatedAria['aria-label'])}
172
+ tabindex=${ifDefined(this.relocatedAria['tabindex'])}
170
173
  form=${ifDefined(formId)}
171
174
  >
172
- ${this.isLoading
173
- ? html`<pkt-icon
174
- class="pkt-btn__icon pkt-btn__spinner"
175
- name="spinner-blue"
176
- path=${ifDefined(this.loadingAnimationPath)}
177
- ></pkt-icon>`
178
- : nothing}
179
- ${this.variant !== 'label-only'
180
- ? html`<pkt-icon
181
- class="pkt-btn__icon pkt-icon"
182
- name=${this.iconName}
183
- path=${ifDefined(this.iconPath)}
184
- ></pkt-icon>`
185
- : nothing}
175
+ ${
176
+ this.isLoading
177
+ ? html`<pkt-icon
178
+ class="pkt-btn__icon pkt-btn__spinner"
179
+ name="spinner-blue"
180
+ path=${ifDefined(this.loadingAnimationPath)}
181
+ ></pkt-icon>`
182
+ : nothing
183
+ }
184
+ ${
185
+ this.variant !== 'label-only'
186
+ ? html`<pkt-icon
187
+ class="pkt-btn__icon pkt-icon"
188
+ name=${this.iconName}
189
+ path=${ifDefined(this.iconPath)}
190
+ ></pkt-icon>`
191
+ : nothing
192
+ }
186
193
  <span class="pkt-btn__text">${slotContent(this)}</span>
187
- ${this.variant === 'icons-right-and-left'
188
- ? html`<pkt-icon
189
- class="pkt-btn__icon"
190
- name=${this.secondIconName}
191
- path=${ifDefined(this.secondIconPath)}
192
- ></pkt-icon>`
193
- : nothing}
194
+ ${
195
+ this.variant === 'icons-right-and-left'
196
+ ? html`<pkt-icon
197
+ class="pkt-btn__icon"
198
+ name=${this.secondIconName}
199
+ path=${ifDefined(this.secondIconPath)}
200
+ ></pkt-icon>`
201
+ : nothing
202
+ }
194
203
  </button>
195
204
  `
196
205
  }
@@ -106,7 +106,7 @@ describe('PktCard', () => {
106
106
  expect(card.tagPosition).toBe('top')
107
107
  expect(card.imageShape).toBe('square')
108
108
  expect(card.openLinkInNewTab).toBe(false)
109
- expect(card.headinglevel).toBe(3)
109
+ expect(card.headingLevel).toBe(3)
110
110
 
111
111
  const article = card.querySelector('article')
112
112
  expect(article).toHaveClass('pkt-card--outlined')
@@ -220,9 +220,9 @@ describe('PktCard', () => {
220
220
 
221
221
  expect(card.heading).toBe('Test Card Title')
222
222
 
223
- const heading = card.querySelector('pkt-heading')
223
+ const heading = card.querySelector('.pkt-card__heading')
224
224
  expect(heading).toBeInTheDocument()
225
- expect(heading).toHaveClass('pkt-card__heading')
225
+ expect(heading?.tagName).toBe('H3')
226
226
  expect(heading?.textContent?.trim()).toBe('Test Card Title')
227
227
  })
228
228
 
@@ -241,10 +241,10 @@ describe('PktCard', () => {
241
241
  const { card } = await createCardTest({ heading: 'Test', headingLevel: 2 })
242
242
  await card.updateComplete
243
243
 
244
- expect(card.headinglevel).toBe(2)
244
+ expect(card.headingLevel).toBe(2)
245
245
 
246
- const heading = card.querySelector('pkt-heading')
247
- expect(heading?.getAttribute('level')).toBe('2')
246
+ const heading = card.querySelector('.pkt-card__heading')
247
+ expect(heading?.tagName).toBe('H2')
248
248
  })
249
249
 
250
250
  test('does not render header when no heading or subheading', async () => {
@@ -263,7 +263,7 @@ describe('PktCard', () => {
263
263
 
264
264
  expect(card.clickCardLink).toBe(null)
265
265
 
266
- const heading = card.querySelector('pkt-heading')
266
+ const heading = card.querySelector('.pkt-card__heading')
267
267
  const link = card.querySelector('.pkt-card__link')
268
268
  expect(heading).toBeInTheDocument()
269
269
  expect(link).not.toBeInTheDocument()
@@ -8,14 +8,14 @@ import { slotContent } from '@/directives/slot-content'
8
8
  import { IPktHeading } from '../heading'
9
9
  import specs from 'componentSpecs/card.json'
10
10
  import '@/components/icon'
11
- /* eslint-disable no-duplicate-imports -- There's a different between the import methods */
11
+
12
12
  import '@/components/tag'
13
- import '@/components/heading'
14
13
  import type { IAriaAttributes, TCardSkin, TLayout } from 'shared-types'
15
14
 
16
15
  export type { TCardSkin, TLayout }
17
16
  export type TCardPadding = 'none' | 'default'
18
17
  export type TCardImageShape = 'square' | 'round'
18
+ export type TCardImageAspect = 'auto' | '1-1' | '4-3' | '3-2' | '16-9' | '19-10'
19
19
  export type TCardTagPosition = 'top' | 'bottom'
20
20
 
21
21
  export interface IPktCard {
@@ -27,9 +27,12 @@ export interface IPktCard {
27
27
  headingLevel?: IPktHeading['level']
28
28
  image?: { src: string; alt: string }
29
29
  imageShape?: TCardImageShape
30
+ imageAspect?: TCardImageAspect | null
31
+ restrictImageHeight?: boolean | null
30
32
  clickCardLink?: string | null
31
33
  openLinkInNewTab?: boolean | null
32
34
  borderOnHover?: boolean | null
35
+ zoom?: boolean | null
33
36
  padding?: TCardPadding
34
37
  skin?: TCardSkin
35
38
  subheading?: string
@@ -43,11 +46,16 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
43
46
  @property({ type: String }) ariaLabel: string = ''
44
47
  @property({ type: String }) metaLead: string | null = null
45
48
  @property({ type: Boolean }) borderOnHover: boolean = true
49
+ @property({ type: Boolean }) zoom: boolean = false
50
+ @property({ type: String }) imageAspect: TCardImageAspect | null = null
51
+ @property({ type: Boolean }) restrictImageHeight: boolean = false
46
52
  @property({ type: String, reflect: true }) clickCardLink: IPktCard['clickCardLink'] = null
47
53
  @property({ type: String }) metaTrail: string | null = null
48
54
  @property({ type: String }) layout: TLayout = specs.props.layout.default as TLayout
49
55
  @property({ type: String }) heading: string = ''
50
- @property({ type: Number }) headinglevel: IPktHeading['level'] = 3
56
+ // Attributtet beholder gamle `headinglevel` eksisterende markup ikke brekker.
57
+ @property({ type: Number, attribute: 'headinglevel' })
58
+ headingLevel: IPktHeading['level'] = 3
51
59
  @property({ type: Object }) image: { src: string; alt: string } = {
52
60
  src: '',
53
61
  alt: '',
@@ -97,6 +105,7 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
97
105
  [`pkt-card--${this.layout}`]: this.layout,
98
106
  [`pkt-card--padding-${this.padding}`]: this.padding,
99
107
  [`pkt-card--border-on-hover`]: this.borderOnHover,
108
+ [`pkt-card--zoom`]: this.zoom,
100
109
 
101
110
  }
102
111
 
@@ -127,59 +136,61 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
127
136
  const imageClasses = {
128
137
  'pkt-card__image': true,
129
138
  [`pkt-card__image-${this.imageShape}`]: this.imageShape,
139
+ [`pkt-card__image-aspect-${this.imageAspect}`]: Boolean(this.imageAspect),
140
+ 'pkt-card__image-restricted': this.restrictImageHeight,
130
141
  }
131
142
 
132
143
  return html`
133
- ${this.image.src &&
134
- html`
135
- <div class=${classMap(imageClasses)}>
136
- <img src=${this.image.src} alt=${this.image.alt || ''} />
137
- </div>
138
- `}
144
+ ${
145
+ this.image.src &&
146
+ html`
147
+ <div class=${classMap(imageClasses)}>
148
+ <img src=${this.image.src} alt=${this.image.alt || ''} />
149
+ </div>
150
+ `
151
+ }
139
152
  `
140
153
  }
141
154
 
155
+ private renderHeadingTag(classes: string, content: unknown) {
156
+ const level =
157
+ this.headingLevel && this.headingLevel >= 1 && this.headingLevel <= 6 ? this.headingLevel : 3
158
+ // Bruker pkt-heading sine klasser her, for å unngå forskjeller i markup
159
+ const all = `pkt-heading pkt-heading--medium pkt-heading--fw-regular ${classes}`
160
+ switch (level) {
161
+ case 1:
162
+ return html`<h1 class=${all}>${content}</h1>`
163
+ case 2:
164
+ return html`<h2 class=${all}>${content}</h2>`
165
+ case 4:
166
+ return html`<h4 class=${all}>${content}</h4>`
167
+ case 5:
168
+ return html`<h5 class=${all}>${content}</h5>`
169
+ case 6:
170
+ return html`<h6 class=${all}>${content}</h6>`
171
+ default:
172
+ return html`<h3 class=${all}>${content}</h3>`
173
+ }
174
+ }
175
+
142
176
  // Do not render heading if link is present, render link heading instead
143
- // Combine the rendering for headings into a renderHeader method
144
177
  renderHeading() {
145
- return html`
146
- ${this.heading && !this.clickCardLink
147
- ? html`
148
- <pkt-heading
149
- class="pkt-card__heading"
150
- .level=${this.headinglevel || 3}
151
- size="medium"
152
- nospacing
153
- weight="regular"
154
- >
155
- ${this.heading}
156
- </pkt-heading>
157
- `
158
- : nothing}
159
- `
178
+ if (!this.heading || this.clickCardLink) return nothing
179
+ return this.renderHeadingTag('pkt-card__heading', this.heading)
160
180
  }
161
181
 
162
182
  renderLinkHeading() {
163
- return html`
164
- ${this.clickCardLink
165
- ? html`
166
- <pkt-heading
167
- class="pkt-card__link-heading pkt-card__heading"
168
- .level=${this.headinglevel || 3}
169
- size="medium"
170
- weight="regular"
171
- nospacing
172
- >
173
- <a
174
- class="pkt-card__link"
175
- href=${this.clickCardLink}
176
- target=${this.openLinkInNewTab ? '_blank' : '_self'}
177
- >${this.heading}</a
178
- >
179
- </pkt-heading>
180
- `
181
- : nothing}
182
- `
183
+ if (!this.clickCardLink) return nothing
184
+ return this.renderHeadingTag(
185
+ 'pkt-card__link-heading pkt-card__heading',
186
+ html`<a
187
+ class="pkt-card__link"
188
+ href=${this.clickCardLink}
189
+ target=${this.openLinkInNewTab ? '_blank' : '_self'}
190
+ rel=${ifDefined(this.openLinkInNewTab ? 'noopener noreferrer' : undefined)}
191
+ >${this.heading}</a
192
+ >`,
193
+ )
183
194
  }
184
195
 
185
196
  renderSubheading() {
@@ -212,29 +223,31 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
212
223
  [`pkt-card__tags-${this.tagPosition}`]: this.tagPosition,
213
224
  }
214
225
  return html`
215
- ${this.tags.length > 0
216
- ? html`
217
- <div
218
- class=${classMap(tagClasses)}
219
- role="list"
220
- aria-label=${this.tags.length > 1 ? 'merkelapper' : 'merkelapp'}
221
- >
222
- ${this.tags.map(
223
- (tag) => html`
224
- <pkt-tag
225
- role="listitem"
226
- textStyle="normal-text"
227
- size="medium"
228
- skin=${ifDefined(tag.skin)}
229
- iconName=${ifDefined(tag.iconName)}
230
- >
231
- <span>${tag.text}</span>
232
- </pkt-tag>
233
- `,
234
- )}
235
- </div>
236
- `
237
- : nothing}
226
+ ${
227
+ this.tags.length > 0
228
+ ? html`
229
+ <div
230
+ class=${classMap(tagClasses)}
231
+ role="list"
232
+ aria-label=${this.tags.length > 1 ? 'merkelapper' : 'merkelapp'}
233
+ >
234
+ ${this.tags.map(
235
+ (tag) => html`
236
+ <pkt-tag
237
+ role="listitem"
238
+ textStyle="normal-text"
239
+ size="medium"
240
+ skin=${ifDefined(tag.skin)}
241
+ iconName=${ifDefined(tag.iconName)}
242
+ >
243
+ <span>${tag.text}</span>
244
+ </pkt-tag>
245
+ `,
246
+ )}
247
+ </div>
248
+ `
249
+ : nothing
250
+ }
238
251
  `
239
252
  }
240
253
 
@@ -244,18 +257,24 @@ export class PktCard extends PktElementWithSlot implements IPktCard {
244
257
 
245
258
  renderMetadata() {
246
259
  return html`
247
- ${this.metaLead || this.metaTrail
248
- ? html`
249
- <footer class="pkt-card__metadata">
250
- ${this.metaLead
251
- ? html`<span class="pkt-card__metadata-lead">${this.metaLead}</span>`
252
- : nothing}
253
- ${this.metaTrail
254
- ? html`<span class="pkt-card__metadata-trail">${this.metaTrail}</span>`
255
- : nothing}
256
- </footer>
257
- `
258
- : nothing}
260
+ ${
261
+ this.metaLead || this.metaTrail
262
+ ? html`
263
+ <footer class="pkt-card__metadata">
264
+ ${
265
+ this.metaLead
266
+ ? html`<span class="pkt-card__metadata-lead">${this.metaLead}</span>`
267
+ : nothing
268
+ }
269
+ ${
270
+ this.metaTrail
271
+ ? html`<span class="pkt-card__metadata-trail">${this.metaTrail}</span>`
272
+ : nothing
273
+ }
274
+ </footer>
275
+ `
276
+ : nothing
277
+ }
259
278
  `
260
279
  }
261
280
  }
@@ -77,8 +77,8 @@ export class PktHelptext extends PktElementWithSlot<IPktStringsProps<'forms'>> {
77
77
  const helptextElement = () => {
78
78
  return html`<div class="${helptextClasses}">
79
79
  <div class="pkt-inputwrapper__helptext" id="${this.forId}-helptext">
80
- <div class="pkt-contents" name="helptext">${slotContent(this)}</div>
81
- ${this.helptext && unsafeHTML(this.helptext)}
80
+ <div class="pkt-contents">${slotContent(this)}</div>
81
+ ${this.helptext ? html`<span>${unsafeHTML(this.helptext)}</span>` : nothing}
82
82
  </div>
83
83
  ${helptextDropdown()}
84
84
  </div>`
@@ -193,6 +193,7 @@ export class PktInputWrapper extends PktElementWithSlot<Props> {
193
193
  <pkt-alert
194
194
  skin="error"
195
195
  .size=${errorAlertSize}
196
+ .role=${'alert'}
196
197
  id=${`${this.forId}-error`}
197
198
  aria-live="assertive"
198
199
  aria-atomic="true"
@@ -30,14 +30,16 @@ export class PktLink extends PktElementWithSlot {
30
30
  'pkt-link--icon-right': !!this.iconName && this.iconPosition === 'right',
31
31
  'pkt-link--external': this.external,
32
32
  }
33
+ const target = this.target && this.target !== '_self' ? this.target : nothing
34
+
33
35
  return html`<a
34
36
  class=${classMap(classes)}
35
37
  href=${this.href}
36
- .target=${this.target}
38
+ target=${target}
37
39
  .rel=${this.external ? 'noopener noreferrer' : nothing}
38
40
  >${this.iconName
39
41
  ? html`<pkt-icon name=${this.iconName} class="pkt-link__icon"></pkt-icon>`
40
- : ''} <span>${slotContent(this)}</span></a
42
+ : ''}${slotContent(this)}</a
41
43
  >`
42
44
  }
43
45
  }
@@ -64,7 +64,7 @@ describe('PktLinkCard', () => {
64
64
  expect(linkCard.href).toBe('#')
65
65
  expect(linkCard.iconName).toBe('')
66
66
  expect(linkCard.openInNewTab).toBe(false)
67
- expect(linkCard.skin).toBe('normal')
67
+ expect(linkCard.skin).toBeUndefined()
68
68
  expect(linkCard.external).toBe(false)
69
69
 
70
70
  expect(link.getAttribute('href')).toBe('#')
@@ -209,7 +209,7 @@ describe('PktLinkCard', () => {
209
209
  test('applies default skin class', async () => {
210
210
  const { link } = await createLinkCardTest()
211
211
  expect(link).toHaveClass('pkt-linkcard')
212
- expect(link).toHaveClass('pkt-linkcard--normal')
212
+ expect(link).not.toHaveClass('pkt-linkcard--normal')
213
213
  })
214
214
 
215
215
  test('applies different skin classes correctly', async () => {
@@ -312,7 +312,7 @@ describe('PktLinkCard', () => {
312
312
 
313
313
  expect(linkCard.href).toBe('/minimal')
314
314
  expect(link.getAttribute('href')).toBe('/minimal')
315
- expect(link).toHaveClass('pkt-linkcard--normal')
315
+ expect(link).not.toHaveClass('pkt-linkcard--normal')
316
316
 
317
317
  // Should not have title or icon
318
318
  expect(linkCard.querySelector('.pkt-linkcard__title')).not.toBeInTheDocument()
@@ -16,7 +16,7 @@ export class PktLinkCard extends PktElementWithSlot<IPktLinkCard> implements IPk
16
16
  @property({ type: String, reflect: true }) iconName: string = ''
17
17
  @property({ type: Boolean, reflect: true }) external: boolean = false
18
18
  @property({ type: Boolean, reflect: true }) openInNewTab: boolean = false
19
- @property({ type: String, reflect: true }) skin: TLinkCardSkin = 'normal'
19
+ @property({ type: String, reflect: true }) skin?: TLinkCardSkin = undefined
20
20
 
21
21
  render() {
22
22
  const classes = ['pkt-linkcard', this.skin && `pkt-linkcard--${this.skin}`]
@@ -83,7 +83,7 @@ describe('PktLoader', () => {
83
83
  expect(loader.isLoading).toBe(true)
84
84
  expect(loader.inline).toBe(false)
85
85
  expect(loader.size).toBe('medium')
86
- expect(loader.variant).toBe('shapes')
86
+ expect(loader.variant).toBe('rainbow')
87
87
  expect(loader.delay).toBe(0)
88
88
  })
89
89
 
@@ -40,8 +40,8 @@ export interface IPktLoader {
40
40
  */
41
41
  size?: TPktSize
42
42
  /**
43
- * The variant of the loader. Default is "shapes" which is the OSLO wave loader.
44
- * Other variants are "blue" and "rainbow" which are spinner variants.
43
+ * The variant of the loader. Default is "rainbow".
44
+ * "shapes" is the OSLO wave loader, "blue" a blue spinner.
45
45
  */
46
46
  variant?: TPktLoaderVariant
47
47
  /**
@@ -56,7 +56,7 @@ export class PktLoader extends PktElementWithSlot implements IPktLoader {
56
56
  @property({ type: Boolean }) isLoading: boolean = true
57
57
  @property({ type: String }) message: string | null = null
58
58
  @property({ type: String }) size: TPktSize = 'medium'
59
- @property({ type: String }) variant: TPktLoaderVariant = 'shapes'
59
+ @property({ type: String }) variant: TPktLoaderVariant = 'rainbow'
60
60
  @property({ type: String }) loadingAnimationPath: string | undefined =
61
61
  typeof window !== 'undefined' ? window.pktAnimationPath : defaultAnimationPath
62
62
 
@@ -72,7 +72,7 @@ describe('PktMessagebox', () => {
72
72
  expect(messagebox.closable).toBe(false)
73
73
  expect(messagebox.compact).toBe(false)
74
74
  expect(messagebox.title).toBe('')
75
- expect(messagebox.skin).toBe('beige')
75
+ expect(messagebox.skin).toBeUndefined()
76
76
  })
77
77
 
78
78
  test('sets properties correctly', async () => {
@@ -29,7 +29,7 @@ export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox
29
29
  @property({ type: Boolean, reflect: true }) closable = specs.props.closable.default
30
30
  @property({ type: Boolean, reflect: true }) compact = specs.props.compact.default
31
31
  @property({ type: String, reflect: true }) title = ''
32
- @property({ type: String, reflect: true }) skin = specs.props.skin.default as TMessageboxSkin
32
+ @property({ type: String, reflect: true }) skin?: TMessageboxSkin = undefined
33
33
 
34
34
  @state() _isClosed: boolean = false
35
35
 
@@ -49,7 +49,7 @@ export class PktMessagebox extends PktElementWithSlot implements IPktMessagebox
49
49
  const classes = {
50
50
  'pkt-messagebox': true,
51
51
  'pkt-messagebox--compact': this.compact,
52
- [`pkt-messagebox--${this.skin}`]: this.skin,
52
+ [`pkt-messagebox--${this.skin}`]: !!this.skin,
53
53
  'pkt-messagebox--closable': this.closable,
54
54
  'pkt-hide': this._isClosed,
55
55
  }
@@ -38,7 +38,7 @@ describe('PktProgressbar', () => {
38
38
  const { progressbar } = await createProgressbarTest({ valueCurrent: 50 })
39
39
 
40
40
  expect(progressbar.valueCurrent).toBe(50)
41
- expect(progressbar.getAttribute('role')).toBe('progressbar')
41
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe('progressbar')
42
42
  })
43
43
  })
44
44
 
@@ -150,10 +150,11 @@ describe('PktProgressbar', () => {
150
150
  ariaLabel: 'File upload progress',
151
151
  })
152
152
 
153
- expect(progressbar.getAttribute('aria-valuemin')).toBe('0')
154
- expect(progressbar.getAttribute('aria-valuemax')).toBe('100')
155
- expect(progressbar.getAttribute('aria-valuenow')).toBe('60')
156
- expect(progressbar.getAttribute('aria-label')).toBe('File upload progress')
153
+ const root = progressbar.querySelector('.pkt-progressbar')
154
+ expect(root?.getAttribute('aria-valuemin')).toBe('0')
155
+ expect(root?.getAttribute('aria-valuemax')).toBe('100')
156
+ expect(root?.getAttribute('aria-valuenow')).toBe('60')
157
+ expect(root?.getAttribute('aria-label')).toBe('File upload progress')
157
158
  })
158
159
 
159
160
  test('updates aria-valuenow when value changes', async () => {
@@ -162,7 +163,7 @@ describe('PktProgressbar', () => {
162
163
  progressbar.valueCurrent = 80
163
164
  await progressbar.updateComplete
164
165
 
165
- expect(progressbar.getAttribute('aria-valuenow')).toBe('80')
166
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('aria-valuenow')).toBe('80')
166
167
  })
167
168
  })
168
169
 
@@ -170,13 +171,14 @@ describe('PktProgressbar', () => {
170
171
  test('uses progressbar role by default', async () => {
171
172
  const { progressbar } = await createProgressbarTest()
172
173
 
173
- expect(progressbar.getAttribute('role')).toBe('progressbar')
174
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe('progressbar')
175
+ expect(progressbar.hasAttribute('role')).toBe(false)
174
176
  })
175
177
 
176
178
  test('uses meter role when specified', async () => {
177
179
  const { progressbar } = await createProgressbarTest({ role: 'meter' })
178
180
 
179
- expect(progressbar.getAttribute('role')).toBe('meter')
181
+ expect(progressbar.querySelector('.pkt-progressbar')?.getAttribute('role')).toBe('meter')
180
182
  })
181
183
  })
182
184