@rogieking/figui3 1.0.13 → 1.0.15
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/example.html +159 -0
- package/fig.css +55 -19
- package/fig.js +24 -13
- package/package.json +1 -1
package/example.html
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport"
|
|
7
|
+
content="width=device-width, initial-scale=1.0">
|
|
8
|
+
<title>Figma UI3 Web Components</title>
|
|
9
|
+
<link rel="stylesheet"
|
|
10
|
+
type="text/css"
|
|
11
|
+
href="fig.css">
|
|
12
|
+
<script src="fig.js"></script>
|
|
13
|
+
</head>
|
|
14
|
+
|
|
15
|
+
<body>
|
|
16
|
+
<fig-header>
|
|
17
|
+
<h3>UI3 Components</h3>
|
|
18
|
+
</fig-header>
|
|
19
|
+
<fig-content>
|
|
20
|
+
<fig-tabs>
|
|
21
|
+
<fig-tab selected>Tab #1</fig-tab>
|
|
22
|
+
<fig-tab>Tab #2</fig-tab>
|
|
23
|
+
</fig-tabs>
|
|
24
|
+
<br /><br />
|
|
25
|
+
<fig-segmented-control>
|
|
26
|
+
<fig-segment selected>One</fig-segment>
|
|
27
|
+
<fig-segment>Two</fig-segment>
|
|
28
|
+
<fig-segment>Three</fig-segment>
|
|
29
|
+
</fig-segmented-control>
|
|
30
|
+
<br /><br />
|
|
31
|
+
<hstack>
|
|
32
|
+
<fig-button>Primary</fig-button>
|
|
33
|
+
<fig-button variant="secondary">Secondary</fig-button>
|
|
34
|
+
<fig-button variant="ghost">Ghost</fig-button>
|
|
35
|
+
<fig-button variant="ghost"
|
|
36
|
+
icon="true">
|
|
37
|
+
<svg class="svg"
|
|
38
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
39
|
+
width="16"
|
|
40
|
+
height="16"
|
|
41
|
+
viewBox="0 0 16 16">
|
|
42
|
+
<path fill="currentColor"
|
|
43
|
+
fill-opacity="1"
|
|
44
|
+
fill-rule="evenodd"
|
|
45
|
+
stroke="none"
|
|
46
|
+
d="M8 3h2c1.933 0 3.5 1.567 3.5 3.5 0 1.933-1.567 3.5-3.5 3.5H4.707l2.147 2.146-.708.708-3-3-.353-.354.353-.354 3-3 .708.708L4.707 9H10c1.38 0 2.5-1.12 2.5-2.5C12.5 5.12 11.38 4 10 4H8z">
|
|
47
|
+
</path>
|
|
48
|
+
</svg>
|
|
49
|
+
</fig-button>
|
|
50
|
+
<fig-tooltip text="Toggle off/on">
|
|
51
|
+
<fig-button variant="toggle"
|
|
52
|
+
icon="true"
|
|
53
|
+
selected="true">
|
|
54
|
+
<svg width="24"
|
|
55
|
+
height="24"
|
|
56
|
+
fill="none"
|
|
57
|
+
viewBox="0 0 24 24">
|
|
58
|
+
<path fill="currentColor"
|
|
59
|
+
fill-rule="evenodd"
|
|
60
|
+
d="M9.5 7h-2a.5.5 0 0 0-.5.5v9a.5.5 0 0 0 .5.5h2a.5.5 0 0 0 .5-.5v-9a.5.5 0 0 0-.5-.5m-2-1A1.5 1.5 0 0 0 6 7.5v9A1.5 1.5 0 0 0 7.5 18h2a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 9.5 6zm9 1h-2a.5.5 0 0 0-.5.5v2a.5.5 0 0 0 .5.5h2a.5.5 0 0 0 .5-.5v-2a.5.5 0 0 0-.5-.5m-2-1A1.5 1.5 0 0 0 13 7.5v2a1.5 1.5 0 0 0 1.5 1.5h2A1.5 1.5 0 0 0 18 9.5v-2A1.5 1.5 0 0 0 16.5 6zm3.384 8.32a.5.5 0 0 0-.768-.64l-2.15 2.58-1.112-1.114a.5.5 0 0 0-.708.708l1.5 1.5a.5.5 0 0 0 .738-.034z"
|
|
61
|
+
clip-rule="evenodd"></path>
|
|
62
|
+
</svg>
|
|
63
|
+
</fig-button>
|
|
64
|
+
</fig-tooltip>
|
|
65
|
+
</hstack>
|
|
66
|
+
<br />
|
|
67
|
+
<fig-dropdown>
|
|
68
|
+
<option>One</option>
|
|
69
|
+
<option>Two</option>
|
|
70
|
+
</fig-dropdown>
|
|
71
|
+
<br />
|
|
72
|
+
<fig-tooltip text="Tooltip text">
|
|
73
|
+
<p>Tooltip</p>
|
|
74
|
+
</fig-tooltip>
|
|
75
|
+
<br /><br />
|
|
76
|
+
<hstack>
|
|
77
|
+
<input type="radio"
|
|
78
|
+
name="radio"
|
|
79
|
+
checked />
|
|
80
|
+
<input type="radio"
|
|
81
|
+
name="radio" />
|
|
82
|
+
</hstack>
|
|
83
|
+
<br /><br />
|
|
84
|
+
<fig-checkbox label="Checkbox"></fig-checkbox>
|
|
85
|
+
<br /><br />
|
|
86
|
+
<fig-radio label="Radio #1"
|
|
87
|
+
name="r1"></fig-radio>
|
|
88
|
+
<br /> <br />
|
|
89
|
+
<fig-radio label="Radio #2"
|
|
90
|
+
name="r1"></fig-radio>
|
|
91
|
+
<br /><br />
|
|
92
|
+
<vstack>
|
|
93
|
+
<fig-switch on="true"></fig-switch>
|
|
94
|
+
<fig-switch indeterminate="true"></fig-switch>
|
|
95
|
+
<fig-switch disabled></fig-switch>
|
|
96
|
+
</vstack>
|
|
97
|
+
<br /><br />
|
|
98
|
+
<fig-input-color value="#00FFFF33"
|
|
99
|
+
text="true"></fig-input-color>
|
|
100
|
+
<br /><br />
|
|
101
|
+
<fig-input-color value="#00FF00"
|
|
102
|
+
alpha="true"
|
|
103
|
+
text="true"></fig-input-color>
|
|
104
|
+
<br /><br />
|
|
105
|
+
<fig-input-text multiline="true"
|
|
106
|
+
value=""
|
|
107
|
+
autoresize="true"
|
|
108
|
+
resizable="true"
|
|
109
|
+
placeholder="Anthropic API key">
|
|
110
|
+
</fig-input-text>
|
|
111
|
+
<br />
|
|
112
|
+
<fig-input-text type="number"
|
|
113
|
+
value="10"></fig-input-text>
|
|
114
|
+
<br /><br />
|
|
115
|
+
<fig-field direction="horizontal">
|
|
116
|
+
<label>Field label</label>
|
|
117
|
+
<fig-input-text value=""
|
|
118
|
+
placeholder="Field placeholder"></fig-input-text>
|
|
119
|
+
</fig-field>
|
|
120
|
+
<fig-field>
|
|
121
|
+
<label>Label</label>
|
|
122
|
+
<fig-input-text value=""
|
|
123
|
+
placeholder="Field placeholder"></fig-input-text>
|
|
124
|
+
</fig-field>
|
|
125
|
+
<fig-slider></fig-slider>
|
|
126
|
+
<br />
|
|
127
|
+
<fig-slider text="true"
|
|
128
|
+
value="50"></fig-slider>
|
|
129
|
+
<br />
|
|
130
|
+
<fig-slider type="opacity"
|
|
131
|
+
value="0.75"
|
|
132
|
+
color="#ff0000"></fig-slider>
|
|
133
|
+
<br />
|
|
134
|
+
<fig-slider type="hue"
|
|
135
|
+
value="55"></fig-slider>
|
|
136
|
+
<br />
|
|
137
|
+
<fig-slider value="50"
|
|
138
|
+
step="25">
|
|
139
|
+
<datalist id="markers">
|
|
140
|
+
<option value="0"></option>
|
|
141
|
+
<option value="25"></option>
|
|
142
|
+
<option value="50"></option>
|
|
143
|
+
<option value="75"></option>
|
|
144
|
+
<option value="100"></option>
|
|
145
|
+
</datalist>
|
|
146
|
+
</fig-slider>
|
|
147
|
+
<br />
|
|
148
|
+
<fig-slider type="delta"
|
|
149
|
+
value="2"
|
|
150
|
+
default="0"
|
|
151
|
+
max="5"
|
|
152
|
+
min="-5"></fig-slider>
|
|
153
|
+
<br />
|
|
154
|
+
<fig-spinner></fig-spinner>
|
|
155
|
+
</fig-content>
|
|
156
|
+
|
|
157
|
+
</body>
|
|
158
|
+
|
|
159
|
+
</html>
|
package/fig.css
CHANGED
|
@@ -361,7 +361,7 @@
|
|
|
361
361
|
--bg-selected-active: #E5F4FF;
|
|
362
362
|
--bg-tooltip: #1E1E1E;
|
|
363
363
|
--body-medium-fontSize: 0.6875rem;
|
|
364
|
-
--border-selected: #0D99FF;
|
|
364
|
+
--figma-color-border-selected: #0D99FF;
|
|
365
365
|
--spacer-1: .25rem;
|
|
366
366
|
--spacer-2: .5rem;
|
|
367
367
|
--spacer-3: 1rem;
|
|
@@ -498,7 +498,7 @@ input[type=number],
|
|
|
498
498
|
color: inherit;
|
|
499
499
|
|
|
500
500
|
&:focus {
|
|
501
|
-
box-shadow: inset 0 0 0 1px var(--border-selected);
|
|
501
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
502
502
|
outline: 0;
|
|
503
503
|
}
|
|
504
504
|
|
|
@@ -563,7 +563,7 @@ input[type=text][list] {
|
|
|
563
563
|
accent-color: var(--figma-color-bg-brand);
|
|
564
564
|
|
|
565
565
|
&:focus {
|
|
566
|
-
box-shadow: inset 0 0 0 1px var(--border-selected);
|
|
566
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
567
567
|
outline: 0;
|
|
568
568
|
}
|
|
569
569
|
|
|
@@ -636,13 +636,6 @@ input[type=button] {
|
|
|
636
636
|
outline: 0;
|
|
637
637
|
background-color: var(--figma-color-bg-selected);
|
|
638
638
|
}
|
|
639
|
-
|
|
640
|
-
&:focus {
|
|
641
|
-
outline: 0;
|
|
642
|
-
background-color: transparent;
|
|
643
|
-
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
644
|
-
}
|
|
645
|
-
|
|
646
639
|
}
|
|
647
640
|
|
|
648
641
|
&[variant="ghost"][disabled=true],
|
|
@@ -731,6 +724,11 @@ input[type=button] {
|
|
|
731
724
|
color: var(--figma-color-icon-brand);
|
|
732
725
|
background-color: var(--figma-color-bg-selected);
|
|
733
726
|
}
|
|
727
|
+
|
|
728
|
+
&:focus {
|
|
729
|
+
outline: 0;
|
|
730
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
731
|
+
}
|
|
734
732
|
}
|
|
735
733
|
|
|
736
734
|
fig-button>button {
|
|
@@ -848,7 +846,7 @@ input[type=color] {
|
|
|
848
846
|
background-color: var(--figma-color-bg-secondary);
|
|
849
847
|
|
|
850
848
|
&:focus {
|
|
851
|
-
box-shadow: inset 0 0 0 1px var(--border-selected);
|
|
849
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
852
850
|
outline: 0;
|
|
853
851
|
}
|
|
854
852
|
}
|
|
@@ -987,6 +985,11 @@ input[type=checkbox]:not(.switch) {
|
|
|
987
985
|
background-color: var(--figma-color-bg-brand);
|
|
988
986
|
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.50012 7.5L7.50012 10.5L11.5001 4.5' stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.125' /%3E%3C/svg%3E%0A");
|
|
989
987
|
}
|
|
988
|
+
|
|
989
|
+
&:focus {
|
|
990
|
+
outline: 0;
|
|
991
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
992
|
+
}
|
|
990
993
|
}
|
|
991
994
|
|
|
992
995
|
.figma-light input[type=checkbox]:not(.switch):hover {
|
|
@@ -1023,8 +1026,15 @@ input[type=radio] {
|
|
|
1023
1026
|
}
|
|
1024
1027
|
|
|
1025
1028
|
&:focus {
|
|
1026
|
-
box-shadow: inset 0 0 0 1px var(--border-selected);
|
|
1027
1029
|
outline: 0;
|
|
1030
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
&:hover:not(:checked) {
|
|
1034
|
+
&::after {
|
|
1035
|
+
transform: scale(1);
|
|
1036
|
+
opacity: 0.25;
|
|
1037
|
+
}
|
|
1028
1038
|
}
|
|
1029
1039
|
|
|
1030
1040
|
&::after {
|
|
@@ -1034,7 +1044,6 @@ input[type=radio] {
|
|
|
1034
1044
|
border-radius: 0.25rem;
|
|
1035
1045
|
background-color: var(--figma-color-text-onbrand);
|
|
1036
1046
|
transform: scale(0);
|
|
1037
|
-
transition: var(--input-transition);
|
|
1038
1047
|
box-shadow:
|
|
1039
1048
|
0px 0 0 0.75px rgba(0, 0, 0, 0.1),
|
|
1040
1049
|
0px 1px 3px 0px rgba(0, 0, 0, 0.1),
|
|
@@ -1168,6 +1177,8 @@ details {
|
|
|
1168
1177
|
fig-slider {
|
|
1169
1178
|
--slider-height: 1rem;
|
|
1170
1179
|
--slider-percent: calc(var(--slider-complete) * 100%);
|
|
1180
|
+
--start-percent: calc(var(--default, 0) * 100%);
|
|
1181
|
+
--slider-tick-size: calc(var(--slider-height)/4);
|
|
1171
1182
|
--slider-handle-shadow: inset 0 0 0 4px var(--figma-color-icon-onbrand),
|
|
1172
1183
|
inset 0 0 0 5px rgba(0, 0, 0, 0.1),
|
|
1173
1184
|
0px 0 0 0.75px rgba(0, 0, 0, 0.1),
|
|
@@ -1180,7 +1191,7 @@ fig-slider {
|
|
|
1180
1191
|
0px 1px 3px 0px rgba(0, 0, 0, 0.1),
|
|
1181
1192
|
0px 3px 8px 0px rgba(0, 0, 0, 0.1),
|
|
1182
1193
|
0px 0px 0.5px 0px rgba(0, 0, 0, 0.18),
|
|
1183
|
-
0 0 0 1px var(--border-selected);
|
|
1194
|
+
0 0 0 1px var(--figma-color-border-selected);
|
|
1184
1195
|
|
|
1185
1196
|
display: inline-flex;
|
|
1186
1197
|
align-items: center;
|
|
@@ -1207,6 +1218,32 @@ fig-slider {
|
|
|
1207
1218
|
}
|
|
1208
1219
|
}
|
|
1209
1220
|
|
|
1221
|
+
/* TODO: Delta sizing */
|
|
1222
|
+
&[type=delta] {
|
|
1223
|
+
.fig-slider-input-container {
|
|
1224
|
+
&::before {
|
|
1225
|
+
--left-start: calc(var(--start-percent) - var(--slider-height)/2);
|
|
1226
|
+
left: min(var(--left-start), var(--slider-percent));
|
|
1227
|
+
--width: calc(var(--slider-percent) - var(--start-percent));
|
|
1228
|
+
--abs-width: max(var(--width) + var(--slider-height)/2, -1*var(--width) + var(--slider-height)/2);
|
|
1229
|
+
width: var(--abs-width);
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
&::after {
|
|
1233
|
+
content: '';
|
|
1234
|
+
width: var(--slider-tick-size);
|
|
1235
|
+
height: var(--slider-tick-size);
|
|
1236
|
+
aspect-ratio: 1;
|
|
1237
|
+
border-radius: 100%;
|
|
1238
|
+
font-size: 0;
|
|
1239
|
+
position: absolute;
|
|
1240
|
+
left: calc(var(--start-percent) - var(--slider-tick-size)/2);
|
|
1241
|
+
top: calc(50% - var(--slider-tick-size)/2);
|
|
1242
|
+
background: var(--figma-color-icon-tertiary);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1210
1247
|
&[type=hue],
|
|
1211
1248
|
&[type=opacity] {
|
|
1212
1249
|
.fig-slider-input-container {
|
|
@@ -1342,7 +1379,6 @@ fig-slider {
|
|
|
1342
1379
|
}
|
|
1343
1380
|
|
|
1344
1381
|
datalist {
|
|
1345
|
-
--dot-size: calc(var(--slider-height)/4);
|
|
1346
1382
|
position: absolute;
|
|
1347
1383
|
inset: 0;
|
|
1348
1384
|
display: flex;
|
|
@@ -1351,7 +1387,7 @@ fig-slider {
|
|
|
1351
1387
|
margin: 0;
|
|
1352
1388
|
border: 0;
|
|
1353
1389
|
appearance: none;
|
|
1354
|
-
padding: 0 calc((var(--slider-height)/2) - var(--
|
|
1390
|
+
padding: 0 calc((var(--slider-height)/2) - var(--slider-tick-size)/2);
|
|
1355
1391
|
height: var(--slider-height);
|
|
1356
1392
|
pointer-events: none;
|
|
1357
1393
|
justify-content: space-between;
|
|
@@ -1359,8 +1395,8 @@ fig-slider {
|
|
|
1359
1395
|
|
|
1360
1396
|
& option {
|
|
1361
1397
|
appearance: none;
|
|
1362
|
-
width: var(--
|
|
1363
|
-
height: var(--
|
|
1398
|
+
width: var(--slider-tick-size);
|
|
1399
|
+
height: var(--slider-tick-size);
|
|
1364
1400
|
aspect-ratio: 1;
|
|
1365
1401
|
margin: 0;
|
|
1366
1402
|
padding: 0;
|
|
@@ -1680,7 +1716,7 @@ fig-input-text {
|
|
|
1680
1716
|
}
|
|
1681
1717
|
|
|
1682
1718
|
&:has(input:focus) {
|
|
1683
|
-
box-shadow: inset 0 0 0 1px var(--border-selected);
|
|
1719
|
+
box-shadow: inset 0 0 0 1px var(--figma-color-border-selected);
|
|
1684
1720
|
outline: 0;
|
|
1685
1721
|
}
|
|
1686
1722
|
}
|
package/fig.js
CHANGED
|
@@ -25,6 +25,7 @@ class FigButton extends HTMLElement {
|
|
|
25
25
|
border: 0;
|
|
26
26
|
font: inherit;
|
|
27
27
|
color: inherit;
|
|
28
|
+
outline: 0;
|
|
28
29
|
background: transparent;
|
|
29
30
|
}
|
|
30
31
|
</style>
|
|
@@ -490,6 +491,7 @@ class FigSlider extends HTMLElement {
|
|
|
490
491
|
#typeDefaults = {
|
|
491
492
|
range: { min: 0, max: 100, step: 1 },
|
|
492
493
|
hue: { min: 0, max: 255, step: 1 },
|
|
494
|
+
delta: { min: -100, max: 100, step: 1 },
|
|
493
495
|
opacity: { min: 0, max: 1, step: 0.01, color: "#FF0000" }
|
|
494
496
|
}
|
|
495
497
|
constructor() {
|
|
@@ -498,6 +500,7 @@ class FigSlider extends HTMLElement {
|
|
|
498
500
|
connectedCallback() {
|
|
499
501
|
|
|
500
502
|
this.value = this.getAttribute("value")
|
|
503
|
+
this.default = this.getAttribute("default") || null
|
|
501
504
|
this.type = this.getAttribute("type") || "range"
|
|
502
505
|
|
|
503
506
|
const defaults = this.#typeDefaults[this.type]
|
|
@@ -554,6 +557,10 @@ class FigSlider extends HTMLElement {
|
|
|
554
557
|
if (this.textInput) {
|
|
555
558
|
this.textInput.addEventListener("input", this.handleTextInput.bind(this))
|
|
556
559
|
}
|
|
560
|
+
|
|
561
|
+
if (this.default) {
|
|
562
|
+
this.style.setProperty("--default", this.calculateNormal(this.default))
|
|
563
|
+
}
|
|
557
564
|
}
|
|
558
565
|
static get observedAttributes() {
|
|
559
566
|
return ['value', 'step', 'min', 'max', 'type', 'disabled']
|
|
@@ -596,13 +603,17 @@ class FigSlider extends HTMLElement {
|
|
|
596
603
|
this.handleInput()
|
|
597
604
|
}
|
|
598
605
|
}
|
|
599
|
-
|
|
600
|
-
handleInput() {
|
|
606
|
+
calculateNormal(value) {
|
|
601
607
|
let min = Number(this.input.min)
|
|
602
608
|
let max = Number(this.input.max)
|
|
609
|
+
let val = Number(value)
|
|
610
|
+
return (val - min) / (max - min)
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
handleInput() {
|
|
603
614
|
let val = Number(this.input.value)
|
|
604
615
|
this.value = val
|
|
605
|
-
let complete = (val
|
|
616
|
+
let complete = this.calculateNormal(val)
|
|
606
617
|
this.style.setProperty("--slider-complete", complete)
|
|
607
618
|
if (this.textInput) {
|
|
608
619
|
this.textInput.value = val
|
|
@@ -678,18 +689,18 @@ class FigField extends HTMLElement {
|
|
|
678
689
|
super()
|
|
679
690
|
}
|
|
680
691
|
connectedCallback() {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
692
|
+
requestAnimationFrame(() => {
|
|
693
|
+
this.label = this.querySelector('label')
|
|
694
|
+
this.input = Array.from(this.childNodes).find(node => node.nodeName.toLowerCase().startsWith("fig-"))
|
|
695
|
+
if (this.input && this.label) {
|
|
696
|
+
this.label.addEventListener('click', this.focus.bind(this))
|
|
697
|
+
let inputId = this.input.getAttribute("id") || uniqueId()
|
|
698
|
+
this.input.setAttribute("id", inputId)
|
|
699
|
+
this.label.setAttribute("for", inputId)
|
|
700
|
+
}
|
|
701
|
+
})
|
|
687
702
|
}
|
|
688
703
|
focus() {
|
|
689
|
-
if (!this.input) {
|
|
690
|
-
this.input = Array.from(this.childNodes).find(node => node.nodeName.toLowerCase().startsWith("fig-"))
|
|
691
|
-
}
|
|
692
|
-
console.log('input:', this.input)
|
|
693
704
|
this.input.focus()
|
|
694
705
|
}
|
|
695
706
|
}
|
package/package.json
CHANGED