@teseor/css 1.2.4 → 1.4.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/dist/compiled.css +1 -1
- package/dist/index.css +23 -7
- package/package.json +1 -1
- package/src/03-layout/app-shell/app-shell.api.json +18 -0
- package/src/03-layout/app-shell/app-shell.docs.json +18 -0
- package/src/03-layout/aspect-ratio/aspect-ratio-visual.png +0 -0
- package/src/03-layout/aspect-ratio/aspect-ratio.api.json +16 -0
- package/src/03-layout/aspect-ratio/aspect-ratio.docs.json +193 -0
- package/src/03-layout/aspect-ratio/aspect-ratio.visual.spec.ts +14 -0
- package/src/03-layout/aspect-ratio/index.scss +23 -0
- package/src/03-layout/content/content-visual.png +0 -0
- package/src/03-layout/content/content.api.json +26 -0
- package/src/03-layout/content/content.docs.json +82 -0
- package/src/03-layout/content/content.visual.spec.ts +14 -0
- package/src/03-layout/content/index.scss +25 -0
- package/src/03-layout/footer/footer-visual.png +0 -0
- package/src/03-layout/footer/footer.api.json +45 -0
- package/src/03-layout/footer/footer.docs.json +110 -0
- package/src/03-layout/footer/footer.visual.spec.ts +14 -0
- package/src/03-layout/footer/index.scss +62 -0
- package/src/03-layout/index.scss +11 -5
- package/src/03-layout/main/index.scss +1 -0
- package/src/03-layout/nav-rail/index.scss +50 -0
- package/src/03-layout/nav-rail/nav-rail-visual.png +0 -0
- package/src/03-layout/nav-rail/nav-rail.api.json +35 -0
- package/src/03-layout/nav-rail/nav-rail.docs.json +76 -0
- package/src/03-layout/nav-rail/nav-rail.visual.spec.ts +14 -0
- package/src/03-layout/page-header/index.scss +52 -0
- package/src/03-layout/page-header/page-header-visual.png +0 -0
- package/src/03-layout/page-header/page-header.api.json +35 -0
- package/src/03-layout/page-header/page-header.docs.json +124 -0
- package/src/03-layout/page-header/page-header.visual.spec.ts +14 -0
- package/src/03-layout/sidebar/index.scss +2 -2
- package/src/03-layout/topbar/index.scss +62 -0
- package/src/03-layout/topbar/topbar-visual.png +0 -0
- package/src/03-layout/topbar/topbar.api.json +45 -0
- package/src/03-layout/topbar/topbar.docs.json +110 -0
- package/src/03-layout/topbar/topbar.visual.spec.ts +14 -0
- package/src/04-components/actions/button-group/button-group-visual.png +0 -0
- package/src/04-components/actions/button-group/button-group.visual.spec.ts +1 -2
- package/src/04-components/actions/button-group/index.scss +3 -1
- package/src/04-components/data-display/avatar/avatar-visual.png +0 -0
- package/src/04-components/data-display/stat/index.scss +47 -0
- package/src/04-components/data-display/stat/stat-visual.png +0 -0
- package/src/04-components/data-display/stat/stat.api.json +18 -0
- package/src/04-components/data-display/stat/stat.docs.json +114 -0
- package/src/04-components/data-display/stat/stat.visual.spec.ts +14 -0
- package/src/04-components/disclosure/accordion/accordion-visual.png +0 -0
- package/src/04-components/disclosure/disclosure/disclosure-visual.png +0 -0
- package/src/04-components/forms/field/field-visual.png +0 -0
- package/src/04-components/forms/input/input-visual.png +0 -0
- package/src/04-components/index.scss +5 -0
- package/src/04-components/layout/spacer/index.scss +11 -0
- package/src/04-components/layout/spacer/spacer-visual.png +0 -0
- package/src/04-components/layout/spacer/spacer.api.json +6 -0
- package/src/04-components/layout/spacer/spacer.docs.json +102 -0
- package/src/04-components/layout/spacer/spacer.visual.spec.ts +14 -0
- package/src/04-components/typography/blockquote/blockquote-visual.png +0 -0
- package/src/04-components/typography/blockquote/blockquote.api.json +18 -0
- package/src/04-components/typography/blockquote/blockquote.docs.json +89 -0
- package/src/04-components/typography/blockquote/blockquote.visual.spec.ts +14 -0
- package/src/04-components/typography/blockquote/index.scss +41 -0
- package/src/04-components/typography/kbd/index.scss +33 -0
- package/src/04-components/typography/kbd/kbd-visual.png +0 -0
- package/src/04-components/typography/kbd/kbd.api.json +15 -0
- package/src/04-components/typography/kbd/kbd.docs.json +61 -0
- package/src/04-components/typography/kbd/kbd.visual.spec.ts +14 -0
- package/src/04-components/typography/mark/index.scss +22 -0
- package/src/04-components/typography/mark/mark-visual.png +0 -0
- package/src/04-components/typography/mark/mark.api.json +12 -0
- package/src/04-components/typography/mark/mark.docs.json +60 -0
- package/src/04-components/typography/mark/mark.visual.spec.ts +14 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "page-header",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"title": "Page Header",
|
|
5
|
+
"description": "Content area header with title, description, actions, and optional breadcrumb.",
|
|
6
|
+
"api": "./page-header.api.json",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"title": "Default",
|
|
10
|
+
"description": "Title with actions on the end side.",
|
|
11
|
+
"examples": [
|
|
12
|
+
{
|
|
13
|
+
"items": [
|
|
14
|
+
{
|
|
15
|
+
"tag": "header",
|
|
16
|
+
"class": "ui-page-header ui-page-header--bordered",
|
|
17
|
+
"children": [
|
|
18
|
+
{
|
|
19
|
+
"tag": "div",
|
|
20
|
+
"class": "ui-page-header__title",
|
|
21
|
+
"children": [
|
|
22
|
+
{ "tag": "h1", "class": "ui-heading ui-heading--xl", "text": "Users" },
|
|
23
|
+
{ "tag": "p", "text": "Manage user accounts and permissions." }
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"tag": "div",
|
|
28
|
+
"class": "ui-page-header__actions",
|
|
29
|
+
"children": [
|
|
30
|
+
{ "tag": "button", "class": "ui-button ui-button--primary", "text": "Add user" }
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"title": "With Breadcrumb",
|
|
41
|
+
"description": "Breadcrumb spans the full width above the title row.",
|
|
42
|
+
"examples": [
|
|
43
|
+
{
|
|
44
|
+
"items": [
|
|
45
|
+
{
|
|
46
|
+
"tag": "header",
|
|
47
|
+
"class": "ui-page-header ui-page-header--bordered",
|
|
48
|
+
"children": [
|
|
49
|
+
{
|
|
50
|
+
"tag": "nav",
|
|
51
|
+
"class": "ui-page-header__breadcrumb",
|
|
52
|
+
"children": [{ "tag": "span", "text": "Home / Settings / Users" }]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"tag": "div",
|
|
56
|
+
"class": "ui-page-header__title",
|
|
57
|
+
"children": [
|
|
58
|
+
{ "tag": "h1", "class": "ui-heading ui-heading--xl", "text": "Users" }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"tag": "div",
|
|
63
|
+
"class": "ui-page-header__actions",
|
|
64
|
+
"children": [{ "tag": "button", "class": "ui-button", "text": "Export" }]
|
|
65
|
+
}
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"title": "Bordered",
|
|
74
|
+
"description": "Bottom border via inset box-shadow.",
|
|
75
|
+
"examples": [
|
|
76
|
+
{
|
|
77
|
+
"items": [
|
|
78
|
+
{
|
|
79
|
+
"tag": "header",
|
|
80
|
+
"class": "ui-page-header ui-page-header--bordered",
|
|
81
|
+
"children": [
|
|
82
|
+
{
|
|
83
|
+
"tag": "div",
|
|
84
|
+
"class": "ui-page-header__title",
|
|
85
|
+
"children": [
|
|
86
|
+
{ "tag": "h1", "class": "ui-heading ui-heading--xl", "text": "Dashboard" }
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"title": "Sticky",
|
|
97
|
+
"description": "Sticks to the top of the scroll container.",
|
|
98
|
+
"examples": [
|
|
99
|
+
{
|
|
100
|
+
"items": [
|
|
101
|
+
{
|
|
102
|
+
"tag": "header",
|
|
103
|
+
"class": "ui-page-header ui-page-header--sticky ui-page-header--bordered",
|
|
104
|
+
"children": [
|
|
105
|
+
{
|
|
106
|
+
"tag": "div",
|
|
107
|
+
"class": "ui-page-header__title",
|
|
108
|
+
"children": [
|
|
109
|
+
{ "tag": "h1", "class": "ui-heading ui-heading--xl", "text": "Sticky Header" }
|
|
110
|
+
]
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"tag": "div",
|
|
114
|
+
"class": "ui-page-header__actions",
|
|
115
|
+
"children": [{ "tag": "button", "class": "ui-button", "text": "Save" }]
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
]
|
|
124
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { expect, test } from '@playwright/test';
|
|
3
|
+
import { saveForLostPixel, setupVisualTestFromDocs, validateGridRhythm } from '../../testing';
|
|
4
|
+
|
|
5
|
+
const DOCS_PATH = resolve(__dirname, 'page-header.docs.json');
|
|
6
|
+
|
|
7
|
+
test.describe('page-header visual regression', () => {
|
|
8
|
+
test('all variations', async ({ page }) => {
|
|
9
|
+
await setupVisualTestFromDocs(page, DOCS_PATH);
|
|
10
|
+
await validateGridRhythm(page, 'page-header');
|
|
11
|
+
await saveForLostPixel(page, 'page-header');
|
|
12
|
+
await expect(page.locator('body')).toHaveScreenshot('page-header.visual.png');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
display: flex;
|
|
4
4
|
flex-direction: column;
|
|
5
5
|
position: fixed;
|
|
6
|
-
inset-block-start: 0;
|
|
6
|
+
inset-block-start: var(--topbar-height, 0);
|
|
7
7
|
inset-inline-start: 0;
|
|
8
8
|
z-index: var(--ui-z-sticky);
|
|
9
9
|
|
|
10
|
-
block-size: 100vh;
|
|
10
|
+
block-size: calc(100vh - var(--topbar-height, 0px));
|
|
11
11
|
inline-size: var(--sidebar-width, calc(var(--unit) * 30));
|
|
12
12
|
overflow-y: auto;
|
|
13
13
|
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
@layer primitives {
|
|
2
|
+
.topbar {
|
|
3
|
+
--_height: var(--ui-topbar-height, var(--ui-row-3));
|
|
4
|
+
--_bg: var(--ui-topbar-bg, var(--ui-color-bg));
|
|
5
|
+
--_padding-inline: var(--ui-topbar-padding-inline, var(--ui-space-3));
|
|
6
|
+
--_border-color: var(--ui-topbar-border-color, var(--ui-color-border));
|
|
7
|
+
--_z: var(--ui-topbar-z, var(--ui-z-sticky));
|
|
8
|
+
|
|
9
|
+
display: flex;
|
|
10
|
+
align-items: center;
|
|
11
|
+
z-index: var(--_z);
|
|
12
|
+
|
|
13
|
+
block-size: var(--_height);
|
|
14
|
+
padding-inline: var(--_padding-inline);
|
|
15
|
+
|
|
16
|
+
background: var(--_bg);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Sections
|
|
20
|
+
.topbar__start {
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-shrink: 0;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: var(--ui-space-2);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.topbar__center {
|
|
28
|
+
display: flex;
|
|
29
|
+
flex: 1;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
gap: var(--ui-space-2);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.topbar__end {
|
|
36
|
+
display: flex;
|
|
37
|
+
flex-shrink: 0;
|
|
38
|
+
align-items: center;
|
|
39
|
+
gap: var(--ui-space-2);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Position modifiers
|
|
43
|
+
.topbar--sticky {
|
|
44
|
+
position: sticky;
|
|
45
|
+
inset-block-start: 0;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.topbar--fixed {
|
|
49
|
+
position: fixed;
|
|
50
|
+
inset-block-start: 0;
|
|
51
|
+
inset-inline: 0;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Visual modifiers
|
|
55
|
+
.topbar--bordered {
|
|
56
|
+
box-shadow: inset 0 calc(var(--ui-border-width-sm) * -1) 0 0 var(--_border-color);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.topbar--raised {
|
|
60
|
+
box-shadow: var(--shadow-sm);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "topbar",
|
|
3
|
+
"element": "header",
|
|
4
|
+
"modifiers": {
|
|
5
|
+
"sticky": {
|
|
6
|
+
"type": "boolean"
|
|
7
|
+
},
|
|
8
|
+
"fixed": {
|
|
9
|
+
"type": "boolean"
|
|
10
|
+
},
|
|
11
|
+
"bordered": {
|
|
12
|
+
"type": "boolean"
|
|
13
|
+
},
|
|
14
|
+
"raised": {
|
|
15
|
+
"type": "boolean"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"elements": {
|
|
19
|
+
"start": {},
|
|
20
|
+
"center": {},
|
|
21
|
+
"end": {}
|
|
22
|
+
},
|
|
23
|
+
"cssVars": [
|
|
24
|
+
{
|
|
25
|
+
"name": "--ui-topbar-height",
|
|
26
|
+
"default": "var(--ui-row-3)"
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"name": "--ui-topbar-bg",
|
|
30
|
+
"default": "var(--ui-color-bg)"
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
"name": "--ui-topbar-padding-inline",
|
|
34
|
+
"default": "var(--ui-space-3)"
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"name": "--ui-topbar-border-color",
|
|
38
|
+
"default": "var(--ui-color-border)"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"name": "--ui-topbar-z",
|
|
42
|
+
"default": "var(--ui-z-sticky)"
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "topbar",
|
|
3
|
+
"type": "primitive",
|
|
4
|
+
"title": "Topbar",
|
|
5
|
+
"description": "Fixed or sticky header bar for app layouts with start, center, and end sections.",
|
|
6
|
+
"api": "./topbar.api.json",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"title": "Default",
|
|
10
|
+
"description": "Basic topbar with three sections: start (brand), center (search/nav), and end (actions).",
|
|
11
|
+
"examples": [
|
|
12
|
+
{
|
|
13
|
+
"items": [
|
|
14
|
+
{
|
|
15
|
+
"tag": "header",
|
|
16
|
+
"class": "ui-topbar ui-topbar--bordered",
|
|
17
|
+
"children": [
|
|
18
|
+
{
|
|
19
|
+
"tag": "div",
|
|
20
|
+
"class": "ui-topbar__start",
|
|
21
|
+
"children": [{ "tag": "strong", "text": "Brand" }]
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"tag": "div",
|
|
25
|
+
"class": "ui-topbar__center",
|
|
26
|
+
"children": [{ "tag": "span", "text": "Center content" }]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"tag": "div",
|
|
30
|
+
"class": "ui-topbar__end",
|
|
31
|
+
"children": [{ "tag": "span", "text": "Actions" }]
|
|
32
|
+
}
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
"title": "Sticky",
|
|
41
|
+
"description": "Stays at the top of the viewport on scroll.",
|
|
42
|
+
"examples": [
|
|
43
|
+
{
|
|
44
|
+
"code": "<header class=\"ui-topbar ui-topbar--sticky ui-topbar--bordered\">\n <div class=\"ui-topbar__start\"><strong>Brand</strong></div>\n <div class=\"ui-topbar__center\">Nav</div>\n <div class=\"ui-topbar__end\">Actions</div>\n</header>"
|
|
45
|
+
}
|
|
46
|
+
]
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
"title": "Bordered",
|
|
50
|
+
"description": "Bottom border via inset box-shadow to preserve grid rhythm.",
|
|
51
|
+
"examples": [
|
|
52
|
+
{
|
|
53
|
+
"items": [
|
|
54
|
+
{
|
|
55
|
+
"tag": "header",
|
|
56
|
+
"class": "ui-topbar ui-topbar--bordered",
|
|
57
|
+
"children": [
|
|
58
|
+
{
|
|
59
|
+
"tag": "div",
|
|
60
|
+
"class": "ui-topbar__start",
|
|
61
|
+
"children": [{ "tag": "strong", "text": "Bordered" }]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"tag": "div",
|
|
65
|
+
"class": "ui-topbar__end",
|
|
66
|
+
"children": [{ "tag": "span", "text": "Actions" }]
|
|
67
|
+
}
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"title": "Raised",
|
|
76
|
+
"description": "Subtle drop shadow below the topbar.",
|
|
77
|
+
"examples": [
|
|
78
|
+
{
|
|
79
|
+
"items": [
|
|
80
|
+
{
|
|
81
|
+
"tag": "header",
|
|
82
|
+
"class": "ui-topbar ui-topbar--raised",
|
|
83
|
+
"children": [
|
|
84
|
+
{
|
|
85
|
+
"tag": "div",
|
|
86
|
+
"class": "ui-topbar__start",
|
|
87
|
+
"children": [{ "tag": "strong", "text": "Raised" }]
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"tag": "div",
|
|
91
|
+
"class": "ui-topbar__end",
|
|
92
|
+
"children": [{ "tag": "span", "text": "Actions" }]
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"title": "Integration with Sidebar",
|
|
102
|
+
"description": "Set --topbar-height on .app-shell so sidebar and main offset correctly. The topbar itself uses --fixed, and sidebar/main read --topbar-height.",
|
|
103
|
+
"examples": [
|
|
104
|
+
{
|
|
105
|
+
"code": "<body class=\"ui-app-shell\" style=\"--topbar-height: var(--ui-row-3)\">\n <header class=\"ui-topbar ui-topbar--fixed ui-topbar--bordered\">\n <div class=\"ui-topbar__start\"><strong>App</strong></div>\n <div class=\"ui-topbar__end\">User</div>\n </header>\n <aside class=\"ui-sidebar\">Sidebar</aside>\n <main class=\"ui-main\">\n <div class=\"ui-container\">Content</div>\n </main>\n</body>"
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { expect, test } from '@playwright/test';
|
|
3
|
+
import { saveForLostPixel, setupVisualTestFromDocs, validateGridRhythm } from '../../testing';
|
|
4
|
+
|
|
5
|
+
const DOCS_PATH = resolve(__dirname, 'topbar.docs.json');
|
|
6
|
+
|
|
7
|
+
test.describe('topbar visual regression', () => {
|
|
8
|
+
test('all variations', async ({ page }) => {
|
|
9
|
+
await setupVisualTestFromDocs(page, DOCS_PATH);
|
|
10
|
+
await validateGridRhythm(page, 'topbar');
|
|
11
|
+
await saveForLostPixel(page, 'topbar');
|
|
12
|
+
await expect(page.locator('body')).toHaveScreenshot('topbar.visual.png');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
Binary file
|
|
@@ -7,8 +7,7 @@ const DOCS_PATH = resolve(__dirname, 'button-group.docs.json');
|
|
|
7
7
|
test.describe('button-group visual regression', () => {
|
|
8
8
|
test('all variations', async ({ page }) => {
|
|
9
9
|
await setupVisualTestFromDocs(page, DOCS_PATH);
|
|
10
|
-
|
|
11
|
-
// await validateGridRhythm(page, 'button-group');
|
|
10
|
+
await validateGridRhythm(page, 'button-group');
|
|
12
11
|
await saveForLostPixel(page, 'button-group');
|
|
13
12
|
await expect(page.locator('body')).toHaveScreenshot('button-group.visual.png');
|
|
14
13
|
});
|
|
Binary file
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
@use '../../../00-config/tokens/variables' as t;
|
|
2
|
+
|
|
3
|
+
@layer components.tokens {
|
|
4
|
+
.stat {
|
|
5
|
+
--_gap: var(--ui-stat-gap, var(--ui-space-1, #{t.$space-1}));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.stat__value {
|
|
9
|
+
--_font-size: var(--ui-stat-value-font-size, var(--ui-font-size-3xl, #{t.$font-size-3xl}));
|
|
10
|
+
--_font-weight: var(--ui-stat-value-font-weight, var(--ui-weight-bold, #{t.$weight-bold}));
|
|
11
|
+
--_line-height: var(--ui-stat-value-line-height, var(--ui-leading-3xl, #{t.$leading-3xl}));
|
|
12
|
+
--_color: var(--ui-stat-value-color, var(--ui-color-text, #{t.$color-text}));
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.stat__label {
|
|
16
|
+
--_font-size: var(--ui-stat-label-font-size, var(--ui-font-size-sm, #{t.$font-size-sm}));
|
|
17
|
+
--_color: var(--ui-stat-label-color, var(--ui-color-text-muted, #{t.$color-text-muted}));
|
|
18
|
+
--_line-height: var(--ui-stat-label-line-height, var(--ui-leading-sm, #{t.$leading-sm}));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.stat--sm .stat__value {
|
|
22
|
+
--_font-size: var(--ui-font-size-xl, #{t.$font-size-xl});
|
|
23
|
+
--_line-height: var(--ui-leading-xl, #{t.$leading-xl});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@layer components.styles {
|
|
28
|
+
.stat {
|
|
29
|
+
display: flex;
|
|
30
|
+
flex-direction: column;
|
|
31
|
+
gap: var(--_gap);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.stat__value {
|
|
35
|
+
font-size: var(--_font-size);
|
|
36
|
+
font-weight: var(--_font-weight);
|
|
37
|
+
line-height: var(--_line-height);
|
|
38
|
+
letter-spacing: var(--ui-tracking-display, #{t.$tracking-display});
|
|
39
|
+
color: var(--_color);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.stat__label {
|
|
43
|
+
font-size: var(--_font-size);
|
|
44
|
+
line-height: var(--_line-height);
|
|
45
|
+
color: var(--_color);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stat",
|
|
3
|
+
"element": "div",
|
|
4
|
+
"modifiers": {
|
|
5
|
+
"size": {
|
|
6
|
+
"values": ["sm"]
|
|
7
|
+
}
|
|
8
|
+
},
|
|
9
|
+
"subElements": ["value", "label"],
|
|
10
|
+
"cssVars": [
|
|
11
|
+
{ "name": "--ui-stat-gap", "default": "var(--ui-space-1)" },
|
|
12
|
+
{ "name": "--ui-stat-value-font-size", "default": "var(--ui-font-size-3xl)" },
|
|
13
|
+
{ "name": "--ui-stat-value-font-weight", "default": "var(--ui-weight-bold)" },
|
|
14
|
+
{ "name": "--ui-stat-value-color", "default": "var(--ui-color-text)" },
|
|
15
|
+
{ "name": "--ui-stat-label-font-size", "default": "var(--ui-font-size-sm)" },
|
|
16
|
+
{ "name": "--ui-stat-label-color", "default": "var(--ui-color-text-muted)" }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "stat",
|
|
3
|
+
"type": "component",
|
|
4
|
+
"title": "Stat",
|
|
5
|
+
"description": "Statistic display with prominent value and descriptive label.",
|
|
6
|
+
"api": "./stat.api.json",
|
|
7
|
+
"sections": [
|
|
8
|
+
{
|
|
9
|
+
"title": "Default",
|
|
10
|
+
"examples": [
|
|
11
|
+
{
|
|
12
|
+
"items": [
|
|
13
|
+
{
|
|
14
|
+
"tag": "div",
|
|
15
|
+
"class": "ui-stat",
|
|
16
|
+
"children": [
|
|
17
|
+
{ "tag": "span", "class": "ui-stat__value", "text": "2,847" },
|
|
18
|
+
{ "tag": "span", "class": "ui-stat__label", "text": "Total users" }
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
]
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"title": "Multiple stats",
|
|
27
|
+
"examples": [
|
|
28
|
+
{
|
|
29
|
+
"items": [
|
|
30
|
+
{
|
|
31
|
+
"tag": "div",
|
|
32
|
+
"class": "ui-cluster ui-cluster--lg",
|
|
33
|
+
"children": [
|
|
34
|
+
{
|
|
35
|
+
"tag": "div",
|
|
36
|
+
"class": "ui-stat",
|
|
37
|
+
"children": [
|
|
38
|
+
{ "tag": "span", "class": "ui-stat__value", "text": "12.5k" },
|
|
39
|
+
{ "tag": "span", "class": "ui-stat__label", "text": "Revenue" }
|
|
40
|
+
]
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"tag": "div",
|
|
44
|
+
"class": "ui-stat",
|
|
45
|
+
"children": [
|
|
46
|
+
{ "tag": "span", "class": "ui-stat__value", "text": "573" },
|
|
47
|
+
{ "tag": "span", "class": "ui-stat__label", "text": "Orders" }
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"tag": "div",
|
|
52
|
+
"class": "ui-stat",
|
|
53
|
+
"children": [
|
|
54
|
+
{ "tag": "span", "class": "ui-stat__value", "text": "98%" },
|
|
55
|
+
{ "tag": "span", "class": "ui-stat__label", "text": "Satisfaction" }
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
]
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"title": "Small",
|
|
66
|
+
"examples": [
|
|
67
|
+
{
|
|
68
|
+
"items": [
|
|
69
|
+
{
|
|
70
|
+
"tag": "div",
|
|
71
|
+
"class": "ui-stat ui-stat--sm",
|
|
72
|
+
"children": [
|
|
73
|
+
{ "tag": "span", "class": "ui-stat__value", "text": "42" },
|
|
74
|
+
{ "tag": "span", "class": "ui-stat__label", "text": "Active now" }
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
]
|
|
78
|
+
}
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
],
|
|
82
|
+
"customization": [
|
|
83
|
+
{
|
|
84
|
+
"token": "--ui-stat-gap",
|
|
85
|
+
"default": "var(--ui-space-1)",
|
|
86
|
+
"description": "Gap between value and label"
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"token": "--ui-stat-value-font-size",
|
|
90
|
+
"default": "var(--ui-font-size-3xl)",
|
|
91
|
+
"description": "Value font size"
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"token": "--ui-stat-value-font-weight",
|
|
95
|
+
"default": "var(--ui-weight-bold)",
|
|
96
|
+
"description": "Value font weight"
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
"token": "--ui-stat-value-color",
|
|
100
|
+
"default": "var(--ui-color-text)",
|
|
101
|
+
"description": "Value text color"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"token": "--ui-stat-label-font-size",
|
|
105
|
+
"default": "var(--ui-font-size-sm)",
|
|
106
|
+
"description": "Label font size"
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"token": "--ui-stat-label-color",
|
|
110
|
+
"default": "var(--ui-color-text-muted)",
|
|
111
|
+
"description": "Label text color"
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { expect, test } from '@playwright/test';
|
|
3
|
+
import { saveForLostPixel, setupVisualTestFromDocs, validateGridRhythm } from '../../../testing';
|
|
4
|
+
|
|
5
|
+
const DOCS_PATH = resolve(__dirname, 'stat.docs.json');
|
|
6
|
+
|
|
7
|
+
test.describe('stat visual regression', () => {
|
|
8
|
+
test('all variations', async ({ page }) => {
|
|
9
|
+
await setupVisualTestFromDocs(page, DOCS_PATH);
|
|
10
|
+
await validateGridRhythm(page, 'stat');
|
|
11
|
+
await saveForLostPixel(page, 'stat');
|
|
12
|
+
await expect(page.locator('body')).toHaveScreenshot('stat.visual.png');
|
|
13
|
+
});
|
|
14
|
+
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
@forward './data-display/card/index';
|
|
6
6
|
@forward './data-display/data-list/index';
|
|
7
7
|
@forward './data-display/icon/index';
|
|
8
|
+
@forward './data-display/stat/index';
|
|
8
9
|
@forward './data-display/status/index';
|
|
9
10
|
@forward './data-display/table/index';
|
|
10
11
|
@forward './data-display/tag/index';
|
|
@@ -26,6 +27,7 @@
|
|
|
26
27
|
@forward './forms/textarea/index';
|
|
27
28
|
@forward './forms/toggle/index';
|
|
28
29
|
@forward './layout/divider/index';
|
|
30
|
+
@forward './layout/spacer/index';
|
|
29
31
|
@forward './navigation/breadcrumb/index';
|
|
30
32
|
@forward './navigation/menu/index';
|
|
31
33
|
@forward './navigation/nav/index';
|
|
@@ -37,6 +39,9 @@
|
|
|
37
39
|
@forward './overlays/overlay/index';
|
|
38
40
|
@forward './overlays/popover/index';
|
|
39
41
|
@forward './overlays/tooltip/index';
|
|
42
|
+
@forward './typography/blockquote/index';
|
|
40
43
|
@forward './typography/code/index';
|
|
41
44
|
@forward './typography/heading/index';
|
|
45
|
+
@forward './typography/kbd/index';
|
|
42
46
|
@forward './typography/link/index';
|
|
47
|
+
@forward './typography/mark/index';
|
|
Binary file
|