@agentero/design-system 0.34.1 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mcp/manifests/components.html +368 -78
- package/mcp/manifests/components.json +197 -9
- package/package.json +5 -1
- package/src/combobox/combobox.d.ts +39 -10
- package/src/combobox/combobox.js +113 -87
- package/src/combobox/index.d.ts +3 -3
- package/src/input-tel/index.d.ts +2 -0
- package/src/input-tel/index.js +2 -0
- package/src/input-tel/input-tel.d.ts +42 -0
- package/src/input-tel/input-tel.js +46 -0
- package/src/input-tel/mask.d.ts +51 -0
- package/src/input-tel/mask.js +39 -0
|
@@ -588,7 +588,7 @@
|
|
|
588
588
|
<header>
|
|
589
589
|
<div class="wrap">
|
|
590
590
|
<h1>Manifest Debugger</h1>
|
|
591
|
-
<div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><span class="filter-pill ok" aria-disabled="true">
|
|
591
|
+
<div class="summary"><a class="filter-pill all" data-k="all" href="#filter-all">All</a><span class="filter-pill ok" aria-disabled="true">37 components ok</span><span class="filter-pill ok" aria-disabled="true">305 stories ok</span></div>
|
|
592
592
|
</div>
|
|
593
593
|
</header>
|
|
594
594
|
<main>
|
|
@@ -2855,7 +2855,7 @@ import { CheckList } from '@agentero/design-system/check-list';
|
|
|
2855
2855
|
<div class="title">
|
|
2856
2856
|
<h2><span class="status-dot dot-ok"></span> Combobox.Root</h2>
|
|
2857
2857
|
<div class="badges">
|
|
2858
|
-
<label for="c-7-components-combobox-props" class="badge ok as-toggle">
|
|
2858
|
+
<label for="c-7-components-combobox-props" class="badge ok as-toggle">41 prop types</label>
|
|
2859
2859
|
|
|
2860
2860
|
<label for="c-7-components-combobox-stories" class="badge ok as-toggle">10 stories</label>
|
|
2861
2861
|
|
|
@@ -2900,7 +2900,7 @@ import { Combobox } from '@agentero/design-system/combobox';
|
|
|
2900
2900
|
<div class="note ok">
|
|
2901
2901
|
<div class="row">
|
|
2902
2902
|
<span class="ex-name">Prop types <small>(react-component-meta)</small></span>
|
|
2903
|
-
<span class="badge ok">
|
|
2903
|
+
<span class="badge ok">41 prop types</span>
|
|
2904
2904
|
</div>
|
|
2905
2905
|
<pre><code>Component: src/combobox/index.ts::Combobox</code></pre>
|
|
2906
2906
|
<pre><code>Props:</code></pre>
|
|
@@ -3047,6 +3047,28 @@ itemToStringValue?: (itemValue: unknown) => string
|
|
|
3047
3047
|
*/
|
|
3048
3048
|
limit?: number = -1
|
|
3049
3049
|
|
|
3050
|
+
/**
|
|
3051
|
+
* Whether the options are being fetched. Once the list has been open and
|
|
3052
|
+
* loading for half a second, `loadingLabel` is announced once: sooner, a
|
|
3053
|
+
* screen reader would cut it off to echo the key just typed, and a faster
|
|
3054
|
+
* answer has no wait to announce. `Content` is marked `aria-busy`, and
|
|
3055
|
+
* `Empty` shows nothing, so "no results" is not read out before the results
|
|
3056
|
+
* arrive. The announcement comes from a visually hidden live region the root
|
|
3057
|
+
* renders next to the field, so it is in place before the list opens. On a search
|
|
3058
|
+
* against an API, pass it from the first render, as `false` while idle: a root
|
|
3059
|
+
* that leaves it out gets no live region. A list filtered in memory never
|
|
3060
|
+
* waits and leaves it out. While loading with no rows yet, the surface shows
|
|
3061
|
+
* whatever placeholder `Content` holds — `Empty` stays quiet.
|
|
3062
|
+
*/
|
|
3063
|
+
loading?: boolean
|
|
3064
|
+
|
|
3065
|
+
/**
|
|
3066
|
+
* What a screen reader hears when `loading` turns `true`. Announced only; any
|
|
3067
|
+
* loading visuals — placeholder rows, a spinner — are yours to render inside
|
|
3068
|
+
* `Content`, hidden from assistive technology. Defaults to `'Loading…'`.
|
|
3069
|
+
*/
|
|
3070
|
+
loadingLabel?: string = 'Loading…'
|
|
3071
|
+
|
|
3050
3072
|
/**
|
|
3051
3073
|
* The locale to use for string comparison.
|
|
3052
3074
|
* Defaults to the user's runtime locale.
|
|
@@ -3340,9 +3362,10 @@ here as tags.</div>
|
|
|
3340
3362
|
<div class="hint">Options fetched as you type, the way the apps load data: the rows are a component
|
|
3341
3363
|
that suspends on the request, so a `Suspense` boundary inside `Content` shows
|
|
3342
3364
|
placeholder rows until the first results land. The rows read a deferred copy of
|
|
3343
|
-
the query, so a new search keeps the previous rows on screen while it loads and
|
|
3344
|
-
|
|
3345
|
-
|
|
3365
|
+
the query, so a new search keeps the previous rows on screen while it loads, and
|
|
3366
|
+
passing that staleness as `loading` announces the wait and marks `Content` busy
|
|
3367
|
+
until they are replaced; the placeholders never come back. Nothing tracks a
|
|
3368
|
+
request by hand, and reading the data by query is what
|
|
3346
3369
|
makes out-of-order responses harmless. With react-query, drop a
|
|
3347
3370
|
`useSuspenseQuery` where `use()` is, or use `placeholderData: keepPreviousData`
|
|
3348
3371
|
with a plain `useQuery` for the same behaviour.</div>
|
|
@@ -3360,12 +3383,14 @@ with a plain `useQuery` for the same behaviour.</div>
|
|
|
3360
3383
|
filter={null}
|
|
3361
3384
|
itemToStringLabel={(agency: Agency) => agency.name}
|
|
3362
3385
|
isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}
|
|
3386
|
+
loading={isStale}
|
|
3387
|
+
loadingLabel="Searching agencies…"
|
|
3363
3388
|
onInputValueChange={(value, { reason }) => {
|
|
3364
3389
|
// Picking a row writes its label into the input; that is not a new search.
|
|
3365
3390
|
if (reason !== 'item-press') setQuery(value);
|
|
3366
3391
|
}}>
|
|
3367
3392
|
<Combobox.Input placeholder="Search agencies" aria-label="Search agencies" />
|
|
3368
|
-
<Combobox.Content
|
|
3393
|
+
<Combobox.Content>
|
|
3369
3394
|
<Suspense fallback={<SkeletonRows />}>
|
|
3370
3395
|
<AgencyItems query={deferredQuery} />
|
|
3371
3396
|
</Suspense>
|
|
@@ -3376,21 +3401,24 @@ with a plain `useQuery` for the same behaviour.</div>
|
|
|
3376
3401
|
</div>
|
|
3377
3402
|
<div class="note ok">
|
|
3378
3403
|
<div class="row">
|
|
3379
|
-
<span class="ex-name">Async Search With
|
|
3404
|
+
<span class="ex-name">Async Search With Loading</span>
|
|
3380
3405
|
<span class="badge ok">story ok</span>
|
|
3381
3406
|
</div>
|
|
3382
|
-
<div>API search that waits for two characters
|
|
3407
|
+
<div>API search that waits for two characters and announces its loading state</div>
|
|
3383
3408
|
<div class="hint">The same search without Suspense, for a consumer that gets a `loading` flag from
|
|
3384
3409
|
its data layer instead: `filter={null}`, the rows arrive through `filteredItems`,
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3410
|
+
and the flag goes to `Root` as `loading`. That is all the wiring the wait needs:
|
|
3411
|
+
`Content` is marked busy, `loadingLabel` is announced once when the request
|
|
3412
|
+
starts, and `Empty` holds back "no results" until the answer is in. Placeholder
|
|
3413
|
+
rows show only while there is nothing to show yet, hidden from assistive
|
|
3414
|
+
technology since the label already speaks for them; after that, the previous
|
|
3415
|
+
rows stay until the new ones replace them. A request that is no longer the
|
|
3416
|
+
latest is dropped.
|
|
3389
3417
|
|
|
3390
3418
|
`minInputLength` keeps the list shut until two characters are typed — focusing
|
|
3391
3419
|
the field opens nothing, and deleting back under the minimum closes it — and
|
|
3392
3420
|
no request goes out for a shorter query either.</div>
|
|
3393
|
-
<pre><code>const
|
|
3421
|
+
<pre><code>const AsyncSearchWithLoading = () => {
|
|
3394
3422
|
const [results, setResults] = useState<Agency[]>([]);
|
|
3395
3423
|
const [isLoading, setIsLoading] = useState(false);
|
|
3396
3424
|
// Only the latest request may land; fast typing returns responses out of order.
|
|
@@ -3420,17 +3448,15 @@ no request goes out for a shorter query either.</div>
|
|
|
3420
3448
|
filteredItems={results}
|
|
3421
3449
|
filter={null}
|
|
3422
3450
|
minInputLength={MIN_QUERY_LENGTH}
|
|
3451
|
+
loading={isLoading}
|
|
3452
|
+
loadingLabel="Searching agencies…"
|
|
3423
3453
|
itemToStringLabel={(agency: Agency) => agency.name}
|
|
3424
3454
|
isItemEqualToValue={(a: Agency, b: Agency) => a.id === b.id}
|
|
3425
3455
|
onInputValueChange={onInputValueChange}>
|
|
3426
3456
|
<Combobox.Input placeholder="Search agencies" aria-label="Search agencies" />
|
|
3427
|
-
<Combobox.Content
|
|
3428
|
-
{/* The rows show the wait; `Status` only announces it. */}
|
|
3429
|
-
<Combobox.Status className="sr-only">
|
|
3430
|
-
{isLoading ? 'Searching…' : undefined}
|
|
3431
|
-
</Combobox.Status>
|
|
3457
|
+
<Combobox.Content>
|
|
3432
3458
|
{isLoading && results.length === 0 && <SkeletonRows />}
|
|
3433
|
-
<Combobox.Empty>
|
|
3459
|
+
<Combobox.Empty>No agencies found</Combobox.Empty>
|
|
3434
3460
|
<Combobox.List>
|
|
3435
3461
|
{(agency: Agency) => (
|
|
3436
3462
|
<Combobox.Item key={agency.id} value={agency}>
|
|
@@ -7875,6 +7901,270 @@ several search fields does not read "Clear search" twice.</div>
|
|
|
7875
7901
|
</div>
|
|
7876
7902
|
|
|
7877
7903
|
|
|
7904
|
+
</div>
|
|
7905
|
+
</article>
|
|
7906
|
+
<article
|
|
7907
|
+
class="card
|
|
7908
|
+
no-error
|
|
7909
|
+
no-info
|
|
7910
|
+
no-story-error
|
|
7911
|
+
no-doc-error"
|
|
7912
|
+
role="listitem"
|
|
7913
|
+
aria-label="InputTel">
|
|
7914
|
+
<div class="head">
|
|
7915
|
+
<div class="title">
|
|
7916
|
+
<h2><span class="status-dot dot-ok"></span> InputTel</h2>
|
|
7917
|
+
<div class="badges">
|
|
7918
|
+
<label for="c-21-components-inputtel-props" class="badge ok as-toggle">1 prop type</label>
|
|
7919
|
+
|
|
7920
|
+
<label for="c-21-components-inputtel-stories" class="badge ok as-toggle">11 stories</label>
|
|
7921
|
+
|
|
7922
|
+
|
|
7923
|
+
</div>
|
|
7924
|
+
</div>
|
|
7925
|
+
<div class="meta" title="./src/input-tel/input-tel.stories.tsx">components-inputtel · ./src/input-tel/input-tel.stories.tsx</div>
|
|
7926
|
+
<div>US phone input with a +1 prefix that masks as you type</div>
|
|
7927
|
+
<div class="hint">InputTel is a US phone number field that masks as you type: the digits are
|
|
7928
|
+
laid out as `(555) 123-4567`, anything else is dropped and the caret stays
|
|
7929
|
+
next to the digit just edited. It is an `Input` of `type="tel"` inside an
|
|
7930
|
+
`InputGroup` frame with a `+1` prefix; `onChange` receives the native event
|
|
7931
|
+
with the masked text already in `event.target.value`.</div>
|
|
7932
|
+
<div class="kv"><span class="chip">summary: US phone input with a +1 prefix that masks as you type</span><span class="chip">dataAttribute: {string} data-slot - Always set to "input-tel" on the frame</span><span class="chip">example: <FieldText>
|
|
7933
|
+
<Label>Phone number</Label>
|
|
7934
|
+
<InputTel name="phone" autoComplete="tel-national" placeholder="(555) 000-0000" />
|
|
7935
|
+
</FieldText></span></div>
|
|
7936
|
+
</div>
|
|
7937
|
+
|
|
7938
|
+
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
7939
|
+
|
|
7940
|
+
|
|
7941
|
+
<input id="c-21-components-inputtel-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
7942
|
+
|
|
7943
|
+
|
|
7944
|
+
<input id="c-21-components-inputtel-props" class="tg tg-props" type="checkbox" hidden />
|
|
7945
|
+
|
|
7946
|
+
<div class="panels">
|
|
7947
|
+
|
|
7948
|
+
|
|
7949
|
+
|
|
7950
|
+
<div class="panel panel-props">
|
|
7951
|
+
<div class="note ok">
|
|
7952
|
+
<div class="row">
|
|
7953
|
+
<span class="ex-name">Prop types <small>(react-component-meta)</small></span>
|
|
7954
|
+
<span class="badge ok">1 prop type</span>
|
|
7955
|
+
</div>
|
|
7956
|
+
<pre><code>Component: src/input-tel/input-tel.tsx::InputTel</code></pre>
|
|
7957
|
+
<pre><code>Props:</code></pre>
|
|
7958
|
+
<pre><code>/**
|
|
7959
|
+
* Control height. Defaults to `'md'`.
|
|
7960
|
+
* - `sm` (32px) — dense layouts where vertical space is tight.
|
|
7961
|
+
* - `md` (40px) — standard form density.
|
|
7962
|
+
* - `lg` (48px) — low-density forms and larger touch targets. Also raises
|
|
7963
|
+
* the text to `base` and the corner radius to `lg`.
|
|
7964
|
+
*/
|
|
7965
|
+
size?: "sm" | "md" | "lg"</code></pre>
|
|
7966
|
+
</div>
|
|
7967
|
+
</div>
|
|
7968
|
+
|
|
7969
|
+
<div class="panel panel-stories">
|
|
7970
|
+
|
|
7971
|
+
|
|
7972
|
+
|
|
7973
|
+
<div class="note ok">
|
|
7974
|
+
<div class="row">
|
|
7975
|
+
<span class="ex-name">Imports</span>
|
|
7976
|
+
</div>
|
|
7977
|
+
<pre><code>import { Button, Field, FieldText, InputContext, InputTel, Label } from "@agentero/design-system";</code></pre>
|
|
7978
|
+
</div>
|
|
7979
|
+
|
|
7980
|
+
|
|
7981
|
+
<div class="note ok">
|
|
7982
|
+
<div class="row">
|
|
7983
|
+
<span class="ex-name">Default</span>
|
|
7984
|
+
<span class="badge ok">story ok</span>
|
|
7985
|
+
</div>
|
|
7986
|
+
<div>Phone field with a +1 prefix masking the digits as they are typed</div>
|
|
7987
|
+
<div class="hint">An uncontrolled phone field with its `+1` prefix. Typing the ten digits lays
|
|
7988
|
+
them out as `(555) 123-4567`, and every `onChange` call carries the masked
|
|
7989
|
+
text in `event.target.value`; the prefix never enters the value.</div>
|
|
7990
|
+
<pre><code>const Default = () => <InputTel
|
|
7991
|
+
aria-label="Phone number"
|
|
7992
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)} />;</code></pre>
|
|
7993
|
+
</div>
|
|
7994
|
+
<div class="note ok">
|
|
7995
|
+
<div class="row">
|
|
7996
|
+
<span class="ex-name">Controlled</span>
|
|
7997
|
+
<span class="badge ok">story ok</span>
|
|
7998
|
+
</div>
|
|
7999
|
+
<div>Controlled phone field storing the masked value</div>
|
|
8000
|
+
<div class="hint">A controlled phone field. The state that owns the value stores what
|
|
8001
|
+
`event.target.value` reports, which is already masked, and the input shows
|
|
8002
|
+
it back unchanged. A partial number carries the separator that comes before
|
|
8003
|
+
the next digit, so six digits read `(555) 123-`.</div>
|
|
8004
|
+
<pre><code>const Controlled = () => {
|
|
8005
|
+
const [phone, setPhone] = useState('');
|
|
8006
|
+
|
|
8007
|
+
return (
|
|
8008
|
+
<InputTel
|
|
8009
|
+
aria-label="Phone number"
|
|
8010
|
+
value={phone}
|
|
8011
|
+
onChange={event => {
|
|
8012
|
+
setPhone(event.target.value);
|
|
8013
|
+
args.onChange?.(event);
|
|
8014
|
+
}} />
|
|
8015
|
+
);
|
|
8016
|
+
};</code></pre>
|
|
8017
|
+
</div>
|
|
8018
|
+
<div class="note ok">
|
|
8019
|
+
<div class="row">
|
|
8020
|
+
<span class="ex-name">Caret In The Middle</span>
|
|
8021
|
+
<span class="badge ok">story ok</span>
|
|
8022
|
+
</div>
|
|
8023
|
+
<div>Caret staying put when a digit is inserted mid-number</div>
|
|
8024
|
+
<div class="hint">Editing in the middle of a full number: a digit typed after `(5` shifts the
|
|
8025
|
+
rest right, the eleventh digit falls off the end and the caret stays after
|
|
8026
|
+
the digit just typed instead of jumping to the end.</div>
|
|
8027
|
+
<pre><code>const CaretInTheMiddle = () => <InputTel
|
|
8028
|
+
aria-label="Phone number"
|
|
8029
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)} />;</code></pre>
|
|
8030
|
+
</div>
|
|
8031
|
+
<div class="note ok">
|
|
8032
|
+
<div class="row">
|
|
8033
|
+
<span class="ex-name">Backspace Over Mask Characters</span>
|
|
8034
|
+
<span class="badge ok">story ok</span>
|
|
8035
|
+
</div>
|
|
8036
|
+
<div>Backspace trimming the separators the mask added</div>
|
|
8037
|
+
<div class="hint">Backspace over the mask's own characters: after `555` the field shows
|
|
8038
|
+
`(555) `, and deleting backwards trims the separators along with the digit
|
|
8039
|
+
under the caret instead of leaving a dangling `) `.</div>
|
|
8040
|
+
<pre><code>const BackspaceOverMaskCharacters = () => <InputTel
|
|
8041
|
+
aria-label="Phone number"
|
|
8042
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)} />;</code></pre>
|
|
8043
|
+
</div>
|
|
8044
|
+
<div class="note ok">
|
|
8045
|
+
<div class="row">
|
|
8046
|
+
<span class="ex-name">Paste</span>
|
|
8047
|
+
<span class="badge ok">story ok</span>
|
|
8048
|
+
</div>
|
|
8049
|
+
<div>Pasted number reduced to its digits and masked</div>
|
|
8050
|
+
<div class="hint">A pasted number in any format is reduced to its digits and masked, so
|
|
8051
|
+
`555-123-4567` from a clipboard ends up as `(555) 123-4567`.</div>
|
|
8052
|
+
<pre><code>const Paste = () => <InputTel
|
|
8053
|
+
aria-label="Phone number"
|
|
8054
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)} />;</code></pre>
|
|
8055
|
+
</div>
|
|
8056
|
+
<div class="note ok">
|
|
8057
|
+
<div class="row">
|
|
8058
|
+
<span class="ex-name">Paste With Country Code</span>
|
|
8059
|
+
<span class="badge ok">story ok</span>
|
|
8060
|
+
</div>
|
|
8061
|
+
<div>Pasted number with a +1 country code</div>
|
|
8062
|
+
<div class="hint">A number that carries the `+1` country code, as copied from a signature or
|
|
8063
|
+
filled in by the browser's autofill, loses the code and keeps its ten
|
|
8064
|
+
national digits: `+1 (555) 123-4567` ends up as `(555) 123-4567`.</div>
|
|
8065
|
+
<pre><code>const PasteWithCountryCode = () => <InputTel
|
|
8066
|
+
aria-label="Phone number"
|
|
8067
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)} />;</code></pre>
|
|
8068
|
+
</div>
|
|
8069
|
+
<div class="note ok">
|
|
8070
|
+
<div class="row">
|
|
8071
|
+
<span class="ex-name">Inside Field Text</span>
|
|
8072
|
+
<span class="badge ok">story ok</span>
|
|
8073
|
+
</div>
|
|
8074
|
+
<div>Label and description reaching the input through the field</div>
|
|
8075
|
+
<div class="hint">Inside a `FieldText` the input takes its label, description and states from
|
|
8076
|
+
the field, and the masked value still reaches a handler the field provides.</div>
|
|
8077
|
+
<pre><code>const InsideFieldText = () => (
|
|
8078
|
+
<FieldText>
|
|
8079
|
+
<Label>Phone number</Label>
|
|
8080
|
+
<InputTel />
|
|
8081
|
+
<Field.Description>We only call about your account.</Field.Description>
|
|
8082
|
+
</FieldText>
|
|
8083
|
+
);</code></pre>
|
|
8084
|
+
</div>
|
|
8085
|
+
<div class="note ok">
|
|
8086
|
+
<div class="row">
|
|
8087
|
+
<span class="ex-name">With React Hook Form</span>
|
|
8088
|
+
<span class="badge ok">story ok</span>
|
|
8089
|
+
</div>
|
|
8090
|
+
<div>Masked value reaching react-hook-form through register</div>
|
|
8091
|
+
<div class="hint">Registered with react-hook-form, the form receives the masked value: the
|
|
8092
|
+
`register` handler reads `event.target.value` like any other change.</div>
|
|
8093
|
+
<pre><code>const WithReactHookForm = () => {
|
|
8094
|
+
const { register, handleSubmit } = useForm<ContactValues>({
|
|
8095
|
+
defaultValues: { phone: '' }
|
|
8096
|
+
});
|
|
8097
|
+
|
|
8098
|
+
return (
|
|
8099
|
+
<form
|
|
8100
|
+
aria-label="Contact"
|
|
8101
|
+
noValidate
|
|
8102
|
+
onSubmit={handleSubmit(values => onSubmit(values))}
|
|
8103
|
+
style={{ display: 'grid', gap: '1rem' }}>
|
|
8104
|
+
<InputTel aria-label="Phone number" {...register('phone')} />
|
|
8105
|
+
<Button type="submit">Save</Button>
|
|
8106
|
+
</form>
|
|
8107
|
+
);
|
|
8108
|
+
};</code></pre>
|
|
8109
|
+
</div>
|
|
8110
|
+
<div class="note ok">
|
|
8111
|
+
<div class="row">
|
|
8112
|
+
<span class="ex-name">Disabled</span>
|
|
8113
|
+
<span class="badge ok">story ok</span>
|
|
8114
|
+
</div>
|
|
8115
|
+
<div>Disabled phone field</div>
|
|
8116
|
+
<div class="hint">A disabled phone field keeps its masked value and takes no input.</div>
|
|
8117
|
+
<pre><code>const Disabled = () => <InputTel
|
|
8118
|
+
aria-label="Phone number"
|
|
8119
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}
|
|
8120
|
+
disabled
|
|
8121
|
+
defaultValue="(555) 123-4567" />;</code></pre>
|
|
8122
|
+
</div>
|
|
8123
|
+
<div class="note ok">
|
|
8124
|
+
<div class="row">
|
|
8125
|
+
<span class="ex-name">Invalid</span>
|
|
8126
|
+
<span class="badge ok">story ok</span>
|
|
8127
|
+
</div>
|
|
8128
|
+
<div>Invalid field driving the frame's destructive border</div>
|
|
8129
|
+
<div class="hint">`invalid` on the surrounding `FieldText` sets `aria-invalid` on the input,
|
|
8130
|
+
which paints the frame's destructive border, and `Field.Error` is announced
|
|
8131
|
+
with the input.</div>
|
|
8132
|
+
<pre><code>const Invalid = () => (
|
|
8133
|
+
<FieldText invalid>
|
|
8134
|
+
<Label>Phone number</Label>
|
|
8135
|
+
<InputTel defaultValue="(555) 12" />
|
|
8136
|
+
<Field.Error errors={[{ message: 'Enter a 10-digit phone number.' }]} />
|
|
8137
|
+
</FieldText>
|
|
8138
|
+
);</code></pre>
|
|
8139
|
+
</div>
|
|
8140
|
+
<div class="note ok">
|
|
8141
|
+
<div class="row">
|
|
8142
|
+
<span class="ex-name">All Sizes</span>
|
|
8143
|
+
<span class="badge ok">story ok</span>
|
|
8144
|
+
</div>
|
|
8145
|
+
<div>The three sizes side by side</div>
|
|
8146
|
+
<div class="hint">The three sizes match Input's: the frame is 32, 40 or 48px tall.</div>
|
|
8147
|
+
<pre><code>const AllSizes = () => <div style={{ display: 'grid', gap: '1rem' }}>
|
|
8148
|
+
<InputTel
|
|
8149
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}
|
|
8150
|
+
size="sm"
|
|
8151
|
+
aria-label="Small"
|
|
8152
|
+
defaultValue="(555) 123-4567" />
|
|
8153
|
+
<InputTel
|
|
8154
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}
|
|
8155
|
+
size="md"
|
|
8156
|
+
aria-label="Medium"
|
|
8157
|
+
defaultValue="(555) 123-4567" />
|
|
8158
|
+
<InputTel
|
|
8159
|
+
onChange={fn((event: ChangeEvent<HTMLInputElement>) => event.target.value)}
|
|
8160
|
+
size="lg"
|
|
8161
|
+
aria-label="Large"
|
|
8162
|
+
defaultValue="(555) 123-4567" />
|
|
8163
|
+
</div>;</code></pre>
|
|
8164
|
+
</div>
|
|
8165
|
+
</div>
|
|
8166
|
+
|
|
8167
|
+
|
|
7878
8168
|
</div>
|
|
7879
8169
|
</article>
|
|
7880
8170
|
<article
|
|
@@ -7889,9 +8179,9 @@ several search fields does not read "Clear search" twice.</div>
|
|
|
7889
8179
|
<div class="title">
|
|
7890
8180
|
<h2><span class="status-dot dot-ok"></span> Label</h2>
|
|
7891
8181
|
<div class="badges">
|
|
7892
|
-
<label for="c-
|
|
8182
|
+
<label for="c-22-components-label-props" class="badge ok as-toggle">3 prop types</label>
|
|
7893
8183
|
|
|
7894
|
-
<label for="c-
|
|
8184
|
+
<label for="c-22-components-label-stories" class="badge ok as-toggle">5 stories</label>
|
|
7895
8185
|
|
|
7896
8186
|
|
|
7897
8187
|
</div>
|
|
@@ -7911,10 +8201,10 @@ still has to carry `required` / `aria-required`.</div>
|
|
|
7911
8201
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
7912
8202
|
|
|
7913
8203
|
|
|
7914
|
-
<input id="c-
|
|
8204
|
+
<input id="c-22-components-label-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
7915
8205
|
|
|
7916
8206
|
|
|
7917
|
-
<input id="c-
|
|
8207
|
+
<input id="c-22-components-label-props" class="tg tg-props" type="checkbox" hidden />
|
|
7918
8208
|
|
|
7919
8209
|
<div class="panels">
|
|
7920
8210
|
|
|
@@ -8038,9 +8328,9 @@ field's control with no `htmlFor`. An explicit `htmlFor` still wins.</div>
|
|
|
8038
8328
|
<div class="title">
|
|
8039
8329
|
<h2><span class="status-dot dot-ok"></span> Loading</h2>
|
|
8040
8330
|
<div class="badges">
|
|
8041
|
-
<label for="c-
|
|
8331
|
+
<label for="c-23-components-loading-props" class="badge ok as-toggle">1 prop type</label>
|
|
8042
8332
|
|
|
8043
|
-
<label for="c-
|
|
8333
|
+
<label for="c-23-components-loading-stories" class="badge ok as-toggle">7 stories</label>
|
|
8044
8334
|
|
|
8045
8335
|
|
|
8046
8336
|
</div>
|
|
@@ -8057,10 +8347,10 @@ parent font size via `em`-based size variants (`sm`, `md`, `lg`).</div>
|
|
|
8057
8347
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
8058
8348
|
|
|
8059
8349
|
|
|
8060
|
-
<input id="c-
|
|
8350
|
+
<input id="c-23-components-loading-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
8061
8351
|
|
|
8062
8352
|
|
|
8063
|
-
<input id="c-
|
|
8353
|
+
<input id="c-23-components-loading-props" class="tg tg-props" type="checkbox" hidden />
|
|
8064
8354
|
|
|
8065
8355
|
<div class="panels">
|
|
8066
8356
|
|
|
@@ -8211,9 +8501,9 @@ against the dark background.</div>
|
|
|
8211
8501
|
<div class="title">
|
|
8212
8502
|
<h2><span class="status-dot dot-ok"></span> Modal.Root</h2>
|
|
8213
8503
|
<div class="badges">
|
|
8214
|
-
<label for="c-
|
|
8504
|
+
<label for="c-24-components-modal-props" class="badge ok as-toggle">5 prop types</label>
|
|
8215
8505
|
|
|
8216
|
-
<label for="c-
|
|
8506
|
+
<label for="c-24-components-modal-stories" class="badge ok as-toggle">6 stories</label>
|
|
8217
8507
|
|
|
8218
8508
|
|
|
8219
8509
|
</div>
|
|
@@ -8259,10 +8549,10 @@ import { Modal } from '@agentero/design-system/modal';
|
|
|
8259
8549
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
8260
8550
|
|
|
8261
8551
|
|
|
8262
|
-
<input id="c-
|
|
8552
|
+
<input id="c-24-components-modal-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
8263
8553
|
|
|
8264
8554
|
|
|
8265
|
-
<input id="c-
|
|
8555
|
+
<input id="c-24-components-modal-props" class="tg tg-props" type="checkbox" hidden />
|
|
8266
8556
|
|
|
8267
8557
|
<div class="panels">
|
|
8268
8558
|
|
|
@@ -8482,9 +8772,9 @@ announced as an `alertdialog`. Only the footer actions close it.</div>
|
|
|
8482
8772
|
<div class="title">
|
|
8483
8773
|
<h2><span class="status-dot dot-ok"></span> Pagination</h2>
|
|
8484
8774
|
<div class="badges">
|
|
8485
|
-
<label for="c-
|
|
8775
|
+
<label for="c-25-components-pagination-props" class="badge ok as-toggle">5 prop types</label>
|
|
8486
8776
|
|
|
8487
|
-
<label for="c-
|
|
8777
|
+
<label for="c-25-components-pagination-stories" class="badge ok as-toggle">7 stories</label>
|
|
8488
8778
|
|
|
8489
8779
|
|
|
8490
8780
|
</div>
|
|
@@ -8514,10 +8804,10 @@ const [page, setPage] = useState(1);
|
|
|
8514
8804
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
8515
8805
|
|
|
8516
8806
|
|
|
8517
|
-
<input id="c-
|
|
8807
|
+
<input id="c-25-components-pagination-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
8518
8808
|
|
|
8519
8809
|
|
|
8520
|
-
<input id="c-
|
|
8810
|
+
<input id="c-25-components-pagination-props" class="tg tg-props" type="checkbox" hidden />
|
|
8521
8811
|
|
|
8522
8812
|
<div class="panels">
|
|
8523
8813
|
|
|
@@ -8672,9 +8962,9 @@ entries summary follow along.</div>
|
|
|
8672
8962
|
<div class="title">
|
|
8673
8963
|
<h2><span class="status-dot dot-ok"></span> Popover.Root</h2>
|
|
8674
8964
|
<div class="badges">
|
|
8675
|
-
<label for="c-
|
|
8965
|
+
<label for="c-26-components-popover-props" class="badge ok as-toggle">5 prop types</label>
|
|
8676
8966
|
|
|
8677
|
-
<label for="c-
|
|
8967
|
+
<label for="c-26-components-popover-stories" class="badge ok as-toggle">5 stories</label>
|
|
8678
8968
|
|
|
8679
8969
|
|
|
8680
8970
|
</div>
|
|
@@ -8703,10 +8993,10 @@ import { Popover } from '@agentero/design-system/popover';
|
|
|
8703
8993
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
8704
8994
|
|
|
8705
8995
|
|
|
8706
|
-
<input id="c-
|
|
8996
|
+
<input id="c-26-components-popover-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
8707
8997
|
|
|
8708
8998
|
|
|
8709
|
-
<input id="c-
|
|
8999
|
+
<input id="c-26-components-popover-props" class="tg tg-props" type="checkbox" hidden />
|
|
8710
9000
|
|
|
8711
9001
|
<div class="panels">
|
|
8712
9002
|
|
|
@@ -8905,9 +9195,9 @@ focus returning to its trigger once the modal closes.</div>
|
|
|
8905
9195
|
<div class="title">
|
|
8906
9196
|
<h2><span class="status-dot dot-ok"></span> Progress</h2>
|
|
8907
9197
|
<div class="badges">
|
|
8908
|
-
<label for="c-
|
|
9198
|
+
<label for="c-27-components-progress-props" class="badge ok as-toggle">4 prop types</label>
|
|
8909
9199
|
|
|
8910
|
-
<label for="c-
|
|
9200
|
+
<label for="c-27-components-progress-stories" class="badge ok as-toggle">4 stories</label>
|
|
8911
9201
|
|
|
8912
9202
|
|
|
8913
9203
|
</div>
|
|
@@ -8926,10 +9216,10 @@ with `currentColor`, so recolor it with a plain text class — e.g.
|
|
|
8926
9216
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
8927
9217
|
|
|
8928
9218
|
|
|
8929
|
-
<input id="c-
|
|
9219
|
+
<input id="c-27-components-progress-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
8930
9220
|
|
|
8931
9221
|
|
|
8932
|
-
<input id="c-
|
|
9222
|
+
<input id="c-27-components-progress-props" class="tg tg-props" type="checkbox" hidden />
|
|
8933
9223
|
|
|
8934
9224
|
<div class="panels">
|
|
8935
9225
|
|
|
@@ -9048,7 +9338,7 @@ percentage: number</code></pre>
|
|
|
9048
9338
|
<div class="badges">
|
|
9049
9339
|
|
|
9050
9340
|
|
|
9051
|
-
<label for="c-
|
|
9341
|
+
<label for="c-28-components-skeleton-stories" class="badge ok as-toggle">4 stories</label>
|
|
9052
9342
|
|
|
9053
9343
|
|
|
9054
9344
|
</div>
|
|
@@ -9065,7 +9355,7 @@ shape it with Tailwind classes to mirror the content it stands in for.</div>
|
|
|
9065
9355
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
9066
9356
|
|
|
9067
9357
|
|
|
9068
|
-
<input id="c-
|
|
9358
|
+
<input id="c-28-components-skeleton-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
9069
9359
|
|
|
9070
9360
|
|
|
9071
9361
|
|
|
@@ -9161,9 +9451,9 @@ shape it with Tailwind classes to mirror the content it stands in for.</div>
|
|
|
9161
9451
|
<div class="title">
|
|
9162
9452
|
<h2><span class="status-dot dot-ok"></span> Switch</h2>
|
|
9163
9453
|
<div class="badges">
|
|
9164
|
-
<label for="c-
|
|
9454
|
+
<label for="c-29-components-switch-props" class="badge ok as-toggle">8 prop types</label>
|
|
9165
9455
|
|
|
9166
|
-
<label for="c-
|
|
9456
|
+
<label for="c-29-components-switch-stories" class="badge ok as-toggle">7 stories</label>
|
|
9167
9457
|
|
|
9168
9458
|
|
|
9169
9459
|
</div>
|
|
@@ -9179,10 +9469,10 @@ a Checkbox for a single boolean that applies instantly, and pair it with a
|
|
|
9179
9469
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
9180
9470
|
|
|
9181
9471
|
|
|
9182
|
-
<input id="c-
|
|
9472
|
+
<input id="c-29-components-switch-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
9183
9473
|
|
|
9184
9474
|
|
|
9185
|
-
<input id="c-
|
|
9475
|
+
<input id="c-29-components-switch-props" class="tg tg-props" type="checkbox" hidden />
|
|
9186
9476
|
|
|
9187
9477
|
<div class="panels">
|
|
9188
9478
|
|
|
@@ -9363,9 +9653,9 @@ size?: "sm" | "md"</code></pre>
|
|
|
9363
9653
|
<div class="title">
|
|
9364
9654
|
<h2><span class="status-dot dot-ok"></span> Table.Root</h2>
|
|
9365
9655
|
<div class="badges">
|
|
9366
|
-
<label for="c-
|
|
9656
|
+
<label for="c-30-components-table-props" class="badge ok as-toggle">6 prop types</label>
|
|
9367
9657
|
|
|
9368
|
-
<label for="c-
|
|
9658
|
+
<label for="c-30-components-table-stories" class="badge ok as-toggle">10 stories</label>
|
|
9369
9659
|
|
|
9370
9660
|
|
|
9371
9661
|
</div>
|
|
@@ -9396,10 +9686,10 @@ import { Table } from '@agentero/design-system/table';
|
|
|
9396
9686
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
9397
9687
|
|
|
9398
9688
|
|
|
9399
|
-
<input id="c-
|
|
9689
|
+
<input id="c-30-components-table-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
9400
9690
|
|
|
9401
9691
|
|
|
9402
|
-
<input id="c-
|
|
9692
|
+
<input id="c-30-components-table-props" class="tg tg-props" type="checkbox" hidden />
|
|
9403
9693
|
|
|
9404
9694
|
<div class="panels">
|
|
9405
9695
|
|
|
@@ -9617,9 +9907,9 @@ keeps its padding.</div>
|
|
|
9617
9907
|
<div class="title">
|
|
9618
9908
|
<h2><span class="status-dot dot-ok"></span> Tabs.Root</h2>
|
|
9619
9909
|
<div class="badges">
|
|
9620
|
-
<label for="c-
|
|
9910
|
+
<label for="c-31-components-tabs-props" class="badge ok as-toggle">9 prop types</label>
|
|
9621
9911
|
|
|
9622
|
-
<label for="c-
|
|
9912
|
+
<label for="c-31-components-tabs-stories" class="badge ok as-toggle">8 stories</label>
|
|
9623
9913
|
|
|
9624
9914
|
|
|
9625
9915
|
</div>
|
|
@@ -9650,10 +9940,10 @@ import { Tabs } from '@agentero/design-system/tabs';
|
|
|
9650
9940
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
9651
9941
|
|
|
9652
9942
|
|
|
9653
|
-
<input id="c-
|
|
9943
|
+
<input id="c-31-components-tabs-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
9654
9944
|
|
|
9655
9945
|
|
|
9656
|
-
<input id="c-
|
|
9946
|
+
<input id="c-31-components-tabs-props" class="tg tg-props" type="checkbox" hidden />
|
|
9657
9947
|
|
|
9658
9948
|
<div class="panels">
|
|
9659
9949
|
|
|
@@ -9874,9 +10164,9 @@ tablist role is announced.</div>
|
|
|
9874
10164
|
<div class="title">
|
|
9875
10165
|
<h2><span class="status-dot dot-ok"></span> Tag</h2>
|
|
9876
10166
|
<div class="badges">
|
|
9877
|
-
<label for="c-
|
|
10167
|
+
<label for="c-32-components-tag-props" class="badge ok as-toggle">8 prop types</label>
|
|
9878
10168
|
|
|
9879
|
-
<label for="c-
|
|
10169
|
+
<label for="c-32-components-tag-stories" class="badge ok as-toggle">12 stories</label>
|
|
9880
10170
|
|
|
9881
10171
|
|
|
9882
10172
|
</div>
|
|
@@ -9895,10 +10185,10 @@ it an interactive link or button, which adds the pointer cursor and hover fill.<
|
|
|
9895
10185
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
9896
10186
|
|
|
9897
10187
|
|
|
9898
|
-
<input id="c-
|
|
10188
|
+
<input id="c-32-components-tag-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
9899
10189
|
|
|
9900
10190
|
|
|
9901
|
-
<input id="c-
|
|
10191
|
+
<input id="c-32-components-tag-props" class="tg tg-props" type="checkbox" hidden />
|
|
9902
10192
|
|
|
9903
10193
|
<div class="panels">
|
|
9904
10194
|
|
|
@@ -10323,9 +10613,9 @@ leading + trailing icons, and icon-only.</div>
|
|
|
10323
10613
|
<div class="title">
|
|
10324
10614
|
<h2><span class="status-dot dot-ok"></span> TextArea</h2>
|
|
10325
10615
|
<div class="badges">
|
|
10326
|
-
<label for="c-
|
|
10616
|
+
<label for="c-33-components-textarea-props" class="badge ok as-toggle">1 prop type</label>
|
|
10327
10617
|
|
|
10328
|
-
<label for="c-
|
|
10618
|
+
<label for="c-33-components-textarea-stories" class="badge ok as-toggle">6 stories</label>
|
|
10329
10619
|
|
|
10330
10620
|
|
|
10331
10621
|
</div>
|
|
@@ -10342,10 +10632,10 @@ states. It wires nothing on its own: `id`, `aria-invalid` and
|
|
|
10342
10632
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
10343
10633
|
|
|
10344
10634
|
|
|
10345
|
-
<input id="c-
|
|
10635
|
+
<input id="c-33-components-textarea-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
10346
10636
|
|
|
10347
10637
|
|
|
10348
|
-
<input id="c-
|
|
10638
|
+
<input id="c-33-components-textarea-props" class="tg tg-props" type="checkbox" hidden />
|
|
10349
10639
|
|
|
10350
10640
|
<div class="panels">
|
|
10351
10641
|
|
|
@@ -10477,9 +10767,9 @@ size and the minimum height shows three rows.</div>
|
|
|
10477
10767
|
<div class="title">
|
|
10478
10768
|
<h2><span class="status-dot dot-ok"></span> Toast</h2>
|
|
10479
10769
|
<div class="badges">
|
|
10480
|
-
<label for="c-
|
|
10770
|
+
<label for="c-34-components-toast-props" class="badge ok as-toggle">11 prop types</label>
|
|
10481
10771
|
|
|
10482
|
-
<label for="c-
|
|
10772
|
+
<label for="c-34-components-toast-stories" class="badge ok as-toggle">11 stories</label>
|
|
10483
10773
|
|
|
10484
10774
|
|
|
10485
10775
|
</div>
|
|
@@ -10498,10 +10788,10 @@ common feedback patterns.</div>
|
|
|
10498
10788
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
10499
10789
|
|
|
10500
10790
|
|
|
10501
|
-
<input id="c-
|
|
10791
|
+
<input id="c-34-components-toast-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
10502
10792
|
|
|
10503
10793
|
|
|
10504
|
-
<input id="c-
|
|
10794
|
+
<input id="c-34-components-toast-props" class="tg tg-props" type="checkbox" hidden />
|
|
10505
10795
|
|
|
10506
10796
|
<div class="panels">
|
|
10507
10797
|
|
|
@@ -10930,9 +11220,9 @@ action (e.g., a sync icon for a sync-in-progress toast).</div>
|
|
|
10930
11220
|
<div class="title">
|
|
10931
11221
|
<h2><span class="status-dot dot-ok"></span> Tooltip</h2>
|
|
10932
11222
|
<div class="badges">
|
|
10933
|
-
<label for="c-
|
|
11223
|
+
<label for="c-35-components-tooltip-props" class="badge ok as-toggle">12 prop types</label>
|
|
10934
11224
|
|
|
10935
|
-
<label for="c-
|
|
11225
|
+
<label for="c-35-components-tooltip-stories" class="badge ok as-toggle">5 stories</label>
|
|
10936
11226
|
|
|
10937
11227
|
|
|
10938
11228
|
</div>
|
|
@@ -10951,10 +11241,10 @@ on hover or focus.</div>
|
|
|
10951
11241
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
10952
11242
|
|
|
10953
11243
|
|
|
10954
|
-
<input id="c-
|
|
11244
|
+
<input id="c-35-components-tooltip-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
10955
11245
|
|
|
10956
11246
|
|
|
10957
|
-
<input id="c-
|
|
11247
|
+
<input id="c-35-components-tooltip-props" class="tg tg-props" type="checkbox" hidden />
|
|
10958
11248
|
|
|
10959
11249
|
<div class="panels">
|
|
10960
11250
|
|
|
@@ -11126,9 +11416,9 @@ sideOffset?: number = 4</code></pre>
|
|
|
11126
11416
|
<div class="title">
|
|
11127
11417
|
<h2><span class="status-dot dot-ok"></span> ValidationList</h2>
|
|
11128
11418
|
<div class="badges">
|
|
11129
|
-
<label for="c-
|
|
11419
|
+
<label for="c-36-components-validationlist-props" class="badge ok as-toggle">2 prop types</label>
|
|
11130
11420
|
|
|
11131
|
-
<label for="c-
|
|
11421
|
+
<label for="c-36-components-validationlist-stories" class="badge ok as-toggle">4 stories</label>
|
|
11132
11422
|
|
|
11133
11423
|
|
|
11134
11424
|
</div>
|
|
@@ -11149,10 +11439,10 @@ your form validation; it does not own the input or block submission.</div>
|
|
|
11149
11439
|
<!-- ⬇️ Hidden toggles must be siblings BEFORE .panels -->
|
|
11150
11440
|
|
|
11151
11441
|
|
|
11152
|
-
<input id="c-
|
|
11442
|
+
<input id="c-36-components-validationlist-stories" class="tg tg-stories" type="checkbox" hidden />
|
|
11153
11443
|
|
|
11154
11444
|
|
|
11155
|
-
<input id="c-
|
|
11445
|
+
<input id="c-36-components-validationlist-props" class="tg tg-props" type="checkbox" hidden />
|
|
11156
11446
|
|
|
11157
11447
|
<div class="panels">
|
|
11158
11448
|
|