@orange-halo/components 2.2.0 → 3.1.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 +565 -328
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js +7 -0
- package/dist/base.js.map +1 -1
- package/dist/index.d.ts +2 -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 +83 -21
- 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 +43 -21
- package/dist/oh-breadcrumb.js.map +1 -1
- package/dist/oh-button.d.ts +50 -24
- package/dist/oh-button.d.ts.map +1 -1
- package/dist/oh-button.js +66 -47
- 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.js +87 -45
- package/dist/oh-checkbox-group.js.map +1 -1
- package/dist/oh-checkbox.d.ts +55 -18
- package/dist/oh-checkbox.d.ts.map +1 -1
- package/dist/oh-checkbox.js +91 -59
- 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 +26 -33
- package/dist/oh-container.js.map +1 -1
- package/dist/oh-drawer.d.ts +36 -14
- package/dist/oh-drawer.d.ts.map +1 -1
- package/dist/oh-drawer.js +57 -26
- 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 +28 -5
- package/dist/oh-icon.js.map +1 -1
- package/dist/oh-input.d.ts +105 -21
- package/dist/oh-input.d.ts.map +1 -1
- package/dist/oh-input.js +207 -68
- 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 +56 -34
- 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 +44 -21
- 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 +32 -13
- 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.js +84 -44
- package/dist/oh-radio-group.js.map +1 -1
- package/dist/oh-radio.d.ts +56 -18
- package/dist/oh-radio.d.ts.map +1 -1
- package/dist/oh-radio.js +93 -60
- 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 +72 -36
- 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 +39 -26
- 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 +56 -30
- package/dist/oh-tabs.d.ts.map +1 -1
- package/dist/oh-tabs.js +89 -70
- 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 +68 -33
- package/dist/oh-toggle.js.map +1 -1
- package/dist/styles/typography.d.ts.map +1 -1
- package/dist/styles/typography.js +1 -2
- package/dist/styles/typography.js.map +1 -1
- package/package.json +3 -7
- package/dist/oh-button.figma.d.ts +0 -2
- package/dist/oh-button.figma.d.ts.map +0 -1
- package/dist/oh-button.figma.js +0 -18
- package/dist/oh-button.figma.js.map +0 -1
- package/dist/oh-checkbox-group.figma.d.ts +0 -2
- package/dist/oh-checkbox-group.figma.d.ts.map +0 -1
- package/dist/oh-checkbox-group.figma.js +0 -24
- package/dist/oh-checkbox-group.figma.js.map +0 -1
- 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.figma.d.ts +0 -2
- package/dist/oh-input.figma.d.ts.map +0 -1
- package/dist/oh-input.figma.js +0 -36
- package/dist/oh-input.figma.js.map +0 -1
- package/dist/oh-radio-group.figma.d.ts +0 -2
- package/dist/oh-radio-group.figma.d.ts.map +0 -1
- package/dist/oh-radio-group.figma.js +0 -22
- package/dist/oh-radio-group.figma.js.map +0 -1
package/dist/oh-card.js
CHANGED
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* oh-card
|
|
3
3
|
*
|
|
4
|
-
* A
|
|
5
|
-
* Designed with the same layered construction as oh-button.
|
|
4
|
+
* A surface that groups related content, with optional header and footer.
|
|
6
5
|
*
|
|
7
6
|
* DESIGN DECISIONS:
|
|
8
7
|
* ─────────────────
|
|
9
|
-
* 1.
|
|
10
|
-
*
|
|
11
|
-
* - Border: visible warm edge
|
|
12
|
-
* - Inner highlight: sunlit top edge
|
|
13
|
-
* - Outer shadow: soft, slightly offset
|
|
8
|
+
* 1. THREE PARTS: header, content and footer are separate parts so each can
|
|
9
|
+
* be styled.
|
|
14
10
|
*
|
|
15
|
-
* 2.
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
*
|
|
11
|
+
* 2. VARIANTS BY ROLE, LOOK FROM TOKENS
|
|
12
|
+
* - default, featured (the one card that should stand out), subtle (quieter)
|
|
13
|
+
* - Each variant's surface, border and shadow come from its own
|
|
14
|
+
* card.variant.<variant>.* tokens and an elevation.surface.* token, so a brand
|
|
15
|
+
* changes the look without touching this file.
|
|
19
16
|
*
|
|
20
|
-
* 3.
|
|
21
|
-
* -
|
|
22
|
-
*
|
|
23
|
-
* - Flat: border-only, minimal shadow
|
|
17
|
+
* 3. INTERACTIVE MODE: role="button" on the inner card, Enter/Space and
|
|
18
|
+
* click fire oh-click. Focus is a solid focus.ring* outline; any
|
|
19
|
+
* focus.glowColor shadow is decoration only.
|
|
24
20
|
*
|
|
25
|
-
*
|
|
21
|
+
* 4. CONTRAST: card surfaces remap color.text.link to color.text.linkRaised
|
|
22
|
+
* so links inside keep 4.5:1.
|
|
26
23
|
*/
|
|
27
24
|
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
28
25
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -31,36 +28,61 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
31
28
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
32
29
|
};
|
|
33
30
|
import { html, css, nothing } from "lit";
|
|
34
|
-
import { customElement, property } from "lit/decorators.js";
|
|
31
|
+
import { customElement, property, state } from "lit/decorators.js";
|
|
35
32
|
import { OhElement, baseStyles } from "./base.js";
|
|
33
|
+
/**
|
|
34
|
+
* A surface that groups related content (a summary, a teaser, a settings group), with optional header and footer.
|
|
35
|
+
*
|
|
36
|
+
* **Use it for** a self-contained block of content among others, or a whole-card link to more detail (`interactive`). **Don't use it for** page layout or spacing alone (use `oh-stack`, `oh-grid`); for a message that needs attention (use `oh-alert`); or for a single action (use `oh-button`).
|
|
37
|
+
*
|
|
38
|
+
* **Variants:** `default`, the standard card; `featured`, for the one card that should stand out; `subtle`, a quieter card, for dense layouts. **Padding:** `none`, `sm`, `md` (default), `lg` set the content padding (and the header and footer padding to match). With `none`, the content sets its own padding.
|
|
39
|
+
*
|
|
40
|
+
* **States (interactive only):** rest, hover, active (pressed) and focus-visible.
|
|
41
|
+
*
|
|
42
|
+
* **Behaviour:** with `interactive`, the card is focusable (`tabindex="0"`), has `role="button"`, and fires `oh-click` on click, Enter or Space. Hover movement is turned off under `prefers-reduced-motion`.
|
|
43
|
+
*
|
|
44
|
+
* **Accessibility:** focus shows a solid outline (`focus.ringWidth`, `focus.ringColor`, `focus.ringOffset`). Links inside use `color.text.linkRaised`, which keeps contrast on card surfaces. An interactive card is one button: give it a short heading so its accessible name makes sense, and don't put other buttons or links inside it.
|
|
45
|
+
*
|
|
46
|
+
* **Look:** set by tokens. `card.variant.<variant>.gradientStart`/`gradientMid`/`gradientEnd` set each variant's surface, `card.variant.<variant>.borderColor` and `card.base.borderWidth` its border, `shape.large` the corners, and `elevation.surface.default`/`subtle`/`featured` its shadow. Hover uses `color.border.strong` (or `card.variant.featured.borderColorHover`), `elevation.surface.hover`/`featuredHover` and `lift.hoverMd`/`lift.hoverSm`; active uses `elevation.surface.active`; focus sets the border to `color.brand.primary` and adds `focus.glowColor` with `elevation.surface.focus`/`featuredFocus`. Header and footer dividers use `card.section.dividerColor` and `stroke.divider`; the header surface uses `card.section.headerGradientStart`/`End`, the footer `color.surface.raised` to `color.surface.inset`; motion uses `motion.gentle` and `motion.easeGentle`.
|
|
47
|
+
*
|
|
48
|
+
* @element oh-card
|
|
49
|
+
* @slot - The card's main content.
|
|
50
|
+
* @slot header - Optional header, above the content, with a divider below. Not drawn when nothing is slotted.
|
|
51
|
+
* @slot footer - Optional footer, below the content, with a divider above (e.g. actions). Not drawn when nothing is slotted.
|
|
52
|
+
* @csspart card - The card surface (the button when `interactive`).
|
|
53
|
+
* @csspart header - The header wrapper.
|
|
54
|
+
* @csspart content - The content wrapper.
|
|
55
|
+
* @csspart footer - The footer wrapper.
|
|
56
|
+
* @fires oh-click - When an `interactive` card is clicked or activated with Enter or Space. `detail.originalEvent` holds the source event.
|
|
57
|
+
*/
|
|
36
58
|
let OhCard = class OhCard extends OhElement {
|
|
37
59
|
constructor() {
|
|
38
60
|
super(...arguments);
|
|
39
|
-
this.variant = "
|
|
61
|
+
this.variant = "default";
|
|
40
62
|
this.interactive = false;
|
|
41
63
|
this.padding = "md";
|
|
64
|
+
this._hasHeader = false;
|
|
65
|
+
this._hasFooter = false;
|
|
42
66
|
}
|
|
43
67
|
static { this.styles = [
|
|
44
68
|
baseStyles,
|
|
45
69
|
css `
|
|
46
70
|
/* ═══════════════════════════════════════════════════════════════
|
|
47
|
-
|
|
48
|
-
|
|
71
|
+
CARD
|
|
72
|
+
The look comes from card.*, elevation.*, shape.* and lift.* tokens
|
|
49
73
|
═══════════════════════════════════════════════════════════════ */
|
|
50
74
|
|
|
51
75
|
:host {
|
|
52
76
|
display: block;
|
|
53
|
-
/*
|
|
77
|
+
/* On card surfaces text.link can fall below 4.5:1; linkRaised keeps it */
|
|
54
78
|
--oh-color-text-link: var(--oh-color-text-link-raised);
|
|
55
79
|
}
|
|
56
80
|
|
|
57
81
|
/* ═══════════════════════════════════════════════════════════════
|
|
58
82
|
BASE CARD
|
|
59
|
-
Layered construction — feels like a physical object
|
|
60
83
|
═══════════════════════════════════════════════════════════════ */
|
|
61
84
|
|
|
62
85
|
.card {
|
|
63
|
-
/* Shape: friendly rounded corners */
|
|
64
86
|
border-radius: var(--oh-shape-large);
|
|
65
87
|
overflow: hidden;
|
|
66
88
|
|
|
@@ -71,98 +93,86 @@ let OhCard = class OhCard extends OhElement {
|
|
|
71
93
|
}
|
|
72
94
|
|
|
73
95
|
/* ═══════════════════════════════════════════════════════════════
|
|
74
|
-
|
|
75
|
-
Subtle gradient surface with layered shadows
|
|
96
|
+
DEFAULT VARIANT
|
|
76
97
|
═══════════════════════════════════════════════════════════════ */
|
|
77
98
|
|
|
78
|
-
.card--
|
|
79
|
-
/* Surface:
|
|
99
|
+
.card--default {
|
|
100
|
+
/* Surface: card.default gradient tokens */
|
|
80
101
|
background: linear-gradient(
|
|
81
102
|
180deg,
|
|
82
|
-
var(--oh-card-
|
|
83
|
-
var(--oh-card-
|
|
84
|
-
var(--oh-card-
|
|
103
|
+
var(--oh-card-variant-default-gradient-start) 0%,
|
|
104
|
+
var(--oh-card-variant-default-gradient-mid) 40%,
|
|
105
|
+
var(--oh-card-variant-default-gradient-end) 100%
|
|
85
106
|
);
|
|
86
107
|
|
|
87
|
-
/* Border: visible warm edge */
|
|
88
108
|
border: var(--oh-card-base-border-width) solid
|
|
89
|
-
var(--oh-card-
|
|
109
|
+
var(--oh-card-variant-default-border-color);
|
|
90
110
|
|
|
91
|
-
|
|
92
|
-
1. Outer: soft, offset shadow (tactile)
|
|
93
|
-
2. Deeper: ambient depth
|
|
94
|
-
3. Inner top: sunlit highlight */
|
|
95
|
-
box-shadow: var(--oh-elevation-surface-raised);
|
|
111
|
+
box-shadow: var(--oh-elevation-surface-default);
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
/* ═══════════════════════════════════════════════════════════════
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
FEATURED VARIANT
|
|
116
|
+
The one card that should stand out
|
|
101
117
|
═══════════════════════════════════════════════════════════════ */
|
|
102
118
|
|
|
103
|
-
.card--
|
|
104
|
-
/* Surface: warm sunlit gradient */
|
|
119
|
+
.card--featured {
|
|
105
120
|
background: linear-gradient(
|
|
106
121
|
180deg,
|
|
107
|
-
var(--oh-card-
|
|
108
|
-
var(--oh-card-
|
|
109
|
-
var(--oh-card-
|
|
122
|
+
var(--oh-card-variant-featured-gradient-start) 0%,
|
|
123
|
+
var(--oh-card-variant-featured-gradient-mid) 30%,
|
|
124
|
+
var(--oh-card-variant-featured-gradient-end) 100%
|
|
110
125
|
);
|
|
111
126
|
|
|
112
|
-
/* Border: warm tinted edge */
|
|
113
127
|
border: var(--oh-card-base-border-width) solid
|
|
114
|
-
var(--oh-card-
|
|
128
|
+
var(--oh-card-variant-featured-border-color);
|
|
115
129
|
|
|
116
|
-
/* Layered shadows with warm glow */
|
|
117
130
|
box-shadow: var(--oh-elevation-surface-featured);
|
|
118
131
|
}
|
|
119
132
|
|
|
120
133
|
/* ═══════════════════════════════════════════════════════════════
|
|
121
|
-
|
|
122
|
-
|
|
134
|
+
SUBTLE VARIANT
|
|
135
|
+
Quieter card: elevation.surface.subtle
|
|
123
136
|
═══════════════════════════════════════════════════════════════ */
|
|
124
137
|
|
|
125
|
-
.card--
|
|
126
|
-
/* Surface: subtle gradient */
|
|
138
|
+
.card--subtle {
|
|
127
139
|
background: linear-gradient(
|
|
128
140
|
180deg,
|
|
129
|
-
var(--oh-card-
|
|
130
|
-
var(--oh-card-
|
|
141
|
+
var(--oh-card-variant-subtle-gradient-start) 0%,
|
|
142
|
+
var(--oh-card-variant-subtle-gradient-end) 100%
|
|
131
143
|
);
|
|
132
144
|
|
|
133
|
-
/* Border: visible edge */
|
|
134
145
|
border: var(--oh-card-base-border-width) solid
|
|
135
|
-
var(--oh-card-
|
|
146
|
+
var(--oh-card-variant-subtle-border-color);
|
|
136
147
|
|
|
137
|
-
|
|
138
|
-
box-shadow: var(--oh-elevation-surface-flat);
|
|
148
|
+
box-shadow: var(--oh-elevation-surface-subtle);
|
|
139
149
|
}
|
|
140
150
|
|
|
141
151
|
/* ═══════════════════════════════════════════════════════════════
|
|
142
152
|
INTERACTIVE STATES
|
|
143
|
-
|
|
153
|
+
Focus is a solid outline; focus.glowColor is decoration only
|
|
144
154
|
═══════════════════════════════════════════════════════════════ */
|
|
145
155
|
|
|
146
156
|
.card--interactive {
|
|
147
157
|
cursor: pointer;
|
|
148
158
|
}
|
|
149
159
|
|
|
150
|
-
/* Hover:
|
|
151
|
-
.card--interactive.card--
|
|
160
|
+
/* Hover: lift.hover* and elevation.surface.hover */
|
|
161
|
+
.card--interactive.card--default:hover {
|
|
152
162
|
border-color: var(--oh-color-border-strong);
|
|
153
|
-
box-shadow: var(--oh-elevation-surface-
|
|
163
|
+
box-shadow: var(--oh-elevation-surface-hover);
|
|
154
164
|
transform: translateY(var(--oh-lift-hover-md));
|
|
155
165
|
}
|
|
156
166
|
|
|
157
|
-
.card--interactive.card--
|
|
158
|
-
border-color: var(--oh-card-
|
|
159
|
-
box-shadow: var(--oh-elevation-surface-featured-
|
|
167
|
+
.card--interactive.card--featured:hover {
|
|
168
|
+
border-color: var(--oh-card-variant-featured-border-color-hover);
|
|
169
|
+
box-shadow: var(--oh-elevation-surface-featured-hover);
|
|
160
170
|
transform: translateY(var(--oh-lift-hover-md));
|
|
161
171
|
}
|
|
162
172
|
|
|
163
|
-
.card--interactive.card--
|
|
173
|
+
.card--interactive.card--subtle:hover {
|
|
164
174
|
border-color: var(--oh-color-border-strong);
|
|
165
|
-
box-shadow: var(--oh-elevation-surface-
|
|
175
|
+
box-shadow: var(--oh-elevation-surface-default);
|
|
166
176
|
transform: translateY(var(--oh-lift-hover-sm));
|
|
167
177
|
}
|
|
168
178
|
|
|
@@ -171,8 +181,8 @@ let OhCard = class OhCard extends OhElement {
|
|
|
171
181
|
transform: translateY(0) !important;
|
|
172
182
|
}
|
|
173
183
|
|
|
174
|
-
.card--interactive.card--
|
|
175
|
-
box-shadow: var(--oh-elevation-surface-
|
|
184
|
+
.card--interactive.card--default:active {
|
|
185
|
+
box-shadow: var(--oh-elevation-surface-active);
|
|
176
186
|
}
|
|
177
187
|
|
|
178
188
|
/* Focus: solid outline is the indicator; the glow is decoration only */
|
|
@@ -182,17 +192,17 @@ let OhCard = class OhCard extends OhElement {
|
|
|
182
192
|
border-color: var(--oh-color-brand-primary);
|
|
183
193
|
}
|
|
184
194
|
|
|
185
|
-
.card--interactive.card--
|
|
186
|
-
.card--interactive.card--
|
|
195
|
+
.card--interactive.card--default:focus-visible,
|
|
196
|
+
.card--interactive.card--subtle:focus-visible {
|
|
187
197
|
box-shadow:
|
|
188
198
|
0 0 16px var(--oh-focus-glow-color),
|
|
189
|
-
var(--oh-elevation-surface-
|
|
199
|
+
var(--oh-elevation-surface-focus);
|
|
190
200
|
}
|
|
191
201
|
|
|
192
|
-
.card--interactive.card--
|
|
202
|
+
.card--interactive.card--featured:focus-visible {
|
|
193
203
|
box-shadow:
|
|
194
204
|
0 0 20px var(--oh-focus-glow-color),
|
|
195
|
-
var(--oh-elevation-surface-featured-
|
|
205
|
+
var(--oh-elevation-surface-featured-focus);
|
|
196
206
|
}
|
|
197
207
|
|
|
198
208
|
/* ═══════════════════════════════════════════════════════════════
|
|
@@ -224,10 +234,6 @@ let OhCard = class OhCard extends OhElement {
|
|
|
224
234
|
);
|
|
225
235
|
}
|
|
226
236
|
|
|
227
|
-
.header:empty {
|
|
228
|
-
display: none;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
237
|
.content {
|
|
232
238
|
/* Padding handled by variant */
|
|
233
239
|
}
|
|
@@ -243,7 +249,10 @@ let OhCard = class OhCard extends OhElement {
|
|
|
243
249
|
);
|
|
244
250
|
}
|
|
245
251
|
|
|
246
|
-
|
|
252
|
+
/* A header or footer with nothing slotted isn't drawn (:empty can't
|
|
253
|
+
see slotted content, so the element tracks it) */
|
|
254
|
+
.header[hidden],
|
|
255
|
+
.footer[hidden] {
|
|
247
256
|
display: none;
|
|
248
257
|
}
|
|
249
258
|
|
|
@@ -273,6 +282,19 @@ let OhCard = class OhCard extends OhElement {
|
|
|
273
282
|
}
|
|
274
283
|
`,
|
|
275
284
|
]; }
|
|
285
|
+
/** True when the slot holds an element or non-whitespace text */
|
|
286
|
+
_slotHasContent(slot) {
|
|
287
|
+
return slot
|
|
288
|
+
.assignedNodes({ flatten: true })
|
|
289
|
+
.some((node) => node.nodeType === Node.ELEMENT_NODE ||
|
|
290
|
+
(node.nodeType === Node.TEXT_NODE && node.textContent?.trim()));
|
|
291
|
+
}
|
|
292
|
+
_onHeaderSlotChange(event) {
|
|
293
|
+
this._hasHeader = this._slotHasContent(event.target);
|
|
294
|
+
}
|
|
295
|
+
_onFooterSlotChange(event) {
|
|
296
|
+
this._hasFooter = this._slotHasContent(event.target);
|
|
297
|
+
}
|
|
276
298
|
_handleClick(event) {
|
|
277
299
|
if (this.interactive) {
|
|
278
300
|
this.emit("oh-click", { originalEvent: event });
|
|
@@ -300,16 +322,16 @@ let OhCard = class OhCard extends OhElement {
|
|
|
300
322
|
@click=${this._handleClick}
|
|
301
323
|
@keydown=${this._handleKeyDown}
|
|
302
324
|
>
|
|
303
|
-
<div class="header" part="header">
|
|
304
|
-
<slot name="header"></slot>
|
|
325
|
+
<div class="header" part="header" ?hidden=${!this._hasHeader}>
|
|
326
|
+
<slot name="header" @slotchange=${this._onHeaderSlotChange}></slot>
|
|
305
327
|
</div>
|
|
306
328
|
|
|
307
329
|
<div class="content" part="content">
|
|
308
330
|
<slot></slot>
|
|
309
331
|
</div>
|
|
310
332
|
|
|
311
|
-
<div class="footer" part="footer">
|
|
312
|
-
<slot name="footer"></slot>
|
|
333
|
+
<div class="footer" part="footer" ?hidden=${!this._hasFooter}>
|
|
334
|
+
<slot name="footer" @slotchange=${this._onFooterSlotChange}></slot>
|
|
313
335
|
</div>
|
|
314
336
|
</div>
|
|
315
337
|
`;
|
|
@@ -324,6 +346,12 @@ __decorate([
|
|
|
324
346
|
__decorate([
|
|
325
347
|
property({ type: String, reflect: true })
|
|
326
348
|
], OhCard.prototype, "padding", void 0);
|
|
349
|
+
__decorate([
|
|
350
|
+
state()
|
|
351
|
+
], OhCard.prototype, "_hasHeader", void 0);
|
|
352
|
+
__decorate([
|
|
353
|
+
state()
|
|
354
|
+
], OhCard.prototype, "_hasFooter", void 0);
|
|
327
355
|
OhCard = __decorate([
|
|
328
356
|
customElement("oh-card")
|
|
329
357
|
], OhCard);
|
package/dist/oh-card.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oh-card.js","sourceRoot":"","sources":["../src/oh-card.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"oh-card.js","sourceRoot":"","sources":["../src/oh-card.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* oh-checkbox-group
|
|
3
3
|
*
|
|
4
|
-
* A checkbox group with
|
|
4
|
+
* A checkbox group with fieldset semantics and group-level error handling.
|
|
5
5
|
* For single checkboxes, use oh-checkbox directly.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Uses <fieldset> and <legend
|
|
10
|
-
* -
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
*
|
|
14
|
-
*
|
|
7
|
+
* DESIGN DECISIONS:
|
|
8
|
+
* ─────────────────
|
|
9
|
+
* - Uses <fieldset> and <legend>, so the legend names the group
|
|
10
|
+
* - One error for the group, after the legend and before the options,
|
|
11
|
+
* linked with aria-describedby; aria-invalid on the fieldset
|
|
12
|
+
* - Each option is a visually hidden native checkbox; focus underlines its
|
|
13
|
+
* label (a solid indicator)
|
|
14
|
+
* - The drawn boxes use the same tokens as oh-checkbox
|
|
15
15
|
*/
|
|
16
16
|
import { type PropertyValues } from "lit";
|
|
17
17
|
import { OhElement } from "./base.js";
|
|
@@ -20,15 +20,58 @@ export interface CheckboxOption {
|
|
|
20
20
|
value: string;
|
|
21
21
|
checked?: boolean;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* A set of related checkboxes under one legend, where any number can be
|
|
25
|
+
* chosen.
|
|
26
|
+
*
|
|
27
|
+
* **Use it for** choosing any number of options from a short list, such as
|
|
28
|
+
* interests or notification types. **Don't use it for** one standalone
|
|
29
|
+
* yes/no option (use `oh-checkbox`), exactly one choice (use
|
|
30
|
+
* `oh-radio-group`, or `oh-select` for a long list), or settings that apply
|
|
31
|
+
* straight away (use `oh-toggle`).
|
|
32
|
+
*
|
|
33
|
+
* **Parts:** a `label` (rendered as the fieldset's `<legend>`) and a list of `options` (`{ label, value }`).
|
|
34
|
+
* `value` is the array of checked option values. **States:** each option
|
|
35
|
+
* unchecked, checked, hover, active and focus; the group can be `required`
|
|
36
|
+
* (a marker on the label) and in error (set `error-text`).
|
|
37
|
+
*
|
|
38
|
+
* **Behaviour:** Tab moves through the options and Space toggles one. Each
|
|
39
|
+
* change updates `value` and fires `oh-change` with the new array. The
|
|
40
|
+
* native checkboxes sit in the shadow root, so they don't submit with a
|
|
41
|
+
* native form: read `value` or listen for `oh-change`. `required` doesn't
|
|
42
|
+
* validate; set the error yourself.
|
|
43
|
+
*
|
|
44
|
+
* **Accessibility:** a `<fieldset>` with a `<legend>`, so screen readers
|
|
45
|
+
* read the label with each option. Always set `label`. The error shows
|
|
46
|
+
* after the legend and before the options, with an icon; the fieldset gets
|
|
47
|
+
* `aria-invalid` and `aria-describedby`, and the error is announced
|
|
48
|
+
* (`role="alert"`) only when it appears after first render. Focus underlines
|
|
49
|
+
* the option's label.
|
|
50
|
+
*
|
|
51
|
+
* **Look:** set by tokens — the same as `oh-checkbox`: `stroke.control` in
|
|
52
|
+
* `color.border.emphasis` (border), `shape.compact` (corners),
|
|
53
|
+
* `elevation.offset.*` with `elevation.color.secondary` / `elevation.color.primary` (shadow),
|
|
54
|
+
* `lift.hoverSm` / `lift.pressSm` (movement on hover and press),
|
|
55
|
+
* `color.brand.primary` and `color.text.onBrand` (checked),
|
|
56
|
+
* `color.feedback.error` and `elevation.color.error` (error); `typography.control.*`
|
|
57
|
+
* for the legend and labels.
|
|
58
|
+
*
|
|
59
|
+
* @element oh-checkbox-group
|
|
60
|
+
* @fires oh-change - An option was toggled. detail: { value } (the checked values)
|
|
61
|
+
*/
|
|
23
62
|
export declare class OhCheckboxGroup extends OhElement {
|
|
24
63
|
static styles: import("lit").CSSResult[];
|
|
25
|
-
legend
|
|
64
|
+
/** The group's label, rendered as the fieldset's <legend>. Always set one */
|
|
65
|
+
label: string;
|
|
26
66
|
name: string;
|
|
27
67
|
options: CheckboxOption[];
|
|
28
68
|
value: string[];
|
|
29
69
|
required: boolean;
|
|
30
|
-
|
|
31
|
-
|
|
70
|
+
/**
|
|
71
|
+
* Error shown with the control and linked to it. Setting it puts the
|
|
72
|
+
* control in its error state; clear it to leave that state.
|
|
73
|
+
*/
|
|
74
|
+
errorText: string;
|
|
32
75
|
private _handleChange;
|
|
33
76
|
/**
|
|
34
77
|
* Errors that appear after first render (e.g. on submit) are announced via
|
|
@@ -36,6 +79,7 @@ export declare class OhCheckboxGroup extends OhElement {
|
|
|
36
79
|
* aria-describedby, so they aren't read out unprompted.
|
|
37
80
|
*/
|
|
38
81
|
private _announceError;
|
|
82
|
+
updated(changed: PropertyValues): void;
|
|
39
83
|
willUpdate(changed: PropertyValues): void;
|
|
40
84
|
render(): import("lit").TemplateResult<1>;
|
|
41
85
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oh-checkbox-group.d.ts","sourceRoot":"","sources":["../src/oh-checkbox-group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,qBACa,eAAgB,SAAQ,SAAS;IAC5C,OAAgB,MAAM,4BAwMpB;
|
|
1
|
+
{"version":3,"file":"oh-checkbox-group.d.ts","sourceRoot":"","sources":["../src/oh-checkbox-group.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAE9D,OAAO,EAAE,SAAS,EAAc,MAAM,WAAW,CAAC;AAElD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qBACa,eAAgB,SAAQ,SAAS;IAC5C,OAAgB,MAAM,4BAwMpB;IAEF,6EAA6E;IAE7E,KAAK,SAAM;IAGX,IAAI,SAAM;IAGV,OAAO,EAAE,cAAc,EAAE,CAAM;IAG/B,KAAK,EAAE,MAAM,EAAE,CAAM;IAGrB,QAAQ,UAAS;IAEjB;;;OAGG;IAEH,SAAS,SAAM;IAEf,OAAO,CAAC,aAAa;IAYrB;;;;OAIG;IAEH,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,OAAO,EAAE,cAAc;IAM/B,UAAU,CAAC,OAAO,EAAE,cAAc;IAMlC,MAAM;CA0DP;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mBAAmB,EAAE,eAAe,CAAC;KACtC;CACF"}
|