Βοηθοί προτιμήσεων

Επτά μικρά πακέτα ανά framework, καθένα από τα οποία κατέχει μία εργασία του χρήστη από την αρχή ως το τέλος, συν μια μπάρα που συναρμολογεί πέντε από αυτά. Έχετε ήδη γνωρίσει το theme-picker· εδώ είναι τα locale-picker, text-size-picker και motion-picker (προτιμήσεις), share-picker και search-picker (ενέργειες), date-time-picker (τιμή φόρμας) και picker-bar.

Τι θα φτιάξετε

Ένας πίνακας ρυθμίσεων όπου οι χρήστες επιλέγουν γλώσσα και μέγεθος κειμένου — επιλογές που ισχύουν για ολόκληρο το έγγραφο, διατηρούνται ανάμεσα στις επισκέψεις και σας κοστίζουν δύο στοιχεία και λίγες γραμμές CSS. Περίπου 15 λεπτά.

Πριν ξεκινήσετε

Ολοκληρώστε πρώτα τον οδηγό του framework για τη στοίβα σας. Τα παρακάτω δείγματα είναι Svelte· οι βοηθοί για React, Vue, Angular, HTML, Nunjucks και Blazor αντιστοιχούν σύμβαση προς σύμβαση.

Το σχήμα που μοιράζονται

  • Ένα headless κουμπί-εικονίδιο που ανοίγει ένα listbox WAI-ARIA APG (ή, για το date-time-picker, ένα διάλογο επιλογής ημερομηνίας) — χωρίς εγγενές <select>, ώστε κάθε framework να παίρνει την ίδια συμπεριφορά πληκτρολογίου και τα ίδια αγκίστρια μορφοποίησης.
  • Ένα αγκίστρι κλάσης ανά πακέτο (.locale-picker, .text-size-picker, .share-picker, .date-time-picker), μηδέν CSS που αποστέλλεται.
  • Ασφαλές για SSR: οι εγγραφές στο DOM γίνονται μόνο στον κύκλο ζωής mount/effect.
  • Καθαρό ως προς το i18n: κάθε ορατή στον χρήστη συμβολοσειρά είναι prop.
  • Διαθέσιμο για Svelte (κανονικό), React, Vue, Angular, προσαρμοσμένο στοιχείο HTML, Nunjucks και Blazor — η ίδια σύμβαση σε καθένα.

Τα theme-picker, locale-picker και text-size-picker κατέχουν το καθένα μία προτίμηση του χρήστη από την αρχή ως το τέλος (επιλογή, εφαρμογή στο DOM, προαιρετική localStorage διατήρηση μέσω του prop storageKey ). Τα share-picker και date-time-picker είναι διαφορετικά στο είδος: το share-picker κατέχει μια ενέργεια — δεν εφαρμόζει τίποτα στο έγγραφο και δεν διατηρεί τίποτα — και το date-time-picker κατέχει μια τιμή φόρμας, αφού μια ημερομηνία σε φόρμα είναι δεδομένα και όχι προτίμηση.

locale-picker — γλώσσα και κατεύθυνση

Αφήνει τον χρήστη να διαλέξει μια τοπική ρύθμιση και μετά γράφει lang και dir στη ρίζα του εγγράφου ώστε η βιβλιοθήκη i18n, το CSS σας και οι υποστηρικτικές τεχνολογίες να την ακολουθούν όλα. Το RTL ανιχνεύεται αυτόματα για αραβικά, εβραϊκά και άλλες γραφές από δεξιά προς αριστερά. Εστιάζει καθαρά στη σηματοδότηση — τη μετάφραση την αναλαμβάνει η βιβλιοθήκη i18n σας.

<script>
  import LocalePicker from "@lilydesignsystem/svelte-locale-picker";

  let locale = $state("en-US");
</script>

<LocalePicker
  label="Language"
  locales={["en-US", "fr", "ar", "he", "ja"]}
  bind:value={locale}
  storageKey="my-app-locale"
/>

Οι επιλογές ονομάζονται από έναν ενσωματωμένο πίνακα ονομάτων τοπικών ρυθμίσεων (παρακάμπτεται μέσω localeLabels), κάθε επιλογή φέρει το δικό της χαρακτηριστικό lang ώστε τα προγράμματα ανάγνωσης οθόνης να προφέρουν το «Français» στα γαλλικά, και κωδικοί με κάτω παύλα όπως en_US μετατρέπονται χωρίς απώλεια προς και από το BCP 47 en-US. Συνδέστε το onChange (ή την δεσμευμένη τιμή) στο i18next, στο Paraglide, στο vue-i18n ή σε ό,τι χρησιμοποιείτε.

text-size-picker — μέγεθος ελεγχόμενο από τον αναγνώστη

Ένα κέρδος προσβασιμότητας που παίρνει λεπτά: ο βοηθός ορίζει το data-text-size="{slug}" στη ρίζα του εγγράφου και το CSS σας αντιστοιχίζει κάθε τιμή σε μέγεθος.

<script>
  import TextSizePicker from "@lilydesignsystem/svelte-text-size-picker";
</script>

<TextSizePicker
  label="Text size"
  sizes={["small", "medium", "large", "x-large"]}
  storageKey="my-app-text-size"
/>
:root[data-text-size="small"]   { font-size: 87.5%; }
:root[data-text-size="medium"]  { font-size: 100%; }
:root[data-text-size="large"]   { font-size: 112.5%; }
:root[data-text-size="x-large"] { font-size: 125%; }

Μετρήστε τη διάταξή σας σε rem και ολόκληρη η εφαρμογή κλιμακώνεται με την επιλογή του χρήστη. Οι ετικέτες σχηματίζονται από τα slugs με κεφαλαίο αρχικό («X Large») ή παρακάμπτονται με sizeLabels.

Ελέγξτε τη δουλειά σας: διαλέξτε «Large» από τον επιλογέα και το κείμενο της σελίδας μεγαλώνει. Επαναφορτώστε — είναι ακόμη μεγάλο: η επιλογή διατηρήθηκε στο localStorage. Αλλάξτε τον επιλογέα γλώσσας σε αραβικά και το dir="rtl" ορίζεται αυτόματα στο έγγραφο.

share-picker — στείλτε αυτή τη σελίδα

Ένα κουμπί με έναν χαρακτήρα που ανοίγει το εγγενές φύλλο κοινοποίησης της συσκευής όπου υπάρχει, και αλλιώς καταφεύγει σε μια λίστα προορισμών που εσείς παρέχετε, συν μια ενέργεια αντιγραφής του URL. Δεν αποστέλλει κανένα URL κοινωνικού δικτύου — ποια δίκτυα ανήκουν στο προϊόν σας είναι δική σας απόφαση, όχι του συστήματος σχεδιασμού.

<script>
  import SharePicker from "@lilydesignsystem/svelte-share-picker";

  const targets = [
    { id: "mastodon", label: "Mastodon",
      href: (url, title) => `https://mastodon.social/share?text=${encodeURIComponent(title)}%20${encodeURIComponent(url)}` },
    { id: "email", label: "Email",
      href: (url, title) => `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(url)}`, newTab: false },
  ];
</script>

<SharePicker
  label="Share this page"
  title="An article worth reading"
  {targets}
  copyLabel="Copy link"
  copiedLabel="Link copied"
/>

url έχει προεπιλογή το location.hrefοπότε η συνηθισμένη περίπτωση δεν χρειάζεται καλωδίωση. Επιβάλετε μια διαδρομή με strategy="list" ή strategy="native" όταν χρειάζεστε συνεπή συμπεριφορά σε όλες τις πλατφόρμες για δοκιμές ή στιγμιότυπα οθόνης.

date-time-picker — μια ημερομηνία, μια ώρα ή και τα δύο

Ένα πεδίο κειμένου στο οποίο μπορείτε να πληκτρολογήσετε, συν ένα κουμπί-εικονίδιο που ανοίγει διάλογο επιλογής ημερομηνίας WAI-ARIA APG. Σωστό ως προς την τοπική ρύθμιση εκ κατασκευής — τα ονόματα μηνών, τα ονόματα ημερών, η πρώτη ημέρα της εβδομάδας και το ρολόι 12 ή 24 ωρών προέρχονται όλα από το Intl — και η τιμή είναι πάντα μια ταξινομήσιμη συμβολοσειρά ISO χωρίς ζώνη ώρας: "2026-03-15" για το mode="date", "09:30" για το mode="time", "2026-03-15T09:30" για το mode="datetime".

<script>
  import DateTimePicker from "@lilydesignsystem/svelte-date-time-picker";

  let appointment = $state("");
</script>

<DateTimePicker
  inputId="appointment"
  name="appointment"
  label="Choose an appointment date"
  locale="en-GB"
  bind:value={appointment}
  labels={{
    previousYear: "Previous year",
    previousMonth: "Previous month",
    nextMonth: "Next month",
    nextYear: "Next year",
    confirm: "OK",
    cancel: "Cancel",
  }}
/>

Η τιμή ISO είναι πανομοιότυπη με αυτήν που στέλνει το <input type="date"> ώστε να μπορείτε να εναλλάσσετε το εγγενές στοιχείο ελέγχου χωρίς να αγγίξετε το backend.

motion-picker — σεβαστείτε τη μειωμένη κίνηση

Ο βοηθός ορίζει το data-motion="{slug}" στη ρίζα του εγγράφου. Η πρώτη του τιμή προέρχεται από τη ρύθμιση prefers-reduced-motion του λειτουργικού συστήματος του επισκέπτη — πάντα, χωρίς σημαία συμμετοχής, επειδή η κίνηση είναι πραγματική ανάγκη προσβασιμότητας (WCAG 2.3.3). Το CSS και τα σενάριά σας αποφασίζουν τι καταστέλλεται.

<script>
  import MotionPicker from "@lilydesignsystem/svelte-motion-picker";
</script>

<MotionPicker
  label="Motion"
  motions={["no-preference", "reduce"]}
  storageKey="my-app-motion"
/>
:root[data-motion="reduce"] *,
:root[data-motion="reduce"] *::before,
:root[data-motion="reduce"] *::after {
  animation: none !important;
  transition: none !important;
  scroll-behavior: auto !important;
}

search-picker — ένα πλαίσιο αναζήτησης που δεν εμποδίζει

Ένα κουμπί-εικονίδιο που ανοίγει πεδίο αναζήτησης. Το πάτημα του Return, ή του κουμπιού ⏎ δίπλα στο πεδίο, πλοηγεί με ένα απλό αίτημα GET στο /?<text> (το κείμενο κόβεται στα άκρα και κωδικοποιείται ως URI· ένα κενό ερώτημα δεν πηγαίνει πουθενά). Τα τρία προσβάσιμα ονόματά του είναι υποχρεωτικά, επειδή ο βοηθός δεν αποστέλλει αγγλικά.

<script>
  import SearchPicker from "@lilydesignsystem/svelte-search-picker";
  import { goto } from "$app/navigation";
</script>

<SearchPicker
  label="Search this site"
  inputLabel="Search terms"
  submitLabel="Search"
  placeholder="Search…"
  action="/search"
  navigate={(href) => goto(href)}
/>

action αλλάζει τη διαδρομή (/search?foo), και το navigate κρατά την πλοήγηση μέσα στην εφαρμογή· χωρίς αυτό ο βοηθός καλεί το location.assign.

picker-bar — ολόκληρη η γραμμή κεφαλίδας μαζί

picker-bar αποδίδει αναζήτηση, θέμα, τοπική ρύθμιση, μέγεθος κειμένου και κοινοποίηση σε μία γραμμή, με το πλήρες σύνολο θεμάτων αναφοράς και την επταβάθμια κλίμακα κειμένου προ-συνδεδεμένα. Κάθε προσβάσιμο όνομα έρχεται σε ένα υποχρεωτικό αντικείμενο labels .

<script>
  import PickerBar from "@lilydesignsystem/svelte-picker-bar";
</script>

<PickerBar
  labels={{
    search: "Search", searchInput: "Search terms", searchSubmit: "Search",
    theme: "Theme", locale: "Language", textSize: "Text size", share: "Share",
  }}
  themesUrl="/themes/"
  locales={["en", "fr", "es"]}
  shareTargets={targets}
/>

Φτάστε σε οποιονδήποτε τυλιγμένο επιλογέα με searchProps, themeProps, localeProps, textSizeProps και shareProps.

Τα εργαλεία συμβουλών είναι ενσωματωμένα

Κάθε επιλογέας δείχνει την ετικέτα του σε ένα εργαλείο συμβουλής όταν ο δείκτης ακουμπά στο κουμπί του ή το κουμπί έχει εστίαση πληκτρολογίου. Το εργαλείο συμβουλής μένει όσο ο δείκτης μετακινείται πάνω του, το Escape το κλείνει όπου κι αν βρίσκεται η εστίαση, και δεν εμφανίζεται ποτέ όσο το αναδυόμενο του επιλογέα είναι ανοιχτό. Φέρει το ίδιο κείμενο με το προσβάσιμο όνομα του κουμπιού, οπότε δεν υπάρχει τίποτα να ρυθμίσετε ούτε να μεταφράσετε δύο φορές· τα θέματα αναφοράς το μορφοποιούν.

Ένας πίνακας ρυθμίσεων σε ένα σημείο

Οι τέσσερις βοηθοί προτιμήσεων συνθέτονται φυσικά:

<fieldset class="fieldset">
  <legend>Preferences</legend>
  <ThemePicker    label="Theme"     themesUrl="/themes/" themes={themes} storageKey="pref-theme" />
  <LocalePicker   label="Language"  locales={locales}    storageKey="pref-locale" />
  <TextSizePicker label="Text size" sizes={sizes}        storageKey="pref-text-size" />
  <MotionPicker   label="Motion"    motions={motions}    storageKey="pref-motion" />
</fieldset>

Επαληθεύτηκε: τα αποσπάσματα των locale-picker, text-size-picker, share-picker, date-time-picker και του συνδυασμένου πίνακα μεταγλωττίστηκαν ξεχωριστά απέναντι στα δημοσιευμένα 0.1.1 πακέτα, μέσω svelte/server (2026-08-29)· τα αποσπάσματα των motion-picker, search-picker και picker-bar αποδόθηκαν απέναντι στα ίδια τα στοιχεία των πακέτων στις 2026-10-06.

Πού θα τα βρείτε

# one directory per package in the monorepo, e.g.
git clone https://github.com/LilyDesignSystem/lily-design-system
cd lily-design-system/lily-design-system-svelte-theme-picker
# or lily-design-system-react-theme-picker, -vue- / -angular- / -html- / -web-components- / -nunjucks- / -blazor-

Κάθε πακέτο έχει το δικό του spec, δοκιμές αντιστοιχισμένες στις ρήτρες του spec, εκτελέσιμα παραδείγματα (συμπεριλαμβανομένων μοτίβων cookie για SSR) και αγωγό δόμησης + δημοσίευσης. Τα πακέτα Svelte είναι τα κανονικά· σε περίπτωση αμφιβολίας, οι συμβάσεις τους κερδίζουν.

Επόμενα βήματα

Ερωτήσεις στην πορεία; Η σελίδα βοήθειας είναι γεμάτη απαντήσεις — και αν ένα βήμα μπορεί να γίνει πιο σαφές, πείτε μας και θα βελτιώσουμε με χαρά τον οδηγό.