diff --git a/assets/js/src/core/components/breadcrumb/breadcrumb.tsx b/assets/js/src/core/components/breadcrumb/breadcrumb.tsx index 5ce2aaead..146ee3c8e 100644 --- a/assets/js/src/core/components/breadcrumb/breadcrumb.tsx +++ b/assets/js/src/core/components/breadcrumb/breadcrumb.tsx @@ -22,6 +22,7 @@ import { Text } from '@Pimcore/components/text/text' import { useBreadcrumbSize } from './hooks/use-breadcrumb-size' import { type ElementType } from 'types/element-type.d' import { useStyle } from './breadcrumb.styles' +import { Filename } from '../filename/filename' interface BreadcrumbProps { path: string @@ -32,6 +33,7 @@ interface BreadcrumbProps { export const Breadcrumb = ({ path, elementType, editorTabsWidth, pageSize }: BreadcrumbProps): React.JSX.Element => { const dispatch = useAppDispatch() + const hasFilename = elementType === 'asset' const [initialBreadcrumbLastElementWidth, setInitialBreadcrumbLastElementWidth] = useState(0) @@ -77,15 +79,28 @@ export const Breadcrumb = ({ path, elementType, editorTabsWidth, pageSize }: Bre } // Generate the breadcrumb text with ellipsis - const generateBreadcrumbText = ({ content, style, className }: { content: string, style?: CSSProperties, className?: string }): ReactElement => ( - - {content} - - ) + const generateBreadcrumbText = ({ content, style, className, hasFilename = false }: { content: string, style?: CSSProperties, className?: string, hasFilename?: boolean }): ReactElement => { + if (hasFilename) { + return ( + + ) + } + + return ( + + {content} + + ) + } // Prepend the "..." menu to the existing items array const addDotsMenu = ({ dotsMenuItems, items }: { dotsMenuItems: MenuItemProps[], items: BreadcrumbItemType[] }): ItemType[] => [ @@ -146,7 +161,8 @@ export const Breadcrumb = ({ path, elementType, editorTabsWidth, pageSize }: Bre {generateBreadcrumbText({ content: partList[partListAmount - 1], style: { ...(isHideBreadcrumb && { maxWidth: `${currentBreadcrumbWidth}px` }) }, - className: styles.breadcrumbLinkLast + className: styles.breadcrumbLinkLast, + hasFilename })} ) diff --git a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.stories.tsx b/assets/js/src/core/components/content-layout/content-layout.stories.tsx similarity index 78% rename from assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.stories.tsx rename to assets/js/src/core/components/content-layout/content-layout.stories.tsx index 74c9d3ea9..85717bee2 100644 --- a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.stories.tsx +++ b/assets/js/src/core/components/content-layout/content-layout.stories.tsx @@ -11,19 +11,19 @@ * @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL */ -import { ContentToolbarSidebarLayout } from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' +import { ContentLayout } from '@Pimcore/components/content-layout/content-layout' import { Sidebar } from '@Pimcore/components/sidebar/sidebar' import { HighlightedEntries as sidebarArgs } from '@Pimcore/components/sidebar/sidebar.stories' import { Toolbar, type ToolbarProps } from '@Pimcore/components/toolbar/toolbar' -import { Secondary } from '@Pimcore/components/toolbar/toolbar.stories' +import { Position, Secondary } from '@Pimcore/components/toolbar/toolbar.stories' import { type Meta } from '@storybook/react' import React from 'react' import { Content } from '../content/content' /* eslint-disable react/jsx-key */ const config: Meta = { - title: 'Components/layout/Content-Toolbar-Sidebar-Layout', - component: ContentToolbarSidebarLayout, + title: 'Components/layout/Content-Layout', + component: ContentLayout, parameters: { layout: 'fullscreen', @@ -38,6 +38,7 @@ export default config const demoData = { children: , + renderTopBar: , renderToolbar: , renderSidebar: } @@ -61,3 +62,10 @@ export const NoSidebar = { renderSidebar: undefined } } + +export const NoTopBar = { + args: { + ...demoData, + renderTopBar: undefined + } +} diff --git a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.styles.tsx b/assets/js/src/core/components/content-layout/content-layout.styles.tsx similarity index 79% rename from assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.styles.tsx rename to assets/js/src/core/components/content-layout/content-layout.styles.tsx index ae554a012..7c6f8105f 100644 --- a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.styles.tsx +++ b/assets/js/src/core/components/content-layout/content-layout.styles.tsx @@ -15,39 +15,47 @@ import { createStyles } from 'antd-style' export const useStyles = createStyles(({ token, css }) => { return { - ContentToolbarSidebarLayout: css` + ContentLayout: css` &.content-toolbar-sidebar-layout { position: relative; display: grid; grid-template-columns: 1fr auto; - grid-template-rows: 1fr auto; + grid-template-rows: auto 1fr auto; height: 100%; width: 100%; overflow: hidden; } + .content-toolbar-sidebar-layout__top-bar { + grid-column: 1 / 2; + grid-row: 1 / 2; + position: sticky; + bottom: 0; + height: max-content; + overflow: hidden; + } + .content-toolbar-sidebar-layout__content { display: flex; grid-column: 1 / 2; - grid-row: 1 / 2; + grid-row: 2 / 3; overflow: auto; height: 100%; width: 100%; } .content-toolbar-sidebar-layout__toolbar { - border-top: 1px solid ${token.colorBorderTertiary}; grid-column: 1 / 2; - grid-row: 2 / 3; + grid-row: 3 / 4; position: sticky; bottom: 0; - height: ${token.sizeXXL}px; + height: max-content; overflow: hidden; } .content-toolbar-sidebar-layout__sidebar { grid-column: 2 / 3; - grid-row: 1 / 3; + grid-row: 1 / 4; } ` } diff --git a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.tsx b/assets/js/src/core/components/content-layout/content-layout.tsx similarity index 82% rename from assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.tsx rename to assets/js/src/core/components/content-layout/content-layout.tsx index 5cbde0a33..b4758c84d 100644 --- a/assets/js/src/core/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout.tsx +++ b/assets/js/src/core/components/content-layout/content-layout.tsx @@ -12,18 +12,19 @@ */ import React, { memo, type ReactNode } from 'react' -import { useStyles } from './content-toolbar-sidebar-layout.styles' +import { useStyles } from './content-layout.styles' import { Content } from '../content/content' interface ContentToolbarViewProps { children: ReactNode - renderToolbar?: ReactNode + renderTopBar?: ReactNode renderSidebar?: ReactNode + renderToolbar?: ReactNode } const Component = (props: ContentToolbarViewProps): React.JSX.Element => { const { styles } = useStyles() - const classes = ['content-toolbar-sidebar-layout', styles.ContentToolbarSidebarLayout] + const classes = ['content-toolbar-sidebar-layout', styles.ContentLayout] if (props.renderToolbar !== undefined) { classes.push('content-toolbar-sidebar-layout--with-toolbar') @@ -31,6 +32,12 @@ const Component = (props: ContentToolbarViewProps): React.JSX.Element => { return (
+ { props.renderTopBar !== undefined && ( +
+ {props.renderTopBar} +
+ )} + {props.children} @@ -50,4 +57,4 @@ const Component = (props: ContentToolbarViewProps): React.JSX.Element => { ) } -export const ContentToolbarSidebarLayout = memo(Component) +export const ContentLayout = memo(Component) diff --git a/assets/js/src/core/components/element-toolbar/element-toolbar.styles.tsx b/assets/js/src/core/components/element-toolbar/element-toolbar.styles.tsx index 30a4b86cb..4ce924dbc 100644 --- a/assets/js/src/core/components/element-toolbar/element-toolbar.styles.tsx +++ b/assets/js/src/core/components/element-toolbar/element-toolbar.styles.tsx @@ -19,12 +19,6 @@ export const useStyle = createStyles(({ token, css }) => { display: flex; align-items: center; gap: 8px; - height: 40px; - border-bottom: 1px solid #DFD7EA; - - .ant-breadcrumb { - padding-left: ${token.paddingXS}px; - } .element-toolbar__info-dropdown { .ant-dropdown-trigger { diff --git a/assets/js/src/core/components/filename/filename.stories.tsx b/assets/js/src/core/components/filename/filename.stories.tsx new file mode 100644 index 000000000..3c1ca20da --- /dev/null +++ b/assets/js/src/core/components/filename/filename.stories.tsx @@ -0,0 +1,37 @@ +/** +* Pimcore +* +* This source file is available under two different licenses: +* - Pimcore Open Core License (POCL) +* - Pimcore Commercial License (PCL) +* Full copyright and license information is available in +* LICENSE.md which is distributed with this source code. +* +* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) +* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL +*/ + +import { type StoryObj, type Meta } from '@storybook/react' +import { Filename, type FilenameProps } from './filename' + +const config: Meta = { + title: 'Components/Data Display/Filename', + component: Filename, + tags: ['autodocs'] +} + +export default config + +export const _default: StoryObj = { + args: { + value: 'filename.jpg', + ellipsis: false + } +} + +export const Ellipsis = { + args: { + value: 'Lorem-ipsum-dolor-sit-amet-consetetur-sadipscing-elitr-sed-diam-nonumy-eirmod-tempor-invidunt-ut-labore-et-dolore-magna-aliquyam-erat-sed-diam-voluptua.jpg', + ellipsis: true + } +} diff --git a/assets/js/src/core/components/filename/filename.tsx b/assets/js/src/core/components/filename/filename.tsx new file mode 100644 index 000000000..b6a846fb8 --- /dev/null +++ b/assets/js/src/core/components/filename/filename.tsx @@ -0,0 +1,49 @@ +/** +* Pimcore +* +* This source file is available under two different licenses: +* - Pimcore Open Core License (POCL) +* - Pimcore Commercial License (PCL) +* Full copyright and license information is available in +* LICENSE.md which is distributed with this source code. +* +* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) +* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL +*/ + +import React from 'react' +import { Text } from '../text/text' +import { Flex } from '../flex/flex' + +export interface FilenameProps extends React.HTMLAttributes { + value: string + ellipsis?: boolean +} + +export const Filename = ({ value, ellipsis, ...props }: FilenameProps): React.JSX.Element => { + const filename = value + const hasExtension = filename.includes('.') + + if (hasExtension && ellipsis === true) { + const parts = filename.split('.') + const extension = parts.pop() + const name = parts.join('.') + + return ( + + {name}. + {extension} + + ) + } + + return ( + { filename } + ) +} diff --git a/assets/js/src/core/components/modal/modal.stories.tsx b/assets/js/src/core/components/modal/modal.stories.tsx index 36b21c42b..07af56311 100644 --- a/assets/js/src/core/components/modal/modal.stories.tsx +++ b/assets/js/src/core/components/modal/modal.stories.tsx @@ -57,6 +57,8 @@ export const Large = (): React.JSX.Element => { } + mask={ false } + maskClosable={ false } onCancel={ handleClose } open={ isOpen } size='L' diff --git a/assets/js/src/core/components/toolbar/toolbar.stories.tsx b/assets/js/src/core/components/toolbar/toolbar.stories.tsx index 8a4f355d9..92037bf22 100644 --- a/assets/js/src/core/components/toolbar/toolbar.stories.tsx +++ b/assets/js/src/core/components/toolbar/toolbar.stories.tsx @@ -17,6 +17,8 @@ import { Toolbar } from '@Pimcore/components/toolbar/toolbar' import { type StoryObj, type Meta } from '@storybook/react' import { Button } from '@Pimcore/components/button/button' import React from 'react' +import { Breadcrumb } from '../breadcrumb/breadcrumb' +import { _default as breadcrumbStory } from '../breadcrumb/breadcrumb.stories' const config: Meta = { title: 'Components/Controls/Toolbar', @@ -73,6 +75,37 @@ export const Secondary: Story = { } } +export const Size: Story = { + args: { + children: ( + <> + + + ), + size: 'small', + theme: 'secondary' + } +} + +export const Position: Story = { + args: { + children: ( + <> + + + ), + position: 'top', + size: 'small', + theme: 'secondary' + } +} + export const RightAligned: Story = { args: { ...demoData, diff --git a/assets/js/src/core/components/toolbar/toolbar.styles.tsx b/assets/js/src/core/components/toolbar/toolbar.styles.tsx index f07f1554f..5ba03fca4 100644 --- a/assets/js/src/core/components/toolbar/toolbar.styles.tsx +++ b/assets/js/src/core/components/toolbar/toolbar.styles.tsx @@ -18,8 +18,6 @@ export const useStyles = createStyles(({ token, css }) => { toolbar: css` width: 100%; height: 48px; - border-top: 1px solid ${token.colorBorder}; - padding: ${token.paddingXS}px; &.toolbar--theme-primary { @@ -30,6 +28,18 @@ export const useStyles = createStyles(({ token, css }) => { &.toolbar--theme-secondary { background-color: ${token.colorBgBase}; } + + &.toolbar--position-top { + border-bottom: 1px solid ${token.colorBorderTertiary}; + } + + &.toolbar--position-bottom { + border-top: 1px solid ${token.colorBorderTertiary}; + } + + &.toolbar--size-small { + height: 40px; + } ` } }) diff --git a/assets/js/src/core/components/toolbar/toolbar.tsx b/assets/js/src/core/components/toolbar/toolbar.tsx index c2f8c11dd..a6b7b4c45 100644 --- a/assets/js/src/core/components/toolbar/toolbar.tsx +++ b/assets/js/src/core/components/toolbar/toolbar.tsx @@ -20,14 +20,18 @@ export interface ToolbarProps { children: React.ReactNode justify?: FlexProps['justify'] theme?: 'primary' | 'secondary' + position?: 'top' | 'bottom' + size?: 'small' | 'default' } -export const Toolbar = ({ children, justify = 'space-between', theme = 'primary', ...props }: ToolbarProps): React.JSX.Element => { +export const Toolbar = ({ children, size = 'default', justify = 'space-between', theme = 'primary', position = 'bottom', ...props }: ToolbarProps): React.JSX.Element => { const { styles } = useStyles() const classes = [ styles.toolbar, 'toolbar', - `toolbar--theme-${theme}` + `toolbar--theme-${theme}`, + `toolbar--position-${position}`, + `toolbar--size-${size}` ].join(' ') return ( diff --git a/assets/js/src/core/modules/asset/editor/detached-tab/detached-tab.tsx b/assets/js/src/core/modules/asset/editor/detached-tab/detached-tab.tsx deleted file mode 100644 index 6d2a089ad..000000000 --- a/assets/js/src/core/modules/asset/editor/detached-tab/detached-tab.tsx +++ /dev/null @@ -1,34 +0,0 @@ -/** -* Pimcore -* -* This source file is available under two different licenses: -* - Pimcore Open Core License (POCL) -* - Pimcore Commercial License (PCL) -* Full copyright and license information is available in -* LICENSE.md which is distributed with this source code. -* -* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org) -* @license https://github.com/pimcore/studio-ui-bundle/blob/1.x/LICENSE.md POCL and PCL -*/ - -import React from 'react' -import { useGlobalAssetContext } from '../../hooks/use-global-asset-context' -import { AssetProvider } from '../../asset-provider' - -interface IDetachedTabProps { - children: React.ReactNode -} - -export const DetachedTab = ({ children }: IDetachedTabProps): React.JSX.Element => { - const { context } = useGlobalAssetContext() - - if (context === undefined) { - return
Missing context
- } - - return ( - - {children} - - ) -} diff --git a/assets/js/src/core/modules/asset/editor/types/audio/tab-manager/tabs/preview/preview-container.tsx b/assets/js/src/core/modules/asset/editor/types/audio/tab-manager/tabs/preview/preview-container.tsx index e8e52ff43..e251125c5 100644 --- a/assets/js/src/core/modules/asset/editor/types/audio/tab-manager/tabs/preview/preview-container.tsx +++ b/assets/js/src/core/modules/asset/editor/types/audio/tab-manager/tabs/preview/preview-container.tsx @@ -16,19 +16,19 @@ import { PreviewView } from './preview-view' import { useAssetGetByIdQuery } from '@Pimcore/modules/asset/asset-api-slice-enhanced' import { AssetContext } from '@Pimcore/modules/asset/asset-provider' import { - ContentToolbarSidebarLayout -} from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' + ContentLayout +} from '@Pimcore/components/content-layout/content-layout' const PreviewContainer = (): React.JSX.Element => { const assetContext = useContext(AssetContext) const { data } = useAssetGetByIdQuery({ id: assetContext.id }) return ( - + - + ) } diff --git a/assets/js/src/core/modules/asset/editor/types/document/tab-manager/tabs/preview/preview-container.tsx b/assets/js/src/core/modules/asset/editor/types/document/tab-manager/tabs/preview/preview-container.tsx index 3f931bc2b..3a79ad1d2 100644 --- a/assets/js/src/core/modules/asset/editor/types/document/tab-manager/tabs/preview/preview-container.tsx +++ b/assets/js/src/core/modules/asset/editor/types/document/tab-manager/tabs/preview/preview-container.tsx @@ -14,8 +14,8 @@ import React, { useEffect, useState } from 'react' import { PreviewView } from './preview-view' import { - ContentToolbarSidebarLayout -} from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' + ContentLayout +} from '@Pimcore/components/content-layout/content-layout' import { Content } from '@Pimcore/components/content/content' import { useAsset } from '@Pimcore/modules/asset/hooks/use-asset' import { useAssetDraft } from '@Pimcore/modules/asset/hooks/use-asset-draft' @@ -45,11 +45,11 @@ const PreviewContainer = (): React.JSX.Element => { } return ( - + - + ) } diff --git a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx index 0b981b226..c76036d76 100644 --- a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx +++ b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/list-container-inner.tsx @@ -29,7 +29,7 @@ import { import { useAppDispatch } from '@Pimcore/app/store' import { type GridProps, type OnUpdateCellDataEvent } from '@Pimcore/types/components/types' import { ListDataProvider } from './list-provider' -import { ContentToolbarSidebarLayout } from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' +import { ContentLayout } from '@Pimcore/components/content-layout/content-layout' import { Content } from '@Pimcore/components/content/content' import { eventBus } from '@Pimcore/lib/event-bus' import { generateQueryArgsForGrid } from './helpers/gridHelpers' @@ -244,7 +244,7 @@ export const ListContainerInner = (): React.JSX.Element => { return useMemo(() => ( - } renderToolbar={ { modifiedCells={ modifiedCells } onUpdateCellData={ onUpdateCellData } /> - + ), [data, page, pageSize, modifiedCells, isLoading]) diff --git a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/filters/filter-container-inner.tsx b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/filters/filter-container-inner.tsx index 03964c6ce..8b65e79fa 100644 --- a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/filters/filter-container-inner.tsx +++ b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/filters/filter-container-inner.tsx @@ -28,8 +28,8 @@ import { useSearchFilter } from './hooks/use-search-filter' import { useIncludeDescendantsFilter } from './hooks/use-include-descendants-filter' import { useListFilterOptions } from '../../hooks/use-list' import { - ContentToolbarSidebarLayout -} from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' + ContentLayout +} from '@Pimcore/components/content-layout/content-layout' import { Toolbar } from '@Pimcore/components/toolbar/toolbar' import { Content } from '@Pimcore/components/content/content' import { @@ -71,7 +71,7 @@ export const FilterContainerInner = (): React.JSX.Element => { } return ( - { )} - + ) } diff --git a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/grid-config/views/edit-view.tsx b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/grid-config/views/edit-view.tsx index 8174669bb..89da5ce30 100644 --- a/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/grid-config/views/edit-view.tsx +++ b/assets/js/src/core/modules/asset/editor/types/folder/tab-manager/tabs/list/sidebar/grid-config/views/edit-view.tsx @@ -12,7 +12,7 @@ */ import { Button } from '@Pimcore/components/button/button' -import { ContentToolbarSidebarLayout } from '@Pimcore/components/content-toolbar-sidebar-layout/content-toolbar-sidebar-layout' +import { ContentLayout } from '@Pimcore/components/content-layout/content-layout' import { Content } from '@Pimcore/components/content/content' import { Header } from '@Pimcore/components/header/header' import { Space } from '@Pimcore/components/space/space' @@ -39,7 +39,7 @@ export const EditView = ({ onCancelClick, onApplyClick, onSaveConfigurationClick const { t } = useTranslation() return ( -