@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,149 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
|
|
4
|
+
@customElement("rel-resizable-handle")
|
|
5
|
+
export class RelResizableHandle extends LitElement {
|
|
6
|
+
/* =======================
|
|
7
|
+
* PUBLIC API
|
|
8
|
+
* ======================= */
|
|
9
|
+
|
|
10
|
+
@property({ type: String, reflect: true }) orientation: "horizontal" | "vertical" = "horizontal";
|
|
11
|
+
|
|
12
|
+
/* =======================
|
|
13
|
+
* INTERNAL STATE
|
|
14
|
+
* ======================= */
|
|
15
|
+
|
|
16
|
+
/** Index of this handle in the parent group */
|
|
17
|
+
public handleIndex = -1;
|
|
18
|
+
|
|
19
|
+
/** Current split value (0-100) for aria-valuenow */
|
|
20
|
+
public splitValue = 50;
|
|
21
|
+
|
|
22
|
+
/* =======================
|
|
23
|
+
* STYLES
|
|
24
|
+
* ======================= */
|
|
25
|
+
|
|
26
|
+
static styles = css`
|
|
27
|
+
:host {
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
justify-content: center;
|
|
31
|
+
flex-shrink: 0;
|
|
32
|
+
position: relative;
|
|
33
|
+
outline: none;
|
|
34
|
+
background: var(--rel-colors-gray-border);
|
|
35
|
+
transition: background 0.15s ease;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:host([orientation="horizontal"]) {
|
|
39
|
+
width: var(--rel-borders-width-stroke-100);
|
|
40
|
+
min-width: var(--rel-borders-width-stroke-100);
|
|
41
|
+
cursor: col-resize;
|
|
42
|
+
padding: 0 var(--rel-spacing-space-xs);
|
|
43
|
+
margin: 0 calc(var(--rel-spacing-space-xs) * -1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:host([orientation="vertical"]) {
|
|
47
|
+
height: var(--rel-borders-width-stroke-100);
|
|
48
|
+
min-height: var(--rel-borders-width-stroke-100);
|
|
49
|
+
cursor: row-resize;
|
|
50
|
+
padding: var(--rel-spacing-space-xs) 0;
|
|
51
|
+
margin: calc(var(--rel-spacing-space-xs) * -1) 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
:host(:hover),
|
|
55
|
+
:host(:focus-visible) {
|
|
56
|
+
background: var(--rel-colors-blue-primary);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
:host(:focus-visible) {
|
|
60
|
+
outline: 2px solid var(--rel-colors-blue-primary);
|
|
61
|
+
outline-offset: 2px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.grabber {
|
|
65
|
+
background: var(--rel-colors-gray-placeholder);
|
|
66
|
+
border-radius: var(--rel-borders-radius-border-radius-500);
|
|
67
|
+
transition: background 0.15s ease;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
:host([orientation="horizontal"]) .grabber {
|
|
71
|
+
width: 4px;
|
|
72
|
+
height: 24px;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
:host([orientation="vertical"]) .grabber {
|
|
76
|
+
width: 24px;
|
|
77
|
+
height: 4px;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
:host(:hover) .grabber,
|
|
81
|
+
:host(:focus-visible) .grabber {
|
|
82
|
+
background: var(--rel-colors-white);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
:host([data-dragging]) {
|
|
86
|
+
background: var(--rel-colors-blue-primary);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
:host([data-dragging]) .grabber {
|
|
90
|
+
background: var(--rel-colors-white);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
@media (prefers-reduced-motion: reduce) {
|
|
94
|
+
:host {
|
|
95
|
+
transition: none;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.grabber {
|
|
99
|
+
transition: none;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
/* =======================
|
|
105
|
+
* LIFECYCLE
|
|
106
|
+
* ======================= */
|
|
107
|
+
|
|
108
|
+
connectedCallback() {
|
|
109
|
+
super.connectedCallback();
|
|
110
|
+
this.setAttribute("tabindex", "0");
|
|
111
|
+
this.setAttribute("role", "separator");
|
|
112
|
+
this.updateAriaOrientation();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
updated(changed: Map<string, unknown>) {
|
|
116
|
+
if (changed.has("orientation")) {
|
|
117
|
+
this.updateAriaOrientation();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* =======================
|
|
122
|
+
* ARIA
|
|
123
|
+
* ======================= */
|
|
124
|
+
|
|
125
|
+
private updateAriaOrientation() {
|
|
126
|
+
this.setAttribute("aria-orientation", this.orientation);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public updateAriaValue(value: number) {
|
|
130
|
+
this.splitValue = value;
|
|
131
|
+
this.setAttribute("aria-valuenow", String(Math.round(value)));
|
|
132
|
+
this.setAttribute("aria-valuemin", "0");
|
|
133
|
+
this.setAttribute("aria-valuemax", "100");
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* =======================
|
|
137
|
+
* RENDER
|
|
138
|
+
* ======================= */
|
|
139
|
+
|
|
140
|
+
render() {
|
|
141
|
+
return html`<div class="grabber"></div>`;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
declare global {
|
|
146
|
+
interface HTMLElementTagNameMap {
|
|
147
|
+
"rel-resizable-handle": RelResizableHandle;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LitElement, html, css } from "lit";
|
|
2
|
+
import { customElement, property } from "lit/decorators.js";
|
|
3
|
+
|
|
4
|
+
@customElement("rel-resizable-panel")
|
|
5
|
+
export class RelResizablePanel extends LitElement {
|
|
6
|
+
/* =======================
|
|
7
|
+
* PUBLIC API
|
|
8
|
+
* ======================= */
|
|
9
|
+
|
|
10
|
+
@property({ type: Number, attribute: "defaultsize" }) defaultSize?: number;
|
|
11
|
+
@property({ type: Number, attribute: "minsize" }) minSize = 10;
|
|
12
|
+
@property({ type: Number, attribute: "maxsize" }) maxSize = 90;
|
|
13
|
+
|
|
14
|
+
/* =======================
|
|
15
|
+
* INTERNAL STATE
|
|
16
|
+
* ======================= */
|
|
17
|
+
|
|
18
|
+
/** Current computed size in percentage */
|
|
19
|
+
public currentSize = 0;
|
|
20
|
+
|
|
21
|
+
/* =======================
|
|
22
|
+
* STYLES
|
|
23
|
+
* ======================= */
|
|
24
|
+
|
|
25
|
+
static styles = css`
|
|
26
|
+
:host {
|
|
27
|
+
display: flex;
|
|
28
|
+
flex-direction: column;
|
|
29
|
+
overflow: auto;
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
}
|
|
32
|
+
`;
|
|
33
|
+
|
|
34
|
+
/* =======================
|
|
35
|
+
* RENDER
|
|
36
|
+
* ======================= */
|
|
37
|
+
|
|
38
|
+
render() {
|
|
39
|
+
return html`<slot></slot>`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
declare global {
|
|
44
|
+
interface HTMLElementTagNameMap {
|
|
45
|
+
"rel-resizable-panel": RelResizablePanel;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# rel-segmented-button
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
A segmented button group for mutually exclusive selections. Displays multiple options as connected buttons with a single active selection. Supports size variants, alignment options, and individual option states (disabled).
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
```html
|
|
8
|
+
<!-- Basic segmented button -->
|
|
9
|
+
<rel-segmented-button id="viewMode" active="grid"></rel-segmented-button>
|
|
10
|
+
<script>
|
|
11
|
+
const viewMode = document.getElementById('viewMode');
|
|
12
|
+
viewMode.options = [
|
|
13
|
+
{ label: 'List', value: 'list' },
|
|
14
|
+
{ label: 'Grid', value: 'grid' },
|
|
15
|
+
{ label: 'Table', value: 'table' }
|
|
16
|
+
];
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<!-- Small size with alignment -->
|
|
20
|
+
<rel-segmented-button
|
|
21
|
+
id="textAlign"
|
|
22
|
+
size="small"
|
|
23
|
+
align="middle"
|
|
24
|
+
active="center">
|
|
25
|
+
</rel-segmented-button>
|
|
26
|
+
<script>
|
|
27
|
+
const textAlign = document.getElementById('textAlign');
|
|
28
|
+
textAlign.options = [
|
|
29
|
+
{ label: 'Left', value: 'left' },
|
|
30
|
+
{ label: 'Center', value: 'center' },
|
|
31
|
+
{ label: 'Right', value: 'right' }
|
|
32
|
+
];
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<!-- With disabled option -->
|
|
36
|
+
<rel-segmented-button id="planSelector"></rel-segmented-button>
|
|
37
|
+
<script>
|
|
38
|
+
const planSelector = document.getElementById('planSelector');
|
|
39
|
+
planSelector.options = [
|
|
40
|
+
{ label: 'Free', value: 'free' },
|
|
41
|
+
{ label: 'Pro', value: 'pro' },
|
|
42
|
+
{ label: 'Enterprise', value: 'enterprise', disabled: true }
|
|
43
|
+
];
|
|
44
|
+
planSelector.active = 'free';
|
|
45
|
+
</script>
|
|
46
|
+
|
|
47
|
+
<!-- Listen for changes -->
|
|
48
|
+
<rel-segmented-button id="sortOrder"></rel-segmented-button>
|
|
49
|
+
<script>
|
|
50
|
+
const sortOrder = document.getElementById('sortOrder');
|
|
51
|
+
sortOrder.options = [
|
|
52
|
+
{ label: 'Newest', value: 'newest' },
|
|
53
|
+
{ label: 'Oldest', value: 'oldest' },
|
|
54
|
+
{ label: 'Popular', value: 'popular' }
|
|
55
|
+
];
|
|
56
|
+
sortOrder.addEventListener('changed', (e) => {
|
|
57
|
+
console.log('Selected:', e.detail.value);
|
|
58
|
+
});
|
|
59
|
+
</script>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## API
|
|
63
|
+
|
|
64
|
+
### Attributes/Properties
|
|
65
|
+
| Name | Type | Default | Description |
|
|
66
|
+
|------|------|---------|-------------|
|
|
67
|
+
| `options` | `SegmentOption[]` | `[]` | Array of segment options (see SegmentOption interface below) |
|
|
68
|
+
| `active` | `string` | `""` | Value of the currently active segment |
|
|
69
|
+
| `size` | `"small" \| "medium"` | `"medium"` | Size variant |
|
|
70
|
+
| `align` | `"left" \| "middle" \| "right"` | `"left"` | Horizontal alignment of the button group |
|
|
71
|
+
|
|
72
|
+
### SegmentOption Interface
|
|
73
|
+
```typescript
|
|
74
|
+
interface SegmentOption {
|
|
75
|
+
label: string; // Display text for the button
|
|
76
|
+
value: string; // Unique value identifier
|
|
77
|
+
disabled?: boolean; // Optional: disable this specific segment
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Events
|
|
82
|
+
| Event | Detail | Description |
|
|
83
|
+
|-------|--------|-------------|
|
|
84
|
+
| `changed` | `{ value: string }` | Fired when a different segment is selected |
|
|
85
|
+
|
|
86
|
+
## Slots
|
|
87
|
+
Default slot not used.
|
|
88
|
+
|
|
89
|
+
## CSS Parts
|
|
90
|
+
None exposed.
|
|
91
|
+
|
|
92
|
+
## Tokens / CSS Variables
|
|
93
|
+
|
|
94
|
+
### Semantic Tokens
|
|
95
|
+
- `--rel-fontFamilies-primary` - Font family
|
|
96
|
+
- `--rel-fontSizes-xs`, `--rel-fontSizes-sm` - Font sizes for small and medium variants
|
|
97
|
+
- `--rel-fontWeights-medium` - Font weight for segment labels
|
|
98
|
+
|
|
99
|
+
### Spacing Tokens
|
|
100
|
+
- `--rel-spacing-space-3xs`, `--rel-spacing-space-2xs` - Vertical padding for sizes
|
|
101
|
+
- `--rel-spacing-space-xs`, `--rel-spacing-space-sm` - Horizontal padding for sizes
|
|
102
|
+
|
|
103
|
+
### Color Tokens
|
|
104
|
+
- `--rel-colors-white` - Default segment background
|
|
105
|
+
- `--rel-colors-gray-border` - Outer border and segment dividers
|
|
106
|
+
- `--rel-text-heading` - Active segment background and default text color
|
|
107
|
+
- `--rel-surface-surface` - Hover and disabled background
|
|
108
|
+
- `--rel-text-disabled` - Disabled text color
|
|
109
|
+
- `--rel-border-info` - Focus outline color
|
|
110
|
+
|
|
111
|
+
### Border Tokens
|
|
112
|
+
- `--rel-borders-radius-border-radius-300` - Border radius for the group
|
|
113
|
+
|
|
114
|
+
## Accessibility
|
|
115
|
+
- Uses native `<button>` elements for proper keyboard navigation
|
|
116
|
+
- Focus visible state with inner outline for keyboard users
|
|
117
|
+
- Disabled segments use `pointer-events: none` and reduced opacity
|
|
118
|
+
- Each segment can receive focus independently
|
|
119
|
+
|
|
120
|
+
### Keyboard Interactions
|
|
121
|
+
- `Tab` - Move focus between segments
|
|
122
|
+
- `Space/Enter` - Activate focused segment
|
|
123
|
+
- `Arrow Left/Right` - Navigate between segments (browser default)
|
|
124
|
+
|
|
125
|
+
### Focus Behavior
|
|
126
|
+
- Focus outline appears inside the button boundary with `-2px` offset
|
|
127
|
+
- Uses info border color for high contrast
|
|
128
|
+
- Active button has `z-index: 1` to ensure focus ring is visible over adjacent segments
|
|
129
|
+
|
|
130
|
+
## Notes / Edge Cases
|
|
131
|
+
- The component is `display: inline-block` and sizes to fit content
|
|
132
|
+
- All segments are connected with shared borders (2px solid gray)
|
|
133
|
+
- The last segment has no right border to avoid doubling with the outer container border
|
|
134
|
+
- Active segment has inverted colors (dark background, white text)
|
|
135
|
+
- Hovering a non-active, non-disabled segment shows a light gray background
|
|
136
|
+
- Hovering the active segment does not change its appearance
|
|
137
|
+
- Disabled segments show reduced opacity (0.5), gray background, and are non-interactive
|
|
138
|
+
- The `align` property uses flexbox justify-content (left → flex-start, middle → center, right → flex-end)
|
|
139
|
+
- Size variants affect both font size and padding
|
|
140
|
+
- Smooth transitions (0.2s ease-in-out) apply to all visual changes
|
|
141
|
+
- Clicking a disabled option will not change the `active` value or dispatch events
|
|
@@ -48,15 +48,20 @@ export class RelSegmentedButton extends LitElement {
|
|
|
48
48
|
|
|
49
49
|
/* Base segment styling */
|
|
50
50
|
.segment {
|
|
51
|
-
background: var(--rel-colors-white);
|
|
51
|
+
background: var(--rel-colors-white, #fff);
|
|
52
52
|
border: none;
|
|
53
53
|
cursor: pointer;
|
|
54
|
-
font-weight: var(--rel-fontWeights-medium);
|
|
55
|
-
border-right: 2px solid var(--rel-colors-gray-border);
|
|
54
|
+
font-weight: var(--rel-fontWeights-medium, 500);
|
|
55
|
+
border-right: 2px solid var(--rel-colors-gray-border, #ddd);
|
|
56
56
|
transition: all 0.2s ease-in-out;
|
|
57
|
-
color: var(--rel-
|
|
58
|
-
font-family: var(--rel-fontFamilies-primary);
|
|
59
|
-
|
|
57
|
+
color: var(--rel-text-heading, #2b2b2b);
|
|
58
|
+
font-family: var(--rel-fontFamilies-primary, sans-serif);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.segment:focus-visible {
|
|
62
|
+
outline: 2px solid var(--rel-border-info, #0091ea);
|
|
63
|
+
outline-offset: -2px;
|
|
64
|
+
z-index: 1;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
67
|
.segment:last-child {
|
|
@@ -65,18 +70,18 @@ export class RelSegmentedButton extends LitElement {
|
|
|
65
70
|
|
|
66
71
|
/* Hover */
|
|
67
72
|
.segment:hover:not(.disabled):not(.active) {
|
|
68
|
-
background: var(--rel-
|
|
73
|
+
background: var(--rel-surface-surface, #f5f5f5);
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
/* Active */
|
|
72
77
|
.segment.active {
|
|
73
|
-
background: var(--rel-
|
|
74
|
-
color: var(--rel-colors-white);
|
|
78
|
+
background: var(--rel-text-heading, #2b2b2b);
|
|
79
|
+
color: var(--rel-colors-white, #fff);
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
.segment.active:hover:not(.disabled) {
|
|
78
|
-
background: var(--rel-
|
|
79
|
-
color: var(--rel-colors-white);
|
|
83
|
+
background: var(--rel-text-heading, #2b2b2b);
|
|
84
|
+
color: var(--rel-colors-white, #fff);
|
|
80
85
|
}
|
|
81
86
|
|
|
82
87
|
/* Disabled */
|
|
@@ -84,8 +89,8 @@ export class RelSegmentedButton extends LitElement {
|
|
|
84
89
|
.segment:disabled {
|
|
85
90
|
cursor: not-allowed;
|
|
86
91
|
opacity: 0.5;
|
|
87
|
-
background: var(--rel-
|
|
88
|
-
color: var(--rel-
|
|
92
|
+
background: var(--rel-surface-surface, #f5f5f5);
|
|
93
|
+
color: var(--rel-text-disabled, #9e9e9e);
|
|
89
94
|
pointer-events: none;
|
|
90
95
|
}
|
|
91
96
|
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# rel-select
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
A customizable dropdown select component with support for icons, multiple states, and sizes. Features built-in validation states, supporting text, and comprehensive styling options for form-based interfaces.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
```html
|
|
8
|
+
<!-- Basic example -->
|
|
9
|
+
<rel-select id="countrySelect" label="Country" selected="USA"></rel-select>
|
|
10
|
+
<script>
|
|
11
|
+
const select = document.getElementById('countrySelect');
|
|
12
|
+
select.options = ['USA', 'Canada', 'Mexico'];
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<!-- Example with common options -->
|
|
16
|
+
<rel-select
|
|
17
|
+
id="emailPreference"
|
|
18
|
+
label="Email Preference"
|
|
19
|
+
selected="Weekly"
|
|
20
|
+
size="medium"
|
|
21
|
+
state="default"
|
|
22
|
+
supportingText="Choose how often you want to receive emails"
|
|
23
|
+
leftIcon="📧">
|
|
24
|
+
</rel-select>
|
|
25
|
+
<script>
|
|
26
|
+
const emailPref = document.getElementById('emailPreference');
|
|
27
|
+
emailPref.options = ['Daily', 'Weekly', 'Monthly', 'Never'];
|
|
28
|
+
</script>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
### Attributes/Properties
|
|
34
|
+
| Name | Type | Default | Description |
|
|
35
|
+
|------|------|---------|-------------|
|
|
36
|
+
| `label` | `string` | `""` | Label text displayed above the select |
|
|
37
|
+
| `options` | `string[]` | `[]` | Array of option values to display in dropdown |
|
|
38
|
+
| `selected` | `string` | `""` | Currently selected option value |
|
|
39
|
+
| `state` | `"default" \| "error" \| "disabled"` | `"default"` | Visual and interaction state of the select |
|
|
40
|
+
| `supportingText` | `string` | `""` | Helper or error text displayed below the select |
|
|
41
|
+
| `size` | `"small" \| "medium" \| "large"` | `"medium"` | Size variant affecting padding and font size |
|
|
42
|
+
| `border` | `"rounded" \| "sharp"` | `"rounded"` | Border radius style |
|
|
43
|
+
| `leftIcon` | `string` | `""` | Icon or text displayed on the left side |
|
|
44
|
+
| `rightIcon` | `string` | `""` | Icon or text displayed on the right side (before dropdown arrow) |
|
|
45
|
+
|
|
46
|
+
## Events
|
|
47
|
+
| Event | Detail | Description |
|
|
48
|
+
|-------|--------|-------------|
|
|
49
|
+
| `changed` | `{ value: string }` | Fired when the selected value changes |
|
|
50
|
+
|
|
51
|
+
## Slots
|
|
52
|
+
Default slot not used.
|
|
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-xs`, `--rel-fontSizes-sm`, `--rel-fontSizes-md` - Font sizes for different size variants
|
|
62
|
+
- `--rel-fontWeights-medium` - Font weight for label
|
|
63
|
+
|
|
64
|
+
### Spacing Tokens
|
|
65
|
+
- `--rel-spacing-space-3xs`, `--rel-spacing-space-2xs`, `--rel-spacing-space-xs` - Internal padding
|
|
66
|
+
- `--rel-spacing-space-sm`, `--rel-spacing-space-lg`, `--rel-spacing-space-xl`, `--rel-spacing-space-2xl`, `--rel-spacing-space-3xl` - Padding and icon positioning
|
|
67
|
+
|
|
68
|
+
### Color Tokens
|
|
69
|
+
- `--rel-colors-gray-heading` - Label text color
|
|
70
|
+
- `--rel-colors-gray-primary` - Icon and border hover color
|
|
71
|
+
- `--rel-colors-gray-border` - Default border color
|
|
72
|
+
- `--rel-colors-gray-placeholder` - Supporting text color
|
|
73
|
+
- `--rel-colors-white` - Background color
|
|
74
|
+
- `--rel-colors-primary-500` - Focus border and shadow color
|
|
75
|
+
- `--rel-colors-red-secondary` - Error state border color
|
|
76
|
+
- `--rel-background-error-light` - Error state focus shadow
|
|
77
|
+
- `--rel-surface-surface` - Disabled background
|
|
78
|
+
- `--rel-text-heading` - Select text color
|
|
79
|
+
- `--rel-text-disabled` - Disabled text color
|
|
80
|
+
|
|
81
|
+
### Border Tokens
|
|
82
|
+
- `--rel-borders-radius-border-radius-300` - Rounded border radius
|
|
83
|
+
|
|
84
|
+
## Accessibility
|
|
85
|
+
- Native `<select>` element provides built-in keyboard navigation
|
|
86
|
+
- Focus visible states with clear visual indicators (border color and box shadow)
|
|
87
|
+
- Label properly associated with select for screen readers
|
|
88
|
+
- Disabled state prevents interaction and reduces opacity
|
|
89
|
+
- Error state communicated through color and supporting text
|
|
90
|
+
|
|
91
|
+
### Keyboard Interactions
|
|
92
|
+
- `Space/Enter` - Open dropdown
|
|
93
|
+
- `Arrow Up/Down` - Navigate options
|
|
94
|
+
- `Escape` - Close dropdown
|
|
95
|
+
- `Tab` - Move focus to next element
|
|
96
|
+
|
|
97
|
+
### Focus Behavior
|
|
98
|
+
- Clear focus ring with primary color on keyboard focus
|
|
99
|
+
- Focus state uses box-shadow for visibility
|
|
100
|
+
|
|
101
|
+
## Notes / Edge Cases
|
|
102
|
+
- When `state="disabled"`, the select becomes non-interactive with reduced opacity and cursor indication
|
|
103
|
+
- Empty `selected` value shows placeholder text "Select Option" which is hidden from the dropdown list
|
|
104
|
+
- Icons (left/right) adjust internal padding automatically to accommodate icon space
|
|
105
|
+
- The native dropdown arrow is always visible on the right side, custom rightIcon appears before it
|
|
106
|
+
- In error state, supporting text is styled with error color for visual consistency
|
|
107
|
+
- Options array is rendered as-is; complex objects not supported (use string values only)
|
|
@@ -28,7 +28,7 @@ export class RelSelect extends LitElement {
|
|
|
28
28
|
static styles = css`
|
|
29
29
|
:host {
|
|
30
30
|
display: block;
|
|
31
|
-
font-family: var(--rel-fontFamilies-primary);
|
|
31
|
+
font-family: var(--rel-fontFamilies-primary, sans-serif);
|
|
32
32
|
width: 100%;
|
|
33
33
|
}
|
|
34
34
|
|
|
@@ -74,26 +74,26 @@ export class RelSelect extends LitElement {
|
|
|
74
74
|
select {
|
|
75
75
|
flex: 1;
|
|
76
76
|
appearance: none;
|
|
77
|
-
border: 1px solid var(--rel-colors-gray-border);
|
|
78
|
-
background-color: var(--rel-colors-white);
|
|
79
|
-
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='
|
|
77
|
+
border: 1px solid var(--rel-colors-gray-border, #ddd);
|
|
78
|
+
background-color: var(--rel-colors-white, #fff);
|
|
79
|
+
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='currentColor' d='M6 9L1 4h10z'/%3E%3C/svg%3E");
|
|
80
80
|
background-repeat: no-repeat;
|
|
81
81
|
background-position: right 12px center;
|
|
82
|
-
font-family: var(--rel-fontFamilies-primary);
|
|
82
|
+
font-family: var(--rel-fontFamilies-primary, sans-serif);
|
|
83
83
|
cursor: pointer;
|
|
84
84
|
transition: all 0.2s ease-in-out;
|
|
85
|
-
color: var(--rel-
|
|
85
|
+
color: var(--rel-text-heading, #2b2b2b);
|
|
86
86
|
width: 100%;
|
|
87
87
|
outline: none;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
select:hover:not(:disabled) {
|
|
91
|
-
border-color: var(--rel-colors-gray-primary);
|
|
91
|
+
border-color: var(--rel-colors-gray-primary, #333);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
select:focus:not(:disabled) {
|
|
95
|
-
border-color: var(--rel-colors-
|
|
96
|
-
box-shadow: 0 0 0
|
|
94
|
+
select:focus-visible:not(:disabled) {
|
|
95
|
+
border-color: var(--rel-colors-primary-500, #0091ea);
|
|
96
|
+
box-shadow: 0 0 0 2px var(--rel-colors-primary-500, #0091ea);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
/* States */
|
|
@@ -102,13 +102,13 @@ export class RelSelect extends LitElement {
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
select.error:focus {
|
|
105
|
-
box-shadow: 0 0 0 3px
|
|
105
|
+
box-shadow: 0 0 0 3px var(--rel-background-error-light);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
select:disabled {
|
|
109
|
-
background-color: var(--rel-
|
|
110
|
-
border-color: var(--rel-colors-gray-border);
|
|
111
|
-
color: var(--rel-
|
|
109
|
+
background-color: var(--rel-surface-surface, #f5f5f5);
|
|
110
|
+
border-color: var(--rel-colors-gray-border, #ddd);
|
|
111
|
+
color: var(--rel-text-disabled, #9e9e9e);
|
|
112
112
|
cursor: not-allowed;
|
|
113
113
|
opacity: 0.6;
|
|
114
114
|
}
|