Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
8bb73a7
Release Tracking (#3873)
primer[bot] Feb 4, 2026
1597a74
Remove newline in file to revert accidental visual regression of Butt…
llastflowers Feb 4, 2026
1c097f1
Bump postcss-preset-env from 10.6.1 to 11.1.2 (#3905)
dependabot[bot] Feb 4, 2026
d53a236
Add accessibility documentation for Layout sidebar row_placement: :no…
liuliu-dev Feb 5, 2026
4ddf815
chore(treeview): add treeitem role to shadow dom node (#3894)
francinelucca Feb 6, 2026
70adb49
Bump markdownlint-cli2 from 0.19.1 to 0.20.0 (#3845)
dependabot[bot] Feb 9, 2026
d3691d6
Bump the all-demo group across 1 directory with 2 updates (#3925)
dependabot[bot] Feb 9, 2026
99d7203
Bump @primer/behaviors from 1.10.0 to 1.10.2 in the production-depend…
dependabot[bot] Feb 10, 2026
e162b98
Revise contributing guidelines for maintenance mode (#3920)
lesliecdubs Feb 11, 2026
0ebf631
Upgrade catalyst to v1.8.0 with explicit controller names (#3930)
Copilot Feb 11, 2026
e060f4d
Chore: add custom selectpanel event (#3919)
francinelucca Feb 11, 2026
2386a09
Update dependabot schedule to monthly (#3932)
Copilot Feb 12, 2026
37ac645
Bump listen from 3.9.0 to 3.10.0 in /demo (#3862)
dependabot[bot] Feb 12, 2026
f8c1cd8
Bump puma from 7.1.0 to 7.2.0 in /demo (#3885)
dependabot[bot] Feb 12, 2026
0e5046d
Bump faraday from 1.10.4 to 1.10.5 in /demo (#3931)
dependabot[bot] Feb 12, 2026
46b3ee1
Bump octicons from 19.21.2 to 19.22.0 in /demo (#3933)
dependabot[bot] Feb 12, 2026
01a397a
Bump changesets/action from 1.4.10 to 1.6.0 (#3889)
dependabot[bot] Feb 12, 2026
ee556b6
Bump actions/cache from 5.0.2 to 5.0.3 in the all-actions group (#3906)
dependabot[bot] Feb 12, 2026
3b848a4
Bump simplecov-console from 0.9.4 to 0.9.5 in the development-depende…
dependabot[bot] Feb 12, 2026
0505fe0
Bump the development-dependencies group with 3 updates (#3926)
dependabot[bot] Feb 12, 2026
be02987
Bump view_component from 4.2.0 to 4.3.0 in /demo (#3935)
dependabot[bot] Feb 12, 2026
48f6344
Bump bootsnap from 1.22.0 to 1.23.0 in /demo (#3936)
dependabot[bot] Feb 12, 2026
4a2ee72
Bump @primer/css from 22.0.2 to 22.1.0 in /demo (#3835)
dependabot[bot] Feb 12, 2026
5ffbc21
Bump the all-actions group across 1 directory with 2 updates (#3937)
dependabot[bot] Feb 12, 2026
b383f2d
Bump rubocop from 1.82.1 to 1.84.1 (#3927)
dependabot[bot] Feb 12, 2026
b585532
Dialog: Fix issue where focus would be lost if multiple 'popovers' we…
TylerJDev Feb 17, 2026
bb4df4a
Bump rack from 3.2.4 to 3.2.5 (#3942)
dependabot[bot] Feb 18, 2026
b7f61e2
Change `ToggleSwitch` ViewComponent `type` to `button` (#3938)
acbreton Feb 18, 2026
5f5a61b
Bump nokogiri from 1.18.9 to 1.19.1 (#3943)
dependabot[bot] Feb 19, 2026
983cc29
Add `text-wrap: balance` to Blankslate heading and description (#3945)
Copilot Feb 20, 2026
598dd86
Bump rack from 3.1.19 to 3.1.20 in /demo (#3941)
dependabot[bot] Feb 23, 2026
3933beb
Bump nokogiri from 1.19.0 to 1.19.1 in /demo (#3944)
dependabot[bot] Feb 23, 2026
c6a00b1
Add button_type parameter to ToggleSwitch component and update tests …
jonrohan Feb 24, 2026
7381ec8
fix: use `scrollbar-gutter: stable` where supported, JS layout fallba…
Copilot Feb 24, 2026
209ec41
Revert "fix: use `scrollbar-gutter: stable` where supported, JS layou…
jonrohan Feb 25, 2026
cea01ed
Merge branch 'bump/primer-upstream-ref' into bump/primer-upstream
HDinger Mar 9, 2026
df67026
Revert "Update dependabot schedule to monthly (#3932)"
HDinger Mar 13, 2026
36ea822
Merge remote-tracking branch 'origin/main' into bump/primer-upstream
HDinger Mar 13, 2026
7ee8978
Generating component snapshots
HDinger Mar 13, 2026
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
5 changes: 5 additions & 0 deletions .changeset/bright-chefs-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
---

Blankslate: Add `text-wrap: balance` to heading and description
5 changes: 5 additions & 0 deletions .changeset/fast-cougars-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
---

Remove newline in file to revert accidental visual regression of Button
5 changes: 5 additions & 0 deletions .changeset/metal-dots-attend.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@openproject/primer-view-components': patch
---

Dialog: Fixes issue in `dialog_helper.ts` where focus could be lost
5 changes: 5 additions & 0 deletions .changeset/nasty-moles-sip.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
---

chore(treeview): add treeitem role to shadow dom node
5 changes: 5 additions & 0 deletions .changeset/rare-jokes-scream.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
---

Chore: add custom "invokerClicked" selectpanel event
5 changes: 5 additions & 0 deletions .changeset/slow-maps-lie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": minor
---

Change `ToggleSwitch` ViewComponent `type` to `button`
5 changes: 5 additions & 0 deletions .changeset/tiny-pianos-deny.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@openproject/primer-view-components": patch
---

Update Catalyst to version 1.8.0 and hard-code controller/custom-element names via their @controller('...') decorators to allow for better minification
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HDinger this is good news - it will fix a bunch of issues we have with eslint and enable us to import PVC as an ESM module (along with proper types).

2 changes: 1 addition & 1 deletion .github/workflows/demo-production-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
with:
ruby-version: '3.3'
bundler-cache: true
- uses: actions/cache@v5.0.2
- uses: actions/cache@v5.0.3
with:
path: demo/gemfiles/vendor/bundle
key: gems-build-kuby-main-ruby-3.3.x-${{ hashFiles('demo/gemfiles/kuby.gemfile.lock') }}
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- uses: actions/checkout@v6
- name: Get specific changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891
uses: tj-actions/changed-files@8cba46e29c11878d930bca7870bb54394d3e8b21
with:
files: |
docs/**/*.md
Expand All @@ -42,7 +42,7 @@ jobs:
- uses: actions/checkout@v6
- name: Get specific changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891
uses: tj-actions/changed-files@8cba46e29c11878d930bca7870bb54394d3e8b21
with:
files: |
app/**/*.rb
Expand All @@ -62,7 +62,7 @@ jobs:
- uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891
uses: tj-actions/changed-files@8cba46e29c11878d930bca7870bb54394d3e8b21
with:
files: |
app/components/**/*.erb
Expand All @@ -79,7 +79,7 @@ jobs:
- uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891
uses: tj-actions/changed-files@8cba46e29c11878d930bca7870bb54394d3e8b21
with:
files: |
app/components/**/*.ts
Expand All @@ -99,7 +99,7 @@ jobs:
- uses: actions/checkout@v6
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@e0021407031f5be11a464abee9a0776171c79891
uses: tj-actions/changed-files@8cba46e29c11878d930bca7870bb54394d3e8b21
with:
files: |
app/components/**/*.pcss
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ jobs:

- name: Create release pull request or publish to npm
id: changesets
uses: changesets/action@v1.4.10
uses: changesets/action@v1.6.0
with:
title: Release Tracking
version: npm run changeset:version
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
- tree:
- treeitem "primer" [expanded] [level=1] [selected]
- group:
- treeitem "Something went wrong Retry" [level=2]:
- text: Something went wrong
- button "Retry"
- treeitem:
- group:
- treeitem "Something went wrong Retry" [level=2]:
- text: Something went wrong
- button "Retry"
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- tree:
- treeitem "primer" [expanded] [level=1] [selected]
- group:
- treeitem [level=2]
- treeitem:
- group:
- treeitem [level=2]
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- tree:
- treeitem "primer" [expanded] [level=1] [selected]
- group:
- treeitem "Loading Loading..." [level=2]
- treeitem:
- group:
- treeitem "Loading Loading..." [level=2]
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ group :development do
gem "rubocop-rails-accessibility", "~> 1.0"
gem "selenium-webdriver", "~> 4.40"
gem "simplecov", "~> 0.22.0"
gem "simplecov-console", "~> 0.9.4"
gem "simplecov-console", "~> 0.9.5"
gem "sprockets"
gem "sprockets-rails"
gem "thor"
Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ GEM
nio4r (2.7.5)
nokogiri (1.18.9-arm64-darwin)
racc (~> 1.4)
nokogiri (1.18.9-x86_64-linux-gnu)
nokogiri (1.19.1-x86_64-linux-gnu)
racc (~> 1.4)
openproject-octicons (19.32.0)
parallel (1.27.0)
Expand All @@ -170,7 +170,7 @@ GEM
puma (7.1.0)
nio4r (~> 2.0)
racc (1.8.1)
rack (3.2.4)
rack (3.2.5)
rack-cors (3.0.0)
logger
rack (>= 3.0.14)
Expand Down Expand Up @@ -257,7 +257,7 @@ GEM
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-console (0.9.4)
simplecov-console (0.9.5)
ansi
simplecov
terminal-table
Expand Down Expand Up @@ -350,7 +350,7 @@ DEPENDENCIES
rubocop-rails-accessibility (~> 1.0)
selenium-webdriver (~> 4.40)
simplecov (~> 0.22.0)
simplecov-console (~> 0.9.4)
simplecov-console (~> 0.9.5)
sourcemap (~> 0.1)
sprockets
sprockets-rails
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/action_bar_element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ enum ItemType {
Divider,
}

@controller
@controller('action-bar')
class ActionBarElement extends HTMLElement {
@targets items: HTMLElement[]
@target itemContainer: HTMLElement
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/action_list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export class ActionListTruncationObserver {
}
}

@controller
@controller('action-list')
export class ActionListElement extends HTMLElement {
#truncationObserver: ActionListTruncationObserver

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type SelectedItem = {
element: Element
}

@controller
@controller('action-menu')
export class ActionMenuElement extends HTMLElement {
@target includeFragment: IncludeFragmentElement
@target overlay: AnchoredPositionElement
Expand Down
8 changes: 6 additions & 2 deletions app/components/primer/alpha/layout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ module Alpha
#
# @accessibility
# Keyboard navigation follows the markup order. Decide carefully how the focus order should be be by deciding whether
# `main` or `sidebar` comes first in code. The code order won’t affect the visual position.
# `main` or `sidebar` comes first in code. The code order won't affect the visual position.
#
# When using `row_placement: :none` on the sidebar, the sidebar content will be hidden at narrow viewports.
# This may cause WCAG 1.4.10 Reflow failures if the sidebar contains essential content. Only use `:none`
# when the sidebar content is non-essential or available elsewhere on the page.
class Layout < Primer::Component
status :alpha

Expand Down Expand Up @@ -60,7 +64,7 @@ class Layout < Primer::Component
#
# @param width [Symbol] <%= one_of(Primer::Alpha::Layout::SIDEBAR_WIDTH_OPTIONS) %>
# @param col_placement [Symbol] Sidebar placement when `Layout` is in column modes. <%= one_of(Primer::Alpha::Layout::SIDEBAR_COL_PLACEMENT_OPTIONS) %>
# @param row_placement [Symbol] Sidebar placement when `Layout` is in row mode. <%= one_of(Primer::Alpha::Layout::SIDEBAR_ROW_PLACEMENT_OPTIONS) %>
# @param row_placement [Symbol] Sidebar placement when `Layout` is in row mode. <%= one_of(Primer::Alpha::Layout::SIDEBAR_ROW_PLACEMENT_OPTIONS) %> **Note:** Using `:none` hides the sidebar at narrow viewports, which may cause WCAG 1.4.10 Reflow issues if the sidebar contains essential content.
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
renders_one :sidebar, lambda { |
width: SIDEBAR_WIDTH_DEFAULT,
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/segmented_control.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {controller, targets} from '@github/catalyst'

@controller
@controller('segmented-control')
export class SegmentedControlElement extends HTMLElement {
@targets items: HTMLElement[]

Expand Down
5 changes: 4 additions & 1 deletion app/components/primer/alpha/select_panel_element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ const updateWhenVisible = (() => {
}
})()

@controller
@controller('select-panel')
export class SelectPanelElement extends HTMLElement {
@target includeFragment: IncludeFragmentElement
@target dialog: HTMLDialogElement
Expand Down Expand Up @@ -813,6 +813,9 @@ export class SelectPanelElement extends HTMLElement {
}

#handleInvokerActivated(event: Event) {
// Let listeners observe the invoker was clicked
this.invokerElement?.dispatchEvent(new CustomEvent('invokerClicked', {bubbles: true}))

event.preventDefault()

// eslint-disable-next-line no-restricted-syntax
Expand Down
3 changes: 3 additions & 0 deletions app/components/primer/alpha/toggle_switch.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class ToggleSwitch < Primer::Component
# Only customize this label if it makes the toggle’s state more meaningful
# in its specific context. For example, for a "Show images" setting,
# you might use "Show" when the switch is OFF.
# @param button_type [Symbol] The type attribute for the underlying button element. If `nil`, the button will not have a type attribute, which means it will default to "submit" if it's inside a form and "button" otherwise.

def initialize(
src: nil,
Expand All @@ -51,6 +52,7 @@ def initialize(
autofocus: nil,
on_label: nil,
off_label: nil,
button_type: nil,
**system_arguments
)
@src = src
Expand All @@ -75,6 +77,7 @@ def initialize(
)

@button_arguments = {
type: button_type,
aria: merge_aria(
@system_arguments,
aria: { pressed: on? }
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/toggle_switch.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {controller, target, attr} from '@github/catalyst'

@controller
@controller('toggle-switch')
class ToggleSwitchElement extends HTMLElement {
@target switch: HTMLElement
@target loadingSpinner: HTMLElement
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/tree_view/tree_view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {SelectStrategy, SelectVariant, TreeViewSubTreeNodeElement} from './tree_
import {useRovingTabIndex} from './tree_view_roving_tab_index'
import type {TreeViewCheckedValue, TreeViewNodeInfo, TreeViewNodeType} from '../../shared_events'

@controller
@controller('tree-view')
export class TreeViewElement extends HTMLElement {
@target formInputContainer: HTMLElement
@target formInputPrototype: HTMLInputElement
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {controller, target} from '@github/catalyst'
import {observeMutationsUntilConditionMet} from '../../utils'

@controller
@controller('tree-view-icon-pair')
export class TreeViewIconPairElement extends HTMLElement {
@target expandedIcon: HTMLElement
@target collapsedIcon: HTMLElement
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {controller} from '@github/catalyst'
import {IncludeFragmentElement} from '@github/include-fragment-element'

@controller
@controller('tree-view-include-fragment')
export class TreeViewIncludeFragmentElement extends IncludeFragmentElement {
request(): Request {
const originalRequest = super.request()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export type SelectStrategy = 'self' | 'descendants' | 'mixed_descendants'

export type SelectVariant = 'none' | 'single' | 'multiple'

@controller
@controller('tree-view-sub-tree-node')
export class TreeViewSubTreeNodeElement extends HTMLElement {
@target node: HTMLElement
@target subTree: HTMLElement
Expand Down Expand Up @@ -188,6 +188,12 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
// sub-tree and no node in the entire tree can be focused
const previousNode = this.subTree.querySelector("[tabindex='0']")
previousNode?.setAttribute('tabindex', '-1')

// Also check if the subtree element itself is an include-fragment with role="treeitem" and has focus
if (this.#isIncludeFragment() && this.subTree.getAttribute('tabindex') === '0') {
this.subTree.setAttribute('tabindex', '-1')
}

this.node.setAttribute('tabindex', '0')

this.treeView.dispatchEvent(
Expand Down Expand Up @@ -279,6 +285,10 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
// request succeeded but element has not yet been replaced
case 'include-fragment-replace':
this.#activeElementIsLoader = document.activeElement === this.loadingIndicator.closest('[role=treeitem]')
// Also check if the include-fragment itself has focus (when it has role="treeitem")
if (!this.#activeElementIsLoader && document.activeElement === this.subTree && this.#isIncludeFragment()) {
this.#activeElementIsLoader = true
}
this.loadingState = 'success'
break

Expand Down Expand Up @@ -432,6 +442,13 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
#update() {
if (this.expanded) {
if (this.subTree) this.subTree.hidden = false
if (this.#isIncludeFragment()) {
this.subTree.setAttribute('role', 'treeitem')
// Ensure the include-fragment can participate in roving tab index
if (!this.subTree.hasAttribute('tabindex')) {
this.subTree.setAttribute('tabindex', '-1')
}
}
this.node.setAttribute('aria-expanded', 'true')
this.treeView?.expandAncestorsForNode(this)

Expand All @@ -445,6 +462,11 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
}
} else {
if (this.subTree) this.subTree.hidden = true
if (this.#isIncludeFragment()) {
this.subTree.removeAttribute('role')
// Remove tabindex when role is removed
this.subTree.removeAttribute('tabindex')
}
this.node.setAttribute('aria-expanded', 'false')

if (this.iconPair) {
Expand Down Expand Up @@ -475,6 +497,10 @@ export class TreeViewSubTreeNodeElement extends HTMLElement {
}
}

#isIncludeFragment(): boolean {
return this.subTree?.getAttribute('data-target')?.includes('tree-view-sub-tree-node.includeFragment') ?? false
}

get #checkboxElement(): HTMLElement | null {
return this.querySelector('.TreeViewItemCheckbox')
}
Expand Down
2 changes: 1 addition & 1 deletion app/components/primer/alpha/x_banner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ declare global {
}
}

@controller
@controller('x-banner')
class XBannerElement extends HTMLElement {
@target titleText: HTMLElement

Expand Down
Loading