@orange-halo/components 2.2.0 → 3.0.0
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/custom-elements.json +551 -314
- package/dist/index.d.ts +1 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/oh-accordion.d.ts +53 -8
- package/dist/oh-accordion.d.ts.map +1 -1
- package/dist/oh-accordion.js +77 -15
- package/dist/oh-accordion.js.map +1 -1
- package/dist/oh-alert.d.ts +26 -8
- package/dist/oh-alert.d.ts.map +1 -1
- package/dist/oh-alert.js +32 -14
- package/dist/oh-alert.js.map +1 -1
- package/dist/oh-badge.d.ts +32 -13
- package/dist/oh-badge.d.ts.map +1 -1
- package/dist/oh-badge.js +35 -16
- package/dist/oh-badge.js.map +1 -1
- package/dist/oh-breadcrumb.d.ts +39 -12
- package/dist/oh-breadcrumb.d.ts.map +1 -1
- package/dist/oh-breadcrumb.js +39 -17
- package/dist/oh-breadcrumb.js.map +1 -1
- package/dist/oh-button.d.ts +49 -23
- package/dist/oh-button.d.ts.map +1 -1
- package/dist/oh-button.js +63 -44
- package/dist/oh-button.js.map +1 -1
- package/dist/oh-card.d.ts +47 -19
- package/dist/oh-card.d.ts.map +1 -1
- package/dist/oh-card.js +110 -82
- package/dist/oh-card.js.map +1 -1
- package/dist/oh-checkbox-group.d.ts +56 -12
- package/dist/oh-checkbox-group.d.ts.map +1 -1
- package/dist/oh-checkbox-group.figma.js +4 -6
- package/dist/oh-checkbox-group.figma.js.map +1 -1
- package/dist/oh-checkbox-group.js +86 -44
- package/dist/oh-checkbox-group.js.map +1 -1
- package/dist/oh-checkbox.d.ts +54 -17
- package/dist/oh-checkbox.d.ts.map +1 -1
- package/dist/oh-checkbox.js +85 -55
- package/dist/oh-checkbox.js.map +1 -1
- package/dist/oh-cluster.d.ts +19 -14
- package/dist/oh-cluster.d.ts.map +1 -1
- package/dist/oh-cluster.js +19 -19
- package/dist/oh-cluster.js.map +1 -1
- package/dist/oh-container.d.ts +19 -16
- package/dist/oh-container.d.ts.map +1 -1
- package/dist/oh-container.js +21 -23
- package/dist/oh-container.js.map +1 -1
- package/dist/oh-drawer.d.ts +28 -11
- package/dist/oh-drawer.d.ts.map +1 -1
- package/dist/oh-drawer.js +31 -14
- package/dist/oh-drawer.js.map +1 -1
- package/dist/oh-footer.d.ts +37 -18
- package/dist/oh-footer.d.ts.map +1 -1
- package/dist/oh-footer.js +38 -19
- package/dist/oh-footer.js.map +1 -1
- package/dist/oh-grid.d.ts +27 -14
- package/dist/oh-grid.d.ts.map +1 -1
- package/dist/oh-grid.js +27 -19
- package/dist/oh-grid.js.map +1 -1
- package/dist/oh-icon.d.ts +21 -5
- package/dist/oh-icon.d.ts.map +1 -1
- package/dist/oh-icon.js +21 -5
- package/dist/oh-icon.js.map +1 -1
- package/dist/oh-input.d.ts +104 -20
- package/dist/oh-input.d.ts.map +1 -1
- package/dist/oh-input.figma.js +2 -2
- package/dist/oh-input.figma.js.map +1 -1
- package/dist/oh-input.js +205 -66
- package/dist/oh-input.js.map +1 -1
- package/dist/oh-link.d.ts +42 -19
- package/dist/oh-link.d.ts.map +1 -1
- package/dist/oh-link.js +47 -29
- package/dist/oh-link.js.map +1 -1
- package/dist/oh-modal.d.ts +29 -6
- package/dist/oh-modal.d.ts.map +1 -1
- package/dist/oh-modal.js +37 -16
- package/dist/oh-modal.js.map +1 -1
- package/dist/oh-navbar.d.ts +42 -19
- package/dist/oh-navbar.d.ts.map +1 -1
- package/dist/oh-navbar.js +42 -19
- package/dist/oh-navbar.js.map +1 -1
- package/dist/oh-progress.d.ts +26 -7
- package/dist/oh-progress.d.ts.map +1 -1
- package/dist/oh-progress.js +31 -12
- package/dist/oh-progress.js.map +1 -1
- package/dist/oh-radio-group.d.ts +55 -13
- package/dist/oh-radio-group.d.ts.map +1 -1
- package/dist/oh-radio-group.figma.js +2 -2
- package/dist/oh-radio-group.figma.js.map +1 -1
- package/dist/oh-radio-group.js +83 -43
- package/dist/oh-radio-group.js.map +1 -1
- package/dist/oh-radio.d.ts +55 -17
- package/dist/oh-radio.d.ts.map +1 -1
- package/dist/oh-radio.js +87 -56
- package/dist/oh-radio.js.map +1 -1
- package/dist/oh-select.d.ts +58 -16
- package/dist/oh-select.d.ts.map +1 -1
- package/dist/oh-select.js +70 -33
- package/dist/oh-select.js.map +1 -1
- package/dist/oh-skip-link.d.ts +33 -15
- package/dist/oh-skip-link.d.ts.map +1 -1
- package/dist/oh-skip-link.js +38 -25
- package/dist/oh-skip-link.js.map +1 -1
- package/dist/oh-stack.d.ts +17 -14
- package/dist/oh-stack.d.ts.map +1 -1
- package/dist/oh-stack.js +18 -20
- package/dist/oh-stack.js.map +1 -1
- package/dist/oh-tabs.d.ts +55 -30
- package/dist/oh-tabs.d.ts.map +1 -1
- package/dist/oh-tabs.js +80 -65
- package/dist/oh-tabs.js.map +1 -1
- package/dist/oh-textarea.d.ts +37 -6
- package/dist/oh-textarea.d.ts.map +1 -1
- package/dist/oh-textarea.js +40 -9
- package/dist/oh-textarea.js.map +1 -1
- package/dist/oh-toggle.d.ts +45 -12
- package/dist/oh-toggle.d.ts.map +1 -1
- package/dist/oh-toggle.js +64 -29
- package/dist/oh-toggle.js.map +1 -1
- package/package.json +3 -7
- package/dist/oh-hero.d.ts +0 -33
- package/dist/oh-hero.d.ts.map +0 -1
- package/dist/oh-hero.js +0 -248
- package/dist/oh-hero.js.map +0 -1
package/dist/oh-input.js
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* oh-input
|
|
3
3
|
*
|
|
4
|
-
* A chunky, inset input field that feels pressed into the page.
|
|
5
|
-
* On focus, it rises to meet you.
|
|
6
|
-
*
|
|
7
4
|
* DESIGN DECISIONS:
|
|
8
5
|
* ─────────────────
|
|
9
|
-
* 1.
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
14
|
-
* 2. INSET SHADOW (PRESSED IN)
|
|
15
|
-
* - Shadow offset to top-left (inset)
|
|
16
|
-
* - Feels pressed into the surface
|
|
17
|
-
* - Opposite of button's outset sticker effect
|
|
6
|
+
* 1. LOOK FROM TOKENS
|
|
7
|
+
* - Border: input.base.borderWidth (stroke.control) in color.border.emphasis
|
|
8
|
+
* - Corners: shape.control (same as oh-button)
|
|
9
|
+
* - Shadow: an inset shadow offset by elevation.offset.md in elevation.color.field
|
|
18
10
|
*
|
|
19
|
-
*
|
|
20
|
-
* - An inset ring in focus.ringColor
|
|
11
|
+
* 2. FOCUS IS A SOLID RING
|
|
12
|
+
* - An inset ring in focus.ringColor inside the border, so focus doesn't
|
|
13
|
+
* shift the layout
|
|
21
14
|
* - Background switches to color.surface.highlight
|
|
22
|
-
* - Clear visual hierarchy
|
|
23
15
|
*
|
|
24
|
-
*
|
|
16
|
+
* 3. A REAL FORM CONTROL
|
|
17
|
+
* - Form-associated, like oh-textarea: its value submits with the form
|
|
18
|
+
* under its name and shows in form.elements, `required` blocks
|
|
19
|
+
* submission, a form reset restores the starting value, and a
|
|
20
|
+
* disabled <fieldset> disables it
|
|
21
|
+
*
|
|
22
|
+
* 4. SUGGESTIONS ARE NATIVE
|
|
23
|
+
* - `suggestions` renders a <datalist> inside the component (a list
|
|
24
|
+
* outside it can't reach an input in the shadow root). The browser
|
|
25
|
+
* draws the list and handles the keyboard and screen readers, so
|
|
26
|
+
* people can still type anything: it suggests, it doesn't restrict
|
|
27
|
+
*
|
|
28
|
+
* 5. ERRORS BEFORE THE FIELD
|
|
29
|
+
* - Error text sits after the label and before the field, with an icon,
|
|
30
|
+
* so it's read before the field is reached. Helper text sits after
|
|
25
31
|
*/
|
|
26
32
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
27
33
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -32,21 +38,91 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
32
38
|
import { html, css, nothing } from "lit";
|
|
33
39
|
import { customElement, property, query, state } from "lit/decorators.js";
|
|
34
40
|
import { OhElement, baseStyles } from "./base.js";
|
|
41
|
+
/**
|
|
42
|
+
* A single-line text field that submits with a native form, with optional
|
|
43
|
+
* typing suggestions.
|
|
44
|
+
*
|
|
45
|
+
* **Use it for** short free text: names, email addresses, search terms.
|
|
46
|
+
* **Don't use it for** several lines (use `oh-textarea`) or a choice from a
|
|
47
|
+
* fixed list (use `oh-select`, or `oh-radio-group` for a few options).
|
|
48
|
+
* `suggestions` offers values while still allowing any text.
|
|
49
|
+
*
|
|
50
|
+
* **Types:** `text` (default), `email`, `password`, `search`, `tel`, `url`.
|
|
51
|
+
* One size. **States:** rest, hover, focus, error (set `error-text`),
|
|
52
|
+
* disabled, required.
|
|
53
|
+
*
|
|
54
|
+
* **Behaviour:** form-associated: the value submits under `name`, `required`
|
|
55
|
+
* blocks submission (validity comes from the inner `<input>`), a form reset
|
|
56
|
+
* restores the starting value, and a disabled `<fieldset>` disables it.
|
|
57
|
+
* Fires `oh-input` as the text changes and `oh-change` when it's committed.
|
|
58
|
+
* `suggestions` renders a native `<datalist>`, so the browser handles its
|
|
59
|
+
* keyboard and screen reader support. `autocomplete` is passed to the inner
|
|
60
|
+
* `<input>`.
|
|
61
|
+
*
|
|
62
|
+
* **Accessibility:** always set `label`: it's the field's name. The error
|
|
63
|
+
* shows after the label and before the field, with an icon, and is linked
|
|
64
|
+
* with `aria-describedby` and `aria-invalid`; it's announced (`role="alert"`)
|
|
65
|
+
* only when it appears after first render. Helper text is linked the same
|
|
66
|
+
* way (it's hidden while an error shows). Focus is a solid inset ring.
|
|
67
|
+
* Set `autocomplete` for personal data (WCAG 1.3.5).
|
|
68
|
+
*
|
|
69
|
+
* **Look:** set by tokens — `input.base.borderWidth` (`stroke.control`) in
|
|
70
|
+
* `color.border.emphasis` (border), `shape.control` (corners),
|
|
71
|
+
* `typography.control.*` (type), `input.size.md.minHeight` (height),
|
|
72
|
+
* `elevation.offset.md` and `elevation.color.field` (inset shadow),
|
|
73
|
+
* `color.border.hover` (hover), `focus.ringColor` and
|
|
74
|
+
* `color.surface.highlight` (focus), `color.feedback.error`,
|
|
75
|
+
* `color.feedback.errorSubtle` and `elevation.color.error` (error),
|
|
76
|
+
* `color.surface.disabled`, `color.border.disabled` and
|
|
77
|
+
* `color.text.disabled` (disabled).
|
|
78
|
+
*
|
|
79
|
+
* @element oh-input
|
|
80
|
+
* @fires oh-input - Whenever the text changes: typing, or picking a suggestion. detail: { value, originalEvent }
|
|
81
|
+
* @fires oh-change - When the value is committed (on blur or Enter). detail: { value, originalEvent }
|
|
82
|
+
* @csspart label - The visible label
|
|
83
|
+
* @csspart input - The text field
|
|
84
|
+
* @csspart helper - The helper text, and the error message (which also has the error part)
|
|
85
|
+
* @csspart error - The error message
|
|
86
|
+
*/
|
|
35
87
|
let OhInput = class OhInput extends OhElement {
|
|
36
88
|
constructor() {
|
|
37
89
|
super(...arguments);
|
|
90
|
+
/** The kind of text: text, email, password, search, tel or url */
|
|
38
91
|
this.type = "text";
|
|
92
|
+
/** The text in the field */
|
|
39
93
|
this.value = "";
|
|
94
|
+
/** Example text shown while the field is empty. Not a replacement for the label */
|
|
40
95
|
this.placeholder = "";
|
|
96
|
+
/** The visible label. Always set one: it names the field */
|
|
41
97
|
this.label = "";
|
|
98
|
+
/** Help shown under the field and linked to it */
|
|
42
99
|
this.helperText = "";
|
|
100
|
+
/** Error shown before the field and linked to it. Setting it puts the field in its error state */
|
|
43
101
|
this.errorText = "";
|
|
102
|
+
/** The name the value is submitted under */
|
|
103
|
+
this.name = "";
|
|
104
|
+
/** Must be filled in before the form submits */
|
|
44
105
|
this.required = false;
|
|
106
|
+
/** Not editable, and left out of the form's data */
|
|
107
|
+
this.disabled = false;
|
|
108
|
+
/**
|
|
109
|
+
* Values offered while typing, shown by the browser as a list under the
|
|
110
|
+
* field. They suggest, they don't restrict: any text is still allowed.
|
|
111
|
+
* Set it as a property (an array of strings) or, in HTML, as a JSON array:
|
|
112
|
+
* suggestions='["Option one","Option two"]'. Browsers also offer the
|
|
113
|
+
* field's autofill history, so set autocomplete="off" to show only these.
|
|
114
|
+
*/
|
|
115
|
+
this.suggestions = [];
|
|
45
116
|
/**
|
|
46
117
|
* Force a visual state (for documentation/Figma sync only)
|
|
47
118
|
* Values: 'hover' | 'focus'
|
|
48
119
|
*/
|
|
49
120
|
this.forceState = "default";
|
|
121
|
+
this._internals = this.attachInternals();
|
|
122
|
+
/** The starting value, restored when the form resets */
|
|
123
|
+
this._defaultValue = "";
|
|
124
|
+
/** Set when a disabled <fieldset> around it disables it */
|
|
125
|
+
this._formDisabled = false;
|
|
50
126
|
/**
|
|
51
127
|
* Errors that appear after first render (e.g. on submit) are announced via
|
|
52
128
|
* role="alert". Errors present on page load are only linked with
|
|
@@ -54,14 +130,10 @@ let OhInput = class OhInput extends OhElement {
|
|
|
54
130
|
*/
|
|
55
131
|
this._announceError = false;
|
|
56
132
|
}
|
|
133
|
+
static { this.formAssociated = true; }
|
|
57
134
|
static { this.styles = [
|
|
58
135
|
baseStyles,
|
|
59
136
|
css `
|
|
60
|
-
/* ═══════════════════════════════════════════════════════════════
|
|
61
|
-
ORANGE HALO INPUT
|
|
62
|
-
Chunky • Inset • Rises on Focus
|
|
63
|
-
═══════════════════════════════════════════════════════════════ */
|
|
64
|
-
|
|
65
137
|
:host {
|
|
66
138
|
display: block;
|
|
67
139
|
}
|
|
@@ -72,7 +144,7 @@ let OhInput = class OhInput extends OhElement {
|
|
|
72
144
|
gap: var(--oh-spacing-2);
|
|
73
145
|
}
|
|
74
146
|
|
|
75
|
-
/* ─── Label:
|
|
147
|
+
/* ─── Label: typography.control.* ─── */
|
|
76
148
|
.label {
|
|
77
149
|
font-family: var(--oh-typography-control-font-family);
|
|
78
150
|
font-size: var(--oh-typography-control-font-size-sm);
|
|
@@ -88,7 +160,7 @@ let OhInput = class OhInput extends OhElement {
|
|
|
88
160
|
|
|
89
161
|
/* ═══════════════════════════════════════════════════════════════
|
|
90
162
|
INPUT FIELD
|
|
91
|
-
|
|
163
|
+
Border, inset shadow and fill from tokens
|
|
92
164
|
═══════════════════════════════════════════════════════════════ */
|
|
93
165
|
|
|
94
166
|
.input {
|
|
@@ -96,17 +168,18 @@ let OhInput = class OhInput extends OhElement {
|
|
|
96
168
|
font-family: var(--oh-typography-control-font-family);
|
|
97
169
|
color: var(--oh-color-text-primary);
|
|
98
170
|
|
|
99
|
-
/*
|
|
171
|
+
/* Fill: color.surface.base */
|
|
100
172
|
background-color: var(--oh-color-surface-base);
|
|
101
173
|
|
|
102
|
-
/*
|
|
174
|
+
/* Border: input.base.borderWidth in color.border.emphasis (a UI
|
|
175
|
+
contrast pair checked by check:contrast) */
|
|
103
176
|
border: var(--oh-input-base-border-width) solid
|
|
104
177
|
var(--oh-color-border-emphasis);
|
|
105
178
|
border-radius: var(--oh-shape-control);
|
|
106
179
|
|
|
107
|
-
/* Inset
|
|
180
|
+
/* Inset shadow: elevation.offset.md in elevation.color.field */
|
|
108
181
|
box-shadow: inset var(--oh-elevation-offset-md)
|
|
109
|
-
var(--oh-elevation-offset-md) 0 0 var(--oh-
|
|
182
|
+
var(--oh-elevation-offset-md) 0 0 var(--oh-elevation-color-field);
|
|
110
183
|
|
|
111
184
|
transition:
|
|
112
185
|
border-color var(--oh-motion-snappy) ease,
|
|
@@ -118,8 +191,8 @@ let OhInput = class OhInput extends OhElement {
|
|
|
118
191
|
color: var(--oh-color-text-secondary); /* Readable placeholder */
|
|
119
192
|
}
|
|
120
193
|
|
|
121
|
-
/* ─── Hover: border
|
|
122
|
-
.input:hover:not(:focus) {
|
|
194
|
+
/* ─── Hover: border in color.border.hover ─── */
|
|
195
|
+
.input:hover:not(:focus):not(:disabled) {
|
|
123
196
|
border-color: var(--oh-color-border-hover);
|
|
124
197
|
}
|
|
125
198
|
|
|
@@ -145,14 +218,14 @@ let OhInput = class OhInput extends OhElement {
|
|
|
145
218
|
|
|
146
219
|
/* ═══════════════════════════════════════════════════════════════
|
|
147
220
|
ERROR STATE
|
|
148
|
-
|
|
221
|
+
color.feedback.error border, errorSubtle fill, elevation.color.error
|
|
149
222
|
═══════════════════════════════════════════════════════════════ */
|
|
150
223
|
|
|
151
224
|
.input--error {
|
|
152
225
|
border-color: var(--oh-color-feedback-error);
|
|
153
226
|
background-color: var(--oh-color-feedback-error-subtle);
|
|
154
227
|
box-shadow: inset var(--oh-elevation-offset-md)
|
|
155
|
-
var(--oh-elevation-offset-md) 0 0 var(--oh-
|
|
228
|
+
var(--oh-elevation-offset-md) 0 0 var(--oh-elevation-color-error);
|
|
156
229
|
}
|
|
157
230
|
|
|
158
231
|
.input--error:focus {
|
|
@@ -164,9 +237,23 @@ let OhInput = class OhInput extends OhElement {
|
|
|
164
237
|
HELPER TEXT
|
|
165
238
|
═══════════════════════════════════════════════════════════════ */
|
|
166
239
|
|
|
240
|
+
/* ─── Disabled: color.*.disabled tokens, no shadow ─── */
|
|
241
|
+
.input:disabled {
|
|
242
|
+
cursor: not-allowed;
|
|
243
|
+
color: var(--oh-color-text-disabled);
|
|
244
|
+
background-color: var(--oh-color-surface-disabled);
|
|
245
|
+
border-color: var(--oh-color-border-disabled);
|
|
246
|
+
box-shadow: none;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.label--disabled {
|
|
250
|
+
color: var(--oh-color-text-disabled);
|
|
251
|
+
}
|
|
252
|
+
|
|
167
253
|
.helper {
|
|
168
254
|
font-family: var(--oh-typography-body-font-family);
|
|
169
255
|
font-size: var(--oh-typography-body-base-font-size);
|
|
256
|
+
line-height: var(--oh-typography-body-base-line-height);
|
|
170
257
|
color: var(--oh-color-text-secondary);
|
|
171
258
|
letter-spacing: var(--oh-typography-control-letter-spacing);
|
|
172
259
|
}
|
|
@@ -222,28 +309,57 @@ let OhInput = class OhInput extends OhElement {
|
|
|
222
309
|
}
|
|
223
310
|
`,
|
|
224
311
|
]; }
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.
|
|
228
|
-
|
|
312
|
+
connectedCallback() {
|
|
313
|
+
super.connectedCallback();
|
|
314
|
+
if (!this.hasUpdated)
|
|
315
|
+
this._defaultValue = this.value;
|
|
229
316
|
}
|
|
230
|
-
|
|
231
|
-
|
|
317
|
+
/** The form this field belongs to */
|
|
318
|
+
get form() {
|
|
319
|
+
return this._internals.form;
|
|
232
320
|
}
|
|
233
|
-
focus() {
|
|
234
|
-
this._input?.focus();
|
|
321
|
+
focus(options) {
|
|
322
|
+
this._input?.focus(options);
|
|
235
323
|
}
|
|
236
324
|
blur() {
|
|
237
325
|
this._input?.blur();
|
|
238
326
|
}
|
|
327
|
+
formResetCallback() {
|
|
328
|
+
this.value = this._defaultValue;
|
|
329
|
+
}
|
|
330
|
+
formDisabledCallback(disabled) {
|
|
331
|
+
this._formDisabled = disabled;
|
|
332
|
+
}
|
|
333
|
+
formStateRestoreCallback(state) {
|
|
334
|
+
if (typeof state === "string")
|
|
335
|
+
this.value = state;
|
|
336
|
+
}
|
|
239
337
|
willUpdate(changed) {
|
|
240
338
|
if (this.hasUpdated && changed.has("errorText")) {
|
|
241
339
|
this._announceError = !!this.errorText;
|
|
242
340
|
}
|
|
243
341
|
}
|
|
342
|
+
updated(changed) {
|
|
343
|
+
if (changed.has("value"))
|
|
344
|
+
this._internals.setFormValue(this.value);
|
|
345
|
+
if (changed.has("value") ||
|
|
346
|
+
changed.has("required") ||
|
|
347
|
+
changed.has("type")) {
|
|
348
|
+
this._internals.setValidity(this._input.validity, this._input.validationMessage, this._input);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
_handleInput(event) {
|
|
352
|
+
this.value = event.target.value;
|
|
353
|
+
this.emit("oh-input", { value: this.value, originalEvent: event });
|
|
354
|
+
}
|
|
355
|
+
_handleChange(event) {
|
|
356
|
+
this.emit("oh-change", { value: this.value, originalEvent: event });
|
|
357
|
+
}
|
|
244
358
|
render() {
|
|
245
359
|
const hasError = !!this.errorText;
|
|
246
|
-
const
|
|
360
|
+
const disabled = this.disabled || this._formDisabled;
|
|
361
|
+
const describedBy = hasError ? "error" : this.helperText ? "helper" : "";
|
|
362
|
+
const suggestions = this.suggestions ?? [];
|
|
247
363
|
const inputClasses = this.classMap({
|
|
248
364
|
input: true,
|
|
249
365
|
"input--error": hasError,
|
|
@@ -253,7 +369,11 @@ let OhInput = class OhInput extends OhElement {
|
|
|
253
369
|
${this.label
|
|
254
370
|
? html `
|
|
255
371
|
<label
|
|
256
|
-
class
|
|
372
|
+
class=${this.classMap({
|
|
373
|
+
label: true,
|
|
374
|
+
"label--required": this.required,
|
|
375
|
+
"label--disabled": disabled,
|
|
376
|
+
})}
|
|
257
377
|
part="label"
|
|
258
378
|
for="input"
|
|
259
379
|
>
|
|
@@ -261,28 +381,12 @@ let OhInput = class OhInput extends OhElement {
|
|
|
261
381
|
</label>
|
|
262
382
|
`
|
|
263
383
|
: nothing}
|
|
264
|
-
|
|
265
|
-
<input
|
|
266
|
-
id="input"
|
|
267
|
-
part="input"
|
|
268
|
-
class=${inputClasses}
|
|
269
|
-
type=${this.type}
|
|
270
|
-
.value=${this.value}
|
|
271
|
-
placeholder=${this.placeholder || nothing}
|
|
272
|
-
autocomplete=${this.autocomplete || nothing}
|
|
273
|
-
?required=${this.required}
|
|
274
|
-
aria-invalid=${hasError ? "true" : nothing}
|
|
275
|
-
aria-describedby=${helperContent ? "helper" : nothing}
|
|
276
|
-
@input=${this._handleInput}
|
|
277
|
-
@change=${this._handleChange}
|
|
278
|
-
/>
|
|
279
|
-
|
|
280
384
|
${hasError
|
|
281
385
|
? html `
|
|
282
386
|
<span
|
|
283
|
-
id="
|
|
387
|
+
id="error"
|
|
284
388
|
class="helper helper--error"
|
|
285
|
-
part="helper"
|
|
389
|
+
part="helper error"
|
|
286
390
|
role=${this._announceError ? "alert" : nothing}
|
|
287
391
|
>
|
|
288
392
|
<svg
|
|
@@ -300,11 +404,34 @@ let OhInput = class OhInput extends OhElement {
|
|
|
300
404
|
${this.errorText}
|
|
301
405
|
</span>
|
|
302
406
|
`
|
|
303
|
-
:
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
407
|
+
: nothing}
|
|
408
|
+
|
|
409
|
+
<input
|
|
410
|
+
id="input"
|
|
411
|
+
part="input"
|
|
412
|
+
class=${inputClasses}
|
|
413
|
+
type=${this.type}
|
|
414
|
+
.value=${this.value}
|
|
415
|
+
placeholder=${this.placeholder || nothing}
|
|
416
|
+
autocomplete=${this.autocomplete || nothing}
|
|
417
|
+
list=${suggestions.length ? "suggestions" : nothing}
|
|
418
|
+
?required=${this.required}
|
|
419
|
+
?disabled=${disabled}
|
|
420
|
+
aria-invalid=${hasError ? "true" : nothing}
|
|
421
|
+
aria-describedby=${describedBy || nothing}
|
|
422
|
+
@input=${this._handleInput}
|
|
423
|
+
@change=${this._handleChange}
|
|
424
|
+
/>
|
|
425
|
+
${suggestions.length
|
|
426
|
+
? html `<datalist id="suggestions">
|
|
427
|
+
${suggestions.map((s) => html `<option value=${s}></option>`)}
|
|
428
|
+
</datalist>`
|
|
429
|
+
: nothing}
|
|
430
|
+
${this.helperText && !hasError
|
|
431
|
+
? html `<span id="helper" class="helper" part="helper"
|
|
432
|
+
>${this.helperText}</span
|
|
433
|
+
>`
|
|
434
|
+
: nothing}
|
|
308
435
|
</div>
|
|
309
436
|
`;
|
|
310
437
|
}
|
|
@@ -322,14 +449,23 @@ __decorate([
|
|
|
322
449
|
property({ type: String })
|
|
323
450
|
], OhInput.prototype, "label", void 0);
|
|
324
451
|
__decorate([
|
|
325
|
-
property({ type: String })
|
|
452
|
+
property({ type: String, attribute: "helper-text" })
|
|
326
453
|
], OhInput.prototype, "helperText", void 0);
|
|
327
454
|
__decorate([
|
|
328
|
-
property({ type: String })
|
|
455
|
+
property({ type: String, attribute: "error-text" })
|
|
329
456
|
], OhInput.prototype, "errorText", void 0);
|
|
457
|
+
__decorate([
|
|
458
|
+
property({ type: String, reflect: true })
|
|
459
|
+
], OhInput.prototype, "name", void 0);
|
|
330
460
|
__decorate([
|
|
331
461
|
property({ type: Boolean, reflect: true })
|
|
332
462
|
], OhInput.prototype, "required", void 0);
|
|
463
|
+
__decorate([
|
|
464
|
+
property({ type: Boolean, reflect: true })
|
|
465
|
+
], OhInput.prototype, "disabled", void 0);
|
|
466
|
+
__decorate([
|
|
467
|
+
property({ type: Array })
|
|
468
|
+
], OhInput.prototype, "suggestions", void 0);
|
|
333
469
|
__decorate([
|
|
334
470
|
property({ type: String })
|
|
335
471
|
], OhInput.prototype, "autocomplete", void 0);
|
|
@@ -339,6 +475,9 @@ __decorate([
|
|
|
339
475
|
__decorate([
|
|
340
476
|
query("input")
|
|
341
477
|
], OhInput.prototype, "_input", void 0);
|
|
478
|
+
__decorate([
|
|
479
|
+
state()
|
|
480
|
+
], OhInput.prototype, "_formDisabled", void 0);
|
|
342
481
|
__decorate([
|
|
343
482
|
state()
|
|
344
483
|
], OhInput.prototype, "_announceError", void 0);
|
package/dist/oh-input.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oh-input.js","sourceRoot":"","sources":["../src/oh-input.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oh-input.js","sourceRoot":"","sources":["../src/oh-input.ts"],"names":[],"mappings":"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"}
|
package/dist/oh-link.d.ts
CHANGED
|
@@ -1,32 +1,55 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* oh-link
|
|
3
3
|
*
|
|
4
|
-
* A warm, playful link with retro-inspired styling.
|
|
5
|
-
* Two variants: inline (for body text) and standalone (for CTAs).
|
|
6
|
-
*
|
|
7
4
|
* DESIGN DECISIONS:
|
|
8
5
|
* ─────────────────
|
|
9
|
-
* 1.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
6
|
+
* 1. Two variants: `inline` for links inside body text, `standalone` for
|
|
7
|
+
* links that stand on their own (CTAs, "View all").
|
|
8
|
+
* 2. The underline is a pseudo-element so it can transition. Its shape comes
|
|
9
|
+
* from the `decoration.underline*` tokens; it retracts on hover.
|
|
10
|
+
* 3. Keyboard focus swaps in a solid underline (`color.brand.primary`,
|
|
11
|
+
* `decoration.underlineFocusThickness`) as the indicator; the
|
|
12
|
+
* `focus.glowColor` tint behind it is decoration only.
|
|
13
|
+
* 4. Links are never colour-only: the underline is visible at rest.
|
|
14
|
+
* 5. `target="_blank"` adds an icon, a visually hidden "(opens in new tab)"
|
|
15
|
+
* and `rel="noopener noreferrer"` (unless `rel` is set).
|
|
16
|
+
*/
|
|
17
|
+
import { OhElement } from "./base.js";
|
|
18
|
+
export type LinkVariant = "inline" | "standalone";
|
|
19
|
+
/**
|
|
20
|
+
* A text link, for use inside body copy or on its own as a call to action.
|
|
14
21
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - Offset shadow on hover (mini sticker effect)
|
|
18
|
-
* - Lift animation like other components
|
|
19
|
-
* - Arrow icon option
|
|
22
|
+
* **Use it for** navigating to another page or place. **Don't use it for**
|
|
23
|
+
* actions that don't navigate (use `oh-button` instead).
|
|
20
24
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
+
* **Variants:** `inline` (default) sits in running text; `standalone` is
|
|
26
|
+
* larger and bolder for links on their own, and can show a trailing arrow
|
|
27
|
+
* (`arrow`). `inverse` is for links on accent surfaces.
|
|
28
|
+
*
|
|
29
|
+
* **Behaviour:** renders a native `<a>`, so Enter follows it and it takes
|
|
30
|
+
* focus in tab order. On hover the underline retracts and the arrow nudges
|
|
31
|
+
* forward. Keyboard focus (`:focus-visible`) shows a solid underline and a
|
|
32
|
+
* tint; mouse focus doesn't. Transitions are cut short under
|
|
33
|
+
* `prefers-reduced-motion`. With `target="_blank"` it adds an external icon,
|
|
34
|
+
* screen-reader text "(opens in new tab)" and `rel="noopener noreferrer"`
|
|
35
|
+
* when `rel` isn't set; the arrow is not shown on external links.
|
|
36
|
+
*
|
|
37
|
+
* **Accessibility:** the underline shows at rest and on focus, so links
|
|
38
|
+
* don't rely on colour. Write link text that makes sense out of context.
|
|
39
|
+
*
|
|
40
|
+
* **Look:** set by tokens — `color.text.link` the colour (`color.text.onAccent`
|
|
41
|
+
* when `inverse`); `decoration.underlineThickness`, `decoration.underlineDash`
|
|
42
|
+
* and `decoration.underlinePeriod` the underline; `color.brand.primary`
|
|
43
|
+
* (`color.text.onAccent` when `inverse`) and
|
|
44
|
+
* `decoration.underlineFocusThickness` the focus underline; `focus.glowColor`
|
|
45
|
+
* (`link.inverse.focusBackground` when `inverse`) the focus tint;
|
|
46
|
+
* `typography.body.fontFamily`, plus `typography.body.lg.fontSize` and
|
|
47
|
+
* `typography.emphasis.fontWeight` for `standalone`; `motion.slow` and
|
|
48
|
+
* `motion.snappy` the transitions.
|
|
25
49
|
*
|
|
26
50
|
* @element oh-link
|
|
51
|
+
* @slot - The link text.
|
|
27
52
|
*/
|
|
28
|
-
import { OhElement } from "./base.js";
|
|
29
|
-
export type LinkVariant = "inline" | "standalone";
|
|
30
53
|
export declare class OhLink extends OhElement {
|
|
31
54
|
static styles: import("lit").CSSResult[];
|
|
32
55
|
href: string;
|
package/dist/oh-link.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oh-link.d.ts","sourceRoot":"","sources":["../src/oh-link.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oh-link.d.ts","sourceRoot":"","sources":["../src/oh-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,YAAY,CAAC;AAElD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,qBACa,MAAO,SAAQ,SAAS;IACnC,OAAgB,MAAM,4BAkSpB;IAGF,IAAI,SAAM;IAGV,MAAM,SAAM;IAGZ,GAAG,SAAM;IAGT,OAAO,EAAE,WAAW,CAAY;IAGhC,KAAK,UAAS;IAGd,OAAO,UAAS;IAEhB,MAAM;CAyDP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,SAAS,EAAE,MAAM,CAAC;KACnB;CACF"}
|
package/dist/oh-link.js
CHANGED
|
@@ -1,29 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* oh-link
|
|
3
3
|
*
|
|
4
|
-
* A warm, playful link with retro-inspired styling.
|
|
5
|
-
* Two variants: inline (for body text) and standalone (for CTAs).
|
|
6
|
-
*
|
|
7
4
|
* DESIGN DECISIONS:
|
|
8
5
|
* ─────────────────
|
|
9
|
-
* 1.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - Arrow icon option
|
|
20
|
-
*
|
|
21
|
-
* 3. ACCESSIBILITY
|
|
22
|
-
* - Underline always visible (not color-only)
|
|
23
|
-
* - Clear focus state
|
|
24
|
-
* - Proper contrast ratios
|
|
25
|
-
*
|
|
26
|
-
* @element oh-link
|
|
6
|
+
* 1. Two variants: `inline` for links inside body text, `standalone` for
|
|
7
|
+
* links that stand on their own (CTAs, "View all").
|
|
8
|
+
* 2. The underline is a pseudo-element so it can transition. Its shape comes
|
|
9
|
+
* from the `decoration.underline*` tokens; it retracts on hover.
|
|
10
|
+
* 3. Keyboard focus swaps in a solid underline (`color.brand.primary`,
|
|
11
|
+
* `decoration.underlineFocusThickness`) as the indicator; the
|
|
12
|
+
* `focus.glowColor` tint behind it is decoration only.
|
|
13
|
+
* 4. Links are never colour-only: the underline is visible at rest.
|
|
14
|
+
* 5. `target="_blank"` adds an icon, a visually hidden "(opens in new tab)"
|
|
15
|
+
* and `rel="noopener noreferrer"` (unless `rel` is set).
|
|
27
16
|
*/
|
|
28
17
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
29
18
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -34,6 +23,40 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
34
23
|
import { html, css, nothing } from "lit";
|
|
35
24
|
import { customElement, property } from "lit/decorators.js";
|
|
36
25
|
import { OhElement, baseStyles } from "./base.js";
|
|
26
|
+
/**
|
|
27
|
+
* A text link, for use inside body copy or on its own as a call to action.
|
|
28
|
+
*
|
|
29
|
+
* **Use it for** navigating to another page or place. **Don't use it for**
|
|
30
|
+
* actions that don't navigate (use `oh-button` instead).
|
|
31
|
+
*
|
|
32
|
+
* **Variants:** `inline` (default) sits in running text; `standalone` is
|
|
33
|
+
* larger and bolder for links on their own, and can show a trailing arrow
|
|
34
|
+
* (`arrow`). `inverse` is for links on accent surfaces.
|
|
35
|
+
*
|
|
36
|
+
* **Behaviour:** renders a native `<a>`, so Enter follows it and it takes
|
|
37
|
+
* focus in tab order. On hover the underline retracts and the arrow nudges
|
|
38
|
+
* forward. Keyboard focus (`:focus-visible`) shows a solid underline and a
|
|
39
|
+
* tint; mouse focus doesn't. Transitions are cut short under
|
|
40
|
+
* `prefers-reduced-motion`. With `target="_blank"` it adds an external icon,
|
|
41
|
+
* screen-reader text "(opens in new tab)" and `rel="noopener noreferrer"`
|
|
42
|
+
* when `rel` isn't set; the arrow is not shown on external links.
|
|
43
|
+
*
|
|
44
|
+
* **Accessibility:** the underline shows at rest and on focus, so links
|
|
45
|
+
* don't rely on colour. Write link text that makes sense out of context.
|
|
46
|
+
*
|
|
47
|
+
* **Look:** set by tokens — `color.text.link` the colour (`color.text.onAccent`
|
|
48
|
+
* when `inverse`); `decoration.underlineThickness`, `decoration.underlineDash`
|
|
49
|
+
* and `decoration.underlinePeriod` the underline; `color.brand.primary`
|
|
50
|
+
* (`color.text.onAccent` when `inverse`) and
|
|
51
|
+
* `decoration.underlineFocusThickness` the focus underline; `focus.glowColor`
|
|
52
|
+
* (`link.inverse.focusBackground` when `inverse`) the focus tint;
|
|
53
|
+
* `typography.body.fontFamily`, plus `typography.body.lg.fontSize` and
|
|
54
|
+
* `typography.emphasis.fontWeight` for `standalone`; `motion.slow` and
|
|
55
|
+
* `motion.snappy` the transitions.
|
|
56
|
+
*
|
|
57
|
+
* @element oh-link
|
|
58
|
+
* @slot - The link text.
|
|
59
|
+
*/
|
|
37
60
|
let OhLink = class OhLink extends OhElement {
|
|
38
61
|
constructor() {
|
|
39
62
|
super(...arguments);
|
|
@@ -47,11 +70,6 @@ let OhLink = class OhLink extends OhElement {
|
|
|
47
70
|
static { this.styles = [
|
|
48
71
|
baseStyles,
|
|
49
72
|
css `
|
|
50
|
-
/* ═══════════════════════════════════════════════════════════════
|
|
51
|
-
ORANGE HALO LINK
|
|
52
|
-
Warm • Playful • Retro-inspired
|
|
53
|
-
═══════════════════════════════════════════════════════════════ */
|
|
54
|
-
|
|
55
73
|
:host {
|
|
56
74
|
display: inline;
|
|
57
75
|
}
|
|
@@ -74,7 +92,7 @@ let OhLink = class OhLink extends OhElement {
|
|
|
74
92
|
text-decoration: none;
|
|
75
93
|
}
|
|
76
94
|
|
|
77
|
-
/*
|
|
95
|
+
/* Underline via pseudo-element (animatable), shaped by decoration tokens */
|
|
78
96
|
.link__text::after {
|
|
79
97
|
content: "";
|
|
80
98
|
position: absolute;
|
|
@@ -96,7 +114,7 @@ let OhLink = class OhLink extends OhElement {
|
|
|
96
114
|
|
|
97
115
|
/* ═══════════════════════════════════════════════════════════════
|
|
98
116
|
INLINE VARIANT
|
|
99
|
-
|
|
117
|
+
Underline shrinks right-to-left on hover
|
|
100
118
|
═══════════════════════════════════════════════════════════════ */
|
|
101
119
|
|
|
102
120
|
.link--inline {
|
|
@@ -148,7 +166,7 @@ let OhLink = class OhLink extends OhElement {
|
|
|
148
166
|
|
|
149
167
|
/* ═══════════════════════════════════════════════════════════════
|
|
150
168
|
STANDALONE VARIANT
|
|
151
|
-
CTA-style
|
|
169
|
+
CTA-style; underline shrinks on hover
|
|
152
170
|
═══════════════════════════════════════════════════════════════ */
|
|
153
171
|
|
|
154
172
|
.link--standalone {
|