@rogieking/figui3 4.5.1 → 4.6.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/README.md CHANGED
@@ -89,7 +89,9 @@ Minimal example:
89
89
  | [Tooltip](#tooltip) | `<fig-tooltip>` | Hover/click tooltip |
90
90
  | [Header](#header) | `<fig-header>` | Section header |
91
91
  | [Layer](#layer) | `<fig-layer>` | Collapsible layer list item |
92
+ | [Media](#media) | `<fig-media>` | Shared media host for image/video |
92
93
  | [Image](#image) | `<fig-image>` | Image display/upload |
94
+ | [Video](#video) | `<fig-video>` | Video display/upload with playback controls |
93
95
  | [Avatar](#avatar) | `<fig-avatar>` | Profile image or initials |
94
96
  | [Spinner](#spinner) | `<fig-spinner>` | Loading spinner |
95
97
  | [Shimmer](#shimmer) | `<fig-shimmer>` | Shimmer loading placeholder |
@@ -993,28 +995,90 @@ A collapsible layer list item with expand/collapse and visibility toggling. Supp
993
995
 
994
996
  ---
995
997
 
998
+ #### Media
999
+
1000
+ `<fig-media>`
1001
+
1002
+ Unified media component that supports image/video modes and shared sizing/upload behavior. Renders a real `<img>` or `<video>` inside the host. By default the host shrinkwraps to the inner media's intrinsic size; set `size` for a token-sized square, or `aspect-ratio` to fill the container width with a fixed ratio.
1003
+
1004
+ | Attribute | Type | Default | Description |
1005
+ |---|---|---|---|
1006
+ | `type` | string | `"image"` | `"image"` or `"video"` |
1007
+ | `src` | string | — | Media URL |
1008
+ | `alt` | string | `""` | Alt text forwarded to the generated `<img>` (image mode) |
1009
+ | `upload` | boolean | `false` | Show upload overlay (`fig-input-file`) |
1010
+ | `label` | string | `"Upload"` | Upload button label |
1011
+ | `size` | string | — | `small` \| `medium` \| `large` \| `auto` (token-sized square) |
1012
+ | `aspect-ratio` | string | — | CSS aspect-ratio (e.g. `"16 / 9"`); fills container width |
1013
+ | `fit` | string | `"contain"` | CSS object-fit (`"cover"`, `"contain"`, etc.) |
1014
+ | `checkerboard` | boolean | `false` | Show checkerboard behind transparent media |
1015
+ | `controls` | boolean | `false` | Show playback controls for video |
1016
+ | `autoplay` | boolean | `false` | Video autoplay |
1017
+ | `loop` | boolean | `false` | Video loop |
1018
+ | `muted` | boolean | `false` | Video muted |
1019
+ | `poster` | string | — | Video poster URL |
1020
+
1021
+ ```html
1022
+ <fig-media type="image" src="photo.jpg"></fig-media>
1023
+ <fig-media type="image" src="photo.jpg" aspect-ratio="16 / 9" fit="cover"></fig-media>
1024
+ <fig-media type="video" src="clip.mp4" controls muted></fig-media>
1025
+ ```
1026
+
1027
+ ---
1028
+
996
1029
  #### Image
997
1030
 
998
1031
  `<fig-image>` — [demo](https://rog.ie/figui3/#image)
999
1032
 
1000
- An image display component with optional upload, aspect ratio, and object-fit control.
1033
+ An image display component with optional upload, aspect ratio, and object-fit control. Renders a real `<img>` inside the host; by default the host shrinkwraps to the image's intrinsic size.
1001
1034
 
1002
1035
  | Attribute | Type | Default | Description |
1003
1036
  |---|---|---|---|
1004
1037
  | `src` | string | — | Image URL |
1038
+ | `alt` | string | `""` | Alt text forwarded to the generated `<img>` |
1005
1039
  | `upload` | boolean | `false` | Show upload overlay (`fig-input-file`) |
1006
1040
  | `label` | string | `"Upload"` | Upload button label |
1007
- | `aspect-ratio` | string | — | CSS aspect-ratio, or `"auto"` for lazy dimension detection |
1008
- | `fit` | string | — | CSS object-fit (`"cover"`, `"contain"`, etc.) |
1041
+ | `size` | string | — | `small` \| `medium` \| `large` \| `auto` (token-sized square) |
1042
+ | `aspect-ratio` | string | — | CSS aspect-ratio (e.g. `"16 / 9"`); fills container width |
1043
+ | `fit` | string | `"contain"` | CSS object-fit (`"cover"`, `"contain"`, etc.) |
1009
1044
  | `checkerboard` | boolean | `false` | Show checkerboard behind transparent images |
1010
1045
 
1011
1046
  ```html
1047
+ <fig-image src="photo.jpg"></fig-image>
1012
1048
  <fig-image src="photo.jpg" aspect-ratio="16 / 9" fit="cover"></fig-image>
1013
1049
  <fig-image upload label="Upload Image"></fig-image>
1014
1050
  ```
1015
1051
 
1016
1052
  ---
1017
1053
 
1054
+ #### Video
1055
+
1056
+ `<fig-video>`
1057
+
1058
+ Video display/upload component with the same host styling model as `fig-image`. Renders a real `<video>` inside the host; by default the host shrinkwraps to the video's intrinsic size.
1059
+
1060
+ | Attribute | Type | Default | Description |
1061
+ |---|---|---|---|
1062
+ | `src` | string | — | Video URL |
1063
+ | `upload` | boolean | `false` | Show upload overlay (`fig-input-file`) |
1064
+ | `label` | string | `"Upload"` | Upload button label |
1065
+ | `size` | string | — | `small` \| `medium` \| `large` \| `auto` (token-sized square) |
1066
+ | `aspect-ratio` | string | — | CSS aspect-ratio (e.g. `"16 / 9"`); fills container width |
1067
+ | `fit` | string | `"contain"` | CSS object-fit (`"cover"`, `"contain"`, etc.) |
1068
+ | `controls` | boolean | `false` | Show playback controls |
1069
+ | `autoplay` | boolean | `false` | Autoplay video |
1070
+ | `loop` | boolean | `false` | Loop video |
1071
+ | `muted` | boolean | `false` | Mute video |
1072
+ | `poster` | string | — | Poster image URL (forwarded to inner `<video>`) |
1073
+
1074
+ ```html
1075
+ <fig-video src="clip.mp4"></fig-video>
1076
+ <fig-video src="clip.mp4" aspect-ratio="16 / 9" controls></fig-video>
1077
+ <fig-video upload label="Upload Video" controls muted></fig-video>
1078
+ ```
1079
+
1080
+ ---
1081
+
1018
1082
  #### Avatar
1019
1083
 
1020
1084
  `<fig-avatar>` — [demo](https://rog.ie/figui3/#avatar)
package/base.css CHANGED
@@ -43,6 +43,20 @@ hr {
43
43
  }
44
44
  }
45
45
 
46
+ iframe{
47
+ border: 0;
48
+ background-color: transparent;
49
+ margin: 0;
50
+ width: max-content;
51
+ height: max-content;
52
+ max-width: 100%;
53
+ max-height: 100%;
54
+ width: 100%;
55
+ flex: 1 1 auto;
56
+ display: block;
57
+ min-height: 0;
58
+ }
59
+
46
60
  *,
47
61
  *:before,
48
62
  *:after {
package/components.css CHANGED
@@ -368,7 +368,7 @@
368
368
  inset 0px 0.75px 0px 0px light-dark(transparent, rgba(255, 255, 255, 0.1));
369
369
 
370
370
  --handle-shadow:
371
- 0px 0px 0px 1px rgba(0, 0, 0, 0.2),
371
+ 0px 0px 0px 1px rgba(0, 0, 0, 0.1),
372
372
  0px 0px 0.5px 0px light-dark(rgba(0, 0, 0, 0.3), rgba(255, 255, 255, 0.1)),
373
373
  0px 1px 3px 0px light-dark(rgba(0, 0, 0, 0.15), transparent);
374
374
  }
@@ -1376,17 +1376,16 @@ fig-input-file {
1376
1376
  }
1377
1377
  }
1378
1378
 
1379
- fig-image {
1379
+ fig-media,
1380
+ fig-image,
1381
+ fig-video {
1380
1382
  --image-size: 2rem;
1383
+ --media-size: var(--image-size);
1381
1384
  --fit: contain;
1382
- --image-width: var(--image-size);
1383
- --image-height: var(--image-size);
1384
1385
  --aspect-ratio: 1 / 1;
1385
1386
  display: inline-grid;
1386
1387
  place-items: center;
1387
- width: var(--image-width);
1388
- height: var(--image-height);
1389
- aspect-ratio: var(--aspect-ratio);
1388
+ max-width: 100%;
1390
1389
  > * {
1391
1390
  grid-area: 1/1;
1392
1391
  }
@@ -1396,19 +1395,50 @@ fig-image {
1396
1395
  --height: 100% !important;
1397
1396
  --padding: 0px;
1398
1397
  --chit-bg-size: var(--fit);
1398
+ z-index: 0;
1399
1399
  &[disabled] {
1400
1400
  opacity: 1;
1401
1401
  }
1402
1402
  }
1403
+ > .fig-media-element[data-generated] {
1404
+ width: auto;
1405
+ height: auto;
1406
+ max-width: 100%;
1407
+ object-fit: var(--fit);
1408
+ border-radius: var(--radius-medium);
1409
+ z-index: 1;
1410
+ }
1411
+ &:has(> .fig-media-element[data-generated][src]:not([src=""])) > fig-chit[data-generated],
1412
+ &:has(> video.fig-media-element[data-generated][poster]:not([poster=""])) > fig-chit[data-generated] {
1413
+ display: none;
1414
+ }
1415
+ &:is(:not([src]), [src=""]):is(:not([poster]), [poster=""])
1416
+ > video.fig-media-element[data-generated] {
1417
+ opacity: 0;
1418
+ pointer-events: none;
1419
+ }
1420
+ &:is(:not([src]), [src=""]) > img.fig-media-element[data-generated] {
1421
+ opacity: 0;
1422
+ pointer-events: none;
1423
+ }
1403
1424
  > fig-input-file[data-generated] {
1404
1425
  opacity: 0;
1405
1426
  pointer-events: none;
1427
+ z-index: 2;
1406
1428
  }
1407
- &:not([src]):not([src=""]) > fig-input-file[data-generated],
1429
+ &:is(:not([src]), [src=""]) > fig-input-file[data-generated],
1408
1430
  &:hover > fig-input-file[data-generated] {
1409
1431
  opacity: 1;
1410
1432
  pointer-events: all;
1411
1433
  }
1434
+ &[size] {
1435
+ width: var(--media-size);
1436
+ height: var(--media-size);
1437
+ > .fig-media-element[data-generated] {
1438
+ width: 100%;
1439
+ height: 100%;
1440
+ }
1441
+ }
1412
1442
  &[size="medium"] {
1413
1443
  --image-size: 4rem;
1414
1444
  }
@@ -1418,11 +1448,17 @@ fig-image {
1418
1448
  &[size="auto"] {
1419
1449
  --image-size: 6rem;
1420
1450
  &[full]:not([full="false"]) {
1421
- --image-width: 100%;
1451
+ width: 100%;
1422
1452
  }
1423
1453
  }
1424
1454
  &[aspect-ratio] {
1455
+ width: 100%;
1425
1456
  height: auto;
1457
+ aspect-ratio: var(--aspect-ratio);
1458
+ > .fig-media-element[data-generated] {
1459
+ width: 100%;
1460
+ height: 100%;
1461
+ }
1426
1462
  fig-chit {
1427
1463
  --size: 100% !important;
1428
1464
  height: auto !important;
@@ -2618,7 +2654,6 @@ dialog,
2618
2654
  border-radius: var(--radius-large, 0.8125rem);
2619
2655
  background: var(--figma-color-bg);
2620
2656
  min-width: var(--popover-min-width);
2621
-
2622
2657
  box-shadow: var(--figma-elevation-500-modal-window);
2623
2658
 
2624
2659
  footer,
@@ -2628,6 +2663,7 @@ dialog,
2628
2663
  padding: var(--spacer-2);
2629
2664
  gap: var(--spacer-2);
2630
2665
  }
2666
+
2631
2667
  p {
2632
2668
  padding: 0 var(--spacer-3);
2633
2669
  }
@@ -2637,6 +2673,11 @@ dialog,
2637
2673
  outline: none !important;
2638
2674
  }
2639
2675
 
2676
+ &[open]{
2677
+ display: flex;
2678
+ flex-direction: column;
2679
+ }
2680
+
2640
2681
  & header {
2641
2682
  height: var(--spacer-6);
2642
2683
  margin: 0;
@@ -2705,12 +2746,6 @@ dialog[is="fig-dialog"] {
2705
2746
  min-width: 12rem;
2706
2747
  min-height: 6rem;
2707
2748
  }
2708
- & > fig-header[dialog-header]:not([borderless]):not([borderless="false"]) {
2709
- margin-bottom: var(--spacer-2-5);
2710
- }
2711
- & > fig-footer:not([borderless]):not([borderless="false"]) {
2712
- margin-top: var(--spacer-2-5);
2713
- }
2714
2749
  }
2715
2750
 
2716
2751
  dialog[is="fig-popup"] {
@@ -2863,6 +2898,8 @@ dialog[is="fig-toast"] {
2863
2898
  }
2864
2899
  }
2865
2900
 
2901
+
2902
+
2866
2903
  /* Tooltip */
2867
2904
  fig-tooltip {
2868
2905
  display: contents;
@@ -3640,6 +3677,7 @@ fig-segmented-control {
3640
3677
  text-overflow: ellipsis;
3641
3678
  white-space: nowrap;
3642
3679
  transition: none;
3680
+ text-transform: capitalize;
3643
3681
 
3644
3682
  &[selected]:not([selected="false"]),
3645
3683
  &[selected="true"] {
@@ -4618,7 +4656,9 @@ fig-chooser {
4618
4656
  > :not(.fig-chooser-nav-start):not(.fig-chooser-nav-end) {
4619
4657
  flex: 1 1 0%;
4620
4658
  }
4621
- fig-image[full] {
4659
+ fig-media[full],
4660
+ fig-image[full],
4661
+ fig-video[full] {
4622
4662
  min-width: 3rem;
4623
4663
  }
4624
4664
  > * {
package/dist/base.css CHANGED
@@ -1 +1 @@
1
- html,:host{color:var(--figma-color-text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:var(--font-family);font-size:16px;font-weight:var(--body-medium-fontWeight);letter-spacing:var(--body-letter-spacing);background-color:var(--figma-color-bg);width:100%;height:100%;margin:0;padding:0}body,:host{font-size:var(--body-medium-fontSize);letter-spacing:var(--body-letter-spacing)}h1,h2{font-weight:var(--body-large-strong-fontWeight);font-size:var(--body-large-fontSize)}h3{font-weight:var(--body-medium-strong-fontWeight);font-size:var(--body-medium-fontSize)}hr{background-color:var(--figma-color-border);margin:var(--spacer-2)0;border:none;width:100%;height:1px}hr[vertical]{margin:0 var(--spacer-2);width:1px;height:100%}*,*:before,*:after{box-sizing:border-box}::selection{background-color:var(--figma-color-text-selection)}::selection{background-color:var(--figma-color-text-selection)}::-webkit-scrollbar{width:var(--spacer-1);height:var(--spacer-1)}::-webkit-scrollbar-thumb{background-color:var(--figma-color-bg-tertiary);border-radius:calc(var(--spacer-1)/2)}::-webkit-scrollbar-thumb:hover{background-color:var(--figma-color-bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--figma-color-bg-tertiary)var(--figma-color-bg-secondary)}.subtle{color:var(--figma-color-text-tertiary)}p{margin:var(--spacer-2)0;color:var(--figma-color-text-secondary);line-height:1rem}label{color:var(--figma-color-text-secondary)}h2{font-weight:var(--body-medium-strong-fontWeight);margin:var(--spacer-2)0}
1
+ html,:host{width:100%;height:100%;color:var(--figma-color-text);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:var(--font-family);font-size:16px;font-weight:var(--body-medium-fontWeight);letter-spacing:var(--body-letter-spacing);background-color:var(--figma-color-bg);margin:0;padding:0}body,:host{font-size:var(--body-medium-fontSize);letter-spacing:var(--body-letter-spacing)}h1,h2{font-weight:var(--body-large-strong-fontWeight);font-size:var(--body-large-fontSize)}h3{font-weight:var(--body-medium-strong-fontWeight);font-size:var(--body-medium-fontSize)}hr{background-color:var(--figma-color-border);width:100%;height:1px;margin:var(--spacer-2) 0;border:none;&[vertical]{width:1px;height:100%;margin:0 var(--spacer-2)}}iframe{background-color:#0000;border:0;flex:auto;width:100%;max-width:100%;height:max-content;min-height:0;max-height:100%;margin:0;display:block}*,:before,:after{box-sizing:border-box}::selection{background-color:var(--figma-color-text-selection)}::selection{background-color:var(--figma-color-text-selection)}::-webkit-scrollbar{width:var(--spacer-1);height:var(--spacer-1)}::-webkit-scrollbar-thumb{background-color:var(--figma-color-bg-tertiary);border-radius:calc(var(--spacer-1) / 2)}::-webkit-scrollbar-thumb:hover{background-color:var(--figma-color-bg-secondary)}*{scrollbar-width:thin;scrollbar-color:var(--figma-color-bg-tertiary) var(--figma-color-bg-secondary)}.subtle{color:var(--figma-color-text-tertiary)}p{margin:var(--spacer-2) 0;color:var(--figma-color-text-secondary);line-height:1rem}label{color:var(--figma-color-text-secondary)}h2{font-weight:var(--body-medium-strong-fontWeight);margin:var(--spacer-2) 0}