From addb84f6412760690246a9b11ba0fd4d9e9694ed Mon Sep 17 00:00:00 2001 From: ItzGerSte Date: Wed, 5 Aug 2026 15:56:40 +0200 Subject: [PATCH 1/3] Initial Commit --- docs/30-components/accordion.mdx | 12 +- .../previews/components/Accordion.tsx | 4 +- .../previews/components/AccordionMultiple.tsx | 66 ++++++++ .../properties/AccordionMultipleProperty.tsx | 150 ++++++++++++++++++ .../previews/properties/ComponentDefaults.tsx | 30 ++++ .../properties/GenerateAccordionMultiple.tsx | 21 +++ src/components/previews/properties/index.ts | 4 +- 7 files changed, 274 insertions(+), 13 deletions(-) create mode 100644 src/components/previews/components/AccordionMultiple.tsx create mode 100644 src/components/previews/properties/AccordionMultipleProperty.tsx create mode 100644 src/components/previews/properties/GenerateAccordionMultiple.tsx diff --git a/docs/30-components/accordion.mdx b/docs/30-components/accordion.mdx index bb11f8ccf5..5bf623f8c4 100644 --- a/docs/30-components/accordion.mdx +++ b/docs/30-components/accordion.mdx @@ -5,6 +5,7 @@ description: Beschreibung, Spezifikation und Beispiele für die Accordion-Kompon import Readme from '@site/readmes/accordion/readme.md'; import AccordionPreview from '@site/src/components/previews/components/Accordion'; +import AccordionMultiplePreview from '@site/src/components/previews/components/AccordionMultiple'; import { ExampleLink } from '@site/src/components/ExampleLink'; import BetaDocsBanner from '@site/src/components/BetaDocsBanner'; @@ -20,16 +21,7 @@ import BetaDocsBanner from '@site/src/components/BetaDocsBanner'; Darstellung der Komponente ohne optional gesetzte Felder. Code kann eingeblendet werden. -Das Frühjahr bringt den Übergang vom Winter zum Sommer. Die Temperaturen steigen langsam, die Tage werden länger, und die Natur erwacht aus dem Winterschlaf: Pflanzen beginnen zu blühen, Bäume treiben neue Knospen, und viele Tierarten aktivieren ihre Fortpflanzungszyklen. Typisch sind wechselhaftes Wetter mit warmen sonnigen Phasen und kühleren Regentagen.

Der Sommer ist die wärmste Jahreszeit mit längsten Tagen und kürzesten Nächten. Die Sonne steht höher am Himmel, was zu intensiverer Einstrahlung führt. Temperaturen erreichen ihre Höchstwerte, Niederschläge treten oft als kurze Gewitter statt als langanhaltender Regen auf. Es ist die Hauptsaison für Vegetation und landwirtschaftliches Wachstum.

Im Herbst nimmt die Tageslänge deutlich ab, die Temperaturen fallen allmählich. Laubbäume verlieren ihr grünes Blattwerk durch die verkürzte Photosyntheseperiode, was zu charakteristischen Braun- und Gelbtönen führt. Die Erntezeit für viele Kulturpflanzen liegt in dieser Jahreszeit. Nebel und spätere Sonnenaufgänge werden häufiger.

Die kalte Jahreszeit mit den kürzesten Tagen und längsten Nächten. Die niedrige Sonnenposition sorgt für geringe Einstrahlungsintensität. Temperaturen fallen unter den Gefrierpunkt, was in vielen Regionen Schnee und Eis ermöglicht. Pflanzen ruhen, viele Tiere halten Winterruhe oder migrieren. Die natürliche Lichtverfügbarkeit ist am geringsten.

', - }} -/> + ## Barrierefreiheit diff --git a/src/components/previews/components/Accordion.tsx b/src/components/previews/components/Accordion.tsx index d2a02513b6..c69eb2daa3 100644 --- a/src/components/previews/components/Accordion.tsx +++ b/src/components/previews/components/Accordion.tsx @@ -6,7 +6,7 @@ import { KolInputText, KolAccordion } from '@public-ui/react-v19'; import { translate } from '@docusaurus/Translate'; import { sanitizeHtml } from '../../../shares/sanitize'; -type AccordionPreviewProps = JSX.KolAccordion & { _slot?: string }; +export type AccordionPreviewProps = JSX.KolAccordion & { _slot?: string }; interface AccordionPreviewComponentProps { initialProps?: AccordionPreviewProps; @@ -20,7 +20,7 @@ const AccordionPreview = (props: AccordionPreviewComponentProps) => { _label: translate({ id: 'preview.component.accordion.label' }), _slot: translate({ id: 'preview.component.accordion.content' }), }), - [], + [] ); return ( diff --git a/src/components/previews/components/AccordionMultiple.tsx b/src/components/previews/components/AccordionMultiple.tsx new file mode 100644 index 0000000000..776ece6f2e --- /dev/null +++ b/src/components/previews/components/AccordionMultiple.tsx @@ -0,0 +1,66 @@ +import React from 'react'; +import Preview, { PreviewLayout } from '../Preview'; +import { AccordionMultipleProperty, GenerateAccordionMultiple } from '../properties'; +import { AccordionPreviewProps } from './Accordion'; +import { AccordionMultipleDefault } from '../properties/ComponentDefaults'; + +export type AccordionMultiplePreviewProps = { _accordions: AccordionPreviewProps[] }; + +interface AccordionMultiplePreviewComponentProps { + initialProps?: AccordionMultiplePreviewProps; + visibleProperties?: '_accordions'[]; + codeCollapsable?: boolean; +} + +const AccordionMultiplePreview = (props: AccordionMultiplePreviewComponentProps) => { + const defaultProps = React.useMemo(() => AccordionMultipleDefault, []); + + const formatSource = (currentProps: AccordionMultiplePreviewProps): string => { + const { _accordions } = currentProps; + const accordions = _accordions ?? []; + + const formatAccordion = (accordions: AccordionPreviewProps, indent: number): string => { + const pad = '\n '.repeat(indent); + const { ...accordion } = accordions; + const accordionProps = Object.entries(accordion as Record) + .filter(([, value]) => value !== undefined && value !== null && value !== '') + .filter(([key]) => key !== '_slot') + .map(([key, value]) => { + if (typeof value === 'string') return `${pad}${key}="${value}"`; + if (typeof value === 'boolean') return value ? `${pad}${key}={${value}}` : ''; + if (typeof value === 'number') return `${pad}${key}={${value}}`; + return `${pad}${key}={${JSON.stringify(value)}}`; + }) + .join(''); + return `${JSON.stringify(accordion._slot).replace( + /^"|"$/g, + '' + )}\n\n
`; + }; + + const accordionsString = accordions.map((accordion) => formatAccordion(accordion, 1)).join('\n'); + + return `${accordionsString}`.replace(/()$/, ''); + }; + + return ( + + propertyComponents={{ + _accordions: , + }} + initialProps={{ ...defaultProps, ...props.initialProps }} + visibleProperties={props.visibleProperties} + componentName="KolAccordion" + codeCollapsable={props.codeCollapsable} + layout={PreviewLayout.FULL_SIZE} + sourceFormatter={formatSource} + > + {(componentProps) => { + const { _accordions } = componentProps; + return GenerateAccordionMultiple(_accordions); + }} + + ); +}; + +export default AccordionMultiplePreview; diff --git a/src/components/previews/properties/AccordionMultipleProperty.tsx b/src/components/previews/properties/AccordionMultipleProperty.tsx new file mode 100644 index 0000000000..4f5f37c5c7 --- /dev/null +++ b/src/components/previews/properties/AccordionMultipleProperty.tsx @@ -0,0 +1,150 @@ +import { KolButton, KolCard, KolDrawer, KolInputCheckbox, KolInputText } from '@public-ui/react-v19'; +import React, { useEffect, useState } from 'react'; +import { AccordionPreviewProps } from '../components/Accordion'; +import { AccordionMultipleDefault } from './ComponentDefaults'; +import { translate } from '@docusaurus/Translate'; + +type AccordionMultiplePropertyProps = { + label: string; + _value?: AccordionPreviewProps; + _on?: { + onInput?: (event: Event, value: unknown) => void; + }; +}; + +const createDefaultAccordion = (label: string): AccordionPreviewProps => ({ + _label: `Label ${label}`, + _slot: `Value ${label}`, +}); + +const INITIAL_ACCORDION: AccordionPreviewProps[] = AccordionMultipleDefault._accordions.map((accordion) => accordion); + +type UpdateFn = (updater: (accordion: AccordionPreviewProps) => AccordionPreviewProps) => void; +type RemoveFn = () => void; + +const AccordionMultipleEditor: React.FC<{ + accordion: AccordionPreviewProps; + index: number; + onUpdate: UpdateFn; + onRemove: RemoveFn; +}> = ({ accordion, index, onUpdate, onRemove }) => { + const label = `Accordion ${index + 1}`; + + const handleFieldChange = (field: keyof AccordionPreviewProps, value: unknown) => { + onUpdate((prev) => ({ ...prev, [field]: value })); + }; + + return ( +
+ +
+ { + handleFieldChange('_label', (e.target as HTMLInputElement).value); + }, + }} + /> + { + handleFieldChange('_slot', (e.target as HTMLInputElement).value); + }, + }} + /> + { + handleFieldChange('_disabled', !!checked); + }, + }} + /> + { + handleFieldChange('_open', !!checked); + }, + }} + /> +
+ +
+
+
+
+ ); +}; + +const AccordionMultipleProperty = (props: AccordionMultiplePropertyProps) => { + const [isEditing, setIsEditing] = useState(false); + const [accordions, setAccordions] = useState(INITIAL_ACCORDION); + + useEffect(() => { + props._on?.onInput?.(new Event('input'), accordions); + }); + + const addAccordion = () => { + setAccordions((prev) => [...prev, createDefaultAccordion(`Accordion ${accordions.length + 1}`)]); + }; + + const updateAccordion = (index: number, updater: (accordion: AccordionPreviewProps) => AccordionPreviewProps) => { + setAccordions((prev) => { + const next = [...prev]; + next[index] = updater(next[index]); + return next; + }); + }; + + const removeAccordion = (index: number) => { + setAccordions((prev) => prev.filter((_, i) => i !== index)); + }; + return ( +
+ setIsEditing(!isEditing) }} /> + + setIsEditing(false) }} + > +
+ {accordions.map((accordion, index) => ( + updateAccordion(index, updater)} + onRemove={() => removeAccordion(index)} + /> + ))} + + + + setIsEditing(false) }} + /> +
+
+
+ ); +}; + +export default AccordionMultipleProperty; diff --git a/src/components/previews/properties/ComponentDefaults.tsx b/src/components/previews/properties/ComponentDefaults.tsx index 6f4dfac4d2..2ce125265c 100644 --- a/src/components/previews/properties/ComponentDefaults.tsx +++ b/src/components/previews/properties/ComponentDefaults.tsx @@ -12,6 +12,7 @@ export const ComboboxSuggestionsDefault: W3CInputValue[] = [ 'PHP', 'Go', ]; + export const SelectOptionsDefault: Option[] = [ { label: 'Baden-Württemberg', value: 'BW' }, { label: 'Bayern', value: 'BY' }, @@ -30,3 +31,32 @@ export const SelectOptionsDefault: Option[] = [ { label: 'Schleswig-Holstein', value: 'SH' }, { label: 'Thüringen', value: 'TH' }, ]; + +export const AccordionMultipleDefault = { + _accordions: [ + { + _label: 'Der Frühling', + _open: true, + _slot: + 'Das Frühjahr bringt den Übergang vom Winter zum Sommer. Die Temperaturen steigen langsam, die Tage werden länger, und die Natur erwacht aus dem Winterschlaf: Pflanzen beginnen zu blühen, Bäume treiben neue Knospen, und viele Tierarten aktivieren ihre Fortpflanzungszyklen. Typisch sind wechselhaftes Wetter mit warmen sonnigen Phasen und kühleren Regentagen.', + }, + { + _label: 'Der Sommer', + _open: false, + _slot: + 'Der Sommer ist die wärmste Jahreszeit mit längsten Tagen und kürzesten Nächten. Die Sonne steht höher am Himmel, was zu intensiverer Einstrahlung führt. Temperaturen erreichen ihre Höchstwerte, Niederschläge treten oft als kurze Gewitter statt als langanhaltender Regen auf. Es ist die Hauptsaison für Vegetation und landwirtschaftliches Wachstum.', + }, + { + _label: 'Der Herbst', + _open: false, + _slot: + 'Im Herbst nimmt die Tageslänge deutlich ab, die Temperaturen fallen allmählich. Laubbäume verlieren ihr grünes Blattwerk durch die verkürzte Photosyntheseperiode, was zu charakteristischen Braun- und Gelbtönen führt. Die Erntezeit für viele Kulturpflanzen liegt in dieser Jahreszeit. Nebel und spätere Sonnenaufgänge werden häufiger.', + }, + { + _label: 'Der Winter', + _open: false, + _slot: + 'Die kalte Jahreszeit mit den kürzesten Tagen und längsten Nächten. Die niedrige Sonnenposition sorgt für geringe Einstrahlungsintensität. Temperaturen fallen unter den Gefrierpunkt, was in vielen Regionen Schnee und Eis ermöglicht. Pflanzen ruhen, viele Tiere halten Winterruhe oder migrieren. Die natürliche Lichtverfügbarkeit ist am geringsten.', + }, + ], +}; diff --git a/src/components/previews/properties/GenerateAccordionMultiple.tsx b/src/components/previews/properties/GenerateAccordionMultiple.tsx new file mode 100644 index 0000000000..0d424d58a0 --- /dev/null +++ b/src/components/previews/properties/GenerateAccordionMultiple.tsx @@ -0,0 +1,21 @@ +import { KolAccordion } from '@public-ui/react-v19'; +import React from 'react'; +import { AccordionPreviewProps } from '../components/Accordion'; +import { sanitizeHtml } from '../../../shares/sanitize'; + +function GenerateAccordionMultiple(_accordions: AccordionPreviewProps[]) { + return ( + <> + {_accordions.map(({ _slot, ...accordion }) => ( + <> + +
+ +
+ + ))} + + ); +} + +export default GenerateAccordionMultiple; diff --git a/src/components/previews/properties/index.ts b/src/components/previews/properties/index.ts index 183f38d149..7bf62c5447 100644 --- a/src/components/previews/properties/index.ts +++ b/src/components/previews/properties/index.ts @@ -24,5 +24,7 @@ export { default as TabBehaviorProperty } from './TabBehaviorProperty'; export { default as TabsProperty } from './TabsProperty'; export { default as TableColumnsProperty } from './TableColumnsProperty'; export { default as TreeItemsProperty } from './TreeItemsProperty'; -export { ComboboxSuggestionsDefault, SelectOptionsDefault } from './ComponentDefaults'; +export { default as GenerateAccordionMultiple } from './GenerateAccordionMultiple'; +export { default as AccordionMultipleProperty } from './AccordionMultipleProperty'; +export { ComboboxSuggestionsDefault, SelectOptionsDefault, AccordionMultipleDefault } from './ComponentDefaults'; export type { TreeItemData } from './TreeItemsProperty'; From ad3f8ebf2bfbf2de46404cf2ad24c51c69667a15 Mon Sep 17 00:00:00 2001 From: ItzGerSte Date: Thu, 6 Aug 2026 14:35:38 +0200 Subject: [PATCH 2/3] Fix Toggle Accordion --- docs/30-components/accordion.mdx | 2 +- src/components/previews/components/AccordionMultiple.tsx | 4 ++-- .../previews/properties/AccordionMultipleProperty.tsx | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/30-components/accordion.mdx b/docs/30-components/accordion.mdx index 5bf623f8c4..c1d38fa57e 100644 --- a/docs/30-components/accordion.mdx +++ b/docs/30-components/accordion.mdx @@ -21,7 +21,7 @@ import BetaDocsBanner from '@site/src/components/BetaDocsBanner'; Darstellung der Komponente ohne optional gesetzte Felder. Code kann eingeblendet werden. - + ## Barrierefreiheit diff --git a/src/components/previews/components/AccordionMultiple.tsx b/src/components/previews/components/AccordionMultiple.tsx index 776ece6f2e..c7b1b866c3 100644 --- a/src/components/previews/components/AccordionMultiple.tsx +++ b/src/components/previews/components/AccordionMultiple.tsx @@ -23,9 +23,9 @@ const AccordionMultiplePreview = (props: AccordionMultiplePreviewComponentProps) const pad = '\n '.repeat(indent); const { ...accordion } = accordions; const accordionProps = Object.entries(accordion as Record) - .filter(([, value]) => value !== undefined && value !== null && value !== '') - .filter(([key]) => key !== '_slot') .map(([key, value]) => { + if (key === '_slot') return ''; + if (value === undefined && value === null && value === '') return ''; if (typeof value === 'string') return `${pad}${key}="${value}"`; if (typeof value === 'boolean') return value ? `${pad}${key}={${value}}` : ''; if (typeof value === 'number') return `${pad}${key}={${value}}`; diff --git a/src/components/previews/properties/AccordionMultipleProperty.tsx b/src/components/previews/properties/AccordionMultipleProperty.tsx index 4f5f37c5c7..d39880358e 100644 --- a/src/components/previews/properties/AccordionMultipleProperty.tsx +++ b/src/components/previews/properties/AccordionMultipleProperty.tsx @@ -6,7 +6,7 @@ import { translate } from '@docusaurus/Translate'; type AccordionMultiplePropertyProps = { label: string; - _value?: AccordionPreviewProps; + _value?: AccordionPreviewProps[]; _on?: { onInput?: (event: Event, value: unknown) => void; }; @@ -91,11 +91,11 @@ const AccordionMultipleEditor: React.FC<{ const AccordionMultipleProperty = (props: AccordionMultiplePropertyProps) => { const [isEditing, setIsEditing] = useState(false); - const [accordions, setAccordions] = useState(INITIAL_ACCORDION); + const [accordions, setAccordions] = useState(props._value ?? INITIAL_ACCORDION); useEffect(() => { props._on?.onInput?.(new Event('input'), accordions); - }); + }, [accordions]); const addAccordion = () => { setAccordions((prev) => [...prev, createDefaultAccordion(`Accordion ${accordions.length + 1}`)]); From f0083dcd5a7ac8577c43149f619b641e41c6e395 Mon Sep 17 00:00:00 2001 From: ItzGerSte Date: Thu, 6 Aug 2026 14:54:28 +0200 Subject: [PATCH 3/3] Fixed linting errors --- src/components/previews/components/AccordionMultiple.tsx | 2 +- .../previews/properties/AccordionMultipleProperty.tsx | 4 ++-- src/components/previews/properties/ComponentDefaults.tsx | 5 +++-- .../previews/properties/GenerateAccordionMultiple.tsx | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/components/previews/components/AccordionMultiple.tsx b/src/components/previews/components/AccordionMultiple.tsx index c7b1b866c3..6b5768b5b1 100644 --- a/src/components/previews/components/AccordionMultiple.tsx +++ b/src/components/previews/components/AccordionMultiple.tsx @@ -1,7 +1,7 @@ import React from 'react'; import Preview, { PreviewLayout } from '../Preview'; import { AccordionMultipleProperty, GenerateAccordionMultiple } from '../properties'; -import { AccordionPreviewProps } from './Accordion'; +import type { AccordionPreviewProps } from './Accordion'; import { AccordionMultipleDefault } from '../properties/ComponentDefaults'; export type AccordionMultiplePreviewProps = { _accordions: AccordionPreviewProps[] }; diff --git a/src/components/previews/properties/AccordionMultipleProperty.tsx b/src/components/previews/properties/AccordionMultipleProperty.tsx index d39880358e..1a00e68fce 100644 --- a/src/components/previews/properties/AccordionMultipleProperty.tsx +++ b/src/components/previews/properties/AccordionMultipleProperty.tsx @@ -1,6 +1,6 @@ import { KolButton, KolCard, KolDrawer, KolInputCheckbox, KolInputText } from '@public-ui/react-v19'; import React, { useEffect, useState } from 'react'; -import { AccordionPreviewProps } from '../components/Accordion'; +import type { AccordionPreviewProps } from '../components/Accordion'; import { AccordionMultipleDefault } from './ComponentDefaults'; import { translate } from '@docusaurus/Translate'; @@ -40,7 +40,7 @@ const AccordionMultipleEditor: React.FC<{
{ handleFieldChange('_label', (e.target as HTMLInputElement).value); diff --git a/src/components/previews/properties/ComponentDefaults.tsx b/src/components/previews/properties/ComponentDefaults.tsx index 2ce125265c..037550e06d 100644 --- a/src/components/previews/properties/ComponentDefaults.tsx +++ b/src/components/previews/properties/ComponentDefaults.tsx @@ -1,4 +1,5 @@ -import { Option, W3CInputValue } from '@public-ui/components'; +import type { Option, W3CInputValue } from '@public-ui/components'; +import type { AccordionMultiplePreviewProps } from '../components/AccordionMultiple'; export const ComboboxSuggestionsDefault: W3CInputValue[] = [ 'JavaScript', @@ -32,7 +33,7 @@ export const SelectOptionsDefault: Option[] = [ { label: 'Thüringen', value: 'TH' }, ]; -export const AccordionMultipleDefault = { +export const AccordionMultipleDefault: AccordionMultiplePreviewProps = { _accordions: [ { _label: 'Der Frühling', diff --git a/src/components/previews/properties/GenerateAccordionMultiple.tsx b/src/components/previews/properties/GenerateAccordionMultiple.tsx index 0d424d58a0..487fe3f3e3 100644 --- a/src/components/previews/properties/GenerateAccordionMultiple.tsx +++ b/src/components/previews/properties/GenerateAccordionMultiple.tsx @@ -1,6 +1,6 @@ import { KolAccordion } from '@public-ui/react-v19'; import React from 'react'; -import { AccordionPreviewProps } from '../components/Accordion'; +import type { AccordionPreviewProps } from '../components/Accordion'; import { sanitizeHtml } from '../../../shares/sanitize'; function GenerateAccordionMultiple(_accordions: AccordionPreviewProps[]) {