@relements/core 0.1.1 → 0.1.3
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/README.md +48 -46
- package/dist/elements/re-tabs.js +26 -3
- package/package.json +13 -3
- package/src/elements/re-tabs.js +33 -4
package/README.md
CHANGED
|
@@ -48,26 +48,26 @@ import "@relements/core/elements/re-tabs";
|
|
|
48
48
|
|
|
49
49
|
All styled with CSS classes and `data-*` attributes. No JavaScript needed for static use.
|
|
50
50
|
|
|
51
|
-
| Class
|
|
52
|
-
|
|
53
|
-
| `.re-button`
|
|
54
|
-
| `.re-link`
|
|
55
|
-
| `.re-input`
|
|
56
|
-
| `.re-textarea`
|
|
57
|
-
| `.re-select`
|
|
58
|
-
| `.re-checkbox`
|
|
59
|
-
| `.re-radio`
|
|
60
|
-
| `.re-field`
|
|
61
|
-
| `.re-field-group`
|
|
62
|
-
| `.re-validation-message` | `<span>`
|
|
63
|
-
| `.re-disclosure`
|
|
64
|
-
| `.re-dialog`
|
|
65
|
-
| `.re-tabs`
|
|
66
|
-
| `.re-menu`
|
|
67
|
-
| `.re-popover`
|
|
68
|
-
| `.re-toast-region`
|
|
69
|
-
| `.re-progress`
|
|
70
|
-
| `.re-meter`
|
|
51
|
+
| Class | Element | Variants / options |
|
|
52
|
+
| ------------------------ | ------------------------------- | ------------------------------------------------------------------ |
|
|
53
|
+
| `.re-button` | `<button>`, `<a>`, submit input | `data-variant`: primary, secondary, ghost, danger |
|
|
54
|
+
| `.re-link` | `<a>` | `data-variant`: muted, subtle, external |
|
|
55
|
+
| `.re-input` | `<input>` | `data-size`: sm, md, lg |
|
|
56
|
+
| `.re-textarea` | `<textarea>` | `data-size`: sm, md, lg |
|
|
57
|
+
| `.re-select` | `<select>` | `data-size`: sm, md, lg |
|
|
58
|
+
| `.re-checkbox` | `<input type="checkbox">` | — |
|
|
59
|
+
| `.re-radio` | `<input type="radio">` | — |
|
|
60
|
+
| `.re-field` | `<label>` | `re-field--inline` for checkbox/radio rows |
|
|
61
|
+
| `.re-field-group` | `<fieldset>` | `data-orientation`: horizontal |
|
|
62
|
+
| `.re-validation-message` | `<span>` | `data-tone`: success, hint, warning |
|
|
63
|
+
| `.re-disclosure` | `<details>` | `data-variant`: plain |
|
|
64
|
+
| `.re-dialog` | `<dialog>` | `showModal()` surface with header/body/footer slots |
|
|
65
|
+
| `.re-tabs` | container | pairs with `[role="tablist"]`, `[role="tab"]`, `[role="tabpanel"]` |
|
|
66
|
+
| `.re-menu` | container | pairs with `[role="menu"]`, `[role="menuitem"]` |
|
|
67
|
+
| `.re-popover` | `[popover]` element | `data-tone`: info, warning, danger |
|
|
68
|
+
| `.re-toast-region` | live region host | — |
|
|
69
|
+
| `.re-progress` | `<progress>` | `data-size`: sm, md, lg |
|
|
70
|
+
| `.re-meter` | `<meter>` | `data-size`: sm, md, lg |
|
|
71
71
|
|
|
72
72
|
## JavaScript behaviors
|
|
73
73
|
|
|
@@ -81,14 +81,14 @@ const controller = enhanceTabs(document);
|
|
|
81
81
|
controller.destroy();
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
| Behavior
|
|
85
|
-
|
|
86
|
-
| `enhanceTabs`
|
|
87
|
-
| `enhanceMenuButton`
|
|
88
|
-
| `enhanceDialog`
|
|
89
|
-
| `enhancePopover`
|
|
90
|
-
| `enhanceDismissible`
|
|
91
|
-
| `showToast(msg, opts)` | `aria-live` toast notifications
|
|
84
|
+
| Behavior | What it does | Key event |
|
|
85
|
+
| ---------------------- | ------------------------------------------------ | ------------ |
|
|
86
|
+
| `enhanceTabs` | Arrow keys, Home/End, roving tabindex | `re-change` |
|
|
87
|
+
| `enhanceMenuButton` | Keyboard nav, outside-click close | `re-select` |
|
|
88
|
+
| `enhanceDialog` | Trigger binding, close buttons, backdrop dismiss | — |
|
|
89
|
+
| `enhancePopover` | Anchored positioning, toggle event bridge | `re-toggle` |
|
|
90
|
+
| `enhanceDismissible` | Dismiss buttons via `[data-re-dismiss]` | `re-dismiss` |
|
|
91
|
+
| `showToast(msg, opts)` | `aria-live` toast notifications | — |
|
|
92
92
|
|
|
93
93
|
## Custom elements
|
|
94
94
|
|
|
@@ -100,19 +100,21 @@ Light-DOM only (no Shadow DOM). Same HTML/CSS contract as the plain class API.
|
|
|
100
100
|
<re-tabs>
|
|
101
101
|
<div role="tablist" aria-label="Account">
|
|
102
102
|
<button role="tab" id="t1" aria-controls="p1" aria-selected="true">Profile</button>
|
|
103
|
-
<button role="tab" id="t2" aria-controls="p2" aria-selected="false" tabindex="-1">
|
|
103
|
+
<button role="tab" id="t2" aria-controls="p2" aria-selected="false" tabindex="-1">
|
|
104
|
+
Settings
|
|
105
|
+
</button>
|
|
104
106
|
</div>
|
|
105
107
|
<section role="tabpanel" id="p1" aria-labelledby="t1">…</section>
|
|
106
108
|
<section role="tabpanel" id="p2" aria-labelledby="t2" hidden>…</section>
|
|
107
109
|
</re-tabs>
|
|
108
110
|
```
|
|
109
111
|
|
|
110
|
-
| Tag
|
|
111
|
-
|
|
112
|
-
| `<re-tabs>`
|
|
113
|
-
| `<re-toast>`
|
|
114
|
-
| `<re-menu>`
|
|
115
|
-
| `<re-popover>` | `enhancePopover`
|
|
112
|
+
| Tag | Wraps | Exposes |
|
|
113
|
+
| -------------- | ------------------- | ----------------------------------- |
|
|
114
|
+
| `<re-tabs>` | `enhanceTabs` | `.value` (selected tab id) |
|
|
115
|
+
| `<re-toast>` | `showToast` | `.show(message, options)` |
|
|
116
|
+
| `<re-menu>` | `enhanceMenuButton` | `.open` boolean |
|
|
117
|
+
| `<re-popover>` | `enhancePopover` | `.show()` / `.hide()` / `.toggle()` |
|
|
116
118
|
|
|
117
119
|
## Theming
|
|
118
120
|
|
|
@@ -124,7 +126,7 @@ All values are `--re-*` CSS custom properties. Override globally or on any subtr
|
|
|
124
126
|
}
|
|
125
127
|
|
|
126
128
|
.my-card {
|
|
127
|
-
--re-color-surface: #1e293b;
|
|
129
|
+
--re-color-surface: #1e293b; /* dark card, light page */
|
|
128
130
|
}
|
|
129
131
|
```
|
|
130
132
|
|
|
@@ -145,16 +147,16 @@ The Renascent theme is the dark navy palette from [renascentelements.hu](https:/
|
|
|
145
147
|
|
|
146
148
|
## Key tokens
|
|
147
149
|
|
|
148
|
-
| Token
|
|
149
|
-
|
|
150
|
-
| `--re-color-accent-600` | `#2563eb`
|
|
151
|
-
| `--re-color-bg`
|
|
152
|
-
| `--re-color-surface`
|
|
153
|
-
| `--re-color-text`
|
|
154
|
-
| `--re-color-border`
|
|
155
|
-
| `--re-color-focus-ring` | `#3b82f6`
|
|
156
|
-
| `--re-space-4`
|
|
157
|
-
| `--re-radius-md`
|
|
150
|
+
| Token | Light default | Purpose |
|
|
151
|
+
| ----------------------- | ------------- | -------------------------- |
|
|
152
|
+
| `--re-color-accent-600` | `#2563eb` | Buttons, links, focus ring |
|
|
153
|
+
| `--re-color-bg` | `#ffffff` | Page background |
|
|
154
|
+
| `--re-color-surface` | `#ffffff` | Card / panel background |
|
|
155
|
+
| `--re-color-text` | `#0f172a` | Body text |
|
|
156
|
+
| `--re-color-border` | `#e2e8f0` | Borders |
|
|
157
|
+
| `--re-color-focus-ring` | `#3b82f6` | Keyboard focus indicator |
|
|
158
|
+
| `--re-space-4` | `1rem` | Base spacing (4 px scale) |
|
|
159
|
+
| `--re-radius-md` | `0.375rem` | Default radius |
|
|
158
160
|
|
|
159
161
|
Full list in [`src/tokens.css`](./src/tokens.css).
|
|
160
162
|
|
package/dist/elements/re-tabs.js
CHANGED
|
@@ -4,19 +4,42 @@ import { enhanceTabs } from '../chunk-GMICGIQW.js';
|
|
|
4
4
|
var ReTabsElement = class extends HTMLElement {
|
|
5
5
|
/** @type {{ destroy: () => void } | null} */
|
|
6
6
|
#controller = null;
|
|
7
|
+
/** @type {MutationObserver | null} */
|
|
8
|
+
#observer = null;
|
|
7
9
|
static get observedAttributes() {
|
|
8
10
|
return ["value"];
|
|
9
11
|
}
|
|
10
12
|
connectedCallback() {
|
|
11
13
|
this.setAttribute("data-re-tabs", "");
|
|
12
|
-
this.#
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
if (this.#hasTabs()) {
|
|
15
|
+
this.#enhance();
|
|
16
|
+
} else {
|
|
17
|
+
this.#observer = new MutationObserver(() => {
|
|
18
|
+
if (this.#hasTabs()) {
|
|
19
|
+
this.#observer?.disconnect();
|
|
20
|
+
this.#observer = null;
|
|
21
|
+
this.#enhance();
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
this.#observer.observe(this, { childList: true, subtree: true });
|
|
25
|
+
}
|
|
15
26
|
}
|
|
16
27
|
disconnectedCallback() {
|
|
28
|
+
this.#observer?.disconnect();
|
|
29
|
+
this.#observer = null;
|
|
17
30
|
this.#controller?.destroy();
|
|
18
31
|
this.#controller = null;
|
|
19
32
|
}
|
|
33
|
+
/** @returns {boolean} */
|
|
34
|
+
#hasTabs() {
|
|
35
|
+
return !!this.querySelector('[role="tablist"] [role="tab"]');
|
|
36
|
+
}
|
|
37
|
+
#enhance() {
|
|
38
|
+
this.#controller?.destroy();
|
|
39
|
+
this.#controller = enhanceTabs(this);
|
|
40
|
+
const initial = this.getAttribute("value");
|
|
41
|
+
if (initial) this.#selectById(initial);
|
|
42
|
+
}
|
|
20
43
|
/**
|
|
21
44
|
* @param {string} name
|
|
22
45
|
* @param {string | null} _oldValue
|
package/package.json
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relements/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"description": "HTML-first design system core: tokens, styles, and progressive enhancement.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/Renascent-Elements/relements.git",
|
|
8
|
+
"directory": "packages/core"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/Renascent-Elements/relements#readme",
|
|
11
|
+
"bugs": "https://github.com/Renascent-Elements/relements/issues",
|
|
5
12
|
"keywords": [
|
|
6
13
|
"design-system",
|
|
7
14
|
"css",
|
|
@@ -18,7 +25,9 @@
|
|
|
18
25
|
"type": "module",
|
|
19
26
|
"sideEffects": [
|
|
20
27
|
"**/*.css",
|
|
21
|
-
"dist/**/*.css"
|
|
28
|
+
"dist/**/*.css",
|
|
29
|
+
"dist/elements/*.js",
|
|
30
|
+
"src/elements/*.js"
|
|
22
31
|
],
|
|
23
32
|
"files": [
|
|
24
33
|
"dist",
|
|
@@ -86,7 +95,8 @@
|
|
|
86
95
|
}
|
|
87
96
|
},
|
|
88
97
|
"publishConfig": {
|
|
89
|
-
"access": "public"
|
|
98
|
+
"access": "public",
|
|
99
|
+
"provenance": true
|
|
90
100
|
},
|
|
91
101
|
"scripts": {
|
|
92
102
|
"build:css": "node build-css.mjs",
|
package/src/elements/re-tabs.js
CHANGED
|
@@ -25,6 +25,8 @@ import { enhanceTabs } from "../behaviors/tabs.js";
|
|
|
25
25
|
export class ReTabsElement extends HTMLElement {
|
|
26
26
|
/** @type {{ destroy: () => void } | null} */
|
|
27
27
|
#controller = null;
|
|
28
|
+
/** @type {MutationObserver | null} */
|
|
29
|
+
#observer = null;
|
|
28
30
|
|
|
29
31
|
static get observedAttributes() {
|
|
30
32
|
return ["value"];
|
|
@@ -33,17 +35,44 @@ export class ReTabsElement extends HTMLElement {
|
|
|
33
35
|
connectedCallback() {
|
|
34
36
|
// Mark the host so enhanceTabs picks it up.
|
|
35
37
|
this.setAttribute("data-re-tabs", "");
|
|
36
|
-
this.#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
if (this.#hasTabs()) {
|
|
39
|
+
this.#enhance();
|
|
40
|
+
} else {
|
|
41
|
+
// Some frameworks (e.g. Angular) connect the host before projecting its
|
|
42
|
+
// children. Enhance once the tabs appear, then stop observing.
|
|
43
|
+
this.#observer = new MutationObserver(() => {
|
|
44
|
+
if (this.#hasTabs()) {
|
|
45
|
+
this.#observer?.disconnect();
|
|
46
|
+
this.#observer = null;
|
|
47
|
+
this.#enhance();
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
this.#observer.observe(this, { childList: true, subtree: true });
|
|
51
|
+
}
|
|
40
52
|
}
|
|
41
53
|
|
|
42
54
|
disconnectedCallback() {
|
|
55
|
+
this.#observer?.disconnect();
|
|
56
|
+
this.#observer = null;
|
|
43
57
|
this.#controller?.destroy();
|
|
44
58
|
this.#controller = null;
|
|
45
59
|
}
|
|
46
60
|
|
|
61
|
+
/** @returns {boolean} */
|
|
62
|
+
#hasTabs() {
|
|
63
|
+
return !!this.querySelector('[role="tablist"] [role="tab"]');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#enhance() {
|
|
67
|
+
// Idempotent: tear down any prior controller first so a reconnected or
|
|
68
|
+
// moved host (with children already present) does not double-wire listeners.
|
|
69
|
+
this.#controller?.destroy();
|
|
70
|
+
this.#controller = enhanceTabs(this);
|
|
71
|
+
// Honor a value attribute if present and different from initial state.
|
|
72
|
+
const initial = this.getAttribute("value");
|
|
73
|
+
if (initial) this.#selectById(initial);
|
|
74
|
+
}
|
|
75
|
+
|
|
47
76
|
/**
|
|
48
77
|
* @param {string} name
|
|
49
78
|
* @param {string | null} _oldValue
|