Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add collapse component #819

Merged
merged 3 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions assets/js/src/core/components/collapse/collapse.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* 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 { Meta, StoryObj } from '@storybook/react'
import { Collapse, type CollapseProps } from './collapse'
import { Extra as CollapseItemDefault } from './item/collapse-item.stories'

const config: Meta = {
title: 'Components/Layout/Collapse/Collapse',
component: Collapse,
tags: ['autodocs']
}

export default config

export const _default: StoryObj<CollapseProps> = {
args: {
items: [
{
key: '1',
...CollapseItemDefault.args
},

{
key: '2',
...CollapseItemDefault.args
},

{
key: '3',
...CollapseItemDefault.args
}
]
}
}

export const Accordion: StoryObj<CollapseProps> = {
args: {
..._default.args,
accordion: true
}
}

export const HandleUniqueItems: StoryObj<CollapseProps> = {
args: {
..._default.args,
items: [
{
key: '1',
...CollapseItemDefault.args
},

{
key: '2',
...CollapseItemDefault.args,
bordered: false,
theme: 'primary',
hasContentSeparator: false
},

{
key: '3',
...CollapseItemDefault.args
}
],
bordered: true,
theme: 'success'
}
}
96 changes: 96 additions & 0 deletions assets/js/src/core/components/collapse/collapse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* 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, { useEffect, useState } from 'react'
import { CollapseItem, type CollapseItemProps, type CollapseStyleProps } from './item/collapse-item'
import { Space, type SpaceProps } from '../space/space'
import cn from 'classnames'

export interface ICollapseItem extends Omit<CollapseItemProps, 'active'> {
key: string
}

export interface CollapseProps extends CollapseStyleProps {
defaultActiveKeys?: string[]
activeKeys?: string[]
onChange?: CollapseItemProps['onChange']
items: ICollapseItem[]
space?: SpaceProps
accordion?: boolean
className?: string
}

export const Collapse = ({ className, items, accordion, space, activeKeys, defaultActiveKeys, onChange, ...props }: CollapseProps): React.JSX.Element => {
const [internalActiveKeys, setInternalActiveKeys] = useState<string[]>(activeKeys ?? defaultActiveKeys ?? [])

useEffect(() => {
if (activeKeys !== undefined) {
setInternalActiveKeys(activeKeys)
}
}, [activeKeys])

const onItemChange = (item: ICollapseItem, keys: string[]): void => {
const isItemActive = keys.includes('0')
let newActiveKeys: string[] = []

if (accordion === true && isItemActive) {
newActiveKeys = [item.key]
} else if (isItemActive) {
newActiveKeys = [...internalActiveKeys, item.key]
} else {
newActiveKeys = internalActiveKeys.filter((key) => key !== item.key)
}

if (activeKeys === undefined) {
setInternalActiveKeys(newActiveKeys)
}

if (onChange !== undefined) {
onChange(newActiveKeys)
}
}

const preparedItems = items.map((item, index) => {
return {
...props,
...item
}
})

const classnames = cn(
'collapse',
className,
'w-full'
)

return (
<Space
className={ classnames }
direction="vertical"
{ ...space }
>
{preparedItems.map((item) => {
const { key, ...preparedItem } = item

return (
<CollapseItem
key={ key }
{ ...preparedItem }
active={ internalActiveKeys.includes(item.key) }
onChange={ (keys) => { onItemChange(item, keys) } }
/>
)
})}
</Space>
)
}
13 changes: 8 additions & 5 deletions assets/js/src/core/components/collapse/item/collapse-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ import { Box, type BoxProps } from '@Pimcore/components/box/box'

type AntdCollapsePropsItem = Exclude<CollapseProps['items'], undefined>[number]

export interface CollapseItemProps extends Omit<AntdCollapsePropsItem, 'key' | 'onChange' | 'showArrow'> {
export interface CollapseStyleProps {
size?: CollapseProps['size']
bordered?: CollapseProps['bordered']
active?: boolean
defaultActive?: boolean
expandIcon?: CollapseProps['expandIcon']
expandIconPosition?: CollapseProps['expandIconPosition']
onChange?: CollapseProps['onChange']
subLabel?: React.ReactNode
extraPosition?: 'start' | 'end'
theme?: 'success' | 'primary' | 'simple' | 'default' | 'card-with-highlight' | 'fieldset'
contentPadding?: BoxProps['padding']
hasContentSeparator?: boolean
}

export interface CollapseItemProps extends Omit<AntdCollapsePropsItem, 'key' | 'onChange' | 'showArrow'>, CollapseStyleProps {
active?: boolean
defaultActive?: boolean
onChange?: CollapseProps['onChange']
subLabel?: React.ReactNode
}

export const ExpandIcon = ({ isActive }: { isActive: boolean }): React.ReactElement => {
return <Icon value={ isActive ? 'chevron-up' : 'chevron-down' } />
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@

import React from 'react'
import { type AbstractObjectLayoutDefinition } from '../../dynamic-type-object-layout-abstract'
import { Accordion as BaseAccordion, type AccordionProps as BaseAccordionProps } from '@Pimcore/components/accordion/accordion'
import { ObjectComponent } from '@Pimcore/modules/data-object/editor/types/object/tab-manager/tabs/edit/components/object-component'
import { BaseView } from '../../views/base-view'
import { Collapse, type CollapseProps } from '@Pimcore/components/collapse/collapse'

export interface AccordionProps extends AbstractObjectLayoutDefinition {
title?: string
Expand All @@ -25,9 +25,9 @@ export interface AccordionProps extends AbstractObjectLayoutDefinition {
}

export const Accordion = ({ children, title, border, collapsed, collapsible }: AccordionProps): React.JSX.Element => {
const items: BaseAccordionProps['items'] = children.map((child, index) => ({
const items: CollapseProps['items'] = children.map((child, index) => ({
key: child.name,
title: child.title,
label: child.title,
forceRender: true,
children: (
<ObjectComponent
Expand All @@ -44,9 +44,9 @@ export const Accordion = ({ children, title, border, collapsed, collapsible }: A
collapsible={ collapsible }
title={ title }
>
<BaseAccordion
<Collapse
accordion
bordered
ghost
items={ items }
/>
</BaseView>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ import { Space } from '@Pimcore/components/space/space'
import i18n from 'i18next'
import { Grid } from '@Pimcore/components/grid/grid'
import { createColumnHelper } from '@tanstack/react-table'
import { Accordion } from '@Pimcore/components/accordion/accordion'
import { formatDateTime } from '@Pimcore/utils/date-time'
import { IconButton } from '@Pimcore/components/icon-button/icon-button'
import { Text } from '@Pimcore/components/text/text'
import { Split } from '@Pimcore/components/split/split'
import { Paragraph } from '@Pimcore/components/paragraph/paragraph'
import { Collapse } from '@Pimcore/components/collapse/collapse'

interface NotesAndEventsTabViewProps {
notes: Note[]
Expand All @@ -57,7 +57,7 @@ export const NotesAndEventsTabView = ({
const NotesAndEvents: Array<{
children: React.JSX.Element
extra: React.JSX.Element
title: React.JSX.Element
label: React.JSX.Element
key: string
}> = notes.map((note) => {
let showDetails = false
Expand Down Expand Up @@ -134,7 +134,7 @@ export const NotesAndEventsTabView = ({

return ({
key: note.id.toString(),
title: <Split
label: <Split
dividerSize='small'
size='extra-small'
theme='secondary'
Expand Down Expand Up @@ -198,10 +198,9 @@ export const NotesAndEventsTabView = ({
text: t('notes-and-events.no-notes-and-events-to-show')
} }
>
<Accordion
<Collapse
accordion={ false }
items={ NotesAndEvents }
spaced
/>
</Content>
</Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { Job } from '../job/job'
import { AnimatePresence, motion } from 'framer-motion'
import { useStyles } from './job-list.styles'
import { useTranslation } from 'react-i18next'
import { Accordion } from '@Pimcore/components/accordion/accordion'
import { useJobs } from '@Pimcore/modules/execution-engine/hooks/useJobs'
import { Collapse } from '@Pimcore/components/collapse/collapse'

export const JobList = (): React.JSX.Element => {
const { jobs } = useJobs()
Expand All @@ -28,7 +28,7 @@ export const JobList = (): React.JSX.Element => {

const item = {
key: '1',
title: <span>{t('jobs.notification.jobs', { count: jobs.length })}</span>,
label: <span>{t('jobs.notification.jobs', { count: jobs.length })}</span>,
children:
<AnimatePresence>
{jobs.map((job) => (
Expand All @@ -49,13 +49,12 @@ export const JobList = (): React.JSX.Element => {
}

return (
<>
<Accordion
activeKey={ item.key }
className={ styles.jobList }
ghost
items={ [item] }
/>
</>
<Collapse
bordered={ false }
className={ styles.jobList }
defaultActiveKeys={ [item.key] }
hasContentSeparator={ false }
items={ [item] }
/>
)
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"entrypoints": {
"vendor": {
"js": [
"/bundles/pimcorestudioui/build/20e396b3-dac0-42ac-b28a-10921ba4b894/vendor.js"
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"bundles/pimcorestudioui/build/20e396b3-dac0-42ac-b28a-10921ba4b894/vendor.js": "/bundles/pimcorestudioui/build/20e396b3-dac0-42ac-b28a-10921ba4b894/vendor.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"entrypoints": {
"main": {
"js": [
"/bundles/pimcorestudioui/build/59a79fa7-db35-498c-a2f5-b28c08f2e640/main.js"
]
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"bundles/pimcorestudioui/build/59a79fa7-db35-498c-a2f5-b28c08f2e640/main.js": "/bundles/pimcorestudioui/build/59a79fa7-db35-498c-a2f5-b28c08f2e640/main.js"
}

This file was deleted.

This file was deleted.

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions public/build/e3dcc470-37b9-4b63-8eb5-e303acd4e23a/core-dll.js

Large diffs are not rendered by default.

Loading
Loading