Skip to content

Commit

Permalink
Add collapse component (#819)
Browse files Browse the repository at this point in the history
* Add collapse component

* Apply eslint-fixer changes

* Automatic frontend build

---------

Co-authored-by: vin0401 <[email protected]>
  • Loading branch information
vin0401 and vin0401 authored Dec 11, 2024
1 parent 837b21f commit c17b643
Show file tree
Hide file tree
Showing 30 changed files with 2,682 additions and 25 deletions.
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] }
/>
)
}
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"
}
2 changes: 2 additions & 0 deletions public/build/20e396b3-dac0-42ac-b28a-10921ba4b894/vendor.js

Large diffs are not rendered by default.

Loading

0 comments on commit c17b643

Please sign in to comment.