Skip to content

Συστατικά ​

@pantoken/components παρέχει στυλ συστατικών βασισμένα σε κλάσεις που δημιουργούνται από τα tokens της Instructure. Εισάγετε το stylesheet και επισημάνετε το markup — δεν απαιτείται πλαίσιο.

ts
import "@pantoken/components/components.css";

[!ΣΗΜΕΙΩΣΗ] Προτιμάτε προσαρμοσμένα στοιχεία; @pantoken/web-components τυλίγει τα ίδια στυλ ως <instui-button>, <instui-alert>, <instui-badge>, <instui-avatar>, <instui-progress> και άλλα — δείτε τον χάρτη πακέτου.

Συμβάσεις ​

Οι συμβάσεις CSS σε αυτό το πακέτο βασίζονται σε τροποποιημένη έκδοση του RSCSS.

Οι τροποποιητές είναι key-value — -<prop>-<val>, ευθυγραμμισμένοι με τα ονόματα props του InstUI — έτσι διαβάζονται αυτόνομα: -color-secondary, -size-sm, -shape-circle, -icon-plus. Τα boolean props είναι μόνο το όνομα του prop, όπου η παρουσία σημαίνει true (-has-shadow, -clickable); ένα default-on boolean που απενεργοποιείται αντιστρέφει (-without-background, -without-border). Τα μεγέθη δέχονται σύντομες και μακρές ονομασίες (-size-sm = -size-small). Όταν ένα όνομα αποκλίνει από το InstUI, η σημασιολογική κλάση InstUI εξακολουθεί να λειτουργεί αλλά είναι καταργημένη (π.χ. -variant-info → χρησιμοποιήστε -color-info).

Παράδειγμα ​

Instructure UI React component:

jsx
<Alert variant="success" transition="fade" hasShadow renderCustomIcon={megaphone}>
  This is the alert content.
</Alert>

pantoken components:

html
<!-- direct instui props -->
<div
  class="instui-alert -variant-success instui-transition -fade-entered -has-shadow -render-custom-icon-megaphone"
>
  This is the alert content.
</div>

<!-- normalized color/icon props -->
<div
  class="instui-alert -color-success instui-transition -fade-entered -has-shadow -icon-megaphone"
>
  This is the alert content.
</div>

Για το prop timeout του InstUI, ορίστε την unitless --timeout custom property σε milliseconds και φορτώστε την αλληλεπίδραση Alert. Μια θετική τιμή προγραμματίζει την απόρριψη· 0 (το προεπιλεγμένο) αφήνει το alert στη θέση του. Προσθέστε τις κλάσεις instui-transition -fade-entered του utility transition για το fade του InstUI· παραλείψτε αυτές για άμεση αφαίρεση. Η αλληλεπίδραση χειρίζεται την κατάσταση -fade-exiting και πυροδοτεί ένα ακυρώσιμο, φυσαλίδα dismiss event πριν από την αφαίρεση, ώστε μια εφαρμογή να μπορεί να καλέσει preventDefault() για να κρατήσει το alert τοποθετημένο.

html
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@pantoken/components/dist/utilities.css"
/>
<div
  class="instui-alert -color-info instui-transition -fade-entered"
  style="--timeout: 5000"
  role="alert"
>
  This alert dismisses after five seconds.
</div>
<script src="https://cdn.jsdelivr.net/npm/@pantoken/interactions/dist/alert.iife.js"></script>

Οι μπάρες προόδου δέχονται αυθαίρετες κλίμακες μέσω --min (0 εξ ορισμού), --value και --max (100 εξ ορισμού), με καταργημένα aliases --value-now και --value-max. Προσθέστε -should-animate για να εφαρμόσετε τη μισο-δευτερόλεπτη μετάβαση του InstUI κάθε φορά που αλλάζει μια τιμή. Το .value βρίσκεται παράλληλα με το .bar ως παιδί της ρίζας· προσθέστε -render-value-inside για να το αποδώσετε πάνω από τη διαδρομή, ευθυγραμμισμένο στην αρχή του, αντίθετα (στοιχειοθετήστε το για αναγνωσιμότητα σε σχέση με το χρώμα του μετρητή). Χρησιμοποιήστε ένα native <progress> για zero-based εύρος και <meter> όταν το minimum δεν είναι μηδέν· τα web components επιλέγουν αυτόματα μεταξύ τους από το min attribute. Το InstUI δεν έχει indeterminate κατάσταση, οπότε ένα <progress> χωρίς το value attribute είναι μια μόνο-του-pantoken καλύτερη εκτίμηση: progress-bar ανιματίζει .bar ως συρόμενο τμήμα και progress-circle περιστρέφει το δακτύλιο σε σταθερή γωνία, κρύβοντας και τα δύο το .value.

html
<label>
  Uploading Document:
  <progress
    class="instui-progress -color-brand -should-animate"
    style="--value: 40; --max: 60"
    value="40"
    max="60"
  >
    40 of 60
  </progress>
</label>

Οι κύκλοι προόδου δέχονται τις ίδιες αυθαίρετες κλίμακες μέσω --min, --value και --max. --value-now και --value-max παραμένουν ως καταργημένα λειτουργικά aliases. Προσθέστε -should-animate και φορτώστε το focused interaction bundle για να αναπαράγετε την mount animation του InstUI· το --animation-delay είναι μια unitless καθυστέρηση σε milliseconds. Οι καταργημένες ορθογραφίες -should-animate-on-mount και -shold-animate-on-mount παραμένουν λειτουργικά aliases.

html
<label for="upload-progress">Uploading Document</label>
<progress
  id="upload-progress"
  class="instui-progress-circle -should-animate"
  style="--value: 40; --max: 60; --animation-delay: 500"
  value="40"
  max="60"
>
  40 of 60
</progress>
<script src="https://cdn.jsdelivr.net/npm/@pantoken/interactions/dist/progress-circle.iife.js"></script>

Πρόθεμα κλάσης ​

Κάθε κλάση ονομάζεται namespace instui- εξ ορισμού. Δημιουργήστε ένα stylesheet με το δικό σας πρόθεμα — ή κανένα — περνώντας prefix σε οποιονδήποτε builder. Οποιαδήποτε falsy τιμή (null, undefined, "", ή παράλειψή της) αφαιρεί το πρόθεμα εντελώς, ώστε να μπορείτε να γράψετε class="heading -level-h1" αντί για class="instui-heading -level-h1":

ts
import { componentsCss } from "@pantoken/components";

componentsCss({ prefix: "ui" }); // .ui-button
componentsCss({ prefix: null }); // .button, .alert — no prefix

Οι τροποποιητές με προθεματικό παύλα (.-color-secondary, .-level-h1) παραμένουν αμετάβλητοι σε κάθε περίπτωση. Τα stylesheets που παρέχει το πακέτο διατηρούν το πρόθεμα instui.

Βάση ​

base.css είναι ένα opt-in reset που ορίζει global defaults εγγράφου από τα tokens: box-sizing, ένα reset body, η επιφάνεια της σελίδας, το βασικό χρώμα κειμένου και γραμματοσειρά, color-scheme (ώστε τα light-dark() tokens και οι native ελέγχοι να ακολουθούν το θέμα), και ένας βασικός σύνδεσμος. Φορτώστε το μία φορά, πριν από τα component και prose sheets, όταν το pantoken διαχειρίζεται τη σελίδα.

ts
import "@pantoken/components/base.css";
import "@pantoken/components/components.css";

Παραλείψτε το όταν ενσωματώνετε συστατικά σε έναν host που ήδη θεματίζει τα δικά του html και body — το reset βάφει την επιφάνεια της σελίδας, οπότε δεν θέλετε να αντιπαρατεθεί με τον host. Όλα όσα ορίζει χρησιμοποιούν χαμηλής ειδικότητας :where() selectors, έτσι οι δικοί σας κανόνες κερδίζουν πάντα.

base.css εφαρμόζει τη γραμματοσειρά brand (font-family: var(--instui-font-family-base), με system fallbacks); για να την φορτώσετε, εισάγετε το opt-in fonts.css — @font-face κανόνες για Atkinson Hyperlegible Next, που δείχνουν τα woff2s που παρέχονται στο πακέτο. Είναι ξεχωριστό επειδή τα fonts είναι ~350 kB και η self-hosting των γραμματοσειρών είναι συνειδητή επιλογή.

ts
import "@pantoken/components/base.css"; // applies the font (falls back to system without fonts.css)
import "@pantoken/components/fonts.css"; // loads the Atkinson Hyperlegible Next woff2s

Περιεχόμενο για οθόνη ανάγνωσης (screen reader) ​

Υπάρχει ένα κρυφό μήνυμα μετά από αυτή την πρόταση.Μόνο οι screen readers ανακοινώνουν αυτό.

html
<span class="instui-screen-reader-content">Only screen readers announce this.</span>

.instui-screen-reader-content κρύβει ένα στοιχείο οπτικά ενώ το διατηρεί στο accessibility tree — για ετικέτες και κείμενα κατάστασης που πρέπει να διαβάζει η βοηθητική τεχνολογία αλλά ο σχεδιασμός δεν πρέπει να εμφανίζει.

Utilities ​

utilities.css είναι ένα opt-in στρώμα cross-cutting κλάσεων: ένα primitive View, spacing στην κλίμακα token, και σημασιολογικές υπερισχύσεις χρώματος. Σε αντίθεση με τις component -modifier κλάσεις, αυτές χρησιμοποιούν double dash (--mod) ώστε ποτέ να μην συγκρούονται με τα ονόματα τροποποιητών του component, και εφαρμόζονται σε οποιοδήποτε στοιχείο — γυμνό, ή συνθετικό πάνω σε ένα component.

ts
import "@pantoken/components/utilities.css";
Επιφάνεια accent-blue με κείμενο on-color.
Κεντραρισμένο με mx-auto.
html
<div class="instui-view --bg-accent-blue --text-on-color --p-md">…</div>
<div class="instui-view --bg-muted --p-sm --mx-auto">…</div>

View — .instui-view είναι το View του InstUI. Είναι η βάση πάνω στην οποία στοιβάζετε spacing και χρώμα, και φέρει key-value τροποποιητές για τα δικά του οπτικά props ώστε να μην χρειάζεται να φτάσετε στα utilities: -background-* (τις επιφάνειές του), -border-radius-{small,medium,large,circle,pill}, -border-width-{small,medium,large} + -border-color-*, -shadow-{resting,above,topmost}, -display-*, -position-*, -overflow-x-*/-overflow-y-*, και -cursor-* — αυτά είναι οι δικοί του single-dash τροποποιητές, ανεξάρτητοι από τα double-dash utilities παρακάτω. Οι props ελεύθερης τιμής (width/height/inset) παραμένουν inline styles· margin/padding χρησιμοποιούν τα spacing utilities.

Spacing — κλάσεις ανά πλευρά στην κλίμακα spacing. Διαβάζονται ως {m|p}{side}-{step}: m για margin ή p για padding (ή οι πλήρεις λέξεις margin/padding), μια προαιρετική λογική πλευρά, και μετά ένα βήμα. Έτσι .--m-lg και .--margin-lg είναι το ίδιο, όπως και .--pt-md και .--paddingt-md.

  • Πλευρές: none (όλες), t/b (block start/end), s/e (inline start/end), x/y (inline/block axis). Οι λογικές πλευρές παραμένουν σωστές σε layouts δεξιά-προς-αριστερά.
  • Βήματα: 0, 2xs, xs, sm, md, lg, xl, 2xl, συν auto μόνο για margin.

Συνθέστε τα για το shorthand margin="small auto large" του InstUI: class="--mt-sm --mx-auto --mb-lg".

Color — σημασιολογικές υπερισχύσεις που παραμένουν εντός παλέτας: .--bg-<name> (background), .--text-<name> (χρώμα κειμένου), και .--border-<name> (χρώμα περιγράμματος). Κάθε <name> είναι ένα σημασιολογικό token χρώματος — τα intents (base, brand, muted, success, warning, error, info, inverse, on-color, strong, …) καθώς και η παλέτα accent-* (accent-blue, accent-green, κ.λπ.). Ένα όνομα υπάρχει μόνο αν το token υπάρχει στην οικογένεια, οπότε text-brand δεν είναι κλάση — το κείμενο δεν έχει brand token. Δεν υπάρχει τρόπος να φτάσετε σε primitive ή αυθαίρετο hex, και κάθε υπερισχύση ακολουθεί το θέμα.

Οικογένειες token — κάθε οικογένεια "ένα token, μία ιδιότητα" έχει μια κλάση ανά token, ονομασμένη μετά το token. Συνθέστε τα ελεύθερα:

  • .--font-family-heading, .--font-family-code, … → font-family
  • .--font-weight-body-strong, .--font-weight-interactive, … → font-weight
  • .--line-height-* → line-height
  • .--border-radius-md, .--border-radius-full, … → border-radius
  • .--border-width-sm/-md/-lg → border-width
  • .--opacity-base, .--opacity-disabled → opacity
  • .--elevation-resting/-above/-topmost (και -depth1…-card) → box-shadow

Κάθε μία ορίζει μόνο την ιδιότητά της, οπότε border-width/border-radius χρειάζονται ένα border-* χρώμα και ένα border style για να σχεδιάσουν πραγματικά ένα περίγραμμα. Αυτές χρησιμοποιούν το πλήρες όνομα token (.--border-radius-md), ενώ τα helpers χρώματος και spacing παραπάνω χρησιμοποιούν μικρές συντομεύσεις (.--bg-brand, .--mt-lg) — οι συντομεύσεις είναι εργονομικά shortcuts· οι κλάσεις token είναι κυριολεκτικές και εξαντλητικές.

Διάταξη — .--display-<value> (block, inline-block, inline, flex, inline-flex, none) και .--text-align-<value> (start, center, end, justify) καλύπτουν τα διασταυρούμενα display και textAlign props του InstUI (View, Button, Metric, Tabs, …) ως συνθέσιμες κλάσεις — οπότε αυτά δεν είναι τροποποιητές ανά-component.

Κάθε double-dash κλάση κερδίζει την cascade με καθοριστικό τρόπο έναντι ενός component modifier με ίδιο όνομα, ανεξάρτητα από τη σειρά εισαγωγής του stylesheet — δείτε τις Συμβάσεις Authoring για τον μηχανισμό.

Όλα εδώ είναι καθαρό CSS που οδηγείται από τα --instui-* tokens, οπότε ακολουθεί το InstUI μέσω του layer των token. Δείτε το API reference για componentsCss και τους per-component builders.

Overlays: διάλογος και popover ​

Τα συστατικά overlay χρησιμοποιούν native platform primitives, οπότε συμπεριφέρονται προσβάσιμα με λίγη ή καθόλου JavaScript.

Modal — βάλτε .instui-modal σε ένα native <dialog>. Παίρνει trapping focus, Esc-to-close, και ένα ::backdrop δωρεάν· το backdrop σκοτεινιάζει με το ίδιο token --instui-component-mask-background-color όπως το .instui-mask (προσθέστε -blur για frost). Ανοίξτε και κλείστε με invoker commands — χωρίς script:

html
<button class="instui-button" command="show-modal" commandfor="dlg">Open</button>
<dialog id="dlg" class="instui-modal">
  <div class="header">Title</div>
  <div class="body">…</div>
  <div class="footer">
    <button class="instui-button" command="close" commandfor="dlg">Close</button>
  </div>
</dialog>

Context view / popover — βάλτε .instui-context-view σε ένα στοιχείο [popover] και εναλλάξτε το με popovertarget. Καλύπτει το πάνω στρώμα και κλείνει με light-dismiss σε κλικ έξω ή Esc, και πάλι χωρίς script:

html
<button class="instui-button" popovertarget="cv">Details</button>
<div id="cv" popover class="instui-context-view">…</div>

Drawer layout — βάλτε .instui-drawer-layout σε μια ρίζα διάταξης με .tray και .content παιδιά. Προσθέστε το attribute open (ή -open) για να αποκαλύψετε το tray, και χρησιμοποιήστε placement="end" (ή -placement-end) για να το εσωκλείσετε στην inline-end πλευρά — η τοποθέτηση επιλύεται μέσω λογικών inset-inline-*/flex-direction ιδιοτήτων, οπότε αναστρέφεται αυτόματα υπό dir="rtl" χωρίς επιπλέον κανόνες. Το focused interaction bundle προσθέτει routing εντολών Invoker και εναλλάσσει το overlay mode (should-overlay-tray) όταν το πλάτος διασχίζει --drawer-layout-min-width (προεπιλεγμένο --instui-breakpoints-sm, μετά 30rem):

html
<button class="instui-button" command="--toggle" commandfor="drawer">Toggle panel</button>
<div id="drawer" class="instui-drawer-layout" open>
  <aside class="tray">…</aside>
  <main class="content" role="region">…</main>
</div>
<script src="https://cdn.jsdelivr.net/npm/@pantoken/interactions/dist/drawer-layout.iife.js"></script>

Mask — .instui-mask μένει για in-flow overlays (ένας spinner πάνω σε κάρτα); το ::backdrop ενός modal καλύπτει την περίπτωση modal.

Και τα δύο μοτίβα τυλίγονται επίσης ως συμπεριφορικά custom elements σε @pantoken/web-components: <instui-modal open> (ένα <dialog> που ελέγχεται από το open attribute του) και <instui-context-view> (ένα native popover).

Υποστήριξη προγραμμάτων περιήγησης: το popover API και το popovertarget είναι Baseline 2024; οι invoker commands (command/commandfor) είναι Baseline 2025, οπότε σε παλαιότερα προγράμματα δέστε τα κουμπιά σε dialog.showModal() ως fallback μιας γραμμής. Τοποθέτηση popover δίπλα στο trigger χρησιμοποιεί CSS anchor positioning όπου υποστηρίζεται (Chromium); αλλού κεντράρεται στο πάνω στρώμα.

Φόρμες ​

FormField — .instui-form-field είναι ένα wrapper CSS-Grid που τοποθετεί μια ετικέτα, τον έλεγχο και τυχόν μηνύματα. Βάλτε το σε ένα <label> ώστε η ετικέτα να συνδεθεί με τον έλεγχο εγγενώς. Έχει τρεις περιοχές grid — label, controls, messages:

html
<label class="instui-form-field">
  <span class="label">Email address</span>
  <span class="controls"><input class="instui-text-input" type="email" required /></span>
  <div class="instui-form-field-messages">
    <span class="instui-form-field-message -type-hint">We'll never share it.</span>
  </div>
</label>

-layout-stacked (προεπιλογή) στοιβάζει τις περιοχές· -layout-inline βάζει την ετικέτα δίπλα στον έλεγχο (ρυθμίστε με -label-align-{start,end} και -v-align-{top,middle,bottom}). -readonly αναχρωματίζει την ετικέτα.

Το αστεράκι απαιτούμενου εμφανίζεται όταν το πεδίο είναι υποχρεωτικό είτε από την κλάση -required ή από ένα native required control μέσα του — έτσι μπορείτε απλά να ορίσετε required στο input και το σημάδι εμφανίζεται. Είναι διακοσμητικό (ένα ::after στην ετικέτα, έξω από το accessibility tree); συνοδέψτε το με σημείωση όπως "πεδία με * είναι υποχρεωτικά" εκτός αν η φόρμα είναι αυτονόητη.

FormFieldGroup — .instui-form-field-group ομαδοποιεί σχετικά πεδία σε ένα <fieldset> με μια περιγραφή <legend>. Είναι καθαρή διάταξη (χωρίς αφιερωμένα tokens): η προεπιλογή στοιβάζει τα πεδία; -layout-columns / -layout-inline τα ρέουν σε responsive στήλες, με -row-spacing-* / -col-spacing-* και -v-align-* για tuning του grid.

RadioInputGroup — .instui-radio-input-group είναι η ίδια <fieldset>/<legend> ομαδοποίηση, ειδική για radios. Επειδή τα παιδικά radios μοιράζονται ένα name, η επιλογή είναι εγγενώς μονο-επιλογής — οπότε ένα σετ toggle buttons συμπεριφέρεται ως ένας έλεγχος, όχι χαλαρά κουμπιά. -variant-simple (προεπιλογή) τοποθετεί τυπικά radios (-layout-columns/-inline τα ρέουν σε σειρά); -variant-toggle συνδέει τα παιδικά .instui-radio.-variant-toggle κουμπιά σε έναν ενιαίο segmented έλεγχο (συμπιεσμένα περιγράμματα, στρογγυλεμένα εξωτερικά άκρα):

html
<fieldset class="instui-radio-input-group -variant-toggle">
  <legend>T-shirt size</legend>
  <label class="instui-radio -variant-toggle"
    ><input type="radio" name="size" checked /> Small</label
  >
  <label class="instui-radio -variant-toggle"><input type="radio" name="size" /> Medium</label>
  <label class="instui-radio -variant-toggle"><input type="radio" name="size" /> Large</label>
</fieldset>

Μηνύματα — .instui-form-field-messages είναι το container; κάθε .instui-form-field-message παίρνει ένα -type-*: -type-hint (γκρι, προεπιλογή), -type-error (κόκκινο κείμενο + glyph κύκλου- συναγερμού), -type-success (πράσινο κείμενο + glyph κύκλου-επιβεβαίωσης), και -type-screenreader-only (οπτικά κλιπαρισμένο, εξακολουθεί να ανακοινώνεται). Τα glyphs χρωματίζονται σε currentColor, έτσι ταιριάζουν πάντα με το χρώμα του μηνύματος. -type-new-error είναι καταργημένο alias του -type-error. Συνδέστε το container με τον έλεγχο με aria-describedby, και ορίστε aria-invalid στον έλεγχο όταν υπάρχει σφάλμα.

Μέσα σε ένα FormField, ένα -type-error μήνυμα ακολουθεί την client-side επικύρωση: μένει κρυφό έως ότου ο έλεγχος του πεδίου είναι :user-invalid (εγγενές, μετά την αλληλεπίδραση του χρήστη) — ή το αναγκάζετε με -invalid στο .instui-form-field (για σφάλμα server-side). Ένα ανεξάρτητο .instui-form-field-messages (όχι σε πεδίο) δεν επηρεάζεται. Ο δακτύλιος εστίασης του ελέγχου ακολουθεί: danger όταν :user-invalid/-invalid, success σε -success.

Κείμενα ελέγχων — .instui-text-input (native <input>), .instui-text-area (native <textarea>, resizable), και .instui-simple-select (native <select> με caret) μοιράζονται μια εμφάνιση και τις ίδιες καταστάσεις: -invalid (περίγραμμα σφάλματος), -success (περίγραμμα επιτυχίας), -readonly, native :disabled, και -size-{sm,md,lg}. Για leading/trailing icon (InstUI's renderBeforeInput/renderAfterInput), τυλίξτε το input σε .instui-input-group και προσθέστε μια θέση .before/.after (ένα glyph -icon-*); -should-not-wrap το κρατά σε μία γραμμή. .instui-number-input είναι αυτό το facade μαζί με μια .arrows +/- στήλη spinner (native type="number"; δεστε τα κουμπιά σε stepUp()/stepDown()). .instui-range-input είναι ένα styled input[type="range"] της οποίας η τιμή εμφανίζεται σε ένα .instui-range-input-value αντίστροφο bubble. Για ένα πλούσιο combobox με listbox popover, χρησιμοποιήστε @instructure/ui — αυτή η βιβλιοθήκη καλύπτει τους native ελέγχους.

Styled select dropdown (πειραματικό) — ένα opt-in select.css αναβαθμίζει το ίδιο στοιχείο .instui-simple-select: στιλιζάρει το ανοιχτό dropdown (το πάνελ και κάθε επιλογή, με hover και selected καταστάσεις) χρησιμοποιώντας το CSS Customizable Select μοντέλο.

[!ΠΡΟΕΙΔΟΠΟΙΗΣΗ] select.css βασίζεται σε appearance: base-select / ::picker(select), τα οποία είναι πειραματικά (Chrome 135+, όχι ακόμη Baseline). Παρέχεται ως ξεχωριστό opt-in sheet και κάθε κανόνας φρουρείται πίσω από @supports (appearance: base-select), οπότε δεν κάνει τίποτα σε μη υποστηριζόμενα προγράμματα — το .instui-simple-select control απλώς παραμένει το απλό native select. Φορτώστε το μόνο αν θέλετε το ενισχυμένο dropdown και αποδέχεστε την περιορισμένη υποστήριξη.

ts
import "@pantoken/components/components.css";
import "@pantoken/components/select.css"; // opt-in, experimental: styles the open dropdown