@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.
- package/dist/components/rel-accordion/README.md +132 -0
- package/dist/components/rel-accordion/rel-accordion.ts +43 -16
- package/dist/components/rel-alert/README.md +141 -0
- package/dist/components/rel-alert/rel-alert.ts +18 -7
- package/dist/components/rel-avatar/README.md +119 -0
- package/dist/components/rel-badge/README.md +86 -0
- package/dist/components/rel-badge/rel-badge.ts +6 -6
- package/dist/components/rel-breadcrumb/README.md +102 -0
- package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +12 -6
- package/dist/components/rel-button/README.md +130 -0
- package/dist/components/rel-calendar/README.md +109 -0
- package/dist/components/rel-calendar/index.ts +1 -0
- package/dist/components/rel-calendar/rel-calendar.ts +467 -0
- package/dist/components/rel-card/README.md +94 -0
- package/dist/components/rel-card/rel-card.ts +12 -3
- package/dist/components/rel-cardmedia/README.md +127 -0
- package/dist/components/rel-cardmedia/rel-cardmedia.ts +14 -4
- package/dist/components/rel-carousel/README.md +166 -0
- package/dist/components/rel-carousel/index.ts +1 -0
- package/dist/components/rel-carousel/rel-carousel.ts +469 -0
- package/dist/components/rel-chart/README.md +286 -0
- package/dist/components/rel-chart/index.ts +1 -0
- package/dist/components/rel-chart/rel-chart.ts +736 -0
- package/dist/components/rel-checkbox/README.md +77 -0
- package/dist/components/rel-checkbox/rel-checkbox.ts +18 -10
- package/dist/components/rel-chip/README.md +114 -0
- package/dist/components/rel-chip/rel-chip.ts +20 -4
- package/dist/components/rel-container/README.md +99 -0
- package/dist/components/rel-date-picker/README.md +253 -0
- package/dist/components/rel-date-picker/index.ts +1 -0
- package/dist/components/rel-date-picker/rel-date-picker.ts +916 -0
- package/dist/components/rel-divider/README.md +100 -0
- package/dist/components/rel-drawer/README.md +200 -0
- package/dist/components/rel-drawer/index.ts +1 -0
- package/dist/components/rel-drawer/rel-drawer.ts +621 -0
- package/dist/components/rel-kbd/README.md +151 -0
- package/dist/components/rel-kbd/rel-kbd.ts +118 -0
- package/dist/components/rel-layout/README.md +88 -0
- package/dist/components/rel-menu/README.md +151 -0
- package/dist/components/rel-menu/rel-menu.ts +18 -10
- package/dist/components/rel-menubar/README.md +329 -0
- package/dist/components/rel-menubar/index.ts +2 -0
- package/dist/components/rel-menubar/rel-menubar-menu.ts +16 -0
- package/dist/components/rel-menubar/rel-menubar.ts +576 -0
- package/dist/components/rel-nav-menu/README.md +289 -0
- package/dist/components/rel-nav-menu/index.ts +3 -0
- package/dist/components/rel-nav-menu/rel-nav-menu-item.ts +143 -0
- package/dist/components/rel-nav-menu/rel-nav-menu-panel.ts +53 -0
- package/dist/components/rel-nav-menu/rel-nav-menu.ts +331 -0
- package/dist/components/rel-navbar/README.md +126 -0
- package/dist/components/rel-navbar/rel-navbar.ts +91 -0
- package/dist/components/rel-otp/README.md +440 -0
- package/dist/components/rel-otp/index.ts +1 -0
- package/dist/components/rel-otp/rel-otp.ts +504 -0
- package/dist/components/rel-pagination/README.md +410 -0
- package/dist/components/rel-pagination/index.ts +1 -0
- package/dist/components/rel-pagination/rel-pagination.ts +376 -0
- package/dist/components/rel-popover/README.md +568 -0
- package/dist/components/rel-popover/index.ts +2 -0
- package/dist/components/rel-popover/rel-popover-content.ts +55 -0
- package/dist/components/rel-popover/rel-popover.ts +327 -0
- package/dist/components/rel-progress/README.md +110 -0
- package/dist/components/rel-progress/rel-progress.ts +32 -5
- package/dist/components/rel-quote-page/README.md +166 -0
- package/dist/components/rel-quote-page/rel-quote-page.ts +816 -0
- package/dist/components/rel-radio/README.md +120 -0
- package/dist/components/rel-radio/rel-radio.ts +13 -5
- package/dist/components/rel-resizable/README.md +140 -0
- package/dist/components/rel-resizable/index.ts +3 -0
- package/dist/components/rel-resizable/rel-resizable-group.ts +374 -0
- package/dist/components/rel-resizable/rel-resizable-handle.ts +149 -0
- package/dist/components/rel-resizable/rel-resizable-panel.ts +47 -0
- package/dist/components/rel-segmented-button/README.md +141 -0
- package/dist/components/rel-segmented-button/rel-segmented-button.ts +18 -13
- package/dist/components/rel-select/README.md +107 -0
- package/dist/components/rel-select/rel-select.ts +14 -14
- package/dist/components/rel-sheet/README.md +224 -0
- package/dist/components/rel-sheet/rel-sheet.ts +683 -0
- package/dist/components/rel-sidebar/README.md +209 -0
- package/dist/components/rel-sidebar/rel-sidebar.ts +1158 -0
- package/dist/components/rel-slider/README.md +135 -0
- package/dist/components/rel-slider/rel-slider.ts +19 -7
- package/dist/components/rel-snackbar/README.md +134 -0
- package/dist/components/rel-snackbar/rel-snackbar.ts +67 -2
- package/dist/components/rel-stepper/README.md +160 -0
- package/dist/components/rel-stepper/rel-stepper.ts +6 -6
- package/dist/components/rel-switch/README.md +102 -0
- package/dist/components/rel-switch/rel-switch.ts +15 -6
- package/dist/components/rel-tab/README.md +163 -0
- package/dist/components/rel-tab/rel-tab.ts +36 -14
- package/dist/components/rel-table/README.md +178 -0
- package/dist/components/rel-table/rel-table-body.ts +16 -0
- package/dist/components/rel-table/rel-table-caption.ts +22 -0
- package/dist/components/rel-table/rel-table-cell.ts +49 -0
- package/dist/components/rel-table/rel-table-footer.ts +18 -0
- package/dist/components/rel-table/rel-table-head.ts +33 -0
- package/dist/components/rel-table/rel-table-header.ts +16 -0
- package/dist/components/rel-table/rel-table-row.ts +32 -0
- package/dist/components/rel-table/rel-table.ts +47 -0
- package/dist/components/rel-textfield/README.md +90 -0
- package/dist/components/rel-textfield/rel-textfield.ts +35 -19
- package/dist/components/rel-toast/README.md +148 -0
- package/dist/components/rel-toast/rel-toast.ts +32 -14
- package/dist/components/rel-tooltip/README.md +103 -0
- package/dist/components/rel-tooltip/rel-tooltip.ts +9 -9
- package/dist/index.d.mts +836 -1
- package/dist/index.d.ts +836 -1
- package/dist/index.js +10658 -1493
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10616 -1499
- package/dist/index.mjs.map +1 -1
- package/dist/styles/vars.css +293 -183
- package/dist/{vars-6ZIUPIU4.css → vars-ITL2K3KO.css} +293 -183
- 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:
|
|
38
|
-
font-weight: 500;
|
|
39
|
-
color: #
|
|
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 #
|
|
48
|
-
border-radius:
|
|
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:
|
|
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: #
|
|
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: #
|
|
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: #
|
|
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: #
|
|
130
|
+
border-color: var(--rel-border-error, #cc0000);
|
|
120
131
|
}
|
|
121
132
|
|
|
122
133
|
.textfield-wrapper.disabled .textfield-container {
|
|
123
|
-
border-color: #
|
|
134
|
+
border-color: var(--rel-border-default, #ddd);
|
|
124
135
|
}
|
|
125
136
|
|
|
126
137
|
/* Supporting text */
|
|
127
138
|
.textfield-support {
|
|
128
|
-
font-size:
|
|
129
|
-
color: #
|
|
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: #
|
|
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: #
|
|
36
|
-
color: #fff;
|
|
37
|
-
font-family: var(--rel-fontFamilies-primary);
|
|
38
|
-
font-size:
|
|
39
|
-
border-radius: 8px;
|
|
40
|
-
padding:
|
|
41
|
-
box-shadow:
|
|
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:
|
|
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:
|
|
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:
|
|
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)
|