---
title: "स्केलेटन"
description: "लोड होने के दौरान उस जगह रहता है जहाँ कॉन्टेंट आएगा। आने वाली चीज़ के आकार के हल्के प्लेसहोल्डर (टेक्स्ट की लाइनें, एक ब्लॉक, एक गोला) वह बॉक्स थामे रखते हैं जो कॉन्टेंट लेगा, ताकि उसके आने पर कुछ न खिसके।"
url: "https://tanrei.chnotchy.com/hi/components/skeleton/"
last_updated: 2026-10-23T21:17:12.000Z
---

# स्केलेटन

> लोड होने के दौरान उस जगह रहता है जहाँ कॉन्टेंट आएगा। आने वाली चीज़ के आकार के हल्के प्लेसहोल्डर (टेक्स्ट की लाइनें, एक ब्लॉक, एक गोला) वह बॉक्स थामे रखते हैं जो कॉन्टेंट लेगा, ताकि उसके आने पर कुछ न खिसके।

## अवलोकन

व्यू अक्सर अपने कॉन्टेंट से पहले आ जाता है। स्केलेटन आने वाली चीज़ का आकार उसी जगह थामे रखता है जहाँ वह होगी: टेक्स्ट की लाइनें, किसी तस्वीर या कंट्रोल के लिए एक ब्लॉक, किसी व्यक्ति की तस्वीर के लिए एक गोला। कॉन्टेंट आने पर वही बॉक्स लेता है जो उसके लिए थामे गए थे, और जिसे व्यक्ति देख रहा था या दबाने वाला था, वह नहीं खिसकता।

स्केलेटन में एक रीजन और उसके प्लेसहोल्डर होते हैं। सहायक तकनीक को रीजन एक बार बताया जाता है (“प्रोजेक्ट लोड हो रहे हैं”, व्यस्त), और प्लेसहोल्डर अपने आप में कुछ नहीं बताते। दिखने से पहले वह पल भर रुकता है, ताकि छोटे इंतज़ार में झपककर आते-जाते आकारों की जगह सही साइज़ की ख़ाली जगह दिखे।

वेब पर यह `class="tanrei-skeleton-placeholder"` वाले आपके अपने एलिमेंट के चारों ओर `<tanrei-skeleton>` है। बाक़ी प्लैटफ़ॉर्म ने इसे अभी इम्प्लीमेंट नहीं किया है।

### स्केलेटन, लोडिंग इंडिकेटर, प्रोग्रेस इंडिकेटर, ख़ाली स्टेट

“यहाँ अभी कुछ नहीं है” का जवाब चार कंपोनेंट देते हैं। कौन-सा इस्तेमाल हो, यह इससे तय होता है कि इंतज़ार के बारे में और आने वाली चीज़ के बारे में क्या पता है।

| स्थिति | क्या इस्तेमाल करें | क्यों |
| --- | --- | --- |
| जाने हुए आकार का कॉन्टेंट व्यू के किसी हिस्से को भरेगा, और इंतज़ार इतना लंबा है कि दिखे। | स्केलेटन | वह लेआउट थामे रखता है, इसलिए कॉन्टेंट आने पर कुछ नहीं खिसकता, और वह दिखाता है कि चीज़ें कहाँ होंगी। |
| अनजान अवधि का छोटा इंतज़ार, जिसके नतीजे का थामने लायक़ कोई आकार नहीं है, या जिसका नतीजा छोटा है: किसी बटन, पंक्ति, फ़ील्ड या स्थिति पंक्ति में। चल रही कोई क्रिया, जैसे सेव करना या भेजना। | [लोडिंग इंडिकेटर](https://tanrei.chnotchy.com/hi/components/loading-indicator/) | एक निशान काफ़ी है। एक पंक्ति या एक आइकन के लिए आकार शोर हैं। |
| ऐसा काम जिसकी प्रगति नापी जा सकती है, या जिसमें कई सेकंड लगते हैं। | [प्रोग्रेस इंडिकेटर](https://tanrei.chnotchy.com/hi/components/progress-indicator/) | स्केलेटन यह नहीं बताता कि काम कितना आगे बढ़ा है, और कुछ सेकंड बाद व्यक्ति को यह जानना होता है। |
| कुछ नहीं आएगा: लिस्ट ख़ाली है, खोज में कुछ नहीं मिला। | [ख़ाली स्टेट](https://tanrei.chnotchy.com/hi/components/empty-state/) | स्केलेटन कॉन्टेंट का वादा करता है। |
| लोड होना विफल रहा। | उसी जगह, त्रुटि की स्थिति वाला [कॉलआउट](https://tanrei.chnotchy.com/hi/components/callout/)। | जो स्केलेटन कभी ख़त्म नहीं होता, वह झूठ है। |
| कॉन्टेंट पहले से वहाँ है, और सिर्फ़ उसकी स्क्रिप्ट, उसकी तस्वीर या उसका फ़ॉन्ट देर से आ रहा है। | चारों में से कोई नहीं। कंपोनेंट अपना बॉक्स ख़ुद थामता है। | स्केलेटन किसी दूसरे कंपोनेंट का साइज़ नहीं जानता। वह कंपोनेंट जानता है। |

### इस्तेमाल

इंतज़ार शुरू होने पर स्केलेटन को वहाँ रखें जहाँ कॉन्टेंट होगा, और इंतज़ार ख़त्म होने पर उसकी जगह कॉन्टेंट रख दें। उसे ऐसा `label` दें जो बताए कि क्या लोड हो रहा है। प्लेसहोल्डर इस क्लास वाला आपका अपना ख़ाली एलिमेंट है: एक `<span>`, जो कहीं भी हो सकता है, या एक `<div>`, जहाँ वह किसी ब्लॉक का चाइल्ड हो, जैसे किसी दूसरे `<div>` का। हेडिंग या पैराग्राफ़ के भीतर वह `<span>` होता है।

**Web**

```html
<link rel="stylesheet" href="@tanrei/web/skeleton.css" />

<!-- जो प्लेसहोल्डर स्केलेटन के अपने चाइल्ड हैं, वे गैप के साथ एक के नीचे एक रखे जाते हैं। -->
<tanrei-skeleton label="प्रोजेक्ट लोड हो रहा है">
  <span class="tanrei-skeleton-placeholder" data-shape="block" style="block-size: 160px"></span>
  <span class="tanrei-skeleton-placeholder" style="inline-size: 12.5rem"></span>
  <span class="tanrei-skeleton-placeholder" data-lines="3"></span>
</tanrei-skeleton>

<!-- इससे आगे जो भी है, वह आपका अपना लेआउट है, जिसमें प्लेसहोल्डर वहाँ हैं जहाँ कॉन्टेंट होगा। -->
<tanrei-skeleton label="लेखक का ब्योरा लोड हो रहा है">
  <div class="byline">
    <span class="tanrei-skeleton-placeholder" data-shape="circle" style="block-size: 40px"></span>
    <div>
      <h3><span class="tanrei-skeleton-placeholder" style="inline-size: 10rem"></span></h3>
      <p><span class="tanrei-skeleton-placeholder" data-lines="2"></span></p>
    </div>
  </div>
</tanrei-skeleton>

<!-- पेज के पहली बार दिखने का हिस्सा, जिसे सर्वर लिखता है: तुरंत दिखता है, और किसी भी स्क्रिप्ट से पहले सही रहता है। -->
<tanrei-skeleton show-delay="0" role="progressbar" aria-busy="true" aria-label="डैशबोर्ड लोड हो रहा है">
  …
</tanrei-skeleton>
<noscript>डैशबोर्ड के लिए JavaScript ज़रूरी है।</noscript>

<script type="module">
  import '@tanrei/web/components/skeleton';
</script>
```

**React**

```tsx
import { Skeleton } from '@tanrei/react';
import '@tanrei/web/skeleton.css';

{project ? (
  <ProjectCard project={project} />
) : (
  <Skeleton label="प्रोजेक्ट लोड हो रहा है">
    <span className="tanrei-skeleton-placeholder" data-shape="block" style={{ blockSize: 160 }} />
    <span className="tanrei-skeleton-placeholder" style={{ inlineSize: '12.5rem' }} />
    <span className="tanrei-skeleton-placeholder" data-lines={3} />
  </Skeleton>
)}
```

वेब पर, किसी भी स्क्रिप्ट के चलने से पहले, स्टाइलशीट ही पूरा कंपोनेंट है: आकार, दिखने से पहले का इंतज़ार, पल्स, जहाँ मोशन कम किया गया है वहाँ ठहराव, और फ़ोर्स्ड कलर्स की आउटलाइन। एलिमेंट वह जोड़ता है जो स्टाइलशीट नहीं कर सकती: सहायक तकनीक के लिए रोल और नाम, स्केलेटन के भीतर की चीज़ों को फ़ोकस के क्रम से बाहर रखना, और जब तक उसे देखा नहीं जा सकता तब तक रुके रहना।

## स्पेक

- Category: Communication
- Level: base
- Listing: default
- Page: https://tanrei.chnotchy.com/components/skeleton/
- Spec: https://github.com/chnotchy/tanrei/blob/main/specs/skeleton.spec.json

### Availability

| Design system | Has it | Notes |
| --- | --- | --- |
| Tanrei (`tanrei`) | Yes | — |
| Cupertino (Apple HIG-inspired) (`cupertino`) | Yes | — |
| M3 Expressive-like (Material 3 Expressive-inspired) (`m3-expressive-like`) | Yes | — |
| M3-like (Material 3-inspired) (`m3-like`) | Yes | — |

### Platforms

- Web: the element `<tanrei-skeleton>`, registered by importing `@tanrei/web` (or only its own module, `@tanrei/web/components/skeleton`).
- React: `Skeleton` from `@tanrei/react`.

| Platform | Name | Status |
| --- | --- | --- |
| Web | `tanrei-skeleton` | lagging |
| SwiftUI | `TanreiSkeleton` | planned |
| Jetpack Compose | `TanreiSkeleton` | planned |
| Flutter | `TanreiSkeleton` | planned |
| React Native | `Skeleton` | planned |

Names a platform gives in its own idiom:

| Spec | Web | SwiftUI | Jetpack Compose | Flutter | React Native |
| --- | --- | --- | --- | --- | --- |
| `decorative` (prop) | `decorative` | `isDecorative` | `decorative` | `decorative` | `decorative` |

Statuses: `planned` — In the inventory. Nothing shippable exists yet. `lagging` — An implementation of an earlier spec exists; it has not caught up with the current one. `alpha` — Implemented with tests. The API may still change. `beta` — Feature complete and at parity. Only fixes are expected. `stable` — Covered by semantic versioning. `deprecated` — Still shipped; scheduled for removal.

### Anatomy

- `container`: The region that stands in the content's place: a block as wide as the place it stands in and as tall as what it holds, with no fill, no edge, no padding and no elevation. It is what assistive technology is told about, once, and it carries no state: a skeleton takes no input.
- `placeholder`: A quiet filled shape in the place of one piece of the content: one or more lines of text, a block (a picture, a card, a control) or a circle (a person's picture, a round mark). It has the size the content will have and says nothing by itself.

### Props

| Prop | Type | Default | Web attribute | Description |
| --- | --- | --- | --- | --- |
| `label` | `string` | `""` | `label` | What is loading, in the product's language ("Loading projects"): the name assistive technology is given for the whole skeleton, once. Never drawn. Left empty, it reads the product's words; Tanrei ships none of its own. Not read while decorative is true. |
| `decorative` | `boolean` | `false` | `decorative` | Whether something else already says this wait: a loading indicator beside it, a status text, a region the product itself exposes as busy and names. True keeps the whole skeleton from assistive technology, so that one wait is said once; it changes nothing that is drawn. |
| `showDelay` | `number` | — | `show-delay` | How long, in milliseconds, this skeleton waits from the moment it is inserted before it is drawn and exposed to assistive technology; 0 shows it as it is inserted. Null takes comp.skeleton.motion.show-delay, the system's answer for every skeleton. Set it to 0 where the skeleton is part of the first presentation of a page or a view, which has nothing else to show; leave it where content is fetched in a view that is already there. |

### Item: `placeholder`

One shape in the place of one piece of the content: lines of text, a block or a circle.

Names: Web `span`, SwiftUI `TanreiSkeletonPlaceholder`, Jetpack Compose `TanreiSkeletonPlaceholder`, Flutter `TanreiSkeletonPlaceholder`, React Native `SkeletonPlaceholder`.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `shape` | `enum`: `text`, `block`, `circle` | `"text"` | What the placeholder stands for. Text is one or more lines of the text style in effect where it stands. Block is a box: a picture, a card, a control, a row. Circle is a round box: a person's picture, a round mark. |
| `lines` | `number` | `1` | For text: how many lines the text will take, a whole number of 1 or more. The placeholder is exactly that many line boxes high. Not read for a block or a circle. |
| `inlineSize` | `number` | — | The placeholder's size along the line, in points. Null leaves it to the layout: the whole inline size of its place for text and for a block, the side of the square for a circle. A size the product's own layout gives the placeholder (a share of a row, a track of a grid) is used as it is and needs no prop. |
| `blockSize` | `number` | — | The placeholder's size across the line, in points: the height of a block, and the side of a circle. Null is one line of the text style in effect, or the size the product's own layout gives. Not read for text, whose height is its lines. |

### States

`enabled`

### Accessibility

- Role: `progressbar`
- Labeling: label is the accessible name of the whole skeleton: what is loading. Once shown, the skeleton is one element — a progressbar with no value, in the platform's busy (indeterminate) state — and its placeholders are hidden; during its show delay, and while decorative is true, it is not exposed at all. It is exposed exactly as a loading indicator is, because it says the same thing: something is loading here.
- Minimum target size: yes

- Not interactive: the skeleton takes no input and is never focusable (SKL-16, SKL-19), so there is no target of its own to size and minimumTarget holds trivially.
- One wait, said once. Every placeholder of a region belongs to one skeleton with one label; a skeleton inside another is silent (SKL-17). Where the same wait is already said — a loading indicator in a status row, a status text, a region the product itself marks busy and names — set decorative, or the wait is read twice.
- The skeleton does not announce that it appeared, and does not announce that the content arrived (SKL-16): it is removed with its busy state. Where arrival should be heard (results in answer to a search, a list that was asked for), the product says so through its own live region or the status text of the component that asked; a view that simply opens with its content needs no announcement.
- A wait shorter than the show delay shows and exposes nothing (SKL-7): no shapes that flash for a sighted person, and no progressbar that appears and vanishes for a screen-reader user.
- Nothing a person should read or use goes inside a skeleton: what it holds is kept from input and from assistive technology (SKL-19). A heading that is already known, a button that already works, stand outside it.
- The fill is decoration, held to no contrast ratio: comp.skeleton.placeholder.color is a low-emphasis fill, and in the default system it has the tone of the highest container step, so a placeholder on a surface of that tone is hard to see. The wait is never said by the fill alone: the label says it to assistive technology, and forced colors draw every placeholder as an outline (SKL-20).
- Motion: a pulse dims the fill by half and returns in 2 seconds in the default system, far below the three-per-second flash threshold; nothing moves and nothing brightens. Reduced motion stops it entirely (SKL-13): a large region that pulses is more than a small mark that does, and the shapes already say that the place is waiting.
- A skeleton that never ends tells a lie. The product replaces it with the content, with an empty state where nothing came, or with a callout of the error status where loading failed, and sets its own limit on the wait; a task that takes many seconds, or whose progress can be measured, is a progress indicator's.
- Text size, text spacing and reflow: SKL-21. A text placeholder follows the text style it stands in, so it grows with the reader's text size; a size given in points does not.

### Behaviour

Requirements in EARS form, each with its stable id.

- **SKL-1** THE skeleton SHALL lay itself out as a block that takes the whole inline size of the place it stands in and is as tall as what it holds: it SHALL lay out the placeholders that stand directly in it in one column, in the order given, each at its own size and at the start edge, comp.skeleton.container.gap apart, and SHALL leave placeholders that stand inside a layout of the product's own (a row, a grid, a card's own structure) to that layout, changing neither their place nor their size. THE skeleton SHALL draw no fill, no edge and no elevation, SHALL bring no padding and no outer space of its own, SHALL set no height of its own and SHALL NOT scroll or clip.
- **SKL-2** THE skeleton SHALL draw each placeholder as one box, or for text one box a line, filled with comp.skeleton.placeholder.color, with the corners of its shape (comp.skeleton.placeholder.shape.text for each line of text, comp.skeleton.placeholder.shape.block for a block, comp.skeleton.placeholder.shape.circle for a circle), never larger than half the box's smaller side, and with no edge, no elevation, no shadow and nothing inside it. THE skeleton SHALL draw nothing else: no glyph, no mark, no text, and never its label.
- **SKL-3** WHILE a placeholder's shape is text THE skeleton SHALL size it by the text style in effect where it stands — the style text placed there would be drawn in, and sys.typescale.body where the platform has no such style and the product gave none: the placeholder SHALL be exactly as tall as lines line boxes of that style, and in each line box THE skeleton SHALL draw one bar as tall as the style's font size, centred in the line box. Each bar SHALL be as long as the placeholder's inline size (inlineSize, else the whole inline size of its place), except that WHILE lines is 2 or more the last bar SHALL be comp.skeleton.placeholder.last-line-inline-size of that size, from the start edge. The placeholder SHALL NOT read blockSize.
- **SKL-4** WHILE a placeholder's shape is block THE skeleton SHALL draw one box whose inline size is inlineSize, else the size the product's layout gives it, else the whole inline size of its place, and whose block size is blockSize, else the size the product's layout gives it (a stretched cell, a ratio the product set), else one line box of the text style in effect where it stands (SKL-3). The block SHALL NOT read lines.
- **SKL-5** WHILE a placeholder's shape is circle THE skeleton SHALL draw one square box whose side is blockSize, else inlineSize, else the size the product's layout gives it, else one line box of the text style in effect where it stands (SKL-3), and SHALL draw it round. WHERE the place is narrower than the side THE skeleton SHALL make the square as large as the place allows and keep it square: a circle is never drawn as an oval. The circle SHALL NOT read lines.
- **SKL-6** THE skeleton SHALL keep the box of every placeholder, and so its own, unchanged from the moment it is inserted to the moment it is removed — while it waits to be shown (SKL-7), while it is shown and while it stirs (SKL-12) — and SHALL NOT guess what is coming: it draws the placeholders the product gave, in the sizes the product gave, and nothing of the content. That the content takes the box its placeholders held is the product's to arrange, by placing each placeholder where its content will be and as that content will be placed.
- **SKL-7** WHEN the skeleton is inserted into a view THE skeleton SHALL wait for its show delay (SKL-9) before it is shown, and WHILE it waits SHALL draw nothing, SHALL run no animation, SHALL be absent from the accessibility tree (no role, no name, no busy state), and SHALL still take the box it takes when shown (SKL-1 to SKL-5), so that nothing around it moves when it appears; a show delay of 0 SHALL show it as it is inserted.
- **SKL-8** WHEN its show delay ends THE skeleton SHALL be shown: it SHALL draw its placeholders at once, at their resting opacity and without an entrance of their own, expose itself as SKL-15 says without announcing itself (SKL-16), and start the animation of SKL-12 at the beginning of a pulse.
- **SKL-9** THE skeleton SHALL take its show delay from showDelay, a number of milliseconds used as given (the motion dial does not scale it). WHILE showDelay is null THE skeleton SHALL use comp.skeleton.motion.show-delay in its place; IF showDelay is negative or not a finite number THE skeleton SHALL use the token likewise and in debug builds report the value it ignored.
- **SKL-10** THE skeleton SHALL treat its show delay as a waiting time, not motion: WHERE motion is reduced it SHALL keep it, on every platform, including one whose reduced-motion setting removes every animation; and it SHALL keep counting it while the skeleton cannot be seen (scrolled out of view, in a hidden view), because the delay measures the wait, not what is seen.
- **SKL-11** WHEN the skeleton is removed before its show delay ends THE skeleton SHALL have drawn, exposed and announced nothing, and WHEN it is removed while shown it SHALL disappear at once, without a motion of its own: how the content enters is the content's. WHEN it is inserted again THE skeleton SHALL wait its whole show delay again; hiding it without removing it (a hidden ancestor, scrolling) SHALL neither restart nor pause the delay (SKL-10). WHEN showDelay changes while the delay is running THE skeleton SHALL finish the running delay as it started and use the new value from its next insertion.
- **SKL-12** WHILE the skeleton is shown THE skeleton SHALL stir as comp.skeleton.motion.animation names, without end. pulse SHALL ease the opacity of every placeholder's fill from its resting value to comp.skeleton.placeholder.dim-opacity of it over comp.skeleton.motion.dim-duration with comp.skeleton.motion.dim-easing and back over the same time on the same curve, every placeholder of the skeleton in step with the others. wave SHALL put each point of each placeholder through the same fall and return, each point later than the skeleton's start edge by a share of one whole pulse equal to its distance from that edge over the skeleton's inline size, so that one dimmer band travels from the start edge to the end edge through all the placeholders as through one surface. none SHALL leave the placeholders still at their resting opacity. In every manner THE skeleton SHALL change the fill's opacity only: no box moves, grows or changes shape, and nothing brighter than the resting fill is drawn.
- **SKL-13** WHERE reduced motion is requested THE skeleton SHALL NOT stir, whatever comp.skeleton.motion.animation names: it SHALL draw its placeholders still, at their resting opacity. The shapes, the label and the busy state still say that the place is waiting, and the show delay is kept (SKL-10).
- **SKL-14** WHILE the skeleton is not visible (scrolled out of view, in a hidden view, or in an app in the background) THE skeleton SHALL NOT run its animation, and SHALL resume it when it becomes visible.
- **SKL-15** WHILE the skeleton is shown and decorative is false THE skeleton SHALL expose itself to assistive technology as one element: the progressbar role with label as its name, no current value, and the platform's busy or indeterminate state. THE skeleton SHALL expose nothing of what it holds: no placeholder, no count of placeholders or of lines, and nothing of a layout the product placed in it.
- **SKL-16** THE skeleton SHALL NOT be focusable and SHALL NOT be a stop in the focus order, SHALL NOT announce itself when it is shown, when it changes or when it is removed, and SHALL NOT move keyboard or screen-reader focus. Saying that the content has arrived, where the product wants it said, is the product's, as it is beside a loading indicator.
- **SKL-17** WHILE decorative is true THE skeleton SHALL keep itself and everything it holds from assistive technology — no role, no name, no busy state — and SHALL draw, wait and stir as it otherwise would. A skeleton that stands inside another skeleton SHALL behave as decorative whatever its prop says: one wait is said once.
- **SKL-18** THE skeleton SHALL take its name from label, and WHILE label is empty from the product's words (the key loadingLabel); it has no words of its own in any language. WHILE both are empty and decorative is false THE skeleton SHALL still be drawn and still be exposed as SKL-15 says, without a name, and in debug builds report once that a skeleton has no label, naming the prop.
- **SKL-19** THE skeleton SHALL NOT take pointer, touch or keyboard input and SHALL NOT change anything it draws under a pointer, a press or focus: it has no hovered, focused, pressed, selected or disabled state and draws no state layer and no focus indicator. Whatever the product places in it besides placeholders SHALL be drawn as given, SHALL take no input and no focus, and SHALL NOT be exposed to assistive technology: a skeleton holds the shape of content, never content.
- **SKL-20** WHERE the platform draws with a person's own forced colors (the web's forced-colors mode, and a platform's equivalent where it has one) THE skeleton SHALL draw each placeholder, and each line of a text placeholder, as the outline of its shape, sys.border.hairline wide and inside its box, in the platform's text color, with no fill, and SHALL NOT stir: a fill is not drawn in that mode, and a placeholder that vanished would leave a blank place that says nothing.
- **SKL-21** WHILE the text size is enlarged THE skeleton SHALL grow its text placeholders with the text style they stand in, and every placeholder whose size is a line box with them, so that the skeleton still holds the box the enlarged content will take; it SHALL keep a size given as inlineSize or blockSize as given, SHALL never draw a placeholder wider than its place, SHALL keep its gap, and SHALL need no horizontal scrolling at a width of 320 points with text at 200 %.
- **SKL-22** WHERE the layout direction is right-to-left THE skeleton SHALL place its placeholders at the right edge, begin the shortened last bar of a text placeholder (SKL-3) and every placeholder narrower than its place at the right, and run a wave from the right edge to the left; a block and a circle are otherwise drawn as they are in a left-to-right layout.
- **SKL-23** THE skeleton SHALL take its layout direction from where it is used — the direction of the nearest ancestor that sets one, and the platform's own where none does — and SHALL have no direction setting of its own; WHEN that direction changes while the skeleton is shown THE skeleton SHALL draw itself for the new direction at once, without a motion of its own, keeping its place in its animation.
- **SKL-24** WHEN label, decorative or a placeholder's shape, lines, inlineSize or blockSize changes, or a placeholder is added or removed, while the skeleton waits or is shown THE skeleton SHALL draw and expose the new value at once, without a motion, without an announcement, and without restarting its show delay or its animation. THE skeleton SHALL neither show nor hide itself and SHALL NOT know when the content arrives: the product puts the skeleton in the content's place when the wait starts and takes it away when the wait ends, whatever the wait ends in.
- **SKL-25** WHEN a placeholder's shape names a value this spec does not have THE skeleton SHALL draw it as text; IF its lines is less than 1 or not a finite number THE skeleton SHALL use 1, and SHALL use the whole number below a lines that is not whole; IF its inlineSize or blockSize is negative or not a finite number THE skeleton SHALL treat it as null; WHEN comp.skeleton.motion.animation names a manner the skeleton does not know THE skeleton SHALL pulse. In each case it SHALL report the value it ignored in debug builds.
- **SKL-26** IF the skeleton holds no placeholder THE skeleton SHALL draw nothing, take no space and expose nothing, and in debug builds report that a skeleton holds no placeholder: a busy region with no shape in it is a blank place, and a wait whose shape is not known is a loading indicator's.

### Tokens

As written in the token documents (DTCG): an alias in braces names the token it takes its value from, which each design system resolves. On the web each token is a CSS custom property: `--tanrei` and the name after `tanrei`, joined by hyphens (`tanrei.comp.skeleton.…` → `--tanrei-comp-skeleton-…`).

#### `tanrei.comp.skeleton`

| Token | Type | Value |
| --- | --- | --- |
| `comp.skeleton.container.gap` | `dimension` | `{tanrei.sys.space.space100}` |
| `comp.skeleton.placeholder.color` | `color` | `{tanrei.sys.color.surface-variant}` |
| `comp.skeleton.placeholder.shape.text` | `dimension` | `{tanrei.sys.shape.corner.extra-small}` |
| `comp.skeleton.placeholder.shape.block` | `dimension` | `{tanrei.sys.shape.corner.medium}` |
| `comp.skeleton.placeholder.shape.circle` | `dimension` | `{tanrei.sys.shape.corner.full}` |
| `comp.skeleton.placeholder.last-line-inline-size` | `number` | `0.6` |
| `comp.skeleton.placeholder.dim-opacity` | `number` | `0.5` |
| `comp.skeleton.motion.animation` | `number` | `0` |
| `comp.skeleton.motion.dim-duration` | `duration` | `{tanrei.sys.motion.duration.extra-long4}` |
| `comp.skeleton.motion.dim-easing` | `cubicBezier` | `{tanrei.sys.motion.easing.standard}` |
| `comp.skeleton.motion.show-delay` | `duration` | `{tanrei.sys.motion.role.show-delay}` |

## दिशानिर्देश

### वह बॉक्स थामे रखता है

स्केलेटन का मक़सद यही है कि कुछ न खिसके। उसका बॉक्स, और हर प्लेसहोल्डर का बॉक्स, डाले जाने के पल से हटाए जाने के पल तक एक जैसा रहता है: जब वह दिखने का इंतज़ार करता है, जब वह दिखता है, और जब उसमें हलचल होती है।

स्केलेटन कोई अंदाज़ा नहीं लगाता। वह वही प्लेसहोल्डर बनाता है जो आपने दिए, उन्हीं साइज़ में जो आपने दिए। कॉन्टेंट वही बॉक्स ले जो उसके प्लेसहोल्डर ने थामा था, इसका इंतज़ाम आपको करना है: हर प्लेसहोल्डर को वहाँ रखें जहाँ उसका कॉन्टेंट होगा, और वैसे ही रखें जैसे वह कॉन्टेंट रखा जाएगा।

- टेक्स्ट का प्लेसहोल्डर उस हेडिंग, पैराग्राफ़ या सेल के भीतर जाता है जिसमें टेक्स्ट होगा। वह वही टेक्स्ट स्टाइल लेता है और ठीक उतना ऊँचा होता है जितनी उस स्टाइल की उतनी लाइनें, तब भी जब पढ़ने वाला टेक्स्ट को बड़ा करता है।
- `data-lines` से बताएँ कि टेक्स्ट कितनी लाइनें लेगा। आपका कॉन्टेंट जितना नियमित होगा, आप उतनी ही बार सही होंगे। जो स्केलेटन एक लाइन छोटा है, वह पेज को एक लाइन खिसकाता है, जो फिर भी उससे कम है जितना ख़ाली जगह उसे खिसकाती है।
- ब्लॉक को तस्वीर या कंट्रोल का साइज़ दें: एक संख्या, एक अनुपात, या वह साइज़ जो आपका लेआउट उसे देता है। गोला एक संख्या लेता है, अपनी भुजा।

### आकार

| `data-shape` | किसकी जगह है | उसका साइज़ |
| --- | --- | --- |
| `text` (डिफ़ॉल्ट) | टेक्स्ट की एक या ज़्यादा लाइनें। | जिस टेक्स्ट स्टाइल में वह है, उसके `data-lines` लाइन बॉक्स। हर लाइन फ़ॉन्ट साइज़ जितनी ऊँची एक पट्टी है। कई लाइनों में आख़िरी छोटी होती है, क्योंकि पैराग्राफ़ कम ही किनारे पर ख़त्म होता है। `inline-size` पट्टियों की लंबाई तय करता है। |
| `block` | एक तस्वीर, एक कार्ड, एक कंट्रोल, एक पंक्ति। | `inline-size` और `block-size`, या वह साइज़ जो आपका लेआउट उसे देता है: खिंचा हुआ सेल, कोई `aspect-ratio`। साइज़ न हो तो वह अपनी जगह जितना चौड़ा और एक लाइन जितना ऊँचा होता है। |
| `circle` | किसी व्यक्ति की तस्वीर, कोई गोल निशान। | एक भुजा: `block-size`, या `inline-size`। साइज़ न हो तो वह एक लाइन जितना ऊँचा होता है। |

जो प्लेसहोल्डर स्केलेटन के अपने चाइल्ड हैं, वे 8 के गैप के साथ एक के नीचे एक रखे जाते हैं। बाक़ी सब कुछ, जैसे दो लाइनों के बग़ल में एक गोला या कार्ड का ग्रिड, स्केलेटन के भीतर आपका अपना लेआउट है। कार्ड या लिस्ट का कोई बना-बनाया स्केलेटन नहीं है: आपकी स्क्रीन आपकी हैं, और उन्हें सिर्फ़ आप जानते हैं।

आपकी अपनी पंक्ति में टेक्स्ट के प्लेसहोल्डर या ब्लॉक को उस पंक्ति से चौड़ाई चाहिए, जैसे कॉन्टेंट को चाहिए होगी: `flex: 1`, ग्रिड का कोई ट्रैक, या कोई `inline-size`।

### एक इंतज़ार, एक संकेत

किसी रीजन के सारे प्लेसहोल्डर एक ही स्केलेटन में रखें, एक `label` के साथ। दूसरे स्केलेटन के भीतर का स्केलेटन कुछ नहीं बताता।

जहाँ कोई और चीज़ पहले से वही इंतज़ार बता रही है, जैसे स्थिति पंक्ति का लोडिंग इंडिकेटर, स्थिति का टेक्स्ट, या ऐसा रीजन जिसे आपने ख़ुद व्यस्त के रूप में चिह्नित करके नाम दिया है, वहाँ `decorative` सेट करें। तब स्केलेटन वैसा ही बनता है और सहायक तकनीक से छिपा रहता है, ताकि इंतज़ार दो बार न पढ़ा जाए।

### वह दिखने से पहले रुकता है

डाले जाने के पल से स्केलेटन 300 ms रुकता है, फिर बनाया जाता है और सहायक तकनीक को दिया जाता है। उसका बॉक्स इस दौरान भी थामा रहता है। जो इंतज़ार इससे पहले ख़त्म हो जाता है, वह ऐसी ख़ाली जगह दिखाता है जो शुरू से ही सही साइज़ की थी।

- इंतज़ार शुरू होने पर स्केलेटन डालें और कॉन्टेंट आने पर उसे हटा दें। देरी डाले जाने से गिनी जाती है। स्केलेटन को छिपाने से वह दोबारा शुरू नहीं होती।
- जहाँ स्केलेटन किसी पेज या व्यू के पहली बार दिखने का हिस्सा है, जिसके पास दिखाने को और कुछ नहीं है, वहाँ `show-delay="0"` सेट करें।
- देरी इंतज़ार है, मोशन नहीं: जहाँ मोशन कम किया गया है, वहाँ भी वह बनी रहती है।

### वह हमेशा किसी चीज़ पर ख़त्म होता है

स्केलेटन की जगह कॉन्टेंट रखें, जहाँ कुछ नहीं आया वहाँ [ख़ाली स्टेट](https://tanrei.chnotchy.com/hi/components/empty-state/), या जहाँ लोड होना विफल रहा वहाँ त्रुटि की स्थिति वाला [कॉलआउट](https://tanrei.chnotchy.com/hi/components/callout/)। उसका समय अपने आप कभी ख़त्म नहीं होता: कब हार माननी है, यह आप जानते हैं।

स्केलेटन यह पढ़कर नहीं सुनाता कि कॉन्टेंट आ गया। जहाँ आना सुनाई देना चाहिए, जैसे किसी खोज के जवाब में आए नतीजे या माँगी गई लिस्ट, वहाँ इसे अपने लाइव रीजन से या माँगने वाले कंपोनेंट के स्थिति के टेक्स्ट से बताएँ। जो व्यू बस अपने कॉन्टेंट के साथ खुलता है, उसे पढ़कर सुनाने की ज़रूरत नहीं है।

### मोशन

डिफ़ॉल्ट रूप से प्लेसहोल्डर पल्स करते हैं: फ़िल आधा हल्का होकर लौटता है, सारे प्लेसहोल्डर में एक साथ, दो सेकंड में एक पल्स। सिर्फ़ ओपैसिटी बदलती है। कुछ खिसकता नहीं, और कुछ भी सामान्य फ़िल से ज़्यादा चमकीला नहीं बनता।

डिज़ाइन सिस्टम टोकन `comp.skeleton.motion.animation` से अपने सारे स्केलेटन के लिए दूसरा ढंग चुन सकता है: `pulse`, `wave` (वही हल्का होना, जो एक बैंड के रूप में पूरे स्केलेटन में शुरुआती किनारे से अंतिम किनारे तक चलता है) या `none`। किसी एक इंस्टेंस के लिए कोई सेटिंग नहीं है।

जहाँ मोशन कम किया गया है, वहाँ प्लेसहोल्डर स्थिर रहते हैं। आकार, लेबल और व्यस्त स्टेट पहले से बताते हैं कि जगह इंतज़ार में है। जब तक स्केलेटन को देखा नहीं जा सकता, उसका ऐनिमेशन नहीं चलता।

### वेब पर, स्क्रिप्ट से पहले

स्केलेटन वह है जो पेज अपनी स्क्रिप्ट के चलने से पहले दिखाता है, इसलिए `@tanrei/web/skeleton.css` उसे एलिमेंट के बिना पूरा बना देती है। कुछ चीज़ों को एलिमेंट चाहिए, और वे उसके डिफ़ाइन होने तक, या जहाँ स्क्रिप्ट कभी नहीं चलती वहाँ, अलग होती हैं:

- रोल और नाम। जिस पेज को अपनी स्क्रिप्ट के चलने से पहले सही होना है, वह ख़ुद एलिमेंट पर `role="progressbar"`, `aria-busy="true"` और `aria-label` लिखता है, और एलिमेंट जो पाता है उसे वैसा ही छोड़ देता है।
- `0` के अलावा कोई `show-delay`। स्टाइलशीट डिज़ाइन सिस्टम की देरी जितना रुकती है।
- टेक्स्ट के एक प्लेसहोल्डर में 24 से ज़्यादा लाइनें।
- `wave` वाला ढंग, जो पल्स के रूप में बनता है।
- जो व्यू दिखाया नहीं जा रहा, उसके भीतर का स्केलेटन अपना इंतज़ार तब शुरू करता है जब व्यू दिखाया जाता है।

जहाँ स्क्रिप्ट कभी नहीं चलती, वहाँ स्केलेटन कभी ख़त्म नहीं होता, जब तक सर्वर उसे बदल न दे। जो कॉन्टेंट सिर्फ़ स्क्रिप्ट से आता है, उसे अपने स्केलेटन के बग़ल में एक `<noscript>` चाहिए।

### करें

- प्लेसहोल्डर को आने वाली चीज़ का आकार और साइज़ दें।
- टेक्स्ट के प्लेसहोल्डर उस एलिमेंट के भीतर रखें जिसमें टेक्स्ट होगा।
- एक इंतज़ार के लिए एक स्केलेटन इस्तेमाल करें, एक लेबल के साथ।
- इंतज़ार ख़त्म होने पर उसे बदल दें, इंतज़ार जिस भी चीज़ पर ख़त्म हो।

### न करें

- स्केलेटन के भीतर ऐसा कुछ न रखें जिसे व्यक्ति को पढ़ना या इस्तेमाल करना हो। उसके भीतर की चीज़ें कोई इनपुट नहीं लेतीं और सहायक तकनीक से छिपी रहती हैं। जो हेडिंग पहले से पता है, जो बटन पहले से काम करता है, वे उसके बाहर रहते हैं।
- इसे किसी कंट्रोल या पंक्ति के छोटे इंतज़ार के लिए, या चल रही किसी क्रिया के लिए इस्तेमाल न करें। वह लोडिंग इंडिकेटर का काम है।
- जो कॉन्टेंट पहले से वहाँ है, उसे इससे न ढकें।
- स्लेटी बॉक्स हाथ से न बनाएँ।

## सुलभता

### कंपोनेंट क्या सँभालता है

- दिखने के बाद स्केलेटन सहायक तकनीक के लिए एक ही एलिमेंट है: बिना मान का, व्यस्त प्रोग्रेस बार, जिसका नाम `label` से आता है। वह वैसे ही दिया जाता है जैसे लोडिंग इंडिकेटर, क्योंकि वह वही बात कहता है।
- उसके प्लेसहोल्डर, उनकी संख्या और उनकी लाइनें नहीं दी जातीं, और न वह लेआउट जो आप उसमें रखते हैं।
- जब तक वह दिखने का इंतज़ार करता है, वह बिलकुल नहीं दिया जाता। देरी से छोटा इंतज़ार ऐसा प्रोग्रेस बार नहीं दिखाता जो आए और ग़ायब हो जाए।
- `decorative` के साथ, या किसी दूसरे स्केलेटन के भीतर, वह सहायक तकनीक से छिपा रहता है।
- उस पर फ़ोकस नहीं जा सकता और वह फ़ोकस के क्रम में कोई पड़ाव नहीं है, और न उसके भीतर की कोई चीज़। वह अपने बारे में कुछ पढ़कर नहीं सुनाता और फ़ोकस को कभी नहीं हटाता।
- जहाँ मोशन कम किया गया है, वहाँ वह स्थिर रहता है। देरी बनी रहती है।
- फ़ोर्स्ड कलर्स में हर प्लेसहोल्डर, और टेक्स्ट की हर लाइन, अपने आकार की आउटलाइन के रूप में टेक्स्ट के रंग में बनती है। उस मोड में फ़िल नहीं बनता, और जो प्लेसहोल्डर ग़ायब हो जाता, वह ख़ाली जगह छोड़ जाता।
- बड़े किए गए टेक्स्ट के साथ टेक्स्ट का प्लेसहोल्डर अपने टेक्स्ट स्टाइल के साथ बढ़ता है, इसलिए स्केलेटन तब भी वही बॉक्स थामे रखता है जो बड़ा किया गया कॉन्टेंट लेता है। संख्या के रूप में दिया गया साइज़ वैसा ही रहता है। कुछ भी अपनी जगह से चौड़ा नहीं होता; 320 की चौड़ाई पर 200% टेक्स्ट के साथ कुछ भी आड़ा स्क्रॉल नहीं होता।
- दाएँ से बाएँ वाले लेआउट में प्लेसहोल्डर दाईं ओर रहते हैं, छोटी आख़िरी लाइन दाईं ओर से शुरू होती है, और वेव दाएँ से बाएँ चलती है।
- अनजान आकार, लाइनों की ऐसी संख्या या ऐसा साइज़ जो इस्तेमाल नहीं हो सकता, बिना प्लेसहोल्डर का स्केलेटन और बिना लेबल का स्केलेटन डीबग बिल्ड में रिपोर्ट किए जाते हैं।

### आपको क्या करना है

- पेज की भाषा में ऐसा `label` दें जो बताए कि क्या लोड हो रहा है (“प्रोजेक्ट लोड हो रहे हैं”), या `setWords({ loadingLabel: … })` से सारे स्केलेटन के लिए यह शब्द एक बार दें। कंपोनेंट कोई शब्द नहीं देता।
- जहाँ कोई और चीज़ पहले से इंतज़ार बता रही है, वहाँ `decorative` सेट करें।
- जहाँ कॉन्टेंट का आना ख़बर है, वहाँ बताएँ कि वह आ गया।
- स्केलेटन को कभी हमेशा के लिए न रहने दें। उसकी जगह कॉन्टेंट, ख़ाली स्टेट या त्रुटि रखें।
- फ़िल सजावट है और उस पर कंट्रास्ट का कोई अनुपात लागू नहीं होता। सबसे ऊँचे कंटेनर टोन वाली सरफ़ेस पर वह मुश्किल से दिखता है। यह बताने के लिए कि जगह इंतज़ार में है, सिर्फ़ उसी पर निर्भर न रहें। जहाँ वह ऐसी सरफ़ेस पर हो, वहाँ एक लेयर में `comp.skeleton.placeholder.color` को किसी ज़्यादा गहरे रोल पर ले जाएँ।
