Entwicklungsanleitung
Diese Anleitung beschreibt den Entwicklungsworkflow und Best Practices für die Smolitux UI Bibliothek.
Entwicklungsumgebung einrichten
Voraussetzungen
- Node.js (v18 oder höher)
- Yarn (v1.22 oder höher)
- Git
Installation
-
Repository klonen:
git clone https://github.com/EcoSphereNetwork/smolitux-ui.git
cd smolitux-ui -
Abhängigkeiten installieren:
yarn install
-
Entwicklungsserver starten:
yarn dev
Projektstruktur
smolitux-ui/
├── docs/ # Dokumentation
├── packages/ # Monorepo-Pakete
│ ├── @smolitux/core/ # Kernkomponenten
│ ├── @smolitux/charts/ # Diagramm-Komponenten
│ ├── @smolitux/layout/ # Layout-Komponenten
│ └── @smolitux/theme/ # Theming-System
├── examples/ # Beispielanwendungen
├── scripts/ # Build- und Entwicklungsskripte
└── .storybook/ # Storybook-Konfiguration
Komponenten entwickeln
Neue Komponente erstellen
-
Erstelle einen neuen Ordner für die Komponente:
mkdir -p packages/@smolitux/core/src/components/MyComponent
-
Erstelle die Komponenten-Dateien:
touch packages/@smolitux/core/src/components/MyComponent/MyComponent.tsx
touch packages/@smolitux/core/src/components/MyComponent/index.ts -
Implementiere die Komponente:
// MyComponent.tsx
import React from 'react';
export interface MyComponentProps {
/** Beschreibung der Prop */
label?: string;
/** Weitere Props... */
}
export const MyComponent: React.FC<MyComponentProps> = ({
label = 'Default',
...props
}) => {
return (
<div className="my-component" {...props}>
{label}
</div>
);
}; -
Erstelle den Export in der index.ts:
// index.ts
export { MyComponent } from './MyComponent';
export type { MyComponentProps } from './MyComponent';
// Für Abwärtskompatibilität
export { MyComponent as default } from './MyComponent'; -
Füge die Komponente zum Hauptexport hinzu:
// packages/@smolitux/core/src/components/index.tsx
export * from './MyComponent';
Tests schreiben
-
Erstelle einen Test-Ordner:
mkdir -p packages/@smolitux/core/src/components/MyComponent/__tests__
-
Erstelle Unit-Tests:
touch packages/@smolitux/core/src/components/MyComponent/__tests__/MyComponent.test.tsx
-
Implementiere die Tests:
// MyComponent.test.tsx
import React from 'react';
import { render, screen } from '@testing-library/react';
import { MyComponent } from '../MyComponent';
describe('MyComponent', () => {
it('renders with default props', () => {
render(<MyComponent />);
expect(screen.getByText('Default')).toBeInTheDocument();
});
it('renders with custom label', () => {
render(<MyComponent label="Custom Label" />);
expect(screen.getByText('Custom Label')).toBeInTheDocument();
});
}); -
Erstelle Snapshot-Tests:
touch packages/@smolitux/core/src/components/MyComponent/__tests__/MyComponent.spec.tsx
-
Implementiere die Snapshot-Tests:
// MyComponent.spec.tsx
import React from 'react';
import { render } from '@testing-library/react';
import { MyComponent } from '../MyComponent';
describe('MyComponent Snapshots', () => {
it('renders correctly with default props', () => {
const { asFragment } = render(<MyComponent />);
expect(asFragment()).toMatchSnapshot();
});
it('renders correctly with custom props', () => {
const { asFragment } = render(<MyComponent label="Custom" />);
expect(asFragment()).toMatchSnapshot();
});
});
Storybook-Beispiele erstellen
-
Erstelle eine Story-Datei:
touch packages/@smolitux/core/src/components/MyComponent/MyComponent.stories.tsx
-
Implementiere die Stories:
// MyComponent.stories.tsx
import React from 'react';
import { Meta, StoryObj } from '@storybook/react';
import { MyComponent } from './MyComponent';
const meta: Meta<typeof MyComponent> = {
title: 'Core/MyComponent',
component: MyComponent,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof MyComponent>;
export const Default: Story = {
args: {},
};
export const WithCustomLabel: Story = {
args: {
label: 'Benutzerdefiniertes Label',
},
};
Code-Qualität
Linting und Formatierung
# Linting ausführen
yarn lint
# Formatierung ausführen
yarn format
# Typen prüfen
yarn typecheck
Performance-Optimierung
-
Verwende
useMemo
für berechnete Werte:const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
-
Verwende
useCallback
für Event-Handler:const handleClick = useCallback(() => {
// Handler-Logik
}, [dependency]); -
Verwende
React.memo
für Komponenten, die sich selten ändern:const MemoizedComponent = React.memo(MyComponent);
Tests ausführen
# Alle Tests ausführen
yarn test
# Tests mit Coverage ausführen
yarn test:coverage
# Tests im Watch-Modus ausführen
yarn test:watch
Dokumentation
Lokale Dokumentation starten
# Dokumentation lokal starten
cd docs
yarn start
Komponenten dokumentieren
- Verwende JSDoc-Kommentare für Props:
export interface ButtonProps {
/** Die Variante des Buttons */
variant?: 'primary' | 'secondary' | 'ghost';
/** Die Größe des Buttons */
size?: 'sm' | 'md' | 'lg';
/** Wird ausgelöst, wenn der Button geklickt wird */
onClick?: () => void;
}
Git-Workflow
-
Feature-Branch erstellen:
git checkout -b feature/neue-komponente
-
Änderungen committen:
git add .
git commit -m "feat: Neue Komponente hinzugefügt" -
Änderungen pushen:
git push origin feature/neue-komponente
-
Pull Request erstellen
Veröffentlichung
Versionierung
Die Bibliothek folgt der Semantic Versioning-Spezifikation:
- MAJOR: Inkompatible API-Änderungen
- MINOR: Funktionen hinzufügen (abwärtskompatibel)
- PATCH: Bugfixes (abwärtskompatibel)
Release-Prozess
-
Version erhöhen:
yarn version:bump
-
Changelog aktualisieren:
yarn changelog
-
Release erstellen:
yarn release
Best Practices
Komponenten-Design
- Einfachheit: Halte Komponenten einfach und fokussiert auf einen Zweck
- Komposition: Bevorzuge Komposition über Vererbung
- Konsistenz: Halte dich an bestehende Muster und Konventionen
- Barrierefreiheit: Implementiere ARIA-Attribute und Keyboard-Navigation
- Responsivität: Stelle sicher, dass Komponenten auf allen Bildschirmgrößen funktionieren
Performance
- Memoization: Verwende useMemo und useCallback für teure Berechnungen
- Lazy Loading: Lade Komponenten bei Bedarf
- Code-Splitting: Teile den Code in kleinere Chunks
- Bundle-Größe: Halte die Bundle-Größe klein
- Rendering-Optimierung: Vermeide unnötige Renderings
Dokumentation
- API-Referenz: Dokumentiere alle Props und ihre Verwendung
- Beispiele: Füge Beispiele für häufige Anwendungsfälle hinzu
- Storybook: Erstelle interaktive Beispiele mit Storybook
- Kommentare: Kommentiere komplexe Logik im Code
- Änderungsprotokoll: Halte das Änderungsprotokoll aktuell