@reliability-design/web 1.0.3 → 1.0.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.
Files changed (114) hide show
  1. package/dist/components/rel-accordion/README.md +132 -0
  2. package/dist/components/rel-accordion/rel-accordion.ts +43 -16
  3. package/dist/components/rel-alert/README.md +141 -0
  4. package/dist/components/rel-alert/rel-alert.ts +18 -7
  5. package/dist/components/rel-avatar/README.md +119 -0
  6. package/dist/components/rel-badge/README.md +86 -0
  7. package/dist/components/rel-badge/rel-badge.ts +6 -6
  8. package/dist/components/rel-breadcrumb/README.md +102 -0
  9. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +12 -6
  10. package/dist/components/rel-button/README.md +130 -0
  11. package/dist/components/rel-calendar/README.md +109 -0
  12. package/dist/components/rel-calendar/index.ts +1 -0
  13. package/dist/components/rel-calendar/rel-calendar.ts +467 -0
  14. package/dist/components/rel-card/README.md +94 -0
  15. package/dist/components/rel-card/rel-card.ts +12 -3
  16. package/dist/components/rel-cardmedia/README.md +127 -0
  17. package/dist/components/rel-cardmedia/rel-cardmedia.ts +14 -4
  18. package/dist/components/rel-carousel/README.md +166 -0
  19. package/dist/components/rel-carousel/index.ts +1 -0
  20. package/dist/components/rel-carousel/rel-carousel.ts +469 -0
  21. package/dist/components/rel-chart/README.md +286 -0
  22. package/dist/components/rel-chart/index.ts +1 -0
  23. package/dist/components/rel-chart/rel-chart.ts +736 -0
  24. package/dist/components/rel-checkbox/README.md +77 -0
  25. package/dist/components/rel-checkbox/rel-checkbox.ts +18 -10
  26. package/dist/components/rel-chip/README.md +114 -0
  27. package/dist/components/rel-chip/rel-chip.ts +20 -4
  28. package/dist/components/rel-container/README.md +99 -0
  29. package/dist/components/rel-date-picker/README.md +253 -0
  30. package/dist/components/rel-date-picker/index.ts +1 -0
  31. package/dist/components/rel-date-picker/rel-date-picker.ts +916 -0
  32. package/dist/components/rel-divider/README.md +100 -0
  33. package/dist/components/rel-drawer/README.md +200 -0
  34. package/dist/components/rel-drawer/index.ts +1 -0
  35. package/dist/components/rel-drawer/rel-drawer.ts +621 -0
  36. package/dist/components/rel-kbd/README.md +151 -0
  37. package/dist/components/rel-kbd/rel-kbd.ts +118 -0
  38. package/dist/components/rel-layout/README.md +88 -0
  39. package/dist/components/rel-menu/README.md +151 -0
  40. package/dist/components/rel-menu/rel-menu.ts +18 -10
  41. package/dist/components/rel-menubar/README.md +329 -0
  42. package/dist/components/rel-menubar/index.ts +2 -0
  43. package/dist/components/rel-menubar/rel-menubar-menu.ts +16 -0
  44. package/dist/components/rel-menubar/rel-menubar.ts +576 -0
  45. package/dist/components/rel-nav-menu/README.md +289 -0
  46. package/dist/components/rel-nav-menu/index.ts +3 -0
  47. package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +143 -0
  48. package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +53 -0
  49. package/dist/components/rel-nav-menu/rel-nav-menu.ts +331 -0
  50. package/dist/components/rel-navbar/README.md +126 -0
  51. package/dist/components/rel-navbar/rel-navbar.ts +91 -0
  52. package/dist/components/rel-otp/README.md +440 -0
  53. package/dist/components/rel-otp/index.ts +1 -0
  54. package/dist/components/rel-otp/rel-otp.ts +504 -0
  55. package/dist/components/rel-pagination/README.md +410 -0
  56. package/dist/components/rel-pagination/index.ts +1 -0
  57. package/dist/components/rel-pagination/rel-pagination.ts +376 -0
  58. package/dist/components/rel-popover/README.md +568 -0
  59. package/dist/components/rel-popover/index.ts +2 -0
  60. package/dist/components/rel-popover/rel-popover-content.ts +55 -0
  61. package/dist/components/rel-popover/rel-popover.ts +327 -0
  62. package/dist/components/rel-progress/README.md +110 -0
  63. package/dist/components/rel-progress/rel-progress.ts +32 -5
  64. package/dist/components/rel-quote-page/README.md +166 -0
  65. package/dist/components/rel-quote-page/rel-quote-page.ts +816 -0
  66. package/dist/components/rel-radio/README.md +120 -0
  67. package/dist/components/rel-radio/rel-radio.ts +13 -5
  68. package/dist/components/rel-resizable/README.md +140 -0
  69. package/dist/components/rel-resizable/index.ts +3 -0
  70. package/dist/components/rel-resizable/rel-resizable-group.ts +374 -0
  71. package/dist/components/rel-resizable/rel-resizable-handle.ts +149 -0
  72. package/dist/components/rel-resizable/rel-resizable-panel.ts +47 -0
  73. package/dist/components/rel-segmented-button/README.md +141 -0
  74. package/dist/components/rel-segmented-button/rel-segmented-button.ts +18 -13
  75. package/dist/components/rel-select/README.md +107 -0
  76. package/dist/components/rel-select/rel-select.ts +14 -14
  77. package/dist/components/rel-sheet/README.md +224 -0
  78. package/dist/components/rel-sheet/rel-sheet.ts +683 -0
  79. package/dist/components/rel-sidebar/README.md +209 -0
  80. package/dist/components/rel-sidebar/rel-sidebar.ts +1158 -0
  81. package/dist/components/rel-slider/README.md +135 -0
  82. package/dist/components/rel-slider/rel-slider.ts +19 -7
  83. package/dist/components/rel-snackbar/README.md +134 -0
  84. package/dist/components/rel-snackbar/rel-snackbar.ts +67 -2
  85. package/dist/components/rel-stepper/README.md +160 -0
  86. package/dist/components/rel-stepper/rel-stepper.ts +6 -6
  87. package/dist/components/rel-switch/README.md +102 -0
  88. package/dist/components/rel-switch/rel-switch.ts +15 -6
  89. package/dist/components/rel-tab/README.md +163 -0
  90. package/dist/components/rel-tab/rel-tab.ts +36 -14
  91. package/dist/components/rel-table/README.md +178 -0
  92. package/dist/components/rel-table/rel-table-body.ts +16 -0
  93. package/dist/components/rel-table/rel-table-caption.ts +22 -0
  94. package/dist/components/rel-table/rel-table-cell.ts +49 -0
  95. package/dist/components/rel-table/rel-table-footer.ts +18 -0
  96. package/dist/components/rel-table/rel-table-head.ts +33 -0
  97. package/dist/components/rel-table/rel-table-header.ts +16 -0
  98. package/dist/components/rel-table/rel-table-row.ts +32 -0
  99. package/dist/components/rel-table/rel-table.ts +47 -0
  100. package/dist/components/rel-textfield/README.md +90 -0
  101. package/dist/components/rel-textfield/rel-textfield.ts +35 -19
  102. package/dist/components/rel-toast/README.md +148 -0
  103. package/dist/components/rel-toast/rel-toast.ts +32 -14
  104. package/dist/components/rel-tooltip/README.md +103 -0
  105. package/dist/components/rel-tooltip/rel-tooltip.ts +9 -9
  106. package/dist/index.d.mts +836 -1
  107. package/dist/index.d.ts +836 -1
  108. package/dist/index.js +10658 -1493
  109. package/dist/index.js.map +1 -1
  110. package/dist/index.mjs +10616 -1499
  111. package/dist/index.mjs.map +1 -1
  112. package/dist/styles/vars.css +293 -183
  113. package/dist/{vars-6ZIUPIU4.css → vars-ITL2K3KO.css} +293 -183
  114. package/package.json +1 -1
@@ -0,0 +1,33 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("rel-table-head")
5
+ export class RelTableHead extends LitElement {
6
+ @property({ type: String, reflect: true }) align: "left" | "center" | "right" = "left";
7
+
8
+ static styles = css`
9
+ :host {
10
+ display: table-cell;
11
+ font-family: var(--rel-fontFamilies-primary);
12
+ padding: var(--rel-spacing-space-sm) var(--rel-spacing-space-md);
13
+ text-align: left;
14
+ font-weight: var(--rel-fontWeights-medium, 500);
15
+ font-size: var(--rel-fontSizes-sm);
16
+ color: var(--rel-colors-gray-placeholder);
17
+ vertical-align: middle;
18
+ height: 48px;
19
+ }
20
+
21
+ :host([align="center"]) {
22
+ text-align: center;
23
+ }
24
+
25
+ :host([align="right"]) {
26
+ text-align: right;
27
+ }
28
+ `;
29
+
30
+ render() {
31
+ return html`<slot></slot>`;
32
+ }
33
+ }
@@ -0,0 +1,16 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement } from "lit/decorators.js";
3
+
4
+ @customElement("rel-table-header")
5
+ export class RelTableHeader extends LitElement {
6
+ static styles = css`
7
+ :host {
8
+ display: table-header-group;
9
+ font-family: var(--rel-fontFamilies-primary);
10
+ }
11
+ `;
12
+
13
+ render() {
14
+ return html`<slot></slot>`;
15
+ }
16
+ }
@@ -0,0 +1,32 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("rel-table-row")
5
+ export class RelTableRow extends LitElement {
6
+ @property({ type: Boolean, reflect: true }) selected = false;
7
+
8
+ static styles = css`
9
+ :host {
10
+ display: table-row;
11
+ font-family: var(--rel-fontFamilies-primary);
12
+ border-bottom: var(--rel-borders-width-stroke-100) solid var(--rel-colors-gray-border);
13
+ transition: background-color 0.15s ease;
14
+ }
15
+
16
+ :host(:hover) {
17
+ background-color: var(--rel-colors-gray-light);
18
+ }
19
+
20
+ :host([selected]) {
21
+ background-color: var(--rel-colors-gray-surface);
22
+ }
23
+
24
+ :host([selected]:hover) {
25
+ background-color: var(--rel-colors-gray-warm);
26
+ }
27
+ `;
28
+
29
+ render() {
30
+ return html`<slot></slot>`;
31
+ }
32
+ }
@@ -0,0 +1,47 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property } from "lit/decorators.js";
3
+
4
+ @customElement("rel-table")
5
+ export class RelTable extends LitElement {
6
+ @property({ type: Boolean, reflect: true }) bordered = false;
7
+ @property({ type: Boolean, reflect: true }) compact = false;
8
+
9
+ static styles = css`
10
+ :host {
11
+ display: block;
12
+ font-family: var(--rel-fontFamilies-primary);
13
+ position: relative;
14
+ width: 100%;
15
+ }
16
+
17
+ .table-wrapper {
18
+ position: relative;
19
+ width: 100%;
20
+ overflow-x: auto;
21
+ }
22
+
23
+ :host([bordered]) .table-wrapper {
24
+ border: var(--rel-borders-width-stroke-100) solid var(--rel-colors-gray-border);
25
+ border-radius: var(--rel-borders-radius-border-radius-200);
26
+ }
27
+
28
+ table {
29
+ width: 100%;
30
+ caption-side: bottom;
31
+ border-collapse: collapse;
32
+ font-size: var(--rel-fontSizes-md);
33
+ color: var(--rel-colors-gray-primary);
34
+ font-family: var(--rel-fontFamilies-primary);
35
+ }
36
+ `;
37
+
38
+ render() {
39
+ return html`
40
+ <div class="table-wrapper">
41
+ <table>
42
+ <slot></slot>
43
+ </table>
44
+ </div>
45
+ `;
46
+ }
47
+ }
@@ -0,0 +1,90 @@
1
+ # rel-textfield
2
+
3
+ ## Overview
4
+
5
+ A text input field component with support for labels, icons, validation states, and supporting text. Used for single-line text entry in forms and user interfaces.
6
+
7
+ ## Usage
8
+
9
+ ```html
10
+ <!-- Basic usage -->
11
+ <rel-textfield label="Email" placeholder="Enter your email"></rel-textfield>
12
+
13
+ <!-- With icons and supporting text -->
14
+ <rel-textfield
15
+ label="Password"
16
+ type="password"
17
+ leftIcon="🔒"
18
+ supportingText="Must be at least 8 characters">
19
+ </rel-textfield>
20
+
21
+ <!-- Setting value via JavaScript -->
22
+ <rel-textfield id="myField" label="Username"></rel-textfield>
23
+ <script>
24
+ const field = document.getElementById('myField');
25
+ field.value = 'john.doe';
26
+ </script>
27
+ ```
28
+
29
+ ## API
30
+
31
+ ### Attributes/Properties
32
+
33
+ | Name | Type | Default | Description |
34
+ |------|------|---------|-------------|
35
+ | `label` | `string` | - | Label text displayed above the input |
36
+ | `placeholder` | `string` | `""` | Placeholder text |
37
+ | `type` | `string` | `"text"` | Input type (text, email, password, etc.) |
38
+ | `value` | `string` | `""` | Current input value |
39
+ | `leftIcon` | `string` | - | Icon content on the left side |
40
+ | `rightIcon` | `string` | - | Icon content on the right side |
41
+ | `supportingText` | `string` | - | Helper or error text below input |
42
+ | `state` | `"default" \| "focused" \| "error" \| "disabled"` | `"default"` | Visual state |
43
+ | `size` | `"small" \| "medium" \| "large"` | `"medium"` | Size variant |
44
+
45
+ ## Events
46
+
47
+ | Event | Detail | Description |
48
+ |-------|--------|-------------|
49
+ | `input-change` | `string` (the current value) | Fires when the input value changes through user interaction |
50
+
51
+ ## Slots
52
+
53
+ Default slot not used. All content controlled via properties.
54
+
55
+ ## CSS Parts
56
+
57
+ None exposed.
58
+
59
+ ## Tokens / CSS Variables
60
+
61
+ - `--rel-fontFamilies-primary`: Font family
62
+ - `--rel-fontSizes-sm`, `--rel-fontSizes-md`: Font sizes
63
+ - `--rel-fontWeights-medium`: Font weight for label
64
+ - `--rel-text-heading`: Label color
65
+ - `--rel-text-primary`: Input text color
66
+ - `--rel-text-placeholder`: Placeholder and icon color
67
+ - `--rel-text-disabled`: Disabled text color
68
+ - `--rel-border-default`: Default border color
69
+ - `--rel-colors-primary-500`: Focus border color
70
+ - `--rel-border-error`: Error state border color
71
+ - `--rel-colors-white`: Input background (light mode)
72
+ - `--rel-surface-surface`: Disabled background
73
+ - `--rel-spacing-space-*`: Spacing tokens
74
+ - `--rel-borders-radius-border-radius-200`: Border radius
75
+
76
+ ## Accessibility
77
+
78
+ - Associates `<label>` with input via `for`/`id`
79
+ - Supports native HTML5 input attributes (`required`, `disabled`, `readonly`, `maxlength`)
80
+ - Focus ring visible on keyboard navigation (`:focus-visible`)
81
+ - Error state communicated visually via border color
82
+ - Supporting text can provide `aria-describedby` context
83
+
84
+ ## Notes / Edge Cases
85
+
86
+ - The `state` prop overrides internal focus state if set explicitly
87
+ - Icons are decorative (text content, not `<img>` elements)
88
+ - Input type `password` does not auto-toggle visibility (use `rightIcon` for toggle button)
89
+ - Error state must be set programmatically; no built-in validation
90
+ - Disabled inputs cannot be focused or edited
@@ -21,22 +21,22 @@ export class RelTextfield extends LitElement {
21
21
  static styles = css`
22
22
  :host {
23
23
  display: block;
24
- font-family: var(--rel-fontFamilies-primary);
24
+ font-family: var(--rel-fontFamilies-primary, sans-serif);
25
25
  }
26
26
 
27
27
  /* Wrapper */
28
28
  .textfield-wrapper {
29
29
  display: flex;
30
30
  flex-direction: column;
31
- gap: 4px;
31
+ gap: var(--rel-spacing-space-2xs, 4px);
32
32
  width: 100%;
33
33
  }
34
34
 
35
35
  /* Label */
36
36
  .textfield-label {
37
- font-size: 0.85rem;
38
- font-weight: 500;
39
- color: #111;
37
+ font-size: var(--rel-fontSizes-sm, 12px);
38
+ font-weight: var(--rel-fontWeights-medium, 500);
39
+ color: var(--rel-text-heading, #2b2b2b);
40
40
  }
41
41
 
42
42
  /* Container */
@@ -44,14 +44,14 @@ export class RelTextfield extends LitElement {
44
44
  display: flex;
45
45
  align-items: center;
46
46
  position: relative;
47
- border: 1px solid #ccc;
48
- border-radius: 6px;
49
- background: white;
47
+ border: 1px solid var(--rel-border-default, #ddd);
48
+ border-radius: var(--rel-borders-radius-border-radius-200, 8px);
49
+ background: var(--rel-colors-white, #fff);
50
50
  transition: border 0.2s;
51
51
  }
52
52
 
53
53
  .textfield-container.disabled {
54
- background: #f5f5f5;
54
+ background: var(--rel-surface-surface, #f5f5f5);
55
55
  cursor: not-allowed;
56
56
  }
57
57
 
@@ -60,22 +60,23 @@ export class RelTextfield extends LitElement {
60
60
  flex: 1;
61
61
  border: none;
62
62
  outline: none;
63
- font-size: 0.9rem;
63
+ font-size: var(--rel-fontSizes-md, 14px);
64
64
  padding: 0.5rem 0.75rem;
65
65
  background: transparent;
66
- font-family: var(--rel-fontFamilies-primary);
66
+ font-family: var(--rel-fontFamilies-primary, sans-serif);
67
+ color: var(--rel-text-primary, #333);
67
68
  }
68
69
 
69
70
  .textfield-input:disabled {
70
71
  cursor: not-allowed;
71
- color: #999;
72
+ color: var(--rel-text-disabled, #9e9e9e);
72
73
  }
73
74
 
74
75
  .icon {
75
76
  position: absolute;
76
77
  display: flex;
77
78
  pointer-events: none;
78
- color: #7e8186;
79
+ color: var(--rel-text-placeholder, #a9a9a9);
79
80
  }
80
81
 
81
82
  .icon.left {
@@ -112,25 +113,40 @@ export class RelTextfield extends LitElement {
112
113
 
113
114
  /* States */
114
115
  .textfield-wrapper.focused .textfield-container {
115
- border-color: #111;
116
+ border-color: var(--rel-colors-primary-500, #0091ea);
117
+ }
118
+
119
+ .textfield-input:focus-visible {
120
+ outline: none;
121
+ }
122
+
123
+ .textfield-wrapper.focused .textfield-container,
124
+ .textfield-container:focus-within {
125
+ border-color: var(--rel-colors-primary-500, #0091ea);
126
+ box-shadow: 0 0 0 1px var(--rel-colors-primary-500, #0091ea);
116
127
  }
117
128
 
118
129
  .textfield-wrapper.error .textfield-container {
119
- border-color: #d50000;
130
+ border-color: var(--rel-border-error, #cc0000);
120
131
  }
121
132
 
122
133
  .textfield-wrapper.disabled .textfield-container {
123
- border-color: #d7d9db;
134
+ border-color: var(--rel-border-default, #ddd);
124
135
  }
125
136
 
126
137
  /* Supporting text */
127
138
  .textfield-support {
128
- font-size: 0.75rem;
129
- color: #666;
139
+ font-size: var(--rel-fontSizes-xs, 10px);
140
+ color: var(--rel-text-placeholder, #a9a9a9);
130
141
  }
131
142
 
132
143
  .textfield-support.error {
133
- color: #d50000;
144
+ color: var(--rel-text-error, #cc0000);
145
+ }
146
+
147
+ /* Placeholder */
148
+ .textfield-input::placeholder {
149
+ color: var(--rel-text-placeholder, #a9a9a9);
134
150
  }
135
151
  `;
136
152
 
@@ -0,0 +1,148 @@
1
+ # rel-toast
2
+
3
+ ## Overview
4
+ A fixed-position toast notification component for brief feedback messages. Features default and error type variants, optional action buttons, auto-dismiss functionality, and slide-up animation. Positioned at the bottom-center of the viewport with `z-index: 1000`.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Basic toast (must be shown programmatically) -->
9
+ <rel-toast id="toast1" message="File saved successfully" type="default"></rel-toast>
10
+ <script>
11
+ const toast = document.getElementById('toast1');
12
+ toast.show(); // Show the toast
13
+ </script>
14
+
15
+ <!-- Error toast -->
16
+ <rel-toast id="errorToast" message="Failed to upload file" type="error"></rel-toast>
17
+ <script>
18
+ document.getElementById('errorToast').show();
19
+ </script>
20
+
21
+ <!-- With action button -->
22
+ <rel-toast
23
+ id="actionToast"
24
+ message="Connection lost"
25
+ actionLabel="RETRY"
26
+ type="default">
27
+ </rel-toast>
28
+ <script>
29
+ const actionToast = document.getElementById('actionToast');
30
+ actionToast.addEventListener('action', () => {
31
+ console.log('Retry clicked');
32
+ // Perform retry logic
33
+ });
34
+ actionToast.show();
35
+ </script>
36
+
37
+ <!-- Custom duration (7 seconds) -->
38
+ <rel-toast
39
+ id="customDuration"
40
+ message="Download complete"
41
+ duration="7000">
42
+ </rel-toast>
43
+ <script>
44
+ document.getElementById('customDuration').show();
45
+ </script>
46
+
47
+ <!-- No auto-dismiss -->
48
+ <rel-toast
49
+ id="persist"
50
+ message="Manual dismiss required"
51
+ duration="0">
52
+ </rel-toast>
53
+ <script>
54
+ const persist = document.getElementById('persist');
55
+ persist.show();
56
+ // Manually close later: persist.close();
57
+ </script>
58
+
59
+ <!-- Listen for dismiss -->
60
+ <rel-toast id="notif" message="Update available"></rel-toast>
61
+ <script>
62
+ const notif = document.getElementById('notif');
63
+ notif.addEventListener('dismissed', () => {
64
+ console.log('Toast was dismissed');
65
+ });
66
+ notif.show();
67
+ </script>
68
+ ```
69
+
70
+ ## API
71
+
72
+ ### Attributes/Properties
73
+ | Name | Type | Default | Description |
74
+ |------|------|---------|-------------|
75
+ | `message` | `string` | `""` | Toast message text |
76
+ | `type` | `"default" \| "error"` | `"default"` | Visual style (default: dark gray, error: red) |
77
+ | `actionLabel` | `string` | - | Optional action button label (e.g., "UNDO", "RETRY") |
78
+ | `duration` | `number` | `4000` | Auto-dismiss duration in milliseconds (0 = no auto-dismiss) |
79
+
80
+ ### Methods
81
+ | Method | Description |
82
+ |--------|-------------|
83
+ | `show()` | Display the toast and start auto-dismiss timer |
84
+ | `close()` | Manually dismiss the toast and clear timer |
85
+
86
+ ## Events
87
+ | Event | Detail | Description |
88
+ |-------|--------|-------------|
89
+ | `action` | None | Fired when the action button is clicked (toast auto-closes after) |
90
+ | `dismissed` | None | Fired when toast is dismissed (via action, close button, or auto-dismiss) |
91
+
92
+ ## Slots
93
+ Default slot not used.
94
+
95
+ ## CSS Parts
96
+ None exposed.
97
+
98
+ ## Tokens / CSS Variables
99
+
100
+ ### Semantic Tokens
101
+ - `--rel-fontFamilies-primary` - Font family
102
+ - `--rel-fontSizes-md` - Font size
103
+
104
+ ### Spacing Tokens
105
+ - `--rel-spacing-space-sm` - Gap between elements
106
+ - `--rel-spacing-space-md` - Padding
107
+ - `--rel-spacing-space-2xs` - Close button padding and margin
108
+
109
+ ### Color Tokens
110
+ - `--rel-surface-toast` - Default background color (dark gray)
111
+ - `--rel-colors-red-secondary` - Error background color
112
+ - `--rel-colors-white` - Text and focus outline color
113
+ - `--rel-colors-green-primary` - Action button text color
114
+
115
+ ### Shadow Tokens
116
+ - `--rel-shadows-shadow-300` - Drop shadow
117
+
118
+ ### Border Tokens
119
+ - `--rel-borders-radius-border-radius-200` - Border radius
120
+
121
+ ## Accessibility
122
+ - Uses `role="status"` and `aria-live="polite"` for screen reader announcements
123
+ - Focus styles on action and close buttons
124
+ - Animation respects `prefers-reduced-motion` media query
125
+ - Close button has `aria-label="Dismiss"`
126
+
127
+ ### Keyboard Interactions
128
+ - `Tab` - Focus action button or close button
129
+ - `Space/Enter` - Activate focused button
130
+
131
+ ### Focus Behavior
132
+ - Buttons show 2px white outline with 2px offset when focused
133
+ - Border radius applied to maintain visual consistency
134
+
135
+ ## Notes / Edge Cases
136
+ - **Important:** Toasts are hidden by default; you must call `show()` to display them
137
+ - The component uses `:host` with `position: fixed`, `bottom: 24px`, `left: 50%`, `transform: translateX(-50%)` for bottom-center positioning
138
+ - `z-index: 1000` ensures toasts appear above most content
139
+ - The toast container is `display: inline-flex` with `pointer-events: all` (while`:host` has `pointer-events: none`)
140
+ - Auto-dismiss timer starts when `show()` is called
141
+ - Calling `close()` sets `visible = false`, dispatches `dismissed`, and clears the timeout
142
+ - Clicking the action button dispatches `action` then automatically calls `close()`
143
+ - Setting `duration="0"` disables auto-dismiss
144
+ - The component includes a `fadeInUp` animation (20px translateY → 0, opacity 0 → 1) on appearance
145
+ - Animation disabled when `prefers-reduced-motion: reduce` is set
146
+ - When `visible` is false, `hidden` class applies `display: none`
147
+ - **Type variants**: `default` uses `--rel-surface-toast`, `error` uses `--rel-colors-red-secondary`
148
+ - The toast appears inline-flex, so it sizes to content width
@@ -31,20 +31,20 @@ export class RelToast extends LitElement {
31
31
  .toast {
32
32
  display: inline-flex;
33
33
  align-items: center;
34
- gap: 12px;
35
- background-color: #111;
36
- color: #fff;
37
- font-family: var(--rel-fontFamilies-primary);
38
- font-size: 0.9rem;
39
- border-radius: 8px;
40
- padding: 1rem 1rem;
41
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
34
+ gap: var(--rel-spacing-space-sm, 12px);
35
+ background-color: var(--rel-surface-toast, #404040);
36
+ color: var(--rel-colors-white, #fff);
37
+ font-family: var(--rel-fontFamilies-primary, sans-serif);
38
+ font-size: var(--rel-fontSizes-md, 14px);
39
+ border-radius: var(--rel-borders-radius-border-radius-200, 8px);
40
+ padding: var(--rel-spacing-space-md, 16px);
41
+ box-shadow: var(--rel-shadows-shadow-300);
42
42
  pointer-events: all;
43
43
  animation: fadeInUp 0.25s ease;
44
44
  }
45
45
 
46
46
  .toast.error {
47
- background-color: #d50000;
47
+ background-color: var(--rel-colors-red-secondary);
48
48
  }
49
49
 
50
50
  .toast.hidden {
@@ -60,7 +60,7 @@ export class RelToast extends LitElement {
60
60
  .toast-action {
61
61
  background: transparent;
62
62
  border: none;
63
- color: #0edb90;
63
+ color: var(--rel-colors-green-primary);
64
64
  font-weight: 600;
65
65
  font-size: 0.85rem;
66
66
  cursor: pointer;
@@ -72,6 +72,12 @@ export class RelToast extends LitElement {
72
72
  opacity: 0.75;
73
73
  }
74
74
 
75
+ .toast-action:focus-visible {
76
+ outline: 2px solid var(--rel-colors-white, #fff);
77
+ outline-offset: 2px;
78
+ border-radius: 2px;
79
+ }
80
+
75
81
  /* Close button */
76
82
  .toast-close {
77
83
  background: transparent;
@@ -80,14 +86,26 @@ export class RelToast extends LitElement {
80
86
  font-size: 1rem;
81
87
  cursor: pointer;
82
88
  line-height: 1;
83
- padding: 0;
84
- margin-left: 4px;
89
+ padding: var(--rel-spacing-space-2xs, 4px);
90
+ margin-left: var(--rel-spacing-space-2xs, 4px);
85
91
  }
86
92
 
87
93
  .toast-close:hover {
88
94
  opacity: 0.75;
89
95
  }
90
96
 
97
+ .toast-close:focus-visible {
98
+ outline: 2px solid var(--rel-colors-white, #fff);
99
+ outline-offset: 2px;
100
+ border-radius: 2px;
101
+ }
102
+
103
+ @media (prefers-reduced-motion: reduce) {
104
+ .toast {
105
+ animation: none;
106
+ }
107
+ }
108
+
91
109
  /* Animations */
92
110
  @keyframes fadeInUp {
93
111
  from {
@@ -135,7 +153,7 @@ export class RelToast extends LitElement {
135
153
 
136
154
  render() {
137
155
  return html`
138
- <div class="toast ${this.type} ${this.visible ? "" : "hidden"}">
156
+ <div class="toast ${this.type} ${this.visible ? "" : "hidden"}" role="status" aria-live="polite">
139
157
  <span class="toast-message">${this.message}</span>
140
158
 
141
159
  ${this.actionLabel
@@ -147,7 +165,7 @@ export class RelToast extends LitElement {
147
165
  </button>`
148
166
  : ""}
149
167
 
150
- <button class="toast-close" @click="${this.close}">✕</button>
168
+ <button class="toast-close" @click="${this.close}" aria-label="Dismiss">✕</button>
151
169
  </div>
152
170
  `;
153
171
  }
@@ -0,0 +1,103 @@
1
+ # rel-tooltip
2
+
3
+ ## Overview
4
+ A simple tooltip component that displays contextual text on hover. Supports above/below positioning and optional tail (arrow pointer). Uses CSS opacity transitions for smooth fade-in/out effects. Content is provided via a `<slot>` for flexible trigger elements.
5
+
6
+ ## Usage
7
+ ```html
8
+ <!-- Basic tooltip (above) -->
9
+ <rel-tooltip text="This is a helpful tooltip">
10
+ <button>Hover me</button>
11
+ </rel-tooltip>
12
+
13
+ <!-- Tooltip positioned below -->
14
+ <rel-tooltip text="Information appears below" position="below">
15
+ <span>Hover for info</span>
16
+ </rel-tooltip>
17
+
18
+ <!-- With tail/arrow -->
19
+ <rel-tooltip text="Tooltip with pointer" position="above" showTail>
20
+ <button>Hover me</button>
21
+ </rel-tooltip>
22
+
23
+ <!-- Tooltip on icon -->
24
+ <rel-tooltip text="Edit item" showTail>
25
+ <img src="edit-icon.svg" alt="Edit">
26
+ </rel-tooltip>
27
+
28
+ <!-- Multiple elements in trigger -->
29
+ <rel-tooltip text="Profile options" position="below">
30
+ <div class="user-avatar">
31
+ <img src="avatar.jpg" alt="User">
32
+ <span>John Doe</span>
33
+ </div>
34
+ </rel-tooltip>
35
+ ```
36
+
37
+ ## API
38
+
39
+ ### Attributes/Properties
40
+ | Name | Type | Default | Description |
41
+ |------|------|---------|-------------|
42
+ | `text` | `string` | `""` | Tooltip text content |
43
+ | `position` | `"above" \| "below"` | `"above"` | Vertical position relative to trigger |
44
+ | `showTail` | `boolean` | `false` | Whether to show the arrow/pointer |
45
+
46
+ ## Events
47
+ None.
48
+
49
+ ## Slots
50
+ | Slot | Description |
51
+ |------|-------------|
52
+ | (default) | Trigger element(s) that activate the tooltip on hover |
53
+
54
+ ## CSS Parts
55
+ None exposed.
56
+
57
+ ## Tokens / CSS Variables
58
+
59
+ ### Semantic Tokens
60
+ - `--rel-fontFamilies-primary` - Font family
61
+ - `--rel-fontSizes-sm` - Font size
62
+
63
+ ### Spacing Tokens
64
+ - `--rel-spacing-space-xs` - Vertical padding
65
+ - `--rel-spacing-space-sm` - Horizontal padding
66
+
67
+ ### Color Tokens
68
+ - `--rel-surface-toast` - Background color (dark gray)
69
+ - `--rel-colors-white` - Text color
70
+
71
+ ### Border Tokens
72
+ - `--rel-borders-radius-border-radius-200` - Border radius
73
+
74
+ ## Accessibility
75
+ - Uses `role="tooltip"` on the tooltip bubble
76
+ - `aria-hidden="true"` on tooltip (content is supplemental, not critical)
77
+ - Tooltip does not receive focus (purely decorative on hover)
78
+ - For critical information, consider alternative patterns (e.g., visible labels or expandable sections)
79
+
80
+ ### Keyboard Interactions
81
+ - No keyboard interactions (hover-only)
82
+ - For keyboard accessibility, ensure slotted content is focusable and consider showing tooltip on focus
83
+
84
+ ### Focus Behavior
85
+ - Tooltip activation is hover-only by default
86
+ - Does not interfere with focus on slotted content
87
+
88
+ ## Notes / Edge Cases
89
+ - The tooltip appears on `:host(:hover)` via CSS `opacity: 1` transition
90
+ - By default, tooltip has `opacity: 0` and `pointer-events: none`
91
+ - **Position "above"**: tooltip is positioned at `bottom: calc(100% + 8px)` (8px gap above trigger)
92
+ - **Position "below"**: tooltip is positioned at `top: calc(100% + 8px)` (8px gap below trigger)
93
+ - The tooltip uses `left: 50%` and `transform: translateX(-50%)` for horizontal centering
94
+ - `white-space: nowrap` prevents text wrapping (tooltip width adjusts to content)
95
+ - **Tail/arrow** is a CSS triangle created with transparent borders:
96
+ - Above pointer: 6px border-top, positioned at `bottom: -6px`
97
+ - Below pointer: 6px border-bottom, positioned at `top: -6px`
98
+ - Tail uses `left: 50%` and `transform: translateX(-50%)` for centering
99
+ - The tooltip has `z-index: 1000` to appear above most content
100
+ - The tooltip is `position: absolute` relative to `:host` (which is `position: relative`)
101
+ - `:host` is `display: inline-block` to size to slotted content
102
+ - Transition duration is `0.2s ease` for opacity changes
103
+ - For very long tooltip text, consider wrapping or alternative UI patterns (max-width not set by default)