@orange-halo/components 2.1.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 +968 -362
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js +1 -2
- package/dist/base.js.map +1 -1
- package/dist/index.d.ts +4 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -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 +99 -29
- 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 +96 -36
- 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 +38 -19
- 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 +66 -25
- 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.figma.js +1 -3
- package/dist/oh-button.figma.js.map +1 -1
- package/dist/oh-button.js +133 -82
- 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 +143 -96
- 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 +114 -49
- 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 +117 -60
- 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 +52 -24
- 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 +28 -21
- 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 +27 -9
- package/dist/oh-icon.js.map +1 -1
- package/dist/oh-input.d.ts +110 -21
- 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 +227 -71
- 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 +83 -38
- package/dist/oh-link.js.map +1 -1
- package/dist/oh-modal.d.ts +35 -6
- package/dist/oh-modal.d.ts.map +1 -1
- package/dist/oh-modal.js +90 -39
- 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 -20
- 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 +35 -14
- 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 +122 -51
- 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 +120 -61
- package/dist/oh-radio.js.map +1 -1
- package/dist/oh-select.d.ts +59 -16
- package/dist/oh-select.d.ts.map +1 -1
- package/dist/oh-select.js +141 -69
- 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 +43 -32
- 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 +100 -76
- package/dist/oh-tabs.js.map +1 -1
- package/dist/oh-textarea.d.ts +129 -0
- package/dist/oh-textarea.d.ts.map +1 -0
- package/dist/oh-textarea.js +401 -0
- package/dist/oh-textarea.js.map +1 -0
- package/dist/oh-toggle.d.ts +45 -12
- package/dist/oh-toggle.d.ts.map +1 -1
- package/dist/oh-toggle.js +84 -34
- package/dist/oh-toggle.js.map +1 -1
- package/dist/styles/typography.js +1 -1
- package/package.json +7 -7
- package/dist/oh-hero.d.ts +0 -33
- package/dist/oh-hero.d.ts.map +0 -1
- package/dist/oh-hero.js +0 -246
- package/dist/oh-hero.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,135 +28,151 @@ 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
|
-
|
|
67
|
-
transition:
|
|
88
|
+
|
|
89
|
+
transition:
|
|
68
90
|
transform var(--oh-motion-gentle) var(--oh-motion-ease-gentle),
|
|
69
91
|
box-shadow var(--oh-motion-gentle) var(--oh-motion-ease-gentle),
|
|
70
92
|
border-color var(--oh-motion-gentle) var(--oh-motion-ease-gentle);
|
|
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
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
1. Outer: soft, offset shadow (tactile)
|
|
92
|
-
2. Deeper: ambient depth
|
|
93
|
-
3. Inner top: sunlit highlight */
|
|
94
|
-
box-shadow: var(--oh-elevation-surface-raised);
|
|
107
|
+
|
|
108
|
+
border: var(--oh-card-base-border-width) solid
|
|
109
|
+
var(--oh-card-variant-default-border-color);
|
|
110
|
+
|
|
111
|
+
box-shadow: var(--oh-elevation-surface-default);
|
|
95
112
|
}
|
|
96
113
|
|
|
97
114
|
/* ═══════════════════════════════════════════════════════════════
|
|
98
|
-
|
|
99
|
-
|
|
115
|
+
FEATURED VARIANT
|
|
116
|
+
The one card that should stand out
|
|
100
117
|
═══════════════════════════════════════════════════════════════ */
|
|
101
118
|
|
|
102
|
-
.card--
|
|
103
|
-
/* Surface: warm sunlit gradient */
|
|
119
|
+
.card--featured {
|
|
104
120
|
background: linear-gradient(
|
|
105
121
|
180deg,
|
|
106
|
-
var(--oh-card-
|
|
107
|
-
var(--oh-card-
|
|
108
|
-
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%
|
|
109
125
|
);
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
/* Layered shadows with warm glow */
|
|
126
|
+
|
|
127
|
+
border: var(--oh-card-base-border-width) solid
|
|
128
|
+
var(--oh-card-variant-featured-border-color);
|
|
129
|
+
|
|
115
130
|
box-shadow: var(--oh-elevation-surface-featured);
|
|
116
131
|
}
|
|
117
132
|
|
|
118
133
|
/* ═══════════════════════════════════════════════════════════════
|
|
119
|
-
|
|
120
|
-
|
|
134
|
+
SUBTLE VARIANT
|
|
135
|
+
Quieter card: elevation.surface.subtle
|
|
121
136
|
═══════════════════════════════════════════════════════════════ */
|
|
122
137
|
|
|
123
|
-
.card--
|
|
124
|
-
/* Surface: subtle gradient */
|
|
138
|
+
.card--subtle {
|
|
125
139
|
background: linear-gradient(
|
|
126
140
|
180deg,
|
|
127
|
-
var(--oh-card-
|
|
128
|
-
var(--oh-card-
|
|
141
|
+
var(--oh-card-variant-subtle-gradient-start) 0%,
|
|
142
|
+
var(--oh-card-variant-subtle-gradient-end) 100%
|
|
129
143
|
);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
box-shadow: var(--oh-elevation-surface-flat);
|
|
144
|
+
|
|
145
|
+
border: var(--oh-card-base-border-width) solid
|
|
146
|
+
var(--oh-card-variant-subtle-border-color);
|
|
147
|
+
|
|
148
|
+
box-shadow: var(--oh-elevation-surface-subtle);
|
|
136
149
|
}
|
|
137
150
|
|
|
138
151
|
/* ═══════════════════════════════════════════════════════════════
|
|
139
152
|
INTERACTIVE STATES
|
|
140
|
-
|
|
153
|
+
Focus is a solid outline; focus.glowColor is decoration only
|
|
141
154
|
═══════════════════════════════════════════════════════════════ */
|
|
142
155
|
|
|
143
156
|
.card--interactive {
|
|
144
157
|
cursor: pointer;
|
|
145
158
|
}
|
|
146
159
|
|
|
147
|
-
/* Hover:
|
|
148
|
-
.card--interactive.card--
|
|
160
|
+
/* Hover: lift.hover* and elevation.surface.hover */
|
|
161
|
+
.card--interactive.card--default:hover {
|
|
149
162
|
border-color: var(--oh-color-border-strong);
|
|
150
|
-
box-shadow: var(--oh-elevation-surface-
|
|
163
|
+
box-shadow: var(--oh-elevation-surface-hover);
|
|
151
164
|
transform: translateY(var(--oh-lift-hover-md));
|
|
152
165
|
}
|
|
153
166
|
|
|
154
|
-
.card--interactive.card--
|
|
155
|
-
border-color: var(--oh-card-
|
|
156
|
-
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);
|
|
157
170
|
transform: translateY(var(--oh-lift-hover-md));
|
|
158
171
|
}
|
|
159
172
|
|
|
160
|
-
.card--interactive.card--
|
|
173
|
+
.card--interactive.card--subtle:hover {
|
|
161
174
|
border-color: var(--oh-color-border-strong);
|
|
162
|
-
box-shadow: var(--oh-elevation-surface-
|
|
175
|
+
box-shadow: var(--oh-elevation-surface-default);
|
|
163
176
|
transform: translateY(var(--oh-lift-hover-sm));
|
|
164
177
|
}
|
|
165
178
|
|
|
@@ -168,8 +181,8 @@ let OhCard = class OhCard extends OhElement {
|
|
|
168
181
|
transform: translateY(0) !important;
|
|
169
182
|
}
|
|
170
183
|
|
|
171
|
-
.card--interactive.card--
|
|
172
|
-
box-shadow: var(--oh-elevation-surface-
|
|
184
|
+
.card--interactive.card--default:active {
|
|
185
|
+
box-shadow: var(--oh-elevation-surface-active);
|
|
173
186
|
}
|
|
174
187
|
|
|
175
188
|
/* Focus: solid outline is the indicator; the glow is decoration only */
|
|
@@ -179,22 +192,32 @@ let OhCard = class OhCard extends OhElement {
|
|
|
179
192
|
border-color: var(--oh-color-brand-primary);
|
|
180
193
|
}
|
|
181
194
|
|
|
182
|
-
.card--interactive.card--
|
|
183
|
-
.card--interactive.card--
|
|
184
|
-
box-shadow:
|
|
195
|
+
.card--interactive.card--default:focus-visible,
|
|
196
|
+
.card--interactive.card--subtle:focus-visible {
|
|
197
|
+
box-shadow:
|
|
198
|
+
0 0 16px var(--oh-focus-glow-color),
|
|
199
|
+
var(--oh-elevation-surface-focus);
|
|
185
200
|
}
|
|
186
201
|
|
|
187
|
-
.card--interactive.card--
|
|
188
|
-
box-shadow:
|
|
202
|
+
.card--interactive.card--featured:focus-visible {
|
|
203
|
+
box-shadow:
|
|
204
|
+
0 0 20px var(--oh-focus-glow-color),
|
|
205
|
+
var(--oh-elevation-surface-featured-focus);
|
|
189
206
|
}
|
|
190
207
|
|
|
191
208
|
/* ═══════════════════════════════════════════════════════════════
|
|
192
209
|
PADDING VARIANTS
|
|
193
210
|
═══════════════════════════════════════════════════════════════ */
|
|
194
211
|
|
|
195
|
-
.card--padding-sm .content {
|
|
196
|
-
|
|
197
|
-
|
|
212
|
+
.card--padding-sm .content {
|
|
213
|
+
padding: var(--oh-spacing-3-5);
|
|
214
|
+
}
|
|
215
|
+
.card--padding-md .content {
|
|
216
|
+
padding: var(--oh-spacing-5);
|
|
217
|
+
}
|
|
218
|
+
.card--padding-lg .content {
|
|
219
|
+
padding: var(--oh-spacing-7);
|
|
220
|
+
}
|
|
198
221
|
|
|
199
222
|
/* ═══════════════════════════════════════════════════════════════
|
|
200
223
|
SLOTS: Header, Content, Footer
|
|
@@ -202,7 +225,8 @@ let OhCard = class OhCard extends OhElement {
|
|
|
202
225
|
|
|
203
226
|
.header {
|
|
204
227
|
padding: var(--oh-spacing-4) var(--oh-spacing-5);
|
|
205
|
-
border-bottom: var(--oh-stroke-divider) solid
|
|
228
|
+
border-bottom: var(--oh-stroke-divider) solid
|
|
229
|
+
var(--oh-card-section-divider-color);
|
|
206
230
|
background: linear-gradient(
|
|
207
231
|
180deg,
|
|
208
232
|
var(--oh-card-section-header-gradient-start) 0%,
|
|
@@ -210,15 +234,14 @@ let OhCard = class OhCard extends OhElement {
|
|
|
210
234
|
);
|
|
211
235
|
}
|
|
212
236
|
|
|
213
|
-
.header:empty { display: none; }
|
|
214
|
-
|
|
215
237
|
.content {
|
|
216
238
|
/* Padding handled by variant */
|
|
217
239
|
}
|
|
218
240
|
|
|
219
241
|
.footer {
|
|
220
242
|
padding: var(--oh-spacing-4) var(--oh-spacing-5);
|
|
221
|
-
border-top: var(--oh-stroke-divider) solid
|
|
243
|
+
border-top: var(--oh-stroke-divider) solid
|
|
244
|
+
var(--oh-card-section-divider-color);
|
|
222
245
|
background: linear-gradient(
|
|
223
246
|
180deg,
|
|
224
247
|
var(--oh-color-surface-raised) 0%,
|
|
@@ -226,7 +249,12 @@ let OhCard = class OhCard extends OhElement {
|
|
|
226
249
|
);
|
|
227
250
|
}
|
|
228
251
|
|
|
229
|
-
|
|
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] {
|
|
256
|
+
display: none;
|
|
257
|
+
}
|
|
230
258
|
|
|
231
259
|
/* Padding adjustments for slots */
|
|
232
260
|
.card--padding-sm .header,
|
|
@@ -247,13 +275,26 @@ let OhCard = class OhCard extends OhElement {
|
|
|
247
275
|
.card {
|
|
248
276
|
transition-duration: 0.01ms !important;
|
|
249
277
|
}
|
|
250
|
-
|
|
278
|
+
|
|
251
279
|
.card--interactive:hover {
|
|
252
280
|
transform: none !important;
|
|
253
281
|
}
|
|
254
282
|
}
|
|
255
283
|
`,
|
|
256
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
|
+
}
|
|
257
298
|
_handleClick(event) {
|
|
258
299
|
if (this.interactive) {
|
|
259
300
|
this.emit("oh-click", { originalEvent: event });
|
|
@@ -281,16 +322,16 @@ let OhCard = class OhCard extends OhElement {
|
|
|
281
322
|
@click=${this._handleClick}
|
|
282
323
|
@keydown=${this._handleKeyDown}
|
|
283
324
|
>
|
|
284
|
-
<div class="header" part="header">
|
|
285
|
-
<slot name="header"></slot>
|
|
325
|
+
<div class="header" part="header" ?hidden=${!this._hasHeader}>
|
|
326
|
+
<slot name="header" @slotchange=${this._onHeaderSlotChange}></slot>
|
|
286
327
|
</div>
|
|
287
|
-
|
|
328
|
+
|
|
288
329
|
<div class="content" part="content">
|
|
289
330
|
<slot></slot>
|
|
290
331
|
</div>
|
|
291
|
-
|
|
292
|
-
<div class="footer" part="footer">
|
|
293
|
-
<slot name="footer"></slot>
|
|
332
|
+
|
|
333
|
+
<div class="footer" part="footer" ?hidden=${!this._hasFooter}>
|
|
334
|
+
<slot name="footer" @slotchange=${this._onFooterSlotChange}></slot>
|
|
294
335
|
</div>
|
|
295
336
|
</div>
|
|
296
337
|
`;
|
|
@@ -305,6 +346,12 @@ __decorate([
|
|
|
305
346
|
__decorate([
|
|
306
347
|
property({ type: String, reflect: true })
|
|
307
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);
|
|
308
355
|
OhCard = __decorate([
|
|
309
356
|
customElement("oh-card")
|
|
310
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,
|
|
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"}
|
|
@@ -6,17 +6,15 @@ import figma, { html } from "@figma/code-connect/html";
|
|
|
6
6
|
*/
|
|
7
7
|
figma.connect("https://www.figma.com/design/q9ZYrOj2w9DrTVmgQFU7bu/OHDS?node-id=1-77", {
|
|
8
8
|
props: {
|
|
9
|
-
|
|
9
|
+
label: figma.string("Legend"),
|
|
10
10
|
required: figma.boolean("Required"),
|
|
11
|
-
|
|
12
|
-
errorMessage: figma.string("Error Message"),
|
|
11
|
+
errorText: figma.string("Error Message"),
|
|
13
12
|
},
|
|
14
13
|
example: (props) => html `
|
|
15
14
|
<oh-checkbox-group
|
|
16
|
-
|
|
15
|
+
label="${props.label}"
|
|
17
16
|
?required="${props.required}"
|
|
18
|
-
|
|
19
|
-
errormessage="${props.errorMessage}"
|
|
17
|
+
error-text="${props.errorText}"
|
|
20
18
|
.options="\${options}"
|
|
21
19
|
></oh-checkbox-group>
|
|
22
20
|
`,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oh-checkbox-group.figma.js","sourceRoot":"","sources":["../src/oh-checkbox-group.figma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;GAIG;AAEH,KAAK,CAAC,OAAO,CACX,uEAAuE,EACvE;IACE,KAAK,EAAE;QACL,
|
|
1
|
+
{"version":3,"file":"oh-checkbox-group.figma.js","sourceRoot":"","sources":["../src/oh-checkbox-group.figma.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEvD;;;;GAIG;AAEH,KAAK,CAAC,OAAO,CACX,uEAAuE,EACvE;IACE,KAAK,EAAE;QACL,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC7B,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;QACnC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC;KACzC;IACD,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAA;;iBAEX,KAAK,CAAC,KAAK;qBACP,KAAK,CAAC,QAAQ;sBACb,KAAK,CAAC,SAAS;;;KAGhC;CACF,CACF,CAAC"}
|