Unterzeichnungsfelder
Entwicklung
09.08.2024
Bis vor Kurzem stellte Documenso eine Reihe von 5 Feldern für die Dokumentenunterzeichnung zur Verfügung: Unterschrift, E-Mail, Name, Datum und ein Textfeld für zusätzliche Informationen. Während diese Felder die grundlegenden Anforderungen für die Dokumentenunterzeichnung abdeckten, erkannten wir die Notwendigkeit für mehr Flexibilität und Vielfalt.
Infolgedessen haben wir beschlossen, mehrere zusätzliche Felder einzuführen, wie z.B.:
(ein verbessertes) Textfeld
Zahlenfeld
Radiofeld
Checkboxfeld
Dropdown-/Auswahlfeld
Diese neuen Felder bringen mehr Flexibilität und Vielfalt zu Documenso. Als Dokumenteneigentümer ermöglichen sie Ihnen, spezifischere oder zusätzliche Informationen von den Unterzeichnern zu sammeln.
Einführung neuer Felder
Schauen wir uns jeden neuen Feldtyp etwas genauer an.
Textfeld
Während das Textfeld zuvor verfügbar war, konnte es nicht konfiguriert werden. Es war ein einfaches Eingabefeld, in das Unterzeichner eine einzige Textzeile eingeben konnten.
Das Bild zeigt das alte Textfeld im Dokumenteneditor.
Das überarbeitete Textfeld bietet nun eine Reihe von Konfigurationsoptionen, die es Ihnen ermöglichen,:
Ein Label, einen Platzhalter, einen Standardtext und ein Zeichenlimit hinzuzufügen
Das Feld als erforderlich oder schreibgeschützt festzulegen
Auf der Unterzeichnerseite blieb das Feld visuell größtenteils gleich. Das Einzige, was sich geändert hat, ist die Funktionalität, die die Validierungsregeln berücksichtigen muss. Zum Beispiel, wenn das Feld erforderlich ist, muss der Unterzeichner einen Wert eingeben, um es zu unterzeichnen. Oder, wenn das Feld ein Zeichenlimit hat, sollte der vom Unterzeichner eingegebene Wert das Limit nicht überschreiten.
Das Bild unten zeigt vier verschiedene Textfelder mit verschiedenen Konfigurationen.
Das erste Textfeld hat keinen Standardwert ("Text hinzufügen") oder Konfiguration. Sie können das Feld unterzeichnen, indem Sie einen beliebigen Text eingeben.
Das zweite Textfeld, "label-1"/"text-1", hat die folgenden Konfigurationen:
Label
Platzhalter
Standardtext
Zeichenlimit
Da es einen Standardwert gibt, unterzeichnet das Feld automatisch mit diesem Wert. Sie können das Feld jedoch erneut mit einem neuen Wert unterzeichnen, der das Zeichenlimit nicht überschreitet.
Das dritte Feld, "label-2"/"text-2", hat die gleichen Konfigurationen wie das zweite, mit einer Ergänzung - die `erforderlich` Option ist aktiviert. Wenn das Feld als `erforderlich` markiert ist, müssen Sie es unterzeichnen, bevor Sie das Dokument abschließen.
Aber abgesehen davon funktioniert es wie das zweite Feld.
Das vierte Feld, "label-3"/"text-3", hat die gleichen Konfigurationen wie das zweite, mit einer Ergänzung—schreibgeschützt
ist aktiviert. Das bedeutet, dass das Feld automatisch mit dem Standardwert unterzeichnet wird, und Sie können es nicht ändern.
Unterschriebene Felder
Sie können ein Feld unsignieren, um den Wert zu ändern und es erneut zu unterzeichnen. Der unsignierte Zustand des Feldes variiert je nach Konfiguration:
Wenn das Feld ein Label hat, wird es anstelle von "Text hinzufügen" unsigniert angezeigt.
Wenn das Feld einen Standardwert hat, wird der Standardwert unsigniert angezeigt.
Wenn das Feld sowohl ein Label als auch einen Standardwert hat, hat das Label Vorrang und wird unsigniert angezeigt.
Das Bild unten zeigt den unsignierten Zustand der Textfelder.
Die einzige Ausnahme ist das vierte, schreibgeschützte Feld, das nicht unsigniert oder geändert werden kann.
Zahlenfeld
Wir haben auch ein neues "Zahl"-Feld eingeführt, um Dokumente mit numerischen Werten einzufügen und zu unterzeichnen. Dieses Feld hilft, Mengen, Maße und andere Daten zu sammeln, die am besten als Zahlen dargestellt werden.
Das "Zahl"-Feld bietet eine Reihe von Konfigurationsoptionen, die es Ihnen ermöglichen:
Ein Label, einen Platzhalter und einen Standardwert festzulegen
Das Zahlenformat anzugeben
Das Feld als erforderlich oder schreibgeschützt zu markieren
Minimale und maximale Werte anzugeben
Das Zahlenfeld sieht ähnlich aus und funktioniert wie das Textfeld. Der Unterschied besteht darin, dass es nur numerische Werte akzeptiert und 2 zusätzliche Konfigurationen hat: das Zahlenformat und die minimalen und maximalen Werte.
Radiofeld
Radio-Buttons ermöglichen den Unterzeichnern, eine einzige Option aus einer vorher definierten Liste auszuwählen, die der Dokumenteneigentümer festlegt.
Bevor Sie das Dokument zur Unterzeichnung senden, müssen Sie mindestens eine Radio-Option hinzufügen, die einen String oder einen leeren Wert enthalten kann und ausgewählt oder nicht ausgewählt sein kann. Es ist jedoch wichtig zu beachten, dass nur eine Option gleichzeitig ausgewählt werden kann.
Was die Feldkonfiguration betrifft, können Sie das Feld als erforderlich oder schreibgeschützt markieren.
Das Bild unten zeigt, was der Unterzeichner sieht, nachdem das Dokument zur Unterzeichnung gesendet wurde.
Hinweis: Das Bild wurde geändert, um sowohl den unsignierten als auch den signierten Zustand des Feldes anzuzeigen.
Da das Feld eine vorausgewählte Option hat (Option radio-val-2-checked
), wird es automatisch mit diesem Wert unterzeichnet und erscheint wie das mit der Nummer 1 markierte Feld.
Wenn das Feld nicht schreibgeschützt ist, kann der Unterzeichner:
Das Feld unsignieren und eine andere Option wählen, indem er darauf klickt.
Mit dem Standardwert erneut unterzeichnen, indem er die Seite aktualisiert, wenn das Feld unsigniert ist.
Wenn das Feld jedoch als schreibgeschützt markiert ist, kann der Unterzeichner den vorausgewählten Wert nicht ändern.
Dropdown-/Auswahlfeld
Wir haben auch ein neues "Dropdown-/Auswahl"-Feld eingeführt, das es den Unterzeichnern ermöglicht, eine Option aus einer vordefinierten Liste von Auswahlmöglichkeiten auszuwählen. Dieser Feldtyp ist ideal für Szenarien mit begrenzten gültigen Optionen, wie z.B. die Auswahl eines Landes, Bundesstaates oder einer Kategorie.
Bei der Einrichtung eines "Dropdown-/Auswahl"-Feldes können Sie:
Mehrere Optionen hinzufügen
Das Feld als erforderlich oder schreibgeschützt markieren
Eine Standardoption aus der Liste der Auswahlmöglichkeiten auswählen
Auf der Unterzeichnungsseite erscheint das "Dropdown-/Auswahl"-Feld wie unten gezeigt:
So funktioniert das "Dropdown-/Auswahl"-Feld:
Wenn kein Standardwert festgelegt ist, wird das Feld nicht automatisch unterzeichnet. Der Unterzeichner muss auf das Feld klicken und eine Option aus der Dropdown-Liste auswählen, um es zu unterzeichnen.
Nach der Unterzeichnung zeigt das Feld den ausgewählten Wert an, ähnlich wie ein signiertes Textfeld.
Wenn das Feld als erforderlich markiert ist, müssen die Unterzeichner einen Wert auswählen, bevor sie den Unterzeichnungsprozess abschließen.
Wenn das Feld als schreibgeschützt markiert ist, können die Unterzeichner den ausgewählten Wert ansehen, aber nicht ändern.
Checkboxfeld
Das letzte eingeführte Feld ist das "Checkbox"-Feld, das es den Unterzeichnern ermöglicht, mehrere Optionen aus einer vordefinierten Liste auszuwählen. Dieses Feld ist hilfreich für Szenarien, in denen die Unterzeichner mehrere Elemente auswählen oder mehreren Bedingungen zustimmen müssen, zum Beispiel.
Bevor Sie das Dokument zur Unterzeichnung senden, müssen Sie mindestens eine Checkbox-Option hinzufügen. Diese Option kann einen String oder einen leeren Wert enthalten und kann ausgewählt oder nicht ausgewählt sein. Im Gegensatz zum "Radio"-Feld kann das "Checkbox"-Feld mehrere ausgewählte Optionen haben.
Wie andere Felder können Sie die "Checkbox" als erforderlich oder schreibgeschützt markieren. Zusätzlich dazu hat es auch ein Validierungsfeld, und Sie können angeben, wie viele Kästchen die Unterzeichner auswählen sollten:
Mindestens X auswählen (eine Zahl von 1 bis 10)
Maximal X auswählen (eine Zahl von 1 bis 10)
Genau X auswählen (eine Zahl von 1 bis 10)
Wenn ein Unterzeichner das Dokument erhält, sieht er das "Checkbox"-Feld wie unten gezeigt:
Das Bild zeigt beide Feldzustände - signiert und unsigniert. In diesem Beispiel hat das 'Checkbox'-Feld zwei Optionen, die standardmäßig ausgewählt sind, sodass es automatisch unterzeichnet wird.
Das Feld, das mit '1' markiert ist, erscheint, wenn der Unterzeichner die Seite zum ersten Mal besucht oder wenn der Benutzer die Seite aktualisiert und keine Option ausgewählt ist. Das Feld, das mit '2' markiert ist, zeigt den geleerten Zustand an, bei dem alle Auswahlmöglichkeiten abgewählt wurden. Dies zeigt, wie das Feld aussieht, wenn ein Benutzer alle Auswahlen aufhebt.
In diesem Beispiel wurde keine Validierungsregel festgelegt, wodurch es dem Unterzeichner ermöglicht wird, beliebige Optionen auszuwählen. Wenn jedoch eine Validierungsregel angewendet wird, müssen die Unterzeichner die angegebenen Kriterien erfüllen, um den Unterzeichnungsprozess abzuschließen.
Entwicklungsherausforderungen
Die Einführung dieser neuen Felder war nicht ohne Herausforderungen. Die Hauptschwierigkeiten waren:
Entscheiden, wie die neuen Informationen für die Felder in der Datenbank gespeichert werden sollen
Unterscheidung der Empfänger mithilfe von Farben
Speichern der erweiterten Einstellungen für die lokalen Felder im Frontend
Implementierung der Checkbox- und Radiofelder
1. Herausforderung: Speichern von Informationen zu neuen Feldern
Die erste Herausforderung bestand darin, zu entscheiden, wie die zusätzlichen Informationen für jedes neue Feld in der Datenbank gespeichert werden sollten. Jedes Feld hat einzigartige Eigenschaften, wobei nur `erforderlich` und `schreibgeschützt` von allen erweiterten Feldern gemeinsam genutzt werden.
Das bestehende `Field`-Modell in der Datenbank sieht so aus:
Ursprünglich hatten wir erwogen, eine neue FieldMeta
-Tabelle mit Spalten für jede Feld-Eigenschaft zu erstellen. Allerdings hat dieser Ansatz 2 Probleme.
Erstens teilen sich die erweiterten Felder nur zwei gemeinsame Eigenschaften: erforderlich
und schreibgeschützt
. Da alle anderen Eigenschaften einzigartig für jeden Feldtyp sind, würde dies zu vielen nullable-Spalten im FieldMeta
-Modell führen.
Zweitens würde die Erstellung einer neuen Datenbanktabelle mit Spalten für jede Feldeigenschaft und den zugehörigen Beziehungen die Komplexität der Datenbank erhöhen.
Infolgedessen haben wir beschlossen, nach einer anderen Lösung zu suchen, die besser zu unserem Anwendungsfall passt.
Lösung: JSONB-Feld
Da die Daten zu den erweiterten Einstellungen einzigartig für jedes Feld sind, haben wir beschlossen, sie als JSON unter Verwendung des `JSONB`-Datentyps von PostgreSQL zu speichern. Wir haben der Field-Modell eine neue optionale `fieldMeta`-Eigenschaft vom Typ `JSONB` hinzugefügt:
Dieser Ansatz ermöglicht es uns, die Einstellungen jedes Feldes als JSON-Objekt zu speichern. Wir verwenden Zod-Schemata, um die Feldmetadaten beim Lesen von oder Schreiben an die Datenbank zu analysieren und zu validieren, um die Datenintegrität sicherzustellen.
Dieser Ansatz hat mehrere Vorteile:
Konsistenz: Die Anwendung verwendet dasselbe Zod-Schema, um Daten in die Datenbank abzurufen und einzufügen. Das bedeutet, dass die Daten in der gesamten Anwendung konsistent sind.
Typensicherheit: Durch das Parsen der Daten mit Zod können wir garantieren, dass die Daten den erwarteten Typen und der Struktur entsprechen. Wir können auch Zods `infer`-Hilfsprogramm verwenden, um starke Typisierung und Autovervollständigung zu ermöglichen.
Bessere Fehlerbehandlung: Zod bietet umfassende Fehlermeldungen, die anzeigen, welcher Teil der Daten ungültig ist. Dadurch wird das Debuggen und Beheben von Problemen einfacher und schneller.
Wartbarkeit: Die Wiederverwendung desselben Zod-Schemas zum Abrufen und Einfügen von Daten in die Datenbank macht die Datenstruktur einfacher zu warten.
Die Verwendung von `JSONB` hat jedoch auch Nachteile, wie z.B. das Datenabfragen. Da die Daten als JSON (genauer gesagt im binären Format) gespeichert werden, können komplexe Abfragen weniger effizient sein im Vergleich zu der Abfrage von normalisierten relationalen Daten. Darüber hinaus erfordert das Abfragen von Daten spezifische Operatoren und Funktionen, wie ->
, ->>
, @>
und ?
. Dies macht das Abfragen umfangreicher und weniger intuitiv, und erfordert daher mehr Finesse.
Ein weiterer Nachteil ist der Speicheraufwand. `JSONB`-Daten werden in einem binären Format gespeichert, was zu einem gewissen Speicheraufwand im Vergleich zu normalisierten relationalen Daten führen kann. In Fällen, in denen die JSON-Daten groß sind oder viele redundante Informationen enthalten, kann der Speicheraufwand erheblich sein.
Trotz dieser Nachteile eignet sich der Typ `JSONB` gut für unseren Anwendungsfall, da die Metainformationen der Felder relativ klein sind und keine komplexen Abfragen erfordern. Die Flexibilität von `JSONB` entspricht der dynamischen Natur des FeldMeta-Feldes.
Postgres bietet 2 Felder zum Speichern von JSON-Daten —
json
undjsonb
. Für weitere Informationen können Sie die Dokumentation einsehen.
2. Herausforderung: Speichern der erweiterten Einstellungen der Felder im Frontend
Die nächste Herausforderung bestand darin, den besten Weg zu finden, die erweiterten Felder, die von Benutzern eingegeben wurden, zu speichern.
Derzeit speichert die Anwendung die Felder und die zugehörigen Einstellungen nur in der Datenbank, wenn der Benutzer zum nächsten Schritt wechselt.
Die Felder werden lokal gespeichert, bis der Benutzer zum nächsten Schritt fortschreitet. Das bedeutet, dass alle Felder und deren Einstellungen verloren gehen, wenn der Benutzer:
Den Tab für die erweiterten Einstellungen schließt
Die Seite aktualisiert
Den Tab schließt
Zum vorherigen Schritt navigiert
In Zukunft planen wir, diesen Ablauf zu verbessern und die Felder beim Verlassen zu speichern, um Benutzerdaten auch dann zu erhalten, wenn sie weg navigieren. Bis dahin benötigten wir jedoch eine Lösung, um die erweiterten Einstellungen zu speichern, wenn der Benutzer den Einstellungs-Tab schließt.
Lösung: Lokal speichern
Unsere vorübergehende Lösung besteht darin, die erweiterten Einstellungen im lokalen Speicher zu speichern, da die Felder nur lokal verfügbar sind. Wenn die Felder in der Datenbank gespeichert wären, könnten wir die erweiterten Einstellungen zusammen mit ihnen speichern.
Da die Felder nicht in der Datenbank gespeichert werden, müssen wir die Daten speichern, bis der Benutzer zum nächsten Schritt wechselt, zu dem Zeitpunkt werden die Daten in der Datenbank gespeichert. Das Speichern der Daten im lokalen Speicher ermöglicht es den Benutzern, verschiedene Felder im Tab für erweiterte Einstellungen zu öffnen, zu schließen und zu konfigurieren, ohne Informationen zu verlieren.
Wenn der Benutzer zum nächsten Schritt fortschreitet, werden die Felder und deren erweiterte Einstellungen in der Datenbank gespeichert, und der lokale Speicher wird gelöscht.
Wir haben auch die Gefahren des Speicherns von Daten im lokalen Speicher erkannt, da Benutzer diese bearbeiten und die Anwendung brechen könnten. Daher haben wir umfangreiche Prüfungen sowohl im Backend als auch im Frontend implementiert, zusätzlich zum Parsen und Validieren der Daten mit Zod.
Die Seite aktualisiert
Zum vorherigen Schritt navigiert
Den Browser schließt
In diesen Fällen werden die Felder aus dem Dokument gelöscht. Eine zukünftige Verbesserung, um Felder beim Verlassen in der Datenbank zu speichern, wird dieses Problem lösen.
3. Herausforderung: Radio- und Checkboxfelder
Die Implementierung der Radio- und Checkboxfelder war sowohl aus logischer als auch aus gestalterischer Perspektive herausfordernd. Beide Felder können leere und nicht leere Werte enthalten, und das Checkboxfeld ermöglicht es den Benutzern, mehrere leere/nicht leere Werte auszuwählen.
Das Bild oben zeigt die Radio- und Checkboxfelder im Dokumenteneditor. Das Radiofeld auf der linken Seite hat 4 Optionen, von denen 1 ausgewählt ist. Das Checkboxfeld auf der rechten Seite hat 4 Optionen, von denen 2 ausgewählt sind.
Das Radiofeld war einfacher zu implementieren, da die Benutzer nur eine Option auswählen können, was zu einer einfacheren Logik führt. Der Unterzeichner klickt auf eine Option, um sie auszuwählen, und das Feld unterzeichnet automatisch mit diesem Wert. Um die Auswahl zu ändern, klickt der Benutzer auf eine andere Option, unsigniert das Feld und unterzeichnet es erneut mit dem neuen Wert.
Das Checkboxfeld war herausfordernder, weil:
Unterzeichner mehrere Optionen gleichzeitig auswählen können, was dazu führt, dass das Feld mehrere Werte enthält.
Es Validierungsregeln haben kann (z.B. mindestens, maximal oder genau X Optionen auszuwählen).
Benutzer Optionen durch Klicken auswählen oder die Auswahl mit einem Button aufheben können.
Diese Faktoren machen das Checkboxfeld komplexer und schwieriger, korrekt zu implementieren.
Lösung
Statt uns auf eine spezifische Lösung zu konzentrieren, werden wir die allgemeine Implementierung und ihre herausforderndsten Aspekte behandeln. Ich werde einen Link zur vollständigen Implementierung für jedes Feld hinzufügen, damit Sie es überprüfen können.
Radiofeld
Die Funktionsweise der Unterzeichnung für das Radiofeld besteht darin, die Daten aus der Datenbank abzurufen und die verfügbaren Optionen anzuzeigen. Wenn das Feld einen Standardwert hat, der vom Absender des Dokuments festgelegt wurde, unterzeichnet es automatisch mit diesem Wert.
Die vollständige Implementierung des Radiofeldes finden Sie in der Datei radio-field.tsx.
Wenn das Feld nicht schreibgeschützt ist und der Benutzer auf eine andere Option klickt, wird das Feld unsigniert und erneut mit dem neuen Wert unterzeichnet. Schreibgeschützte Felder können nicht bearbeitet werden.
Der Wert wird in der Datenbank gespeichert, sobald das Feld unterzeichnet wird, sei es durch automatische Unterzeichnung oder durch den Benutzer. Ebenso wird der Wert aus der Datenbank entfernt, wenn das Feld unsigniert wird.
Da das Radiofeld leere Werte enthalten kann, gehen wir über die Werte und ersetzen die leeren durch einen eindeutigen String empty-value-${item.id}
. Dies liegt daran, dass die leere Zeichenfolge kein gültiger Wert für das Feld ist und wir zwischen leeren und nicht leeren Werten unterscheiden müssen.
Checkboxfeld
Die Implementierung des Checkboxfeldes ähnelt der des Radiofeldes, wobei die Hauptunterschiede sind:
Checkboxfelder können mehrere Werte enthalten.
Checkboxfelder haben Validierungsregeln, die durchgesetzt werden müssen.
Wie beim Radiofeld gehen wir über die Werte und ersetzen leere durch einen eindeutigen String. Wir verfolgen auch die ausgewählten Werte, um das Feld korrekt anzuzeigen und sie gegen die Validierungsregeln zu validieren.
Dann rufen wir die Validierungsregel und die Länge aus der Datenbank ab und finden das entsprechende Validierungssymbol (z.B. ">=", "=", "\<=") basierend auf dem Regelbezeichner. Das Array `checkboxValidationSigns` verknüpft Regelbezeichner mit ihren entsprechenden Zeichen.
Wir überprüfen dann, ob die Längenbedingung basierend auf der Validierungsregel, dem Zeichen und der Länge erfüllt ist. Wenn dies der Fall ist, kann der Benutzer mit der Unterzeichnung des Feldes fortfahren. Andernfalls müssen sie die richtige Anzahl von Optionen auswählen.
Zusammenfassend ermöglicht das Checkboxfeld den Unterzeichnern, mehrere Optionen auszuwählen, wobei das Feld automatisch basierend auf diesen Auswahlen unterzeichnet. Unterzeichner können das Feld unsignieren, indem sie Optionen abwählen oder alle Auswahlen zurücksetzen. Das System setzt während dieses Prozesses Validierungsregeln durch, um sicherzustellen, dass die Unterzeichner die erforderliche Anzahl von Optionen auswählen, um das Feld erfolgreich zu unterzeichnen.
Die vollständige Implementierung des Checkboxfeldes finden Sie in der Datei checkbox-field.tsx.
4. Herausforderung: Farben der Empfänger
Eine weitere Herausforderung, der wir gegenüberstanden, war die Verwendung von Farben, um die Empfänger zu unterscheiden. Wir mussten die gleichen Tailwind-Klassen dynamisch generieren und wiederverwenden, die über mehrere Komponenten hinweg verwendet werden. Allerdings schließt TailwindCSS nur die im Projekt verwendeten CSS-Klassen ein und verwirft ungenutzte Klassen aus dem endgültigen Build. Dies führte dazu, dass Farben nicht auf die Komponenten angewendet wurden, da die Klassen im Code nicht verwendet wurden.
Die Bilder unten veranschaulichen die Farben der Empfänger in 2 verschiedenen Zuständen.
Im ersten Bild befindet sich das "Unterschrift"-Feld rechts im aktiven Zustand (blau), was ausgelöst wird, wenn der Benutzer auf das Feld klickt, um es auf das Dokument zu ziehen. Das Unterschriftfeld links, das im Dokument platziert ist, befindet sich im normalen Zustand.
Das erste Bild verdeutlicht das "Unterschrift"-Feld im aktiven Zustand, das ausgelöst wird, wenn der Benutzer darauf klickt.
Das zweite Bild zeigt das "Unterschrift"-Feld im normalen Zustand.
Der Dokumenteneditor besteht aus verschiedenen Komponenten (Feldern, Empfängern usw.), was bedeutet, dass die gleichen Farben und der gleiche Code über mehrere Komponenten hinweg wiederverwendet werden.
Der obige Code zeigt eine naive Lösung, die ein combinedStyles
-Objekt verwendet, das TailwindCSS-Klassen für verschiedene Komponentenstile (Ring, Rand, Hover usw.) enthält.
Komponenten würden benutzerdefinierte Hooks verwenden, um geeignete Stile basierend auf dem ausgewählten Empfänger anzuwenden. Beispielsweise würde Empfänger 1 green-500
-Stile verwenden, die alle zugehörigen Elemente grün machen.
Das Problem mit diesem Ansatz besteht darin, dass wir das combinedStyles
-Objekt nicht in anderen Komponenten importieren können, da TailwindCSS die ungenutzten Klassen entfernt. Das bedeutet, wir mussten dasselbe Objekt in mehrere Dateien kopieren und einfügen. Infolgedessen verschmutzt dies den Code mit dupliziertem Code, was die Wartung und Skalierung des Codes erschwert. Wenn die Anwendung wächst, wird das combinedStyles
-Objekt größer und komplexer. Darüber hinaus ist es nicht sehr flexibel, da es keine einfache Anpassung der Farben erlaubt.
Obwohl dieser Ansatz funktioniert, gibt es eine effizientere und skalierbare Lösung.
Lösung: Modularisierung der Logik und Verwendung von CSS-Variablen
Um das Problem der Wiederverwendung von Farben über Komponenten hinweg anzugehen, haben wir die Farben und zugehörigen Hooks in eine separate Datei verschoben, die Stile nur in dieser Datei definiert und sie von Komponenten über benutzerdefinierte Hooks abrufbar macht.
Die Datei wurde zur besseren Lesbarkeit gekürzt. Sie können den vollständigen Code in der Datei signer-colors.ts aus dem Documenso-Repository sehen.
Das SIGNER_COLOR_STYLES
-Objekt enthält die Stile für jede Farbe, wie Hintergrund-, Rand- und Hover-Farben. Basierend auf dem Index des Unterzeichners erhält der useSignerColors
-Hook die Stile für eine bestimmte Farbe. Die Funktion getSignerColorStyles
ist eine Hilfsfunktion, die die Stile für einen bestimmten Unterzeichner zurückgibt.
Jetzt können die Komponenten die Farben und Stile über benutzerdefinierte Hooks abrufen. Zum Beispiel, um die Stile für einen bestimmten Unterzeichner zu erhalten, kann die Komponente den useSignerColors
-Hook mit dem Index des Unterzeichners aufrufen.
Der Hook gibt die Stile für diesen Unterzeichner zurück, die dann auf die Komponente angewendet werden können. Zum Beispiel haben Sie Zugriff auf die Hintergrundfarbe des Unterzeichners mit signerStyles.default.background
.
Dieser Ansatz erleichtert die Verwaltung der Farben und Stile, da sie in einer einzelnen Datei definiert sind. Änderungen oder Hinzufügungen von Farben können an einem Ort durchgeführt werden, wodurch der Code modularer und wiederverwendbarer wird.
Wir haben auch CSS-Variablen verwendet, um Farben zu definieren, was mehr Flexibilität und Konsistenz im Styling ermöglicht. Eine einzige CSS-Variable für jede Farbe kann eine breite Palette von Zuständen abdecken, ohne auf mehrere TailwindCSS-Klassen angewiesen zu sein. Zum Beispiel können Sie die Opazität und Helligkeit der Farbe problemlos einstellen, ohne mehrere Klassen verwenden zu müssen. CSS-Variablen helfen dabei, Farben mit unseren Markenrichtlinien in Einklang zu bringen und den gesamten Stylingprozess zu vereinfachen.
Das Ende
Wir freuen uns, die neuen erweiterten Felder veröffentlicht zu sehen, da sie unseren Benutzern mehr Flexibilität, Vielfalt und Anpassungsoptionen bieten. Die Implementierung der neuen Felder brachte ihre Herausforderungen mit sich, aber wir haben sie überwunden und daraus gelernt. Wir freuen uns darauf, Documenso weiter zu verbessern und unseren Benutzern die beste Dokumentenunterzeichnungserfahrung zu bieten.