@operato/styles 10.23.0 → 10.29.9
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/CHANGELOG.md +26 -0
- package/dist/src/button-styles.d.ts +25 -0
- package/dist/src/button-styles.js +127 -0
- package/dist/src/button-styles.js.map +1 -0
- package/dist/src/form-field-styles.js +20 -0
- package/dist/src/form-field-styles.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/page-frame-styles.d.ts +0 -30
- package/dist/src/page-frame-styles.js +105 -7
- package/dist/src/page-frame-styles.js.map +1 -1
- package/dist/test/page-ground.test.d.ts +1 -0
- package/dist/test/page-ground.test.js +164 -0
- package/dist/test/page-ground.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -2
- package/test/page-ground.test.ts +180 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { expect, fixture, html } from '@open-wc/testing'
|
|
2
|
+
import { css, LitElement } from 'lit'
|
|
3
|
+
|
|
4
|
+
import { ButtonContainerStyles } from '../src/button-container-styles.js'
|
|
5
|
+
import { ButtonStyles } from '../src/button-styles.js'
|
|
6
|
+
import { FormFieldStyles } from '../src/form-field-styles.js'
|
|
7
|
+
import { DocumentPageStyles, WorkSurfacePageStyles } from '../src/page-frame-styles.js'
|
|
8
|
+
|
|
9
|
+
/*
|
|
10
|
+
* The ground the page frames lay, and the button and field sizes (operato-application/design/ui/page-standard.md).
|
|
11
|
+
*
|
|
12
|
+
* What these stand on: a screen that forgot to set a value used to fall to the browser default -
|
|
13
|
+
* 16px body text, rgb(0 0 238) links, Korean broken mid-word, cards wider than their header. The
|
|
14
|
+
* frame now lays the value; a screen that says otherwise still wins. Measured on rendered elements,
|
|
15
|
+
* not on the stylesheet text.
|
|
16
|
+
*
|
|
17
|
+
* The tokens are defined here because a test page has no shell theme.
|
|
18
|
+
*/
|
|
19
|
+
const TOKENS = css`
|
|
20
|
+
:host {
|
|
21
|
+
--ui-t-body: 13px;
|
|
22
|
+
--ui-ink: rgb(27, 27, 27);
|
|
23
|
+
--ui-accent: rgb(0, 114, 126);
|
|
24
|
+
--ui-gutter: 16px;
|
|
25
|
+
--context-action-height: 32px;
|
|
26
|
+
--cell-action-height: 26px;
|
|
27
|
+
--form-element-height-medium: 32px;
|
|
28
|
+
--form-element-height-small: 26px;
|
|
29
|
+
--md-sys-color-primary: rgb(0, 114, 126);
|
|
30
|
+
--md-sys-color-surface-container-lowest: rgb(255, 255, 255);
|
|
31
|
+
}
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
class DocumentProbe extends LitElement {
|
|
35
|
+
static styles = [DocumentPageStyles, ButtonStyles, FormFieldStyles, TOKENS]
|
|
36
|
+
render() {
|
|
37
|
+
return html`
|
|
38
|
+
<div class="page">
|
|
39
|
+
<section class="page-section">
|
|
40
|
+
<p class="page-section-note">note</p>
|
|
41
|
+
<div class="page-card" id="card" style="width: 300px; padding: 16px">card</div>
|
|
42
|
+
<span id="text">text</span>
|
|
43
|
+
<a id="thing" href="#a">LOT-1</a>
|
|
44
|
+
<a id="go" class="page-nav-link" href="#b">go</a>
|
|
45
|
+
<div style="display: grid; grid-template-columns: 400px">
|
|
46
|
+
<button id="plain">add</button>
|
|
47
|
+
</div>
|
|
48
|
+
<button id="raised" raised>save</button>
|
|
49
|
+
<button id="small" small>hold</button>
|
|
50
|
+
<input id="field" />
|
|
51
|
+
<input id="small-field" small />
|
|
52
|
+
<textarea id="area"></textarea>
|
|
53
|
+
</section>
|
|
54
|
+
</div>
|
|
55
|
+
`
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
customElements.define('document-probe', DocumentProbe)
|
|
59
|
+
|
|
60
|
+
class SurfaceProbe extends LitElement {
|
|
61
|
+
static styles = [WorkSurfacePageStyles, TOKENS]
|
|
62
|
+
render() {
|
|
63
|
+
return html`<div class="page-headroom"><span>range</span></div>`
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
customElements.define('surface-probe', SurfaceProbe)
|
|
67
|
+
|
|
68
|
+
class OwnRuleProbe extends LitElement {
|
|
69
|
+
static styles = [
|
|
70
|
+
DocumentPageStyles,
|
|
71
|
+
ButtonStyles,
|
|
72
|
+
TOKENS,
|
|
73
|
+
css`
|
|
74
|
+
:host {
|
|
75
|
+
font-size: 15px;
|
|
76
|
+
}
|
|
77
|
+
button {
|
|
78
|
+
height: 48px;
|
|
79
|
+
}
|
|
80
|
+
a {
|
|
81
|
+
color: rgb(255, 0, 0);
|
|
82
|
+
}
|
|
83
|
+
`
|
|
84
|
+
]
|
|
85
|
+
render() {
|
|
86
|
+
return html`<span id="text">t</span><button id="own">x</button><a id="a" href="#">a</a>`
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
customElements.define('own-rule-probe', OwnRuleProbe)
|
|
90
|
+
|
|
91
|
+
const style = (el: Element) => getComputedStyle(el)
|
|
92
|
+
|
|
93
|
+
describe('page frame ground', () => {
|
|
94
|
+
it('body text is the body token, not the browser 16px', async () => {
|
|
95
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
96
|
+
expect(style(el.shadowRoot!.querySelector('#text')!).fontSize).to.equal('13px')
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
it('a link to a thing reads as text; a link to a screen takes the accent; neither underlines at rest', async () => {
|
|
100
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
101
|
+
const thing = style(el.shadowRoot!.querySelector('#thing')!)
|
|
102
|
+
const go = style(el.shadowRoot!.querySelector('#go')!)
|
|
103
|
+
expect(thing.color).to.equal('rgb(27, 27, 27)')
|
|
104
|
+
expect(thing.textDecorationLine).to.equal('none')
|
|
105
|
+
expect(go.color).to.equal('rgb(0, 114, 126)')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('Korean wraps at words, and a word with no break point still breaks', async () => {
|
|
109
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
110
|
+
const text = style(el.shadowRoot!.querySelector('#text')!)
|
|
111
|
+
expect(text.wordBreak).to.equal('keep-all')
|
|
112
|
+
expect(text.overflowWrap).to.equal('anywhere')
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('padding stays inside the width (a card is not wider than it was told)', async () => {
|
|
116
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
117
|
+
expect(el.shadowRoot!.querySelector('#card')!.getBoundingClientRect().width).to.equal(300)
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('the document column is not held to 1080px, and its side gutters are equal', async () => {
|
|
121
|
+
const el = (await fixture(html`<document-probe style="display: block; width: 1600px"></document-probe>`)) as DocumentProbe
|
|
122
|
+
const page = el.shadowRoot!.querySelector('.page')!
|
|
123
|
+
expect(style(page).maxWidth).to.equal('none')
|
|
124
|
+
expect(page.getBoundingClientRect().width).to.equal(1600)
|
|
125
|
+
expect(style(page).paddingLeft).to.equal('16px')
|
|
126
|
+
expect(style(page).paddingRight).to.equal('16px')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('the work surface headroom uses the same gutter', async () => {
|
|
130
|
+
const el = (await fixture(html`<surface-probe></surface-probe>`)) as SurfaceProbe
|
|
131
|
+
expect(style(el.shadowRoot!.querySelector('.page-headroom')!).paddingLeft).to.equal('16px')
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
it("a screen's own rule still wins over the ground", async () => {
|
|
135
|
+
const el = (await fixture(html`<own-rule-probe></own-rule-probe>`)) as OwnRuleProbe
|
|
136
|
+
expect(style(el.shadowRoot!.querySelector('#text')!).fontSize).to.equal('15px')
|
|
137
|
+
expect(style(el.shadowRoot!.querySelector('#own')!).height).to.equal('48px')
|
|
138
|
+
expect(style(el.shadowRoot!.querySelector('#a')!).color).to.equal('rgb(255, 0, 0)')
|
|
139
|
+
})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
describe('buttons and fields', () => {
|
|
143
|
+
it('a button is as tall as its place and as wide as its label - it does not stretch to a grid track', async () => {
|
|
144
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
145
|
+
const plain = el.shadowRoot!.querySelector('#plain')!
|
|
146
|
+
expect(style(plain).height).to.equal('32px')
|
|
147
|
+
expect(style(plain).fontSize).to.equal('13px')
|
|
148
|
+
expect(style(plain).fontWeight).to.equal('600')
|
|
149
|
+
expect(plain.getBoundingClientRect().width).to.be.below(100)
|
|
150
|
+
expect(style(el.shadowRoot!.querySelector('#small')!).height).to.equal('26px')
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
it('a raised button is filled, a plain one is not', async () => {
|
|
154
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
155
|
+
const raised = style(el.shadowRoot!.querySelector('#raised')!).backgroundColor
|
|
156
|
+
const plain = style(el.shadowRoot!.querySelector('#plain')!).backgroundColor
|
|
157
|
+
expect(raised).to.not.equal(plain)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('one-line fields take the form height; a small one the cell height; a textarea keeps its own', async () => {
|
|
161
|
+
const el = (await fixture(html`<document-probe></document-probe>`)) as DocumentProbe
|
|
162
|
+
expect(style(el.shadowRoot!.querySelector('#field')!).height).to.equal('32px')
|
|
163
|
+
expect(style(el.shadowRoot!.querySelector('#small-field')!).height).to.equal('26px')
|
|
164
|
+
expect(style(el.shadowRoot!.querySelector('#area')!).height).to.not.equal('32px')
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
|
|
168
|
+
describe('ButtonContainerStyles', () => {
|
|
169
|
+
/*
|
|
170
|
+
* dssp draws 26 of its own pages with this block. ButtonStyles was taken out next to it, not out of
|
|
171
|
+
* it: the CSS this block emits must stay byte for byte what 10.29.1 published.
|
|
172
|
+
* sha-256 of ButtonContainerStyles.cssText in the published 10.29.1 (2026-10-05).
|
|
173
|
+
*/
|
|
174
|
+
it('emits the same CSS as the published 10.29.1', async () => {
|
|
175
|
+
const bytes = new TextEncoder().encode(ButtonContainerStyles.cssText)
|
|
176
|
+
const digest = await crypto.subtle.digest('SHA-256', bytes)
|
|
177
|
+
const hex = [...new Uint8Array(digest)].map(b => b.toString(16).padStart(2, '0')).join('')
|
|
178
|
+
expect(hex).to.equal('bcab002afc1a4521cd7da312cacba2bcd594cfe0e3dcd6c1d62a388adfd25203')
|
|
179
|
+
})
|
|
180
|
+
})
|