ជំនួយការចំណូលចិត្ត

កញ្ចប់តូចៗប្រាំពីរក្នុងមួយក្របខណ្ឌ នីមួយៗជាម្ចាស់ការងារអ្នកប្រើមួយពីដើមដល់ចប់ បូករបារដែលផ្គុំប្រាំក្នុងចំណោមពួកវា។ អ្នកបានជួប theme-pickerរួចហើយ; នេះគឺ locale-picker, text-size-picker និង motion-picker (ចំណូលចិត្ត), share-picker និង search-picker (សកម្មភាព), date-time-picker (តម្លៃទម្រង់) និង picker-bar។

អ្វីដែលអ្នកនឹងសាងសង់

បន្ទះការកំណត់ដែលអ្នកប្រើជ្រើសរើសភាសា និងទំហំអក្សររបស់ពួកគេ — ជម្រើសដែលអនុវត្តលើឯកសារទាំងមូល ស្ថិតស្ថេររវាងការទស្សនា និងអស់សមាសភាគពីរ និង CSS ប៉ុន្មានជួរ។ ប្រហែល ១៥ នាទី។

មុនពេលអ្នកចាប់ផ្តើម

បញ្ចប់ មេរៀនក្របខណ្ឌ សម្រាប់ស្ទែករបស់អ្នក។ គំរូខាងក្រោមជា Svelte; ជំនួយការ React, Vue, Angular, HTML, Nunjucks និង Blazor ត្រូវគ្នាកិច្ចសន្យាដោយកិច្ចសន្យា។

រូបរាងដែលពួកវាចែករំលែក

  • ប៊ូតុងរូបតំណាងគ្មានក្បាលដែលបើកប្រអប់បញ្ជី WAI-ARIA APG (ឬសម្រាប់ date-time-picker ប្រអប់ជ្រើសកាលបរិច្ឆេទ) — គ្មានដើម <select>ដូច្នេះក្របខណ្ឌនីមួយៗទទួលបានអាកប្បកិរិយាក្តារចុច និង hook រចនាប័ទ្មដូចគ្នា។
  • class hook មួយក្នុងមួយកញ្ចប់ (.locale-picker, .text-size-picker, .share-picker, .date-time-picker), CSS សូន្យត្រូវបានដឹកជញ្ជូន។
  • សុវត្ថិភាព SSR៖ ការសរសេរ DOM កើតឡើងតែក្នុងវដ្តជីវិត mount/effect ប៉ុណ្ណោះ។
  • ស្អាតចំពោះ i18n៖ អក្សរនីមួយៗដែលអ្នកប្រើមើលឃើញជាលក្ខណៈសម្បត្តិ។
  • មានសម្រាប់ Svelte (ស្តង់ដារ) React, Vue, Angular, ធាតុផ្ទាល់ខ្លួន HTML, Nunjucks និង Blazor — កិច្ចសន្យាដូចគ្នាក្នុងនីមួយៗ។

theme-picker, locale-picker និង text-size-picker នីមួយៗជាម្ចាស់ ចំណូលចិត្ត អ្នកប្រើមួយពីដើមដល់ចប់ (ការជ្រើសរើស ការអនុវត្ត DOM ជាជម្រើស localStorage ភាពស្ថិតស្ថេរ 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 ហើយកម្មវិធីទាំងមូលធ្វើមាត្រដ្ឋានតាមជម្រើសរបស់អ្នកប្រើ។ ស្លាកត្រូវបានធ្វើជាអក្សរធំពី slug (“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។ ត្រឹមត្រូវតាមតំបន់ភាសាតាមការរចនា — ឈ្មោះខែ ឈ្មោះថ្ងៃក្នុងសប្តាហ៍ ថ្ងៃដំបូងនៃសប្តាហ៍ និងនាឡិកា ១២ ឬ ២៤ ម៉ោង ទាំងអស់មកពី 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 ជាស្តង់ដារ; នៅពេលសង្ស័យ កិច្ចសន្យារបស់ពួកវាឈ្នះ។

ជំហានបន្ទាប់

មានសំណួរតាមផ្លូវ? ទំព័រជំនួយ ពេញដោយចម្លើយ — ហើយប្រសិនបើជំហានណាអាចច្បាស់ជាងនេះ ប្រាប់យើង ហើយយើងនឹងកែលម្អមេរៀនដោយអំណរ។