mnfst 0.5.166 → 0.5.168

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/lib/manifest.css CHANGED
@@ -945,6 +945,217 @@
945
945
  }
946
946
  }
947
947
 
948
+ /* Manifest Chat */
949
+
950
+ @layer utilities {
951
+
952
+ :where(.chat-wrapper) {
953
+ display: flex;
954
+ flex-direction: column;
955
+ gap: 1rem;
956
+ width: 100%;
957
+ height: 100%;
958
+ box-shadow: var(--shadow);
959
+ overflow: hidden;
960
+
961
+ /* Chat log scroll container. column-reverse pins the view to the
962
+ bottom natively: new messages and a growing composer never hide
963
+ the latest message, and reading history isn't yanked on updates. */
964
+ :where([role="log"]) {
965
+ display: flex;
966
+ flex-direction: column-reverse;
967
+ flex: 1;
968
+ font-size: 0.875rem;
969
+ overflow-y: auto;
970
+
971
+ /* Message column */
972
+ > :where(div) {
973
+ display: flex;
974
+ flex-direction: column;
975
+ justify-content: flex-end;
976
+ gap: 2rem;
977
+ min-height: 100%;
978
+ width: calc(var(--spacing-content-width, 74rem) - 4rem);
979
+ max-width: 100%;
980
+ margin-inline-start: auto;
981
+ margin-inline-end: auto;
982
+ padding-inline-start: 1rem;
983
+ padding-inline-end: 1rem;
984
+ padding-block-start: 1.5rem;
985
+ padding-block-end: 5rem;
986
+ }
987
+
988
+ /* Messages */
989
+ :where(div div) {
990
+
991
+ /* Markdown spacing */
992
+ :where(p) {
993
+ margin-block: 0.5rem;
994
+ }
995
+
996
+ :where(p:first-child) {
997
+ margin-block-start: 0;
998
+ }
999
+
1000
+ :where(p:last-child) {
1001
+ margin-block-end: 0;
1002
+ }
1003
+ }
1004
+
1005
+ /* Own messages */
1006
+ :where([data-own]) {
1007
+ width: fit-content;
1008
+ max-width: calc(var(--spacing-content-width, 74rem) - 10rem);
1009
+ margin-inline-start: auto;
1010
+ padding-block: 0.5rem;
1011
+ padding-inline: 0.75rem;
1012
+ background: color-mix(in oklch, var(--color-surface-2) 50%, transparent);
1013
+ border-radius: var(--radius);
1014
+ }
1015
+
1016
+ /* Attachments */
1017
+ :where(img, video) {
1018
+ display: block;
1019
+ max-width: 20rem;
1020
+ max-height: 15rem;
1021
+ margin-block: 0.5rem;
1022
+ border-radius: var(--radius);
1023
+ }
1024
+
1025
+ :where(audio) {
1026
+ display: block;
1027
+ width: 18rem;
1028
+ max-width: 100%;
1029
+ margin-block: 0.5rem;
1030
+ }
1031
+
1032
+ :where(a[download]) {
1033
+ display: inline-flex;
1034
+ align-items: center;
1035
+ gap: 0.4rem;
1036
+ margin-block: 0.5rem;
1037
+ padding-block: 0.35rem;
1038
+ padding-inline: 0.6rem;
1039
+ background: var(--color-surface-2);
1040
+ border-radius: var(--radius);
1041
+ }
1042
+ }
1043
+
1044
+ /* Chat input */
1045
+ :where(form) {
1046
+ position: relative;
1047
+ width: var(--spacing-content-width, 74rem);
1048
+ max-width: 100%;
1049
+ margin-inline-start: auto;
1050
+ margin-inline-end: auto;
1051
+
1052
+ :where(textarea) {
1053
+ padding-inline-end: 2.5rem;
1054
+ field-sizing: content;
1055
+ resize: none;
1056
+ }
1057
+
1058
+ &:has(button[data-action="attach"]) :where(textarea) {
1059
+ padding-inline-start: 2.5rem;
1060
+ }
1061
+
1062
+ /* Submit button */
1063
+ :where(button[type="submit"]) {
1064
+ position: absolute;
1065
+ bottom: var(--spacing-field-padding, 0.625rem);
1066
+ inset-inline-end: calc(var(--spacing-field-padding, 0.625rem) * 1.3);
1067
+ }
1068
+
1069
+ /* Toolbar buttons (data-action) — attach, formatting, voice, … */
1070
+ :where(button[data-action="attach"]) {
1071
+ position: absolute;
1072
+ bottom: var(--spacing-field-padding, 0.625rem);
1073
+ inset-inline-start: calc(var(--spacing-field-padding, 0.625rem) * 1.3);
1074
+ }
1075
+
1076
+ /* Composer variant — the form itself is the field (.textarea):
1077
+ [ attachment thumbnails ]
1078
+ [ attach | growing textarea | send ] */
1079
+ &:where(.textarea) {
1080
+ display: grid;
1081
+ grid-template-columns: auto 1fr auto;
1082
+ align-items: end;
1083
+ gap: 0.25rem;
1084
+ padding: 0.375rem;
1085
+
1086
+ /* Buttons sit in-flow at the row's bottom corners */
1087
+ :where(button[type="submit"], button[data-action]) {
1088
+ position: static;
1089
+ }
1090
+
1091
+ /* The inner textarea is a bare well inside the field */
1092
+ :where(textarea) {
1093
+ padding-inline: 0.25rem;
1094
+ padding-block: 0.45rem;
1095
+
1096
+ &,
1097
+ &:hover,
1098
+ &:active,
1099
+ &:focus-visible {
1100
+ background: transparent;
1101
+ }
1102
+ }
1103
+
1104
+ /* Attachment thumbnails — removable, X-scrollable */
1105
+ :where(menu) {
1106
+ grid-column: 1 / -1;
1107
+ display: flex;
1108
+ gap: 0.5rem;
1109
+ margin: 0;
1110
+ padding: 0.375rem 0.25rem 0.125rem;
1111
+ list-style: none;
1112
+ overflow-x: auto;
1113
+
1114
+ :where(li) {
1115
+ position: relative;
1116
+ flex: 0 0 auto;
1117
+ }
1118
+
1119
+ :where(img) {
1120
+ display: block;
1121
+ width: 3.5rem;
1122
+ height: 3.5rem;
1123
+ object-fit: cover;
1124
+ border-radius: calc(var(--radius, 0.5rem) * 0.75);
1125
+ }
1126
+
1127
+ /* Non-image attachments — file chip */
1128
+ :where(li > span) {
1129
+ display: flex;
1130
+ align-items: center;
1131
+ gap: 0.3rem;
1132
+ height: 3.5rem;
1133
+ padding-inline: 0.6rem;
1134
+ font-size: 0.75rem;
1135
+ white-space: nowrap;
1136
+ background: var(--color-surface-2);
1137
+ border-radius: calc(var(--radius, 0.5rem) * 0.75);
1138
+ }
1139
+
1140
+ /* Remove button — revealed on hover/focus */
1141
+ :where(button) {
1142
+ position: absolute;
1143
+ inset-block-start: -0.35rem;
1144
+ inset-inline-end: -0.35rem;
1145
+ opacity: 0;
1146
+ transition: var(--transition, all .05s ease-in-out);
1147
+ }
1148
+
1149
+ :where(li:hover, li:focus-within) :where(button) {
1150
+ opacity: 1;
1151
+ }
1152
+ }
1153
+ }
1154
+ }
1155
+ }
1156
+
1157
+ }
1158
+
948
1159
  /* Manifest Checkboxes */
949
1160
 
950
1161
  @layer components {
@@ -1582,16 +1793,25 @@
1582
1793
  gap: var(--spacing, 0.25rem);
1583
1794
  max-width: 100%;
1584
1795
  height: calc(var(--spacing-field-height, 2.25rem) - var(--spacing, 0.25rem) * 2.5);
1796
+ margin: 0;
1797
+ padding: 0;
1585
1798
  padding-inline-start: calc(var(--spacing, 0.25rem) * 2);
1586
1799
  font-size: 0.875rem;
1800
+ line-height: normal;
1587
1801
  color: var(--color-content-stark, oklch(43.9% 0 0));
1588
1802
  background-color: var(--color-popover-surface, oklch(100% 0 0));
1803
+ border: 0;
1589
1804
  border-radius: calc(var(--radius, 0.5rem) * 0.7);
1590
1805
  overflow: hidden;
1591
1806
  user-select: none;
1592
1807
 
1593
1808
  /* Label */
1594
1809
  &>span {
1810
+ min-width: 0;
1811
+ margin: 0;
1812
+ padding: 0;
1813
+ border: 0;
1814
+ font: inherit;
1595
1815
  overflow: hidden;
1596
1816
  text-overflow: ellipsis;
1597
1817
  white-space: nowrap
@@ -1602,15 +1822,23 @@
1602
1822
  display: inline-flex;
1603
1823
  align-items: center;
1604
1824
  justify-content: center;
1825
+ box-sizing: border-box;
1826
+ flex: none;
1827
+ width: auto !important;
1605
1828
  min-width: 0;
1829
+ max-width: none;
1606
1830
  height: 100%;
1831
+ min-height: 0;
1607
1832
  aspect-ratio: 1 / 1;
1833
+ margin: 0;
1608
1834
  padding: 0;
1835
+ border: 0;
1836
+ border-radius: 0;
1609
1837
  font-size: 1em;
1610
1838
  line-height: 1;
1611
1839
  color: var(--color-content-neutral, oklch(43.9% 0 0));
1612
1840
  background: transparent;
1613
- border-radius: 0;
1841
+ box-shadow: none;
1614
1842
  cursor: pointer;
1615
1843
 
1616
1844
  &:hover {
@@ -2877,28 +3105,29 @@
2877
3105
  width: 100%
2878
3106
  }
2879
3107
 
2880
- & input {
3108
+ & input,
3109
+ & :where(label, .label):has(> button[command="--copy"]) {
2881
3110
  width: fit-content
2882
3111
  }
2883
3112
 
2884
3113
  /* Groups connect interactive elements */
2885
3114
  &:where([role=group]) {
2886
3115
 
2887
- &>:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) {
3116
+ &>:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) {
2888
3117
 
2889
3118
  /* First participant */
2890
- &:not(:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &) {
3119
+ &:not(:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &) {
2891
3120
  border-start-end-radius: 0;
2892
3121
  border-end-end-radius: 0
2893
3122
  }
2894
3123
 
2895
3124
  /* Middle participants */
2896
- &:where(:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &):has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"])) {
3125
+ &:where(:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &):has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"])) {
2897
3126
  border-radius: 0
2898
3127
  }
2899
3128
 
2900
3129
  /* Last participant */
2901
- &:not(:has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]))) {
3130
+ &:not(:has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]))) {
2902
3131
  border-start-start-radius: 0;
2903
3132
  border-end-start-radius: 0
2904
3133
  }
@@ -3027,7 +3256,7 @@
3027
3256
  }
3028
3257
 
3029
3258
  /* Label wrapper */
3030
- :where(label:not(:has(.label)), .label):has(button, [role=button], [type=button], [type=submit], select, input:not([role=button], [type=checkbox], [type=radio], [type=file], [type=search]), textarea):not(:has(data)):not(.unstyle) {
3259
+ :where(label:not(:has(.label)), .label):has(button, [role=button], [type=button], [type=submit], select, input:not([role=button], [type=checkbox], [type=radio], [type=file], [type=search]), textarea):not(:has(data)):not(:has(> button[command="--copy"])):not(.unstyle) {
3031
3260
  display: flex;
3032
3261
  flex-direction: column;
3033
3262
  gap: 0.2ch;
@@ -3096,6 +3325,18 @@
3096
3325
  background-color: transparent;
3097
3326
  cursor: default;
3098
3327
 
3328
+ /* Stack label text above the .label field when not inlined via <data> */
3329
+ &:not(:has(data)) {
3330
+ display: flex;
3331
+ flex-direction: column;
3332
+ gap: 0.2ch;
3333
+ text-indent: calc(var(--radius, 0.5rem) / 2);
3334
+
3335
+ & .label {
3336
+ text-indent: 0
3337
+ }
3338
+ }
3339
+
3099
3340
  :where([type=search]) {
3100
3341
  width: 100%;
3101
3342
  max-width: 100%
@@ -3105,9 +3346,16 @@
3105
3346
 
3106
3347
  /* Manifest Inputs */
3107
3348
 
3349
+ :root {
3350
+
3351
+ /* Copy button icons */
3352
+ --icon-field-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/g%3E%3C/svg%3E");
3353
+ --icon-field-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m12 15 2 2 4-4'/%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/g%3E%3C/svg%3E")
3354
+ }
3355
+
3108
3356
  @layer components {
3109
3357
 
3110
- :where(input:not([type=range], [type=color]), textarea, label:has([type=search], [type=file]), .label:has([type=search], [type=file])):not(.unstyle) {
3358
+ :where(input:not([type=range], [type=color]), textarea, .textarea, label:has([type=search], [type=file], > button[command="--copy"]), .label:has([type=search], [type=file], > button[command="--copy"])):not(.unstyle) {
3111
3359
  width: 100%;
3112
3360
  max-width: 100%;
3113
3361
  color: var(--color-field-inverse, oklch(43.9% 0 0));
@@ -3217,6 +3465,98 @@
3217
3465
  }
3218
3466
  }
3219
3467
 
3468
+ /* Copied confirmation icon (tooltip content) */
3469
+ :where(.field-copied-icon) {
3470
+ display: inline-block;
3471
+ vertical-align: middle;
3472
+ width: 1em;
3473
+ height: 1em;
3474
+ background-color: currentColor;
3475
+ mask-image: var(--icon-field-copied);
3476
+ mask-size: 1em;
3477
+ mask-repeat: no-repeat;
3478
+ mask-position: center;
3479
+
3480
+ /* Fill the line box so the mask centers optically */
3481
+ @supports (height: 1lh) {
3482
+ height: 1lh;
3483
+ vertical-align: top
3484
+ }
3485
+ }
3486
+
3487
+ /* Copy button icon */
3488
+ :where(button[command="--copy"]):not(.unstyle) {
3489
+
3490
+ &::after {
3491
+ content: '';
3492
+ display: block;
3493
+ width: 0.8125rem;
3494
+ height: 0.8125rem;
3495
+ background-color: var(--color-content-neutral, oklch(43.9% 0 0));
3496
+ mask-image: var(--icon-field-copy);
3497
+ mask-size: contain;
3498
+ mask-repeat: no-repeat;
3499
+ mask-position: center
3500
+ }
3501
+
3502
+ &:hover::after,
3503
+ &:active::after,
3504
+ &:focus-visible::after {
3505
+ background-color: var(--color-field-inverse, oklch(43.9% 0 0))
3506
+ }
3507
+
3508
+ &.copied::after {
3509
+ mask-image: var(--icon-field-copied)
3510
+ }
3511
+ }
3512
+
3513
+ /* Label wrapper for inputs with a copy button */
3514
+ :where(label, .label):has(> button[command="--copy"]):not(.unstyle) {
3515
+ display: flex;
3516
+ flex-flow: row;
3517
+ align-items: center;
3518
+ justify-content: start;
3519
+ padding-inline-end: 0.375rem;
3520
+
3521
+ /* Input element overrides */
3522
+ & :where(input) {
3523
+ background: transparent;
3524
+
3525
+ &:hover,
3526
+ &:focus-visible {
3527
+ background: transparent
3528
+ }
3529
+
3530
+ &:focus-visible {
3531
+ box-shadow: 0 0 0 0 transparent
3532
+ }
3533
+ }
3534
+
3535
+ /* Copy button, compact and hidden until reveal */
3536
+ & :where(button[command="--copy"]) {
3537
+ flex-shrink: 0;
3538
+ min-width: 0;
3539
+ width: calc(var(--spacing-field-height, 2.25rem) - 0.75rem);
3540
+ height: calc(var(--spacing-field-height, 2.25rem) - 0.75rem);
3541
+ padding: 0;
3542
+ background-color: transparent;
3543
+ opacity: 0;
3544
+
3545
+ &:hover,
3546
+ &:active,
3547
+ &:focus-visible {
3548
+ background-color: transparent
3549
+ }
3550
+ }
3551
+
3552
+ /* Reveal on hover, focus, or after copying */
3553
+ &:hover :where(button[command="--copy"]),
3554
+ &:focus-within :where(button[command="--copy"]),
3555
+ & :where(button[command="--copy"].copied) {
3556
+ opacity: 1
3557
+ }
3558
+ }
3559
+
3220
3560
  /* Hide search input cancel button */
3221
3561
  :where(input[type=search]):not(.unstyle)::-webkit-search-cancel-button {
3222
3562
  appearance: none;
@@ -3226,7 +3566,7 @@
3226
3566
  }
3227
3567
 
3228
3568
  /* Textarea-specific styles */
3229
- :where(textarea):not(.unstyle) {
3569
+ :where(textarea, .textarea):not(.unstyle) {
3230
3570
  display: block;
3231
3571
  height: auto;
3232
3572
  padding: var(--spacing-field-padding, 0.625rem) calc(var(--spacing-field-padding, 0.625rem) * 1.3)
@@ -22,28 +22,29 @@
22
22
  width: 100%
23
23
  }
24
24
 
25
- & input {
25
+ & input,
26
+ & :where(label, .label):has(> button[command="--copy"]) {
26
27
  width: fit-content
27
28
  }
28
29
 
29
30
  /* Groups connect interactive elements */
30
31
  &:where([role=group]) {
31
32
 
32
- &>:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) {
33
+ &>:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) {
33
34
 
34
35
  /* First participant */
35
- &:not(:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &) {
36
+ &:not(:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &) {
36
37
  border-start-end-radius: 0;
37
38
  border-end-end-radius: 0
38
39
  }
39
40
 
40
41
  /* Middle participants */
41
- &:where(:where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &):has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"])) {
42
+ &:where(:where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]) ~ &):has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"])) {
42
43
  border-radius: 0
43
44
  }
44
45
 
45
46
  /* Last participant */
46
- &:not(:has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]))) {
47
+ &:not(:has(~ :where(button, [role=button], input:not([type=hidden]), select, textarea, label:has(> button[command="--copy"]), .label:has(> button[command="--copy"])):not([hidden]):not([popover]):not(.hidden):not([style*="display: none"]))) {
47
48
  border-start-start-radius: 0;
48
49
  border-end-start-radius: 0
49
50
  }
@@ -172,7 +173,7 @@
172
173
  }
173
174
 
174
175
  /* Label wrapper */
175
- :where(label:not(:has(.label)), .label):has(button, [role=button], [type=button], [type=submit], select, input:not([role=button], [type=checkbox], [type=radio], [type=file], [type=search]), textarea):not(:has(data)):not(.unstyle) {
176
+ :where(label:not(:has(.label)), .label):has(button, [role=button], [type=button], [type=submit], select, input:not([role=button], [type=checkbox], [type=radio], [type=file], [type=search]), textarea):not(:has(data)):not(:has(> button[command="--copy"])):not(.unstyle) {
176
177
  display: flex;
177
178
  flex-direction: column;
178
179
  gap: 0.2ch;
@@ -241,6 +242,18 @@
241
242
  background-color: transparent;
242
243
  cursor: default;
243
244
 
245
+ /* Stack label text above the .label field when not inlined via <data> */
246
+ &:not(:has(data)) {
247
+ display: flex;
248
+ flex-direction: column;
249
+ gap: 0.2ch;
250
+ text-indent: calc(var(--radius, 0.5rem) / 2);
251
+
252
+ & .label {
253
+ text-indent: 0
254
+ }
255
+ }
256
+
244
257
  :where([type=search]) {
245
258
  width: 100%;
246
259
  max-width: 100%
@@ -1,8 +1,15 @@
1
1
  /* Manifest Inputs */
2
2
 
3
+ :root {
4
+
5
+ /* Copy button icons */
6
+ --icon-field-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/g%3E%3C/svg%3E");
7
+ --icon-field-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Cpath d='m12 15 2 2 4-4'/%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/g%3E%3C/svg%3E")
8
+ }
9
+
3
10
  @layer components {
4
11
 
5
- :where(input:not([type=range], [type=color]), textarea, label:has([type=search], [type=file]), .label:has([type=search], [type=file])):not(.unstyle) {
12
+ :where(input:not([type=range], [type=color]), textarea, .textarea, label:has([type=search], [type=file], > button[command="--copy"]), .label:has([type=search], [type=file], > button[command="--copy"])):not(.unstyle) {
6
13
  width: 100%;
7
14
  max-width: 100%;
8
15
  color: var(--color-field-inverse, oklch(43.9% 0 0));
@@ -112,6 +119,98 @@
112
119
  }
113
120
  }
114
121
 
122
+ /* Copied confirmation icon (tooltip content) */
123
+ :where(.field-copied-icon) {
124
+ display: inline-block;
125
+ vertical-align: middle;
126
+ width: 1em;
127
+ height: 1em;
128
+ background-color: currentColor;
129
+ mask-image: var(--icon-field-copied);
130
+ mask-size: 1em;
131
+ mask-repeat: no-repeat;
132
+ mask-position: center;
133
+
134
+ /* Fill the line box so the mask centers optically */
135
+ @supports (height: 1lh) {
136
+ height: 1lh;
137
+ vertical-align: top
138
+ }
139
+ }
140
+
141
+ /* Copy button icon */
142
+ :where(button[command="--copy"]):not(.unstyle) {
143
+
144
+ &::after {
145
+ content: '';
146
+ display: block;
147
+ width: 0.8125rem;
148
+ height: 0.8125rem;
149
+ background-color: var(--color-content-neutral, oklch(43.9% 0 0));
150
+ mask-image: var(--icon-field-copy);
151
+ mask-size: contain;
152
+ mask-repeat: no-repeat;
153
+ mask-position: center
154
+ }
155
+
156
+ &:hover::after,
157
+ &:active::after,
158
+ &:focus-visible::after {
159
+ background-color: var(--color-field-inverse, oklch(43.9% 0 0))
160
+ }
161
+
162
+ &.copied::after {
163
+ mask-image: var(--icon-field-copied)
164
+ }
165
+ }
166
+
167
+ /* Label wrapper for inputs with a copy button */
168
+ :where(label, .label):has(> button[command="--copy"]):not(.unstyle) {
169
+ display: flex;
170
+ flex-flow: row;
171
+ align-items: center;
172
+ justify-content: start;
173
+ padding-inline-end: 0.375rem;
174
+
175
+ /* Input element overrides */
176
+ & :where(input) {
177
+ background: transparent;
178
+
179
+ &:hover,
180
+ &:focus-visible {
181
+ background: transparent
182
+ }
183
+
184
+ &:focus-visible {
185
+ box-shadow: 0 0 0 0 transparent
186
+ }
187
+ }
188
+
189
+ /* Copy button, compact and hidden until reveal */
190
+ & :where(button[command="--copy"]) {
191
+ flex-shrink: 0;
192
+ min-width: 0;
193
+ width: calc(var(--spacing-field-height, 2.25rem) - 0.75rem);
194
+ height: calc(var(--spacing-field-height, 2.25rem) - 0.75rem);
195
+ padding: 0;
196
+ background-color: transparent;
197
+ opacity: 0;
198
+
199
+ &:hover,
200
+ &:active,
201
+ &:focus-visible {
202
+ background-color: transparent
203
+ }
204
+ }
205
+
206
+ /* Reveal on hover, focus, or after copying */
207
+ &:hover :where(button[command="--copy"]),
208
+ &:focus-within :where(button[command="--copy"]),
209
+ & :where(button[command="--copy"].copied) {
210
+ opacity: 1
211
+ }
212
+ }
213
+
115
214
  /* Hide search input cancel button */
116
215
  :where(input[type=search]):not(.unstyle)::-webkit-search-cancel-button {
117
216
  appearance: none;
@@ -121,7 +220,7 @@
121
220
  }
122
221
 
123
222
  /* Textarea-specific styles */
124
- :where(textarea):not(.unstyle) {
223
+ :where(textarea, .textarea):not(.unstyle) {
125
224
  display: block;
126
225
  height: auto;
127
226
  padding: var(--spacing-field-padding, 0.625rem) calc(var(--spacing-field-padding, 0.625rem) * 1.3)
@@ -1,9 +1,9 @@
1
1
  {
2
- "manifest.appwrite.auth.js": "sha384-+4T3vdzf2NsDrSpatkIqg7cO2HUnY3tNNwSgfyXCCU0NZ7K9eqX2dzhDJIlochlz",
2
+ "manifest.appwrite.auth.js": "sha384-mHMJ2sVgZ82AdmLXK6ZyUpkWyX6KOtmIf5P/ribCUb2ejtvu/lwMhB68IgAcy9po",
3
3
  "manifest.appwrite.data.js": "sha384-KFKVo5TQESLJB7wgk+C8Zb/sAl43QAMdioWW3tQRWYq5umfdpGCZ5Hld9y9f6/Np",
4
4
  "manifest.appwrite.presences.js": "sha384-JyVDWFT69b7Svq8J8p9tNWe2v9PZNQBY5UyhtOl1vnuHFAX0CRQ3MA9SiKq5wzNh",
5
5
  "manifest.charts.js": "sha384-wTQlB3hJ9V9lmisCgm8l6YkpJV+nA4+Vci3dI0x1nBtWnS9TFr+eXaJelP7AusyD",
6
- "manifest.chat.js": "sha384-lBsqJdnSC4Gclt+te4Yh5V1LXZSGn3CCeCKPwtOk5gp6UlCROigBepvaAY3NKNZp",
6
+ "manifest.chat.js": "sha384-3+eva9YYz5DrdS3DeRGw9oXH/CreuYX+ZHHtYP25vmnYDHiEpFf9nEGLvwSHBXjz",
7
7
  "manifest.code.js": "sha384-G3MNfvQRWWY+gm4SGGrSsgQbDeil9MP+ON2DTk6Rcq9Nsex8woHMDt5EJHrFH0Nj",
8
8
  "manifest.color.js": "sha384-6Rv3LxyTcZNjrhtayQfqRdCx0uSZ4BiEbgEI98I62eTvp8Aw7LBIoNJ0Je1oktwL",
9
9
  "manifest.colorpicker.js": "sha384-N5ezEwgKrDodV4YdURxhdyZKmg1n/QhqvmAC4SEG03mw1pEAZAA8Gphp+NLAOxts",
@@ -25,7 +25,7 @@
25
25
  "manifest.tabs.js": "sha384-7Kb1EHIbqh1NOl8J1NMp087lcF1gVmwm55QNM3s7JamV6sYiH/WZbdnknAZFtsfW",
26
26
  "manifest.tailwind.js": "sha384-r/Jvqb+Piz21jUts10BbVAJoKkShOdJRVFpywyi4HPIi/OfOJq5CtPyWAPbdkMgt",
27
27
  "manifest.toasts.js": "sha384-ytd5rDbax/Ou9z23uedFXPZbxDPsk2E/pxCTq4WLvfv+os1qTI6kELp0kPp07g24",
28
- "manifest.tooltips.js": "sha384-2zjZgufiF8TuXJMwb06o0kdzJ3yojhCsFrRFk+suE9ZaROTEZzQ5z9kOBmYDUDxn",
28
+ "manifest.tooltips.js": "sha384-HeJ0BGK3ebut1t8lm+MGeUUxd1pOZDyX8e6HFLsa4kAiRL+LwGDr67ckkRqv7to1",
29
29
  "manifest.url.parameters.js": "sha384-FIufiClqDx1rJpU/QUc9z/D43qClQ6Qm8rBahipbJl9BDHUvhrOsUDegmTWW7Tuf",
30
30
  "manifest.utilities.js": "sha384-MtzNaVOrgyepjlY5nz38pAJk67yiFPU1H5WoPNfcNbUZTXy+oin1lrtKCIcobEOJ",
31
31
  "manifest.virtual.js": "sha384-c194pXD0Ld48QJ+HPVNibvbn54/ETJRuYhUOWesEBjtOIQcQMIKo0DnCyQMvDlLg",