Skip to content

Commit 827edf8

Browse files
idaivmarkus-moserberfinyukselxIrusuxValeriaMaltseva
authored
[Studio UI] Fix full-height tabs and compact tab spacing (#3884)
* Automatic frontend build * Add concurrency group to prevent auto-commit push races * Automatic frontend build * Automatic frontend build * Automatic frontend build * 🔄 synced file(s) with pimcore/platform-version * Automatic frontend build * Automatic frontend build * Automatic frontend build * Automatic frontend build * Automatic frontend build * Polish UI of Grid Config (#3855) * Rename "Grid config" to "Grid Config" in sidebar and modal - Fix capitalization in EN translation key listing.grid-config.title - Replace hardcoded string in grid-config-modal.tsx with translation key * Auto-scroll to newly added column in grid config sidebar and modal Replaces the sentinel div approach with a container ref + querySelectorAll approach in both GridConfigList components: - Skips scroll on initial mount to avoid triggering on template load - Detects true user-initiated appends (length increase with order preserved) - Uses uniqueId (data-object) or key (asset) for stable tracking - Scrolls to the specific new item via .stack-list__item selector - Uses block:'start' for advanced columns (shows form header at top) - Uses block:'nearest' for simple columns (minimal scroll) - Modal view covered automatically (shares GridConfigList) * Fix scroll-to-new-column position and consistency Replace scrollIntoView with explicit scroll parent detection + scrollTo: - findScrollableParent walks the DOM to find the actual scrollable container, avoiding issues where scrollIntoView latches onto the wrong ancestor (e.g. dnd-kit wrappers or intermediate containers) - Wrap in requestAnimationFrame to defer past any dnd-kit transform animations that would cause incorrect position measurements - Compute exact scrollTo delta using getBoundingClientRect for precise control: item bottom + 8px buffer for simple columns, item top - 8px from container top for advanced columns * Polish UI of Grid Config - Use colorBorderSecondary consistently on stack list items; fix double border on advanced column collapse items - Remove collapse header/body separator border; align header and body paddings - Advanced column form: remove title divider and wrapper padding, remove Form.Item margin-bottom, fix tabs equal-width layout (no nav padding, no sibling margin) - Source/transformer cards: symmetric 8px left/right padding, 8px vertical outer padding, small trash button, 8px gap between form fields - Relation field: switch to Pimcore Select component for consistent styling; capitalise "Relation" label - Fields-to-add panel: reduce header/search gap to 4px, add 4px header left padding via createStyles, set collapse button to type=text with tooltip - Add-column controls: increase button gap from 4px to 8px - Grid config modal: add reload IconButton (matches app-wide refresh pattern), remove bottom toolbar y-padding, add right padding to column list, reduce split divider to 16px wide with 4px top/bottom inset - Preview: rename "Select Item" to "Preview Item" with ID + truncated path breadcrumb and full-path tooltip; symmetric 12px padding; colorTextDescription for no-preview and error detail texts; move all token-based colors from inline styles to createStyles files - Split layout divider: reduce min-width from 24px to 16px * fix: add type guard for fullpath to resolve no-unsafe-argument ESLint error * fix: cast item.data to typed record to resolve no-unsafe-argument ESLint error * Apply eslint-fixer changes * Automatic frontend build --------- * Automatic frontend build * Automatic frontend build * Update maintenance branch in CONTRIBUTING.md to 2026.2 (#187) Co-authored-by: Claude Fable 5 <noreply@anthropic.com> * Automatic frontend build * Rename new-docs.yml to docs.yml * Remove new-docs.yml after rename to docs.yml * Rename new-php-cs-fixer.yaml to php-cs-fixer.yaml * Remove new-php-cs-fixer.yaml after rename to php-cs-fixer.yaml * Rename new-poeditor-export.yaml to poeditor-export.yaml * Remove new-poeditor-export.yaml after rename to poeditor-export.yaml * Rename new-static-analysis.yaml to static-analysis.yaml * Remove new-static-analysis.yaml after rename to static-analysis.yaml * Automatic frontend build * Make the workflow transition modal reusable outside the element editor (#3859) * Automatic frontend build * Automatic frontend build * [Versions] [UI improvement] Remove unnecessary usage of open where paths are already available (#3864) * [Versions] Remove redundant Open button for relations in versions view In the read-only versions view, relation fields already display the element's full path, making the "Open" button redundant. Hide it for all relation types (many-to-one, many-to-many, advanced, reverse, and object variants) by injecting a version-only `hideOpenButton` flag via each type's `getVersionObjectDataComponent`. The normal editor is unchanged, including read-only/inherited fields where opening the element is still useful. For the many-to-many grid, also drop the whole "Actions" column when it would otherwise render empty (open hidden and removal disabled). Closes #2787 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Automatic frontend build --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: ValeriaMaltseva <11871778+ValeriaMaltseva@users.noreply.github.com> * Automatic frontend build * Remove committed frontend build artifacts from public/build/ (#3870) * Automatic frontend build * Trigger the frontend build on pushes to N.x version branches (#3873) * Automatic frontend build * Automatic frontend build * Remove committed frontend build artifacts from public/build/ (#3881) * [Studio UI] Fix full-height tabs and compact tab spacing - Fix tab content areas not filling available height (add content-holder flex, min-height, relative positioning, overflow hidden) - Set consistent 12px gap between tabs in noPadding tab variant - Reduce modal title gap from 8px to 4px Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Automatic frontend build * [Studio UI] Replace pixel values with design tokens - Modal title gap: 4px → token.marginXXS - Tab no-padding margin: 12px → token.marginSM Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Automatic frontend build --------- Co-authored-by: markus-moser <4639428+markus-moser@users.noreply.github.com> Co-authored-by: berfinyuksel <99557970+berfinyuksel@users.noreply.github.com> Co-authored-by: Christine Altmann <christine.altmann@pimcore.com> Co-authored-by: xIrusux <42359615+xIrusux@users.noreply.github.com> Co-authored-by: Valeriia Maltseva <valeriia.maltseva@pimcore.com> Co-authored-by: ValeriaMaltseva <11871778+ValeriaMaltseva@users.noreply.github.com> Co-authored-by: Pimcore Deployments Bot <pimcore-deployments@pimcore.com> Co-authored-by: pimcore-deployments <71881008+pimcore-deployments@users.noreply.github.com> Co-authored-by: Marvin Bertram <marvin.bertram@pimcore.com> Co-authored-by: vin0401 <26813978+vin0401@users.noreply.github.com> Co-authored-by: markus-moser <markus.moser@pimcore.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: robertSt7 <104770750+robertSt7@users.noreply.github.com>
1 parent fa32791 commit 827edf8

51 files changed

Lines changed: 688 additions & 190 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/frontend-build-pr.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ on:
44
push:
55
branches:
66
- "[0-9]+.[0-9]+"
7+
- "[0-9]+.x"
78
- "feature-*"
89
- "nightly"
910
# TEMP (remove before merge): regenerate build-dist/build-<id>.zip on every push to
File renamed without changes.
File renamed without changes.

CONTRIBUTING.md

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,84 @@
1-
## Contributing Studio Pull Requests
2-
We gladly accept community pull requests. This is the preferred way to contribute to Pimcore. There are a few necessary steps before we can accept a pull request:
1+
# Contributing to Pimcore
2+
As an open core project we love to work together with our community to improve and develop our products.
3+
It's also important for us to make clear that **we're not working for you or your company**,
4+
but we enjoy to work together to solve issues or improve the product.
5+
6+
## Contributing Pull Requests
7+
We gladly accept community pull requests. This is the preferred way to contribute to Pimcore.
8+
There are a few necessary steps before we can accept a pull request:
9+
10+
> **Note:** Before opening a PR, also see our [Pull Request Guidelines](https://github.com/orgs/pimcore/discussions/19239) for the automated checks your PR must pass.
311
412
* [Fork us!](https://help.github.com/articles/fork-a-repo/)
5-
* Select the right branch. `main`(`2026.x`) for features and improvements or latest maintenance branch for bug fixes (`2025.4`)
13+
* Select the right branch. `main`(`2026.x`) for features and improvements or latest maintenance branch for bug fixes (`2026.2`)
14+
* Code! Follow the coding standards defined [here](https://github.com/pimcore/pimcore/blob/2026.x/.php-cs-fixer.dist.php) and [here](https://github.com/pimcore/pimcore/blob/2026.x/doc/19_Development_Tools_and_Details/29_Testing/02_Core_Tests.md#perform-phpstan-analysis)
615
* [Send a pull request](https://help.github.com/articles/using-pull-requests/) from your fork’s branch to our repo branch.
716
* [Sign the CLA](https://cla-assistant.io/pimcore/pimcore) - see also below.
8-
* Ensure that Github pipelines pass (linter, frontend build...)
917

10-
For details please check also the contributing docs of [pimcore/pimcore](https://github.com/pimcore/pimcore/blob/2026.x/CONTRIBUTING.md).
18+
19+
## Bug Reports
20+
**Please provide a fix for the bug as a pull request (PR) whenever possible!**
21+
If you've created a pull request, it's not necessary anymore to create an issue for the bug.
22+
23+
* Only file an issue if you're not able to fix the bug and provide the patch as a pull request.
24+
* Please keep in mind that the Pimcore team will only work on system critical and security bugs.
25+
* [Open an issue](https://github.com/pimcore/platform-version/issues) here on GitHub.
26+
* Report security issues only by using [security advisories](https://github.com/pimcore/platform-version/security/advisories).
27+
* Please be patient as not all items will be tested immediately - remember, pimcore is open core and free of charge.
28+
* Occasionally we'll close issues if they appear stale or are too vague - please don't take this personally!
29+
Please feel free to re-open issues we've closed if there's something we've missed and they still need to be addressed.
30+
31+
### Package Types
32+
Please note that we categorize our packages into two types, as indicated in the 'About' section of each GitHub repository.
33+
This categorization helps us prioritize and focus our resources effectively:
34+
35+
* **Core Packages**: These are packages under active development by the Pimcore team, and of course we also welcome and incorporate contributions from the community.
36+
* **Community Packages**: These packages are not currently being actively developed by the Pimcore team. However, we remain committed to their basic maintenance, as well as to reviewing and accepting pull requests, especially for critical bug fixes, and will release new versions as needed.
37+
38+
### Inactive Issue Closing Policy
39+
Pimcore uses a bot that closes abandoned issues after a period of inactivity.
40+
If an issue was not labeled as "Priority" or "Backlog" by us,
41+
this means that we're not going to work on that anytime soon.
42+
In case of a bug report, you can create a pull request fixing the issue instead,
43+
which will be then reviewed as soon as possible.
44+
If you're interested in contributing a feature, please contact us first,
45+
before creating a pull request, we'll then decide whether we'd accept it or not.
46+
47+
## Contributor License Agreement
48+
The following terms are used throughout this agreement:
49+
50+
* **You** - the person or legal entity including its affiliates asked to accept this agreement. An affiliate is any
51+
entity that controls or is controlled by the legal entity, or is under common control with it.
52+
53+
* **Project** - is an umbrella term that refers to any and all Pimcore projects.
54+
55+
* **Contribution** - any type of work that is submitted to a Project, including any modifications or additions to
56+
existing work.
57+
58+
* **Submitted** - conveyed to a Project via a pull request, commit, issue, or any form of electronic, written, or
59+
verbal communication with Pimcore, contributors or maintainers.
60+
61+
#### 1. Grant of Copyright License.
62+
Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and
63+
to Pimcore a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce,
64+
prepare derivative works of, publicly display, publicly perform, sublicense, and distribute Your contributions and such
65+
derivative works. Except for this license, You reserve all rights, title, and interest in your contributions.
66+
67+
#### 2. Grant of Patent License.
68+
Subject to the terms and conditions of this agreement, You grant to the Projects’ maintainers, contributors, users and
69+
to Pimcore a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section)
70+
patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer your contributions, where
71+
such license applies only to those patent claims licensable by you that are necessarily infringed by your contribution
72+
or by combination of your contribution with the project to which this contribution was submitted.
73+
74+
If any entity institutes patent litigation - including cross-claim or counterclaim in a lawsuit - against You alleging
75+
that your contribution or any project it was submitted to constitutes or is responsible for direct or contributory
76+
patent infringement, then any patent licenses granted to that entity under this agreement shall terminate as of the
77+
date such litigation is filed.
78+
79+
#### 3. Source of Contribution.
80+
Your contribution is either your original creation, based upon previous work that, to the best of your knowledge, is
81+
covered under an appropriate open source license and you have the right under that license to submit that work with
82+
modifications, whether created in whole or in part by you, or you have clearly identified the source of the contribution
83+
and any license or other restriction (like related patents, trademarks, and license agreements) of which you are
84+
personally aware.

assets/js/src/core/components/many-to-many-relation/grid.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export interface ManyToManyRelationGridProps {
4141
handleOrderChange: (data: ManyToManyRelationValue) => void
4242
pathFormatterConfig?: { name: string | undefined, class: string | undefined }
4343
enableRowVirtualizer: boolean
44+
hideOpenButton?: boolean
4445
}
4546

4647
export const ManyToManyRelationGrid = forwardRef(function ManyToManyRelationGrid (props: ManyToManyRelationGridProps, ref: MutableRefObject<HTMLDivElement>): React.JSX.Element {

assets/js/src/core/components/many-to-many-relation/hooks/use-columns.tsx

Lines changed: 71 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,18 @@ export const useColumns = (props: UseColumnsProps): UseColumnsReturn => {
7575
? [...props.columnDefinition]
7676
: defaultColumns
7777

78-
columns.push(
79-
columnHelper.accessor('actions', {
80-
header: t('actions'),
81-
size: 110,
82-
cell: (info) => {
83-
const rowIndex = info.row.index
84-
const rowValue = info.row.original as DisplayManyToManyRelationValueItem
85-
86-
const buttons: ReactElement[] = []
78+
const showActionsColumn = props.hideOpenButton !== true || props.assetInlineDownloadAllowed || props.disabled !== true
79+
80+
const actionsColumn = columnHelper.accessor('actions', {
81+
header: t('actions'),
82+
size: 110,
83+
cell: (info) => {
84+
const rowIndex = info.row.index
85+
const rowValue = info.row.original as DisplayManyToManyRelationValueItem
86+
87+
const buttons: ReactElement[] = []
88+
89+
if (props.hideOpenButton !== true) {
8790
buttons.push(
8891
<Tooltip
8992
key="open"
@@ -103,65 +106,69 @@ export const useColumns = (props: UseColumnsProps): UseColumnsReturn => {
103106
/>
104107
</Tooltip>
105108
)
109+
}
106110

107-
if (props.assetInlineDownloadAllowed && rowValue.type === 'asset') {
108-
buttons.push(
109-
<Tooltip
110-
key="download"
111-
title={ t('download') }
112-
>
113-
<IconButton
114-
aria-label={ t('aria.asset.image-sidebar.tab.details.download-thumbnail') }
115-
icon={ { value: 'download' } }
116-
onClick={ () => {
117-
download(
118-
rowValue.id.toString()
119-
)
120-
} }
121-
type="link"
122-
/>
123-
</Tooltip>
124-
)
125-
}
126-
127-
if (props.disabled !== true) {
128-
buttons.push(
129-
<Tooltip
130-
key="remove"
131-
title={ t('remove') }
132-
>
133-
<IconButton
134-
icon={ { value: 'trash' } }
135-
onClick={ () => {
136-
confirm({
137-
title: t('remove'),
138-
content: t('delete-confirmation-advanced', {
139-
type: t('relation'),
140-
value: rowValue.originalPath ?? rowValue.fullPath,
141-
interpolation: { escapeValue: false }
142-
}),
143-
onOk: () => {
144-
props.deleteItem(rowIndex)
145-
}
146-
})
147-
} }
148-
type="link"
149-
/>
150-
</Tooltip>
151-
)
152-
}
153-
154-
return (
155-
<Box padding="mini">
156-
<ButtonGroup
157-
items={ buttons }
158-
noSpacing
111+
if (props.assetInlineDownloadAllowed && rowValue.type === 'asset') {
112+
buttons.push(
113+
<Tooltip
114+
key="download"
115+
title={ t('download') }
116+
>
117+
<IconButton
118+
aria-label={ t('aria.asset.image-sidebar.tab.details.download-thumbnail') }
119+
icon={ { value: 'download' } }
120+
onClick={ () => {
121+
download(
122+
rowValue.id.toString()
123+
)
124+
} }
125+
type="link"
159126
/>
160-
</Box>
127+
</Tooltip>
161128
)
162129
}
163-
})
164-
)
130+
131+
if (props.disabled !== true) {
132+
buttons.push(
133+
<Tooltip
134+
key="remove"
135+
title={ t('remove') }
136+
>
137+
<IconButton
138+
icon={ { value: 'trash' } }
139+
onClick={ () => {
140+
confirm({
141+
title: t('remove'),
142+
content: t('delete-confirmation-advanced', {
143+
type: t('relation'),
144+
value: rowValue.originalPath ?? rowValue.fullPath,
145+
interpolation: { escapeValue: false }
146+
}),
147+
onOk: () => {
148+
props.deleteItem(rowIndex)
149+
}
150+
})
151+
} }
152+
type="link"
153+
/>
154+
</Tooltip>
155+
)
156+
}
157+
158+
return (
159+
<Box padding="mini">
160+
<ButtonGroup
161+
items={ buttons }
162+
noSpacing
163+
/>
164+
</Box>
165+
)
166+
}
167+
})
168+
169+
if (showActionsColumn) {
170+
columns.push(actionsColumn)
171+
}
165172

166173
return {
167174
columns

assets/js/src/core/components/many-to-many-relation/many-to-many-relation.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface ManyToManyRelationClassDefinitionProps {
3131
height: number | string | null
3232
assetInlineDownloadAllowed?: boolean | null
3333
onUpdateCellData?: (event: OnUpdateCellDataEvent) => void
34+
hideOpenButton?: boolean
3435
}
3536

3637
export interface ManyToManyRelationProps extends IRelationAllowedTypesDataComponent, ManyToManyRelationClassDefinitionProps {
@@ -114,6 +115,7 @@ export const ManyToManyRelation = ({ enableRowDrag = true, ...props }: ManyToMan
114115
enrichRowData={ props.enrichRowData }
115116
handleOrderChange={ onOrderChange }
116117
height={ props.height }
118+
hideOpenButton={ props.hideOpenButton }
117119
hint={ props.hint }
118120
inherited={ props.inherited }
119121
onUpdateCellData={ handleUpdateCellData }

assets/js/src/core/components/modal/modal.styles.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const useStyle = createStyles(({ token, css }) => {
4242
display: inline-flex;
4343
flex-direction: column;
4444
align-items: start;
45-
gap: ${token.marginSM}px;
45+
gap: ${token.marginXXS}px;
4646
4747
.ant-modal-header {
4848
margin-bottom: 0;

0 commit comments

Comments
 (0)