Skip to content
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
12 changes: 2 additions & 10 deletions docs/30-components/accordion.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -20,16 +21,7 @@ import BetaDocsBanner from '@site/src/components/BetaDocsBanner';

Darstellung der Komponente ohne optional gesetzte Felder. Code kann eingeblendet werden.

<AccordionPreview
codeCollapsable
visibleProperties={[]}
initialProps={{
_label: 'Die Jahreszeiten',
_open: true,
_slot:
'<p>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.</p><p>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.</p><p>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.<p/><p>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.</p>',
}}
/>
<AccordionMultiplePreview codeCollapsable visibleProperties={[]} />

## Barrierefreiheit

Expand Down
4 changes: 2 additions & 2 deletions src/components/previews/components/Accordion.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +20,7 @@ const AccordionPreview = (props: AccordionPreviewComponentProps) => {
_label: translate({ id: 'preview.component.accordion.label' }),
_slot: translate({ id: 'preview.component.accordion.content' }),
}),
[],
[]
);

return (
Expand Down
66 changes: 66 additions & 0 deletions src/components/previews/components/AccordionMultiple.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import React from 'react';
import Preview, { PreviewLayout } from '../Preview';
import { AccordionMultipleProperty, GenerateAccordionMultiple } from '../properties';
import type { 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<AccordionMultiplePreviewProps>(() => 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<string, unknown>)
.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}}`;
return `${pad}${key}={${JSON.stringify(value)}}`;
})
.join('');
return `<KolAccordion${accordionProps}\n>${JSON.stringify(accordion._slot).replace(
/^"|"$/g,
''
)}\n</KolAccordion>\n<br/>`;
};

const accordionsString = accordions.map((accordion) => formatAccordion(accordion, 1)).join('\n');

return `${accordionsString}`.replace(/(<br\/>)$/, '');
};

return (
<Preview<AccordionMultiplePreviewProps>
propertyComponents={{
_accordions: <AccordionMultipleProperty label="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);
}}
</Preview>
);
};

export default AccordionMultiplePreview;
150 changes: 150 additions & 0 deletions src/components/previews/properties/AccordionMultipleProperty.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { KolButton, KolCard, KolDrawer, KolInputCheckbox, KolInputText } from '@public-ui/react-v19';
import React, { useEffect, useState } from 'react';
import type { 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 (
<div style={{ marginLeft: undefined, borderLeft: undefined, paddingLeft: undefined }}>
<KolCard _label={label}>
<div className="flex flex-col gap-2">
<KolInputText
_label="Label"
_value={accordion._label}
_on={{
onInput: (e: Event) => {
handleFieldChange('_label', (e.target as HTMLInputElement).value);
},
}}
/>
<KolInputText
_label="Value"
_value={accordion._slot}
_on={{
onInput: (e: Event) => {
handleFieldChange('_slot', (e.target as HTMLInputElement).value);
},
}}
/>
<KolInputCheckbox
_label="Disabled"
_checked={accordion._disabled ?? false}
_variant="switch"
_on={{
onInput: (_e: Event, checked: unknown) => {
handleFieldChange('_disabled', !!checked);
},
}}
/>
<KolInputCheckbox
_label="Opened"
_checked={accordion._open ?? true}
_variant="switch"
_on={{
onInput: (_e: Event, checked: unknown) => {
handleFieldChange('_open', !!checked);
},
}}
/>
<div className="flex gap-2">
<KolButton
_label={translate({ id: 'preview.component.select.options.remove' })}
_variant="danger"
_on={{ onClick: onRemove }}
/>
</div>
</div>
</KolCard>
</div>
);
};

const AccordionMultipleProperty = (props: AccordionMultiplePropertyProps) => {
const [isEditing, setIsEditing] = useState(false);
const [accordions, setAccordions] = useState<AccordionPreviewProps[]>(props._value ?? INITIAL_ACCORDION);

useEffect(() => {
props._on?.onInput?.(new Event('input'), accordions);
}, [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 (
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
<KolButton _label={props.label} _variant="secondary" _on={{ onClick: () => setIsEditing(!isEditing) }} />

<KolDrawer
_label={translate({ id: 'preview.component.select.options.edit' })}
_open={isEditing}
_align="right"
_hasCloser
_on={{ onClose: () => setIsEditing(false) }}
>
<div className="flex flex-col gap-4 py-4">
{accordions.map((accordion, index) => (
<AccordionMultipleEditor
key={index}
accordion={accordion}
index={index}
onUpdate={(updater) => updateAccordion(index, updater)}
onRemove={() => removeAccordion(index)}
/>
))}

<KolButton _label="+ Accordion" _variant="secondary" _on={{ onClick: addAccordion }} />

<KolButton
_label={translate({ id: 'preview.component.select.options.closeedit' })}
_variant="primary"
_on={{ onClick: () => setIsEditing(false) }}
/>
</div>
</KolDrawer>
</div>
);
};

export default AccordionMultipleProperty;
33 changes: 32 additions & 1 deletion src/components/previews/properties/ComponentDefaults.tsx
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -12,6 +13,7 @@ export const ComboboxSuggestionsDefault: W3CInputValue[] = [
'PHP',
'Go',
];

export const SelectOptionsDefault: Option<string>[] = [
{ label: 'Baden-Württemberg', value: 'BW' },
{ label: 'Bayern', value: 'BY' },
Expand All @@ -30,3 +32,32 @@ export const SelectOptionsDefault: Option<string>[] = [
{ label: 'Schleswig-Holstein', value: 'SH' },
{ label: 'Thüringen', value: 'TH' },
];

export const AccordionMultipleDefault: AccordionMultiplePreviewProps = {
_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.',
},
],
};
21 changes: 21 additions & 0 deletions src/components/previews/properties/GenerateAccordionMultiple.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { KolAccordion } from '@public-ui/react-v19';
import React from 'react';
import type { AccordionPreviewProps } from '../components/Accordion';
import { sanitizeHtml } from '../../../shares/sanitize';

function GenerateAccordionMultiple(_accordions: AccordionPreviewProps[]) {
return (
<>
{_accordions.map(({ _slot, ...accordion }) => (
<>
<KolAccordion {...accordion}>
<div dangerouslySetInnerHTML={{ __html: sanitizeHtml(_slot ?? '') }} />
</KolAccordion>
<br />
</>
))}
</>
);
}

export default GenerateAccordionMultiple;
4 changes: 3 additions & 1 deletion src/components/previews/properties/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Loading