@thebase/ui 1.1.4 → 1.1.6

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.
@@ -1697,13 +1697,13 @@
1697
1697
  }
1698
1698
  ],
1699
1699
  "integrity": {
1700
- "baseui.min.css": "sha384-RP2d04etuqh6nmVNHdJFYqK79B7N55jITUg52YrEXI3lyla5kJA4AHa2hUq79v0m",
1700
+ "baseui.min.css": "sha384-CJXU0BIk1YJ6i2k4WqGlnxRXisLJ1pvbbdAOaIYXbsq3NjdqvCsST304XieDxyIp",
1701
1701
  "bootstrap.bundle.min.js": "sha384-RMbllTJcplkCRnELNTOc5Kz/3AvFDE/rNlJqWqfgmRWruobClBdfwvl10akQZkR1",
1702
- "baseui.min.js": "sha384-6WmmDQaq2vveoleqTuVjap7gNc/1I9cKo+GmkXdLpgKwap8gwo8P5Yw80YWT+Cuj",
1703
- "baseui.esm.js": "sha384-9haHF/FrXo5MXP2GQGK33GkmwAXQAde21ogM5mvCuWyOHwhyEwSw8isxrzgaHrs7",
1702
+ "baseui.min.js": "sha384-RRvp6vUHm/o+shXVAySNrLIPTaWQis8FmnhSPziowptMMfxaPmfWvrwCqKqNpYTo",
1703
+ "baseui.esm.js": "sha384-lqsK9lnh8XSA2lx94aLjn0Ndngg3B6lRVp734RbJmO51IUA0xufqGYyE5+nV9kKu",
1704
1704
  "baseui.icons.esm.js": "sha384-hj39VMhzcFvmYnjob2hlioMOAqwAXCURGreF6s9RitXFp/iYi7rUdqtfCI+ICQeS",
1705
- "baseui.templates.xml": "sha384-4pEOfbxiBDpMq0vJHvl9+ZFNcnTDhvZGdTZcmCFOELE0vXQrateo0qlO8VeuoKdq",
1706
- "baseui.block-viewer.esm.js": "sha384-6GNPYUTwsoi1ZsfOWhVWqw4vI328WX6Xb5f7A4HygyT5s+fmJaEbL7ZQmPamoyJz",
1705
+ "baseui.templates.xml": "sha384-7ALCzje9vh+KVAMbUXRuj10oa2Fnreo1X8wv2+MFVsMo1wXYNL59Yh/HCk35Vn8d",
1706
+ "baseui.block-viewer.esm.js": "sha384-y7RT1EQqZt+wRpYQOjJW1vV/flr7rMB62ri6NmYbf8Yg+YQEIhFBeywjB90YIaML",
1707
1707
  "baseui.analytics.esm.js": "sha384-M6TVmchmceTvpSzgI+DNA6zAn9xmz9a+YEexCLslSo/Ngxyp2kmzs9fm+PxWy+Da",
1708
1708
  "baseui.analytics.min.js": "sha384-B0hBkVDbT7gmDmUMazlN4Nc1KnYGSpL+IcW2hd8840knx73HGImPgGs84MvS3hKE",
1709
1709
  "icons/lucide.json": "sha384-mc5mzpmq9eOgZVa2IcjrL33Ty4nMXE8aoZMfy+lgkC/jMQ4aYnk2S58mFsSGFnW1",
@@ -1085,16 +1085,7 @@
1085
1085
  </t>
1086
1086
  <t t-name="baseui.Combobox">
1087
1087
  <div t-att-class="'bu-combobox' + (props.className ? ' ' + props.className : '')" t-att-style="props.style" t-ref="root">
1088
- <input
1089
- class="form-control"
1090
- role="combobox"
1091
- t-att-id="props.id"
1092
- t-att-aria-expanded="disclosure.open ? 'true' : 'false'"
1093
- t-att-placeholder="props.placeholder"
1094
- t-att-value="state.query"
1095
- t-on-input="onInput"
1096
- t-on-focus="onFocus"
1097
- />
1088
+ <t t-call="baseui.Outlined"><t t-call="baseui.Combobox.field"/></t>
1098
1089
  <div t-if="disclosure.open" class="bu-combobox-list" role="listbox">
1099
1090
  <div
1100
1091
  t-foreach="filteredOptions"
@@ -1109,6 +1100,21 @@
1109
1100
  </div>
1110
1101
  </div>
1111
1102
  </t>
1103
+ <t t-name="baseui.Combobox.field">
1104
+ <input
1105
+ t-att-class="classNames"
1106
+ role="combobox"
1107
+ t-att-id="props.id"
1108
+ t-att-disabled="props.disabled"
1109
+ t-att-aria-expanded="disclosure.open ? 'true' : 'false'"
1110
+ t-att-aria-invalid="isInvalid ? 'true' : undefined"
1111
+ t-att-aria-describedby="describedBy"
1112
+ t-att-placeholder="fieldPlaceholder"
1113
+ t-att-value="state.query"
1114
+ t-on-input="onInput"
1115
+ t-on-focus="onFocus"
1116
+ />
1117
+ </t>
1112
1118
  <t t-name="Combobox" t-call="baseui.Combobox"/>
1113
1119
  <t t-name="baseui.command">
1114
1120
  <div b-ui="command" class="bu-command"/>
@@ -1344,12 +1350,17 @@
1344
1350
  <input class="form-control" type="date"/>
1345
1351
  </t>
1346
1352
  <t t-name="baseui.DatePicker">
1353
+ <t t-call="baseui.Outlined"><t t-call="baseui.DatePicker.field"/></t>
1354
+ </t>
1355
+ <t t-name="baseui.DatePicker.field">
1347
1356
  <input
1348
1357
  type="date"
1349
1358
  t-att-class="classNames"
1350
1359
  t-att-style="props.style"
1351
1360
  t-att-value="props.value"
1352
1361
  t-att-disabled="props.disabled"
1362
+ t-att-aria-invalid="isInvalid ? 'true' : undefined"
1363
+ t-att-aria-describedby="describedBy"
1353
1364
  t-on-input="onInput"
1354
1365
  />
1355
1366
  </t>
@@ -1616,13 +1627,7 @@
1616
1627
  t-att-class="classNames"
1617
1628
  t-att-style="props.style"
1618
1629
  >
1619
- <label t-if="props.label" class="bu-field-label" data-slot="field-label">
1620
- <t t-esc="props.label"/>
1621
- </label>
1622
1630
  <t t-slot="default"/>
1623
- <div t-if="props.error" role="alert" class="bu-field-error" data-slot="field-error">
1624
- <t t-esc="props.error"/>
1625
- </div>
1626
1631
  </div>
1627
1632
  </t>
1628
1633
  <t t-name="Field" t-call="baseui.Field"/>
@@ -1746,7 +1751,7 @@
1746
1751
  </t>
1747
1752
  <t t-name="HoverCardTrigger" t-call="baseui.HoverCardTrigger"/>
1748
1753
  <t t-name="baseui.HoverCardContent">
1749
- <span t-if="open" class="bu-hover-card-content" t-att-style="props.style" role="dialog"><t t-slot="default"/></span>
1754
+ <span t-if="open" t-att-class="'bu-hover-card-content' + (props.className ? ' ' + props.className : '')" t-att-style="props.style" role="dialog"><t t-slot="default"/></span>
1750
1755
  </t>
1751
1756
  <t t-name="HoverCardContent" t-call="baseui.HoverCardContent"/>
1752
1757
  <t t-name="baseui.Icon">
@@ -1761,20 +1766,24 @@
1761
1766
  ></span>
1762
1767
  </t>
1763
1768
  <t t-name="Icon" t-call="baseui.Icon"/>
1764
- <t t-name="baseui.Input">
1765
- <div t-if="isOutlined" t-att-class="outlinedClassNames">
1769
+ <t t-name="baseui.Outlined">
1770
+ <div t-if="isOutlined" t-att-class="outlinedClassNames" t-att-style="labelStyle">
1766
1771
  <div class="bu-input-box">
1767
- <Icon t-if="props.leadingIcon" name="props.leadingIcon" className="'bu-input-icon bu-input-leading'"/>
1768
- <t t-call="baseui.Input.field"/>
1769
- <span class="bu-input-label" t-esc="props.label"/>
1772
+ <Icon t-if="leadingIcon" name="leadingIcon" className="'bu-input-icon bu-input-leading'"/>
1773
+ <t t-out="0"/>
1774
+ <span class="bu-input-label" t-esc="label"/>
1770
1775
  <Icon t-if="trailingIcon" name="trailingIcon" className="'bu-input-icon bu-input-trailing'"/>
1776
+ <Tooltip t-if="tipText" content="tipText" className="'bu-input-tip'"><t t-set-slot="trigger"><Icon name="'info'"/></t></Tooltip>
1771
1777
  </div>
1772
1778
  <div t-if="supportingText or props.maxLength" class="bu-input-support">
1773
1779
  <span t-att-id="supportId" t-esc="supportingText"/>
1774
1780
  <span t-if="props.maxLength" class="bu-input-counter" t-esc="counter"/>
1775
1781
  </div>
1776
1782
  </div>
1777
- <t t-else="" t-call="baseui.Input.field"/>
1783
+ <t t-else="" t-out="0"/>
1784
+ </t>
1785
+ <t t-name="baseui.Input">
1786
+ <t t-call="baseui.Outlined"><t t-call="baseui.Input.field"/></t>
1778
1787
  </t>
1779
1788
  <t t-name="baseui.Input.field">
1780
1789
  <input
@@ -1791,7 +1800,7 @@
1791
1800
  t-att-maxlength="props.maxLength"
1792
1801
  t-att-aria-label="ariaLabel"
1793
1802
  t-att-aria-invalid="isInvalid ? 'true' : undefined"
1794
- t-att-aria-describedby="supportingText ? supportId : undefined"
1803
+ t-att-aria-describedby="describedBy"
1795
1804
  t-att-min="props.min"
1796
1805
  t-att-max="props.max"
1797
1806
  t-att-step="props.step"
@@ -1802,7 +1811,11 @@
1802
1811
  <t t-name="Input" t-call="baseui.Input"/>
1803
1812
  <t t-name="baseui.input-group"><div b-ui="input-group"><t t-esc="props.content"/></div></t>
1804
1813
  <t t-name="baseui.InputGroup">
1805
- <div t-att-class="classNames" t-att-style="props.style" data-slot="input-group" role="group"><t t-slot="default"/></div>
1814
+ <t t-call="baseui.Outlined"><t t-call="baseui.InputGroup.box"/></t>
1815
+ </t>
1816
+ <t t-name="baseui.InputGroup.box">
1817
+ <div t-att-class="classNames" t-att-style="props.style" data-slot="input-group" role="group"
1818
+ t-att-aria-describedby="describedBy"><t t-slot="default"/></div>
1806
1819
  </t>
1807
1820
  <t t-name="baseui.InputGroupAddon">
1808
1821
  <div
@@ -1837,7 +1850,7 @@
1837
1850
  t-att-class="classNames"
1838
1851
  t-att-style="props.style"
1839
1852
  t-att-type="props.type || 'text'"
1840
- t-att-placeholder="props.placeholder"
1853
+ t-att-placeholder="fieldPlaceholder"
1841
1854
  t-att-value="props.value"
1842
1855
  t-att-disabled="props.disabled"
1843
1856
  t-att-readonly="props.readonly"
@@ -1851,7 +1864,7 @@
1851
1864
  <textarea
1852
1865
  t-att-class="classNames"
1853
1866
  t-att-style="props.style"
1854
- t-att-placeholder="props.placeholder"
1867
+ t-att-placeholder="fieldPlaceholder"
1855
1868
  t-att-rows="props.rows"
1856
1869
  t-att-disabled="props.disabled"
1857
1870
  t-att-readonly="props.readonly"
@@ -2044,8 +2057,13 @@
2044
2057
  <select b-ui="native-select"><t t-slot="default"/></select>
2045
2058
  </t>
2046
2059
  <t t-name="baseui.NativeSelect">
2060
+ <t t-call="baseui.Outlined"><t t-call="baseui.NativeSelect.field"/></t>
2061
+ </t>
2062
+ <t t-name="baseui.NativeSelect.field">
2047
2063
  <select t-att-class="classNames" t-att-disabled="props.disabled" t-att-value="props.value"
2048
- t-att-aria-label="ariaLabel" t-att-id="props.id" t-att-style="props.style" t-on-change="onChange">
2064
+ t-att-aria-label="ariaLabel" t-att-id="props.id" t-att-style="props.style"
2065
+ t-att-aria-invalid="isInvalid ? 'true' : undefined" t-att-aria-describedby="describedBy"
2066
+ t-on-change="onChange">
2049
2067
  <t t-slot="default"/>
2050
2068
  </select>
2051
2069
  </t>
@@ -2256,7 +2274,14 @@
2256
2274
  <t t-name="Separator" t-call="baseui.Separator"/>
2257
2275
  <t t-name="baseui.select"><div b-ui="select"><t t-esc="props.content"/></div></t>
2258
2276
  <t t-name="baseui.Select">
2259
- <div t-att-class="classNames" t-att-style="props.style" t-ref="root"><t t-slot="default"/></div>
2277
+ <div t-att-class="classNames" t-att-style="rootStyle" t-ref="root">
2278
+ <t t-slot="default"/>
2279
+ <span t-if="isOutlined" class="bu-input-label" t-esc="label"/>
2280
+ <Tooltip t-if="isOutlined and tipText" content="tipText" className="'bu-input-tip'"><t t-set-slot="trigger"><Icon name="'info'"/></t></Tooltip>
2281
+ <div t-if="isOutlined and supportingText" class="bu-input-support">
2282
+ <span t-att-id="supportId" t-esc="supportingText"/>
2283
+ </div>
2284
+ </div>
2260
2285
  </t>
2261
2286
  <t t-name="Select" t-call="baseui.Select"/>
2262
2287
  <t t-name="baseui.SelectTrigger">
@@ -2732,15 +2757,21 @@
2732
2757
  <textarea b-ui="textarea"></textarea>
2733
2758
  </t>
2734
2759
  <t t-name="baseui.Textarea">
2760
+ <t t-call="baseui.Outlined"><t t-call="baseui.Textarea.field"/></t>
2761
+ </t>
2762
+ <t t-name="baseui.Textarea.field">
2735
2763
  <textarea
2736
2764
  t-att-class="classNames"
2737
2765
  t-att-style="props.style"
2738
- t-att-placeholder="props.placeholder"
2766
+ t-att-placeholder="fieldPlaceholder"
2739
2767
  t-att-rows="props.rows"
2740
2768
  t-att-disabled="props.disabled"
2741
2769
  t-att-readonly="props.readonly"
2742
2770
  t-att-value="props.value"
2743
2771
  t-att-id="props.id"
2772
+ t-att-maxlength="props.maxLength"
2773
+ t-att-aria-invalid="isInvalid ? 'true' : undefined"
2774
+ t-att-aria-describedby="describedBy"
2744
2775
  t-on-input="onInput"
2745
2776
  t-on-change="onChange"
2746
2777
  ></textarea>
package/docs/analytics.md CHANGED
@@ -13,12 +13,12 @@ init({ backendUrl: "https://stats.example.com" });
13
13
  ```html
14
14
  <!-- ES module from the CDN (or map it as "@base/analytics" in an import map) -->
15
15
  <script type="module">
16
- import { init } from "https://cdn.jsdelivr.net/npm/@thebase/ui@1.1.3/dist/baseui.analytics.esm.js";
16
+ import { init } from "https://cdn.jsdelivr.net/npm/@thebase/ui@1.1.6/dist/baseui.analytics.esm.js";
17
17
  init({ backendUrl: "https://stats.example.com" });
18
18
  </script>
19
19
 
20
20
  <!-- Classic script tag: sets window.thebase.analytics (load order vs dist/baseui.min.js doesn't matter) -->
21
- <script src="https://cdn.jsdelivr.net/npm/@thebase/ui@1.1.3/dist/baseui.analytics.min.js"></script>
21
+ <script src="https://cdn.jsdelivr.net/npm/@thebase/ui@1.1.6/dist/baseui.analytics.min.js"></script>
22
22
  <script>
23
23
  thebase.analytics.init({ backendUrl: "https://stats.example.com" });
24
24
  </script>
@@ -228,7 +228,7 @@ curl -i -X POST http://localhost:8080/api/event -H 'Content-Type: text/plain' \
228
228
 
229
229
  [`examples/analytics/`](../examples/analytics/dashboard/?backend=http://localhost:8080) contains a working dashboard plus two complete sample backends: [`server-go`](../examples/analytics/server-go/main.go) (Fiber v3) and [`server-fastapi`](../examples/analytics/server-fastapi/main.py). Each one extends the receivers above with an in-memory store, a daily-salted cookieless visitor hash, a `GET /api/stats` endpoint, and static hosting for the dashboard.
230
230
 
231
- The dashboard ([`dashboard/`](../examples/analytics/dashboard/?backend=http://localhost:8080)) is a pure application that loads `@thebase/ui@1.1.3` from jsDelivr: KPI `Card`s, an area `Chart`, top pages/sources/events `Table`s, site and period `NativeSelect`s, and a `ThemeButton`. It refreshes every 30 s and tracks its own visits through `@thebase/ui/analytics`, so a fresh backend has data straight away.
231
+ The dashboard ([`dashboard/`](../examples/analytics/dashboard/?backend=http://localhost:8080)) is a pure application that loads `@thebase/ui@1.1.6` from jsDelivr: KPI `Card`s, an area `Chart`, top pages/sources/events `Table`s, site and period `NativeSelect`s, and a `ThemeButton`. It refreshes every 30 s and tracks its own visits through `@thebase/ui/analytics`, so a fresh backend has data straight away.
232
232
 
233
233
  ```sh
234
234
  # Go (1.25+)
package/docs/blocks.md CHANGED
@@ -13,7 +13,7 @@ Blocks are not standalone runtime components. Paste the markup and load the norm
13
13
  <script src="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.js" defer></script>
14
14
  ```
15
15
 
16
- `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.3`, or `@1` to take only non-breaking updates) instead of `@latest` for production. Blocks are static markup, so they only need the static `b-ui` runtime above — see [Usage Guide](usage-guide.md) if the surrounding page is itself an application and you'd rather compose the equivalent layout from [Base Components](owl-components.md).
16
+ `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) instead of `@latest` for production. Blocks are static markup, so they only need the static `b-ui` runtime above — see [Usage Guide](usage-guide.md) if the surrounding page is itself an application and you'd rather compose the equivalent layout from [Base Components](owl-components.md).
17
17
 
18
18
  Use `b-block` to select the block style:
19
19
 
@@ -20,7 +20,7 @@ import { Combobox } from "@thebase/ui";
20
20
  { value: 'nuxtjs', label: 'Nuxt.js' },
21
21
  { value: 'remix', label: 'Remix' },
22
22
  { value: 'astro', label: 'Astro' },
23
- ]" placeholder="'Select a framework'"/>
23
+ ]" label="'Framework'" placeholder="'Select a framework'"/>
24
24
  </div>
25
25
  ```
26
26
 
@@ -32,6 +32,7 @@ import { Combobox } from "@thebase/ui";
32
32
  | `Combobox` | `className` | `String` | optional |
33
33
  | `Combobox` | `id` | `String` | optional, e.g. for `Label`'s `for` |
34
34
  | `Combobox` | `onChange` | `Function` | optional |
35
+ | `Combobox` | `label`, `labelBackground`, `supportingText`, `useTip`, `errorText`, `invalid`, `disabled` | `String` / `Boolean` | Material-style outlined field, same behaviour as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border, `errorText` replaces `supportingText`. Also inherited from a parent `Field`. |
35
36
 
36
37
  See [Base Components](/examples/blocks.html#/docs/guide/owl-components) for how to load `@base/owl` and `dist/baseui.templates.xml`.
37
38
 
@@ -13,9 +13,9 @@ import { DatePicker } from "@thebase/ui";
13
13
  ```
14
14
 
15
15
  ```base-ui
16
- <div style="max-width: 28rem" class="w-100 d-flex flex-column gap-2">
17
- <Label>Date of birth</Label>
18
- <DatePicker/>
16
+ <div style="max-width: 28rem" class="w-100 d-flex flex-column gap-4">
17
+ <DatePicker label="'Date of birth'" supportingText="'As on your ID'"/>
18
+ <DatePicker label="'Start date'" errorText="'Pick a date'"/>
19
19
  </div>
20
20
  ```
21
21
 
@@ -25,6 +25,7 @@ import { DatePicker } from "@thebase/ui";
25
25
  | `DatePicker` | `disabled` | `Boolean` | optional |
26
26
  | `DatePicker` | `className` | `String` | optional |
27
27
  | `DatePicker` | `onChange` | `Function` | optional |
28
+ | `DatePicker` | `label`, `labelBackground`, `supportingText`, `useTip`, `errorText`, `invalid` | `String` / `Boolean` | Material-style outlined field, same behaviour as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border, `errorText` replaces `supportingText`. Also inherited from a parent `Field`. |
28
29
 
29
30
  See [Base Components](/examples/blocks.html#/docs/guide/owl-components) for how to load `@base/owl` and `dist/baseui.templates.xml`.
30
31
 
@@ -25,37 +25,31 @@ import {
25
25
  <FieldLegend>Payment Method</FieldLegend>
26
26
  <FieldDescription>All transactions are secure and encrypted</FieldDescription>
27
27
  <FieldGroup className="'mt-3 gap-3 d-flex flex-column'">
28
- <Field>
29
- <FieldLabel for="'card-name'">Name on Card</FieldLabel>
28
+ <Field label="'Name on Card'">
30
29
  <Input id="'card-name'" value="'Evil Rabbit'"/>
31
30
  </Field>
32
31
 
33
- <Field>
34
- <FieldLabel for="'card-number'">Card Number</FieldLabel>
35
- <Input id="'card-number'" value="'1234 5678 9012 3456'"/>
36
- <FieldDescription>Enter your 16-digit card number</FieldDescription>
32
+ <Field label="'Card Number'" description="'Enter your 16-digit card number'">
33
+ <Input id="'card-number'" value="'1234 5678 9012 3456'" leadingIcon="'credit-card'"/>
37
34
  </Field>
38
35
 
39
36
  <div class="row g-3">
40
37
  <div class="col-4">
41
- <Field>
42
- <FieldLabel for="'expiry-month'">Month</FieldLabel>
43
- <NativeSelect id="'expiry-month'" ariaLabel="'Month'">
38
+ <Field label="'Month'">
39
+ <NativeSelect id="'expiry-month'">
44
40
  <option>MM</option>
45
41
  </NativeSelect>
46
42
  </Field>
47
43
  </div>
48
44
  <div class="col-4">
49
- <Field>
50
- <FieldLabel for="'expiry-year'">Year</FieldLabel>
51
- <NativeSelect id="'expiry-year'" ariaLabel="'Year'">
45
+ <Field label="'Year'">
46
+ <NativeSelect id="'expiry-year'">
52
47
  <option>YYYY</option>
53
48
  </NativeSelect>
54
49
  </Field>
55
50
  </div>
56
51
  <div class="col-4">
57
- <Field>
58
- <FieldLabel for="'card-cvv'">CVV</FieldLabel>
52
+ <Field label="'CVV'">
59
53
  <Input id="'card-cvv'" value="'123'"/>
60
54
  </Field>
61
55
  </div>
@@ -72,8 +66,7 @@ import {
72
66
  </Field>
73
67
  </FieldSet>
74
68
 
75
- <Field>
76
- <FieldLabel for="'comments'">Comments</FieldLabel>
69
+ <Field label="'Comments'">
77
70
  <Textarea id="'comments'" placeholder="'Add any additional comments'" rows="3"/>
78
71
  </Field>
79
72
  </FieldGroup>
@@ -86,6 +79,19 @@ import {
86
79
  </form>
87
80
  ```
88
81
 
82
+ ### Outlined controls
83
+
84
+ `Field` accepts `label`, `labelBackground`, `description`, `useTip` (1 = show the description in a tooltip), `error` and `invalid`, and hands them to the control inside it. `Input`, `Textarea`, `NativeSelect`, `Select`, `Combobox` and `DatePicker` draw them in the Material outlined style (floating label, helper text, error text and icon). A control's own `label`/`supportingText`/`errorText` props win over the `Field` values.
85
+
86
+ ```base-ui
87
+ <div class="d-grid gap-4" style="max-width: 28rem; width: 100%">
88
+ <Field label="'Email'" description="'We never share it'"><Input leadingIcon="'mail'"/></Field>
89
+ <Field label="'Bio'" error="'Too short'"><Textarea/></Field>
90
+ </div>
91
+ ```
92
+
93
+ Use one control per labelled `Field`. For checkboxes, radios and switches keep `FieldLabel` and `FieldDescription`; `Field`'s `label` prop no longer renders a standalone label.
94
+
89
95
  ## Static component
90
96
 
91
97
  ```base-ui
@@ -10,15 +10,12 @@ import { HoverCard, HoverCardContent, HoverCardTrigger } from "@thebase/ui";
10
10
  <div style="max-width: 28rem">
11
11
  <HoverCard>
12
12
  <HoverCardTrigger>
13
- <a href="https://twitter.com/shadcn" class="text-decoration-underline">@shadcn</a>
13
+ <a href="https://thebase.vn" class="text-decoration-underline">@thebase</a>
14
14
  </HoverCardTrigger>
15
15
  <HoverCardContent className="'w-auto'">
16
16
  <div class="d-flex justify-content-between gap-3" style="width: 20rem">
17
- <Avatar src="'https://github.com/shadcn.png'" alt="'@shadcn'">
18
- <t t-set-slot="fallback">SC</t>
19
- </Avatar>
20
- <div class="d-flex flex-column gap-1">
21
- <h4 class="small fw-semibold mb-0">@shadcn</h4>
17
+ <div class="d-flex flex-column gap-1" style="min-width: 0">
18
+ <h4 class="small fw-semibold mb-0">@thebase</h4>
22
19
  <p class="small mb-0">The React Framework – created and maintained by @vercel.</p>
23
20
  <div class="d-flex align-items-center pt-2">
24
21
  <span class="small text-muted">Joined December 2021</span>
@@ -15,22 +15,22 @@ import {
15
15
 
16
16
  ```base-ui
17
17
  <div class="d-flex flex-column gap-4 w-100" style="max-width: 28rem">
18
- <InputGroup>
19
- <InputGroupInput placeholder="'Search...'"/>
18
+ <InputGroup label="'Search'" supportingText="'Search the docs'">
19
+ <InputGroupInput/>
20
20
  <InputGroupAddon align="'inline-end'">
21
21
  <Icon name="'search'"/>
22
22
  </InputGroupAddon>
23
23
  </InputGroup>
24
24
 
25
- <InputGroup>
25
+ <InputGroup label="'Website'">
26
26
  <InputGroupInput placeholder="'https://'"/>
27
27
  <InputGroupAddon align="'inline-end'">
28
28
  <InputGroupButton>Search</InputGroupButton>
29
29
  </InputGroupAddon>
30
30
  </InputGroup>
31
31
 
32
- <InputGroup>
33
- <InputGroupTextarea placeholder="'Enter message...'" rows="3"/>
32
+ <InputGroup label="'Message'">
33
+ <InputGroupTextarea rows="3"/>
34
34
  <InputGroupAddon align="'block-end'">
35
35
  <InputGroupText>0/280</InputGroupText>
36
36
  <InputGroupButton variant="'default'" className="'ms-auto'">Send</InputGroupButton>
@@ -42,6 +42,7 @@ import {
42
42
  | Component | Prop | Type | Notes |
43
43
  | --- | --- | --- | --- |
44
44
  | `InputGroup` | `className` | `String` | optional |
45
+ | `InputGroup` | `label`, `labelBackground`, `supportingText`, `useTip`, `errorText`, `invalid` | `String` / `Boolean` | Material-style outlined group, same label as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border once the control is focused or filled. Also inherited from a parent `Field`. |
45
46
  | `InputGroupAddon` | `align` | `String` | `inline-start` (default), `inline-end`, `block-start`, `block-end` |
46
47
  | `InputGroupButton` | `variant` | `String` | `default`, `destructive`, `outline`, `secondary`, `ghost` (default), `link` |
47
48
  | `InputGroupButton` | `size` | `String` | `xs` (default), `icon-xs`, `sm`, `icon-sm` |
@@ -30,7 +30,9 @@ import { Input } from "@thebase/ui";
30
30
  | --- | --- | --- |
31
31
  | `value` | `String` | controlled value; the component never mutates it itself |
32
32
  | `label` | `String` | Material-style outlined field: label rests inside, floats onto the border when focused/filled (or when `placeholder` is set) |
33
+ | `labelBackground` | `String` | any CSS colour for the floated label's background (default matches the field, `--bu-field-bg`); use it when the field sits on a surface of a different colour |
33
34
  | `supportingText` | `String` | helper line under the field, linked via `aria-describedby` |
35
+ | `useTip` | `Number` | `0` (default) shows `supportingText` under the field; `1` hides it and shows it in a tooltip on an info icon (error text still shows under the field) |
34
36
  | `errorText` | `String` | marks the field invalid, replaces `supportingText`, swaps the trailing icon for an error icon, sets `aria-invalid` |
35
37
  | `leadingIcon` / `trailingIcon` | `String` | Lucide icon names (outlined mode only) |
36
38
  | `maxLength` | `Number` | native limit; outlined mode also shows a `n/max` counter |
@@ -10,8 +10,7 @@ import { NativeSelect } from "@thebase/ui";
10
10
 
11
11
  ```base-ui
12
12
  <div class="d-grid w-100 gap-2" style="max-width: 24rem">
13
- <Label for="'fruit'">Fruit</Label>
14
- <NativeSelect>
13
+ <NativeSelect label="'Fruit'">
15
14
  <option value="'apple'">Apple</option>
16
15
  <option value="'banana'">Banana</option>
17
16
  <option value="'blueberry'">Blueberry</option>
@@ -29,6 +28,7 @@ import { NativeSelect } from "@thebase/ui";
29
28
  | `NativeSelect` | `ariaLabel` / `aria-label` | `String` | optional, accessible name for the control |
30
29
  | `NativeSelect` | `id` | `String` | optional, e.g. for `Label`'s `for` |
31
30
  | `NativeSelect` | `onChange` | `Function` | optional |
31
+ | `NativeSelect` | `label`, `labelBackground`, `supportingText`, `useTip`, `errorText`, `invalid` | `String` / `Boolean` | Material-style outlined field, same behaviour as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border, `errorText` replaces `supportingText`. Also inherited from a parent `Field`. |
32
32
 
33
33
  See [Base Components](/examples/blocks.html#/docs/guide/owl-components) for how to load `@base/owl` and `dist/baseui.templates.xml`.
34
34
 
@@ -7,9 +7,9 @@ import { Select, SelectContent, SelectItem, SelectTrigger } from "@thebase/ui";
7
7
  ```
8
8
 
9
9
  ```base-ui
10
- <div style="max-width: 180px">
11
- <Select value="'dark'">
12
- <SelectTrigger>Theme</SelectTrigger>
10
+ <div style="max-width: 240px">
11
+ <Select label="'Theme'" value="'dark'">
12
+ <SelectTrigger>Dark</SelectTrigger>
13
13
  <SelectContent>
14
14
  <SelectItem value="'light'">Light</SelectItem>
15
15
  <SelectItem value="'dark'">Dark</SelectItem>
@@ -24,6 +24,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger } from "@thebase/ui";
24
24
  | `Select` | `value` | `String` | optional |
25
25
  | `Select` | `onChange` | `Function` | optional |
26
26
  | `Select` | `className` | `String` | optional |
27
+ | `Select` | `label`, `labelBackground`, `supportingText`, `useTip`, `errorText`, `invalid` | `String` / `Boolean` | Material-style outlined field, same behaviour as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border, `errorText` replaces `supportingText`. Also inherited from a parent `Field`. |
27
28
  | `SelectContent` | `className` | `String` | optional |
28
29
  | `SelectItem` | `value` | `String` | required |
29
30
  | `SelectItem` | `className` | `String` | optional |
@@ -10,25 +10,20 @@ import { Textarea } from "@thebase/ui";
10
10
 
11
11
  ```base-ui
12
12
  <div class="d-flex flex-column gap-4" style="max-width: 28rem; width: 100%">
13
- <Textarea placeholder="'Type your message here.'"/>
13
+ <Textarea label="'Message'"/>
14
14
 
15
- <div class="d-grid gap-3">
16
- <Label htmlFor="'message'">Your message</Label>
17
- <Textarea placeholder="'Type your message here.'" id="'message'"/>
18
- </div>
15
+ <Textarea label="'Your message'" placeholder="'Type your message here.'" id="'message'"/>
19
16
 
20
- <div class="d-grid gap-3">
21
- <Label htmlFor="'message-2'">Your Message</Label>
22
- <Textarea placeholder="'Type your message here.'" id="'message-2'"/>
23
- <Typography variant="'small'" className="'text-muted'">Your message will be copied to the support team.</Typography>
24
- </div>
17
+ <Textarea label="'Your message'" supportingText="'Your message will be copied to the support team.'" maxLength="200"/>
18
+
19
+ <Textarea label="'Your message'" errorText="'Message is required'"/>
25
20
 
26
21
  <div class="d-grid gap-2">
27
- <Textarea placeholder="'Type your message here.'"/>
22
+ <Textarea label="'Feedback'"/>
28
23
  <Button>Send message</Button>
29
24
  </div>
30
25
 
31
- <Textarea placeholder="'Type your message here.'" disabled="true"/>
26
+ <Textarea label="'Disabled'" placeholder="'Type your message here.'" disabled="true"/>
32
27
  </div>
33
28
  ```
34
29
 
@@ -44,6 +39,7 @@ import { Textarea } from "@thebase/ui";
44
39
  | `Textarea` | `id` | `String` | optional, e.g. for `Label`'s `for` |
45
40
  | `Textarea` | `onInput` | `Function` | optional |
46
41
  | `Textarea` | `onChange` | `Function` | optional |
42
+ | `Textarea` | `label`, `supportingText`, `useTip`, `errorText`, `maxLength`, `invalid`, `placeholder` | `String` / `Boolean` | Material-style outlined field, same behaviour as [Input](/examples/blocks.html#/docs/components/input): the label floats onto the border, `errorText` replaces `supportingText`. Also inherited from a parent `Field`. |
47
43
 
48
44
  See [Base Components](/examples/blocks.html#/docs/guide/owl-components) for how to load `@base/owl` and `dist/baseui.templates.xml`.
49
45
 
package/docs/icons.md CHANGED
@@ -22,7 +22,7 @@ Load the normal the Base UI assets. No separate icon script is required.
22
22
  <script src="https://cdn.jsdelivr.net/npm/@thebase/ui@latest/dist/baseui.min.js" defer></script>
23
23
  ```
24
24
 
25
- `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.3`, or `@1` to take only non-breaking updates) instead of `@latest` for production. `b-icon` also works with the [pure Base `Icon` component](components/icon.md) — the recommended API in an application; the classic script above is for pages using the static `b-ui` API.
25
+ `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) instead of `@latest` for production. `b-icon` also works with the [pure Base `Icon` component](components/icon.md) — the recommended API in an application; the classic script above is for pages using the static `b-ui` API.
26
26
 
27
27
  The build publishes every Lucide SVG to `dist/icons/lucide/` and writes the generated icon manifest to `dist/icons/lucide.json`.
28
28
 
@@ -4,7 +4,7 @@ See the [Usage Guide](usage-guide.md) for the end-to-end integration path (choos
4
4
 
5
5
  The Base UI is distributed as one CSS file and one JavaScript file for browser use. `dist/baseui.min.js` is fully self-contained: Bootstrap's JS bundle (Popper.js included) and the Owl runtime are embedded ahead of the Base UI's own code, in load order (Bootstrap, then Owl, then the Base UI) — nothing else needs to load first. Both install paths below load this same file; the Base component API is the recommended way to consume the Base UI in an application, with the base static markup (`b-ui`) API available as a lighter-weight alternative for non-Owl pages.
6
6
 
7
- The snippets below use the `@latest` tag for readability. Pin an exact version instead (e.g. `@1.1.3`, or `@1` to take only non-breaking updates) for any production page — `@latest` can silently change what your page loads the moment a new version is published.
7
+ The snippets below use the `@latest` tag for readability. Pin an exact version instead (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) for any production page — `@latest` can silently change what your page loads the moment a new version is published.
8
8
 
9
9
  ## Base component install (recommended)
10
10
 
@@ -43,7 +43,7 @@ For static HTML, a server-rendered page, or a Base HUB website page that has no
43
43
 
44
44
  Bootstrap 5 is the bundled baseline CSS framework, and its JS bundle now drives the Base UI's interactive components directly.
45
45
 
46
- `@thebase/ui` is published on npm, so [unpkg](https://unpkg.com/@thebase/ui@latest/) mirrors the same files as an alternative CDN (`https://unpkg.com/@thebase/ui@latest/dist/baseui.min.css` / `baseui.min.js`) if jsDelivr is unreachable in your environment. Pin an exact version (e.g. `@1.1.3`, or `@1` to take only non-breaking updates) instead of `@latest` for production.
46
+ `@thebase/ui` is published on npm, so [unpkg](https://unpkg.com/@thebase/ui@latest/) mirrors the same files as an alternative CDN (`https://unpkg.com/@thebase/ui@latest/dist/baseui.min.css` / `baseui.min.js`) if jsDelivr is unreachable in your environment. Pin an exact version (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) instead of `@latest` for production.
47
47
 
48
48
  For npm/self-hosted usage:
49
49
 
@@ -55,7 +55,7 @@ Everything — the static `b-ui` runtime, the Owl framework, every Base componen
55
55
  </script>
56
56
  ```
57
57
 
58
- `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable — swap the host in each URL above. For a self-hosted build, replace the CDN host with your own served path (e.g. `/dist/baseui.esm.js`). These snippets use `@latest` for readability; pin an exact version (e.g. `@1.1.0`, or `@1` to take only non-breaking updates) in production so a new release can't change what your page loads.
58
+ `https://unpkg.com/@thebase/ui@latest/dist/...` mirrors the same files as an alternative CDN if jsDelivr is unreachable — swap the host in each URL above. For a self-hosted build, replace the CDN host with your own served path (e.g. `/dist/baseui.esm.js`). These snippets use `@latest` for readability; pin an exact version (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) in production so a new release can't change what your page loads.
59
59
 
60
60
  No `@odoo/owl` import appears anywhere in that snippet — `@base/owl` is the only Owl entry point the Base UI components and consumer apps need. Because `@base/owl`, `@base/component`, and `@base/theme` all point at the exact same `dist/baseui.esm.js` URL, the browser fetches and evaluates it once and every key shares the same module instance — no separate classic `<script>` needs to load first to set up a shared global.
61
61
 
package/docs/theming.md CHANGED
@@ -38,7 +38,7 @@ For a reusable theme toggle with persistence, URL override, button-label sync, a
38
38
  </script>
39
39
  ```
40
40
 
41
- `https://unpkg.com/@thebase/ui@latest/dist/baseui.esm.js` mirrors the same file as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.3`, or `@1` to take only non-breaking updates) instead of `@latest` for production. Npm/bundler consumers can import the same API from `@thebase/ui`.
41
+ `https://unpkg.com/@thebase/ui@latest/dist/baseui.esm.js` mirrors the same file as an alternative CDN if jsDelivr is unreachable. Pin an exact version (e.g. `@1.1.6`, or `@1` to take only non-breaking updates) instead of `@latest` for production. Npm/bundler consumers can import the same API from `@thebase/ui`.
42
42
 
43
43
  For a ready-made icon button, use the Base UI component instead of wiring your own click handler:
44
44