@swiftwc/ui 1.0.0-canary.4 → 1.0.1-canary.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.
@@ -2,7 +2,7 @@ import { ButtonBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A control that starts an action. Styled with a standard border, adapting to the button’s surroundings.
4
4
  *
5
- * @example <button is="bordered-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a bordered button
5
+ * @example <button is="bordered-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a bordered button
6
6
  *
7
7
  * @slot overlay
8
8
  *
@@ -5,7 +5,7 @@ import { Snapshot } from '../snapshot';
5
5
  /**
6
6
  * @summary A control that starts an action. Styled with a standard border, adapting to the button’s surroundings.
7
7
  *
8
- * @example <button is="bordered-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a bordered button
8
+ * @example <button is="bordered-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a bordered button
9
9
  *
10
10
  * @slot overlay
11
11
  *
@@ -2,7 +2,7 @@ import { ButtonBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A control that starts an action. Styled with a prominent border, adapting to the button’s surroundings.
4
4
  *
5
- * @example <button is="bordered-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a prominent bordered button
5
+ * @example <button is="bordered-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a bordered prominent button
6
6
  *
7
7
  * @slot overlay
8
8
  *
@@ -5,7 +5,7 @@ import { Snapshot } from '../snapshot';
5
5
  /**
6
6
  * @summary A control that starts an action. Styled with a prominent border, adapting to the button’s surroundings.
7
7
  *
8
- * @example <button is="bordered-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a prominent bordered button
8
+ * @example <button is="bordered-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a bordered prominent button
9
9
  *
10
10
  * @slot overlay
11
11
  *
@@ -2,7 +2,7 @@ import { ButtonBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A control that starts an action. Styled without any borders.
4
4
  *
5
- * @example <button is="borderless-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a `borderless-button`
5
+ * @example <button is="borderless-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a borderless button
6
6
  *
7
7
  * @slot overlay
8
8
  *
@@ -5,7 +5,7 @@ import { Snapshot } from '../snapshot';
5
5
  /**
6
6
  * @summary A control that starts an action. Styled without any borders.
7
7
  *
8
- * @example <button is="borderless-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a `borderless-button`
8
+ * @example <button is="borderless-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a borderless button
9
9
  *
10
10
  * @slot overlay
11
11
  *
@@ -2,7 +2,7 @@ import { DetailsBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A view that shows or hides another view when the user opens or closes it.
4
4
  *
5
- * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details>
5
+ * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details> — Use the `is` attribute to convert a `details` element into a disclosure group
6
6
  *
7
7
  * @fires is-expanded
8
8
  * @fires is-collapsed
@@ -5,7 +5,7 @@ const toggleTimers = new WeakMap();
5
5
  /**
6
6
  * @summary A view that shows or hides another view when the user opens or closes it.
7
7
  *
8
- * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details>
8
+ * @example <details is="disclosure-group"><summary><label-view title="Items"></label-view></summary><label-view title="Item 1"></label-view><label-view title="Item 2"></label-view><details is="disclosure-group"><summary><label-view title="Sub-items"></label-view></summary><label-view title="Sub-item 1"></label-view></details></details> — Use the `is` attribute to convert a `details` element into a disclosure group
9
9
  *
10
10
  * @fires is-expanded
11
11
  * @fires is-collapsed
@@ -2,7 +2,7 @@ import { ButtonBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A control that starts an action. Styled with a glass border, adapting to the button’s surroundings.
4
4
  *
5
- * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a glass button
5
+ * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a glass button
6
6
  *
7
7
  * @slot overlay
8
8
  *
@@ -5,7 +5,7 @@ import { Snapshot } from '../snapshot';
5
5
  /**
6
6
  * @summary A control that starts an action. Styled with a glass border, adapting to the button’s surroundings.
7
7
  *
8
- * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a glass button
8
+ * @example <button is="glass-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a glass button
9
9
  *
10
10
  * @slot overlay
11
11
  *
@@ -2,7 +2,7 @@ import { ButtonBase } from '../namespace-browser/base';
2
2
  /**
3
3
  * @summary A control that starts an action. Styled with a prominent glass border, adapting to the button’s surroundings.
4
4
  *
5
- * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a prominent glass button
5
+ * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a prominent glass button
6
6
  *
7
7
  * @slot overlay
8
8
  *
@@ -5,7 +5,7 @@ import { Snapshot } from '../snapshot';
5
5
  /**
6
6
  * @summary A control that starts an action. Styled with a prominent glass border, adapting to the button’s surroundings.
7
7
  *
8
- * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Creating a prominent glass button
8
+ * @example <button is="glass-prominent-button"><label-view system-image="hand-tap" title="Tap Me"></label-view></button> — Use the `is` attribute to style a `button` as a prominent glass button
9
9
  *
10
10
  * @slot overlay
11
11
  *
@@ -1,5 +1,5 @@
1
1
  import { FormAssociatedBase } from '../internal/class/form-associated-base';
2
- declare const pickerStyles: readonly ["menu", "inline", "navigation-link", "sheet", "radio-group", "palette", "segmented", "automatic"];
2
+ declare const pickerStyles: readonly ["menu", "inline", "navigation-link", "sheet", "radio-group", "palette", "tabs", "automatic"];
3
3
  export type PickerStyle = (typeof pickerStyles)[number];
4
4
  export type { DictEntry, Dictionary } from '../internal/class/dict-entry';
5
5
  /**
@@ -9,7 +9,7 @@ import { queryInsertPosition, startViewTransition } from '../internal/privateNam
9
9
  import { $, ancestors, debug, kebabCase, onoff } from '../internal/utils';
10
10
  import { queryMorph } from '../morphdom';
11
11
  import { html, render } from '../tpl';
12
- const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'radio-group', 'palette', 'segmented', 'automatic'];
12
+ const pickerStyles = ['menu', 'inline', 'navigation-link', 'sheet', 'radio-group', 'palette', 'tabs', 'automatic'];
13
13
  const update = (path, node, overwrite = true) => {
14
14
  debug(`PickerView: update`);
15
15
  if (!(path instanceof NavigationPath))
@@ -311,7 +311,7 @@ export class PickerView extends FormAssociatedBase {
311
311
  this.#reflectButtons(source, menu);
312
312
  break;
313
313
  }
314
- case 'segmented':
314
+ case 'tabs':
315
315
  case 'palette':
316
316
  case 'radio-group': {
317
317
  // capture
@@ -403,7 +403,7 @@ export class PickerView extends FormAssociatedBase {
403
403
  case 'sheet':
404
404
  case 'navigation-link':
405
405
  _a.#templates.set(this.pickerStyle, $(html `
406
- <label part="root picker-stack">
406
+ <div part="root picker-stack">
407
407
  <div part="root picker-label-stack">
408
408
  <slot name="label"></slot>
409
409
  </div>
@@ -412,12 +412,12 @@ export class PickerView extends FormAssociatedBase {
412
412
  </div>
413
413
  <slot name="list" hidden></slot>
414
414
  <slot name="validity-options" hidden></slot>
415
- </label>
415
+ </div>
416
416
  `));
417
417
  break;
418
418
  case 'menu':
419
419
  _a.#templates.set(this.pickerStyle, $(html `
420
- <label part="root picker-stack">
420
+ <div part="root picker-stack">
421
421
  <div part="root picker-label-stack">
422
422
  <slot name="label"></slot>
423
423
  </div>
@@ -426,14 +426,14 @@ export class PickerView extends FormAssociatedBase {
426
426
  </div>
427
427
  <slot name="list" hidden></slot>
428
428
  <slot name="validity-options" hidden></slot>
429
- </label>
429
+ </div>
430
430
  `));
431
431
  break;
432
- case 'segmented':
432
+ case 'tabs':
433
433
  case 'palette':
434
434
  case 'radio-group':
435
435
  _a.#templates.set(this.pickerStyle, $(html `
436
- <label part="root picker-stack">
436
+ <div part="root picker-stack">
437
437
  <div part="root picker-label-stack">
438
438
  <slot name="label"></slot>
439
439
  </div>
@@ -442,7 +442,7 @@ export class PickerView extends FormAssociatedBase {
442
442
  </div>
443
443
  <slot name="list" hidden></slot>
444
444
  <slot name="validity-options" hidden></slot>
445
- </label>
445
+ </div>
446
446
  `));
447
447
  break;
448
448
  // break
@@ -615,8 +615,11 @@ export class PickerView extends FormAssociatedBase {
615
615
  CleanupRegistry.unregister(this, 'datalist'); //off1()
616
616
  CleanupRegistry.register(this, onoff('slotchange', this.#handleListSlotchange, this.#slots?.get('list')).on(), 'datalist');
617
617
  // #renderSlotted should run automatically now by slotchange initial event
618
- // switch (this.pickerStyle) {
619
- // }
618
+ switch (this.pickerStyle) {
619
+ case 'tabs':
620
+ this.setAttribute('js-init-tabs', '');
621
+ break;
622
+ }
620
623
  }
621
624
  #sendValueToForm = (dispatchEvent = true) => {
622
625
  // input.value has already been updated/synced !!
@@ -638,7 +641,7 @@ export class PickerView extends FormAssociatedBase {
638
641
  this.dispatchEvent(new CustomEvent('selection', { detail: { selection: this.#selection }, bubbles: true, composed: true }));
639
642
  };
640
643
  #handleTriggerClick = async ({ type, target }) => {
641
- debug(`${_a.name} ⚡️ ${type}`);
644
+ debug(`${_a.name} ⚡️ trigger.${type}`);
642
645
  if (!(target instanceof HTMLElement))
643
646
  return;
644
647
  this.#spawn?.remove?.();
@@ -694,7 +697,7 @@ export class PickerView extends FormAssociatedBase {
694
697
  if (!(target instanceof HTMLElement))
695
698
  return;
696
699
  switch (this.pickerStyle) {
697
- case 'segmented':
700
+ case 'tabs':
698
701
  case 'palette':
699
702
  case 'radio-group':
700
703
  const radio = target.closest('input[type="radio"]');
@@ -743,8 +746,8 @@ export class PickerView extends FormAssociatedBase {
743
746
  const tag = node.value;
744
747
  const mount = document.createElement('div');
745
748
  switch (this.pickerStyle) {
746
- case 'segmented':
747
- render(_a.#morphSegmentedBtn({ name: this.#guuid, node, tag }), mount);
749
+ case 'tabs':
750
+ render(_a.#morphTabsBtn({ name: this.#guuid, node, tag }), mount);
748
751
  return mount.firstElementChild; //btn
749
752
  case 'palette':
750
753
  render(_a.#morphPaletteBtn({ name: this.#guuid, node, tag }), mount);
@@ -782,7 +785,7 @@ export class PickerView extends FormAssociatedBase {
782
785
  }
783
786
  static #morphPaletteBtn({ name, node, tag }) {
784
787
  if ('string' === typeof tag) {
785
- const style = node.src ? `background-image: url('${node.src}')` : null;
788
+ const style = node.src ? `background-image: url('${this.#cssUrl(node.src)}')` : null;
786
789
  return html `<label tabindex="0">
787
790
  <v-stack template="auto spacer" spacing="5">
788
791
  <input type="radio" name="${name}" value="${tag}" style="${style}" />
@@ -798,37 +801,32 @@ export class PickerView extends FormAssociatedBase {
798
801
  </v-stack>
799
802
  </label>`;
800
803
  }
801
- static #morphSegmentedBtn({ name, node, tag }) {
802
- const cssUrl = (src) => {
803
- if ('string' !== typeof src)
804
- return null;
805
- try {
806
- const { protocol, href } = new URL(src, location.href);
807
- if (protocol !== 'https:' && protocol !== 'http:' && protocol !== 'blob:')
808
- return null;
809
- // URL.href already percent-encodes " < > ` space and \ in path/query.
810
- // Encode the remaining chars that matter inside url('...')
811
- return href.replace(/['()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
812
- }
813
- catch {
804
+ static #cssUrl = (src) => {
805
+ if ('string' !== typeof src)
806
+ return null;
807
+ try {
808
+ const { protocol, href } = new URL(src, location.href);
809
+ if (protocol !== 'https:' && protocol !== 'http:' && protocol !== 'blob:')
814
810
  return null;
815
- }
816
- };
811
+ // URL.href already percent-encodes " < > ` space and \ in path/query.
812
+ // Encode the remaining chars that matter inside url('...')
813
+ return href.replace(/['()]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
814
+ }
815
+ catch {
816
+ return null;
817
+ }
818
+ };
819
+ static #morphTabsBtn({ name, node, tag }) {
817
820
  if ('string' === typeof tag) {
818
- const style = node.src ? `background-image: url('${cssUrl(node.src)}')` : null;
819
821
  return html `<label tabindex="0">
820
- <v-stack template="auto spacer" spacing="5">
821
- <input type="radio" name="${name}" value="${tag}" style="${style}" />
822
- ${_a.#morphITSLabel(node)}
823
- </v-stack>
822
+ <input type="radio" name="${name}" value="${tag}" />
823
+ ${_a.#morphITSLabel(node)}
824
824
  </label>`;
825
825
  }
826
826
  else
827
827
  return html `<label>
828
- <v-stack template="auto spacer" spacing="5">
829
- <input type="radio" name="${name}" disabled />
830
- ${_a.#morphITSLabel(node)}
831
- </v-stack>
828
+ <input type="radio" name="${name}" disabled />
829
+ ${_a.#morphITSLabel(node)}
832
830
  </label>`;
833
831
  }
834
832
  static #morphITSLabel({ title, subtitle, systemImage }) {
@@ -844,8 +842,8 @@ export class PickerView extends FormAssociatedBase {
844
842
  debug(`${_a.name} #wrapOptgroupTag`);
845
843
  const mount = document.createElement('div');
846
844
  switch (this.pickerStyle) {
847
- case 'segmented':
848
- render(_a.#morphSegmentedBtn({ name: this.#guuid, node }), mount);
845
+ case 'tabs':
846
+ render(_a.#morphTabsBtn({ name: this.#guuid, node }), mount);
849
847
  return mount.firstElementChild;
850
848
  case 'palette':
851
849
  render(_a.#morphPaletteBtn({ name: this.#guuid, node }), mount);
@@ -870,8 +868,8 @@ export class PickerView extends FormAssociatedBase {
870
868
  #wrapDatalistTag(node) {
871
869
  const mount = document.createElement('div');
872
870
  switch (this.pickerStyle) {
873
- case 'segmented':
874
- render(_a.#morphSegmentedBtn({ name: this.#guuid, node }), mount);
871
+ case 'tabs':
872
+ render(_a.#morphTabsBtn({ name: this.#guuid, node }), mount);
875
873
  return mount.firstElementChild;
876
874
  case 'palette':
877
875
  render(_a.#morphPaletteBtn({ name: this.#guuid, node }), mount);
@@ -893,7 +891,7 @@ export class PickerView extends FormAssociatedBase {
893
891
  }
894
892
  #reflectButtons(nodes, container) {
895
893
  debug(`${_a.name} #reflectButtons`);
896
- const flatten = ['radio-group', 'palette', 'segmented'].includes(this.pickerStyle);
894
+ const flatten = ['radio-group', 'palette', 'tabs'].includes(this.pickerStyle);
897
895
  for (const node of nodes) {
898
896
  if (DictEntry.isLeaf(node)) {
899
897
  container.appendChild(this.#wrapOptionTag(node));
@@ -927,8 +925,7 @@ export class PickerView extends FormAssociatedBase {
927
925
  self.requestAnimationFrame(() => {
928
926
  this.ariaCurrent = this.#selection;
929
927
  const groupMap = Dictionary.index(this.#lastIndexedRoot);
930
- const groupContainsSelection = (e) => DictEntry.leafValues(e).includes(this.#selection);
931
- const syncButtons = (root) => {
928
+ const groupContainsSelection = (e) => DictEntry.leafValues(e).includes(this.#selection), syncButtons = (root) => {
932
929
  // 1. plain value buttons
933
930
  for (const el of root.querySelectorAll('button[value]:not([slot])'))
934
931
  // $.prop('visibility', el.getAttribute('value') === this.#selection ? 'visible' : 'hidden', el.querySelector<HTMLElement>('label-view[data-role="check"]'))
@@ -945,12 +942,22 @@ export class PickerView extends FormAssociatedBase {
945
942
  btn.querySelector('label-view[data-role="check"]')?.style.setProperty('visibility', hasSelectedDescendant ? 'visible' : 'hidden');
946
943
  }
947
944
  // 4. radio inputs
948
- for (const el of root.querySelectorAll('input[type=radio][value]'))
945
+ for (const el of root.querySelectorAll('input[type=radio][value]')) {
949
946
  el.checked = el.getAttribute('value') === this.#selection;
947
+ switch (this.pickerStyle) {
948
+ case 'tabs':
949
+ const label = el.closest('label');
950
+ if (!label)
951
+ break;
952
+ setTimeout(() => (label.ariaSelected = `${label.matches(':has(input[type=radio]:checked)')}`), 100);
953
+ break;
954
+ }
955
+ }
950
956
  };
951
957
  syncButtons(this);
952
958
  if (this.#spawn)
953
959
  syncButtons(this.#spawn);
960
+ setTimeout(() => this.removeAttribute('js-init-tabs'), 200);
954
961
  });
955
962
  }
956
963
  /**
@@ -129,12 +129,17 @@
129
129
  --toggle-dot-active-bg: var(--control-clear-glass-active-bg);
130
130
  --toggle-dot-active-bg-dark: var(--control-clear-glass-active-bg-dark);
131
131
  --toggle-dot-box-shadow: var(--control-clear-glass-box-shadow);
132
- --segented-picker-track-bg: red;
133
- --segented-picker-track-border-radius: var(--pill-border-radius);
134
- --segented-picker-track-block-size: 3rem;
135
- --segented-picker-track-padding-inline: 0.1rem;
136
- --segented-picker-track-padding-block: 0.1rem;
137
- --segented-picker-button-min-inline-size: 3rem;
132
+ --tabs-picker-track-gap: 0rem;
133
+ --palette-picker-track-gap: 1rem;
134
+ --radio-group-picker-track-gap: 0.2rem;
135
+ --tabs-picker-track-border-radius: var(--pill-border-radius);
136
+ --tabs-picker-track-block-size: 3rem;
137
+ --tabs-picker-track-padding-inline: 0.1rem;
138
+ --tabs-picker-track-padding-block: 0.1rem;
139
+ --tabs-picker-segment-min-inline-size: 2rem;
140
+ --tabs-picker-segment-max-inline-size: min(20rem, 100svw);
141
+ --tabs-picker-segment-padding-inline: 1rem;
142
+ --tabs-picker-segment-padding-block: 0.5rem;
138
143
  --label-footnote-font-size: 1rem;
139
144
  --label-footnote-line-height: 1.1875;
140
145
  --label-footnote-font-weight: 400;
@@ -5275,6 +5280,8 @@
5275
5280
  :where(picker-view)::part(picker-input-stack) {
5276
5281
  display: var(--picker--inputstack-display, grid);
5277
5282
  text-align: var(--picker--inputstack-text-align, );
5283
+ justify-content: var(--picker--inputstack-justify-content, );
5284
+ justify-self: var(--picker--inputstack-justify-self, );
5278
5285
  gap: var(--picker--inputstack-gap, );
5279
5286
  flex-flow: var(--picker--inputstack-flex-flow, );
5280
5287
  grid-auto-flow: var(--picker--inputstack-grid-auto-flow, );
@@ -5286,6 +5293,8 @@
5286
5293
  padding-inline: var(--picker--inputstack-padding-inline, );
5287
5294
  padding-block: var(--picker--inputstack-padding-block, );
5288
5295
  overflow: var(--picker--inputstack-overflow, );
5296
+ backdrop-filter: var(--picker--inputstack-backdrop-filter, );
5297
+ box-shadow: var(--picker--inputstack-box-shadow, );
5289
5298
  }
5290
5299
  :where(picker-view)::part(picker-label-stack) {
5291
5300
  display: var(--picker--labelstack-display, none);
@@ -5307,30 +5316,34 @@
5307
5316
  }
5308
5317
  @supports (x: if(else:red)) {
5309
5318
  :where(picker-view) {
5310
- --picker--inputstack-grid-auto-flow: if(style(--picker-style: segmented): column; );
5311
- --picker--inputstack-gap: if(style(--picker-style: segmented): 1rem; style(--picker-style: palette): 1rem; style(--picker-style: radio-group): 1rem; );
5319
+ --picker--inputstack-grid-auto-flow: if(style(--picker-style: tabs): column; );
5320
+ --picker--inputstack-gap: if(style(--picker-style: tabs): var(--tabs-picker-track-gap); style(--picker-style: palette): var(--palette-picker-track-gap); style(--picker-style: radio-group): var(--radio-group-picker-track-gap); );
5321
+ --picker--inputstack-justify-self: if(style(--picker-style: tabs): center; );
5322
+ --picker--inputstack-background: if(style(--picker-style: tabs): light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark)); );
5323
+ --picker--inputstack-backdrop-filter: if(style(--picker-style: tabs): var(--liquid-glass-backdrop-filter); );
5324
+ --picker--inputstack-box-shadow: if(style(--picker-style: tabs): var(--liquid-glass-box-shadow); );
5325
+ --picker--inputstack-border-radius: if(style(--picker-style: tabs): var(--tabs-picker-track-border-radius); );
5326
+ --picker--inputstack-position: if(style(--picker-style: tabs): relative; );
5327
+ --picker--inputstack-min-inline-size: if(style(--picker-style: tabs): calc(var(--tabs-picker-segment-min-inline-size) + 1rem); );
5328
+ --picker--inputstack-block-size: if(style(--picker-style: tabs): var(--tabs-picker-track-block-size); );
5329
+ --picker--inputstack-padding-inline: if(style(--picker-style: tabs): var(--tabs-picker-track-padding-inline); );
5330
+ --picker--inputstack-padding-block: if(style(--picker-style: tabs): var(--tabs-picker-track-padding-block); );
5331
+ --picker--inputstack-overflow: if(style(--picker-style: tabs): auto clip; );
5312
5332
  --picker--inputstack-display: if(style(--picker-style: palette): flex; );
5313
5333
  --picker--inputstack-flex-flow: if(style(--picker-style: palette): row wrap; );
5334
+ --picker--inputstack-justify-content: if(style(--picker-style: palette): start; );
5314
5335
  }
5315
5336
  :where(form picker-view) {
5316
- --picker--labelstack-display: if(style(--picker-style: segmented): grid; style(--picker-style: palette): grid; style(--picker-style: radio-group): grid; style(--picker-style: menu): grid; style(--picker-style: navigation-link): grid; style(--picker-style: sheet): grid; else: none ;);
5317
- --picker--inputstack-text-align: if(style(--picker-style: segmented): start; style(--picker-style: palette): start; style(--picker-style: radio-group): start; style(--picker-style: menu): start; style(--picker-style: navigation-link): end; style(--picker-style: sheet): end; );
5318
- --picker--inputstack-background: if(style(--picker-style: segmented): var(--segented-picker-track-bg); );
5319
- --picker--inputstack-border-radius: if(style(--picker-style: segmented): var(--segented-picker-track-border-radius); );
5320
- --picker--inputstack-position: if(style(--picker-style: segmented): relative; );
5321
- --picker--inputstack-min-inline-size: if(style(--picker-style: segmented): calc(var(--segented-picker-button-min-inline-size) + 1rem); );
5322
- --picker--inputstack-block-size: if(style(--picker-style: segmented): var(--segented-picker-track-block-size); );
5323
- --picker--inputstack-padding-inline: if(style(--picker-style: segmented): var(--segented-picker-track-padding-inline); );
5324
- --picker--inputstack-padding-block: if(style(--picker-style: segmented): var(--segented-picker-track-padding-block); );
5325
- --picker--inputstack-overflow: if(style(--picker-style: segmented): auto clip; );
5326
- --picker--host-row-gap: if(style(--picker-style: segmented): var(--labeled-content-row-gap); style(--picker-style: palette): var(--labeled-content-row-gap); style(--picker-style: radio-group): var(--labeled-content-row-gap); style(--picker-style: menu): var(--labeled-content-row-gap); style(--picker-style: navigation-link): var(--labeled-content-row-gap); style(--picker-style: sheet): var(--labeled-content-row-gap); );
5327
- --picker--host-column-gap: if(style(--picker-style: segmented): var(--labeled-content-column-gap); style(--picker-style: palette): var(--labeled-content-column-gap); style(--picker-style: radio-group): var(--labeled-content-column-gap); style(--picker-style: menu): var(--labeled-content-column-gap); style(--picker-style: navigation-link): var(--labeled-content-column-gap); style(--picker-style: sheet): var(--labeled-content-column-gap); );
5328
- --picker--host-padding-inline: if(style(--picker-style: segmented): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: palette): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: radio-group): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: menu): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: navigation-link): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: sheet): var(--itempadistart, ) var(--itempadiend, ); );
5329
- --picker--host-padding-block: if(style(--picker-style: segmented): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: palette): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: radio-group): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: menu): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: navigation-link): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: sheet): var(--itempadbstart, ) var(--itempadbend, ); );
5330
- --picker--host-border-radius: if(style(--picker-style: segmented): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: palette): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: radio-group): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: menu): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: navigation-link): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: sheet): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); );
5331
- --picker--host-background: if(style(--picker-style: segmented): var(--itemface, ); style(--picker-style: palette): var(--itemface, ); style(--picker-style: radio-group): var(--itemface, ); style(--picker-style: menu): var(--itemface, ); style(--picker-style: navigation-link): var(--itemface, ); style(--picker-style: sheet): var(--itemface, ); );
5332
- --picker--host-color: if(style(--picker-style: segmented): var(--itemtext, ); style(--picker-style: palette): var(--itemtext, ); style(--picker-style: radio-group): var(--itemtext, ); style(--picker-style: menu): var(--itemtext, ); style(--picker-style: navigation-link): var(--itemtext, ); style(--picker-style: sheet): var(--itemtext, ); );
5333
- --picker--host-border: if(style(--picker-style: segmented): var(--itemborder, ); style(--picker-style: palette): var(--itemborder, ); style(--picker-style: radio-group): var(--itemborder, ); style(--picker-style: menu): var(--itemborder, ); style(--picker-style: navigation-link): var(--itemborder, ); style(--picker-style: sheet): var(--itemborder, ); );
5337
+ --picker--labelstack-display: if(style(--picker-style: tabs): grid; style(--picker-style: palette): grid; style(--picker-style: radio-group): grid; style(--picker-style: menu): grid; style(--picker-style: navigation-link): grid; style(--picker-style: sheet): grid; else: none ;);
5338
+ --picker--inputstack-text-align: if(style(--picker-style: tabs): start; style(--picker-style: palette): start; style(--picker-style: radio-group): start; style(--picker-style: menu): start; style(--picker-style: navigation-link): end; style(--picker-style: sheet): end; );
5339
+ --picker--host-row-gap: if(style(--picker-style: tabs): var(--labeled-content-row-gap); style(--picker-style: palette): var(--labeled-content-row-gap); style(--picker-style: radio-group): var(--labeled-content-row-gap); style(--picker-style: menu): var(--labeled-content-row-gap); style(--picker-style: navigation-link): var(--labeled-content-row-gap); style(--picker-style: sheet): var(--labeled-content-row-gap); );
5340
+ --picker--host-column-gap: if(style(--picker-style: tabs): var(--labeled-content-column-gap); style(--picker-style: palette): var(--labeled-content-column-gap); style(--picker-style: radio-group): var(--labeled-content-column-gap); style(--picker-style: menu): var(--labeled-content-column-gap); style(--picker-style: navigation-link): var(--labeled-content-column-gap); style(--picker-style: sheet): var(--labeled-content-column-gap); );
5341
+ --picker--host-padding-inline: if(style(--picker-style: tabs): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: palette): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: radio-group): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: menu): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: navigation-link): var(--itempadistart, ) var(--itempadiend, ); style(--picker-style: sheet): var(--itempadistart, ) var(--itempadiend, ); );
5342
+ --picker--host-padding-block: if(style(--picker-style: tabs): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: palette): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: radio-group): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: menu): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: navigation-link): var(--itempadbstart, ) var(--itempadbend, ); style(--picker-style: sheet): var(--itempadbstart, ) var(--itempadbend, ); );
5343
+ --picker--host-border-radius: if(style(--picker-style: tabs): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: palette): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: radio-group): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: menu): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: navigation-link): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); style(--picker-style: sheet): var(--itemradiustl, ) var(--itemradiustr, ) var(--itemradiusbr, ) var(--itemradiusbl, ); );
5344
+ --picker--host-background: if(style(--picker-style: tabs): var(--itemface, ); style(--picker-style: palette): var(--itemface, ); style(--picker-style: radio-group): var(--itemface, ); style(--picker-style: menu): var(--itemface, ); style(--picker-style: navigation-link): var(--itemface, ); style(--picker-style: sheet): var(--itemface, ); );
5345
+ --picker--host-color: if(style(--picker-style: tabs): var(--itemtext, ); style(--picker-style: palette): var(--itemtext, ); style(--picker-style: radio-group): var(--itemtext, ); style(--picker-style: menu): var(--itemtext, ); style(--picker-style: navigation-link): var(--itemtext, ); style(--picker-style: sheet): var(--itemtext, ); );
5346
+ --picker--host-border: if(style(--picker-style: tabs): var(--itemborder, ); style(--picker-style: palette): var(--itemborder, ); style(--picker-style: radio-group): var(--itemborder, ); style(--picker-style: menu): var(--itemborder, ); style(--picker-style: navigation-link): var(--itemborder, ); style(--picker-style: sheet): var(--itemborder, ); );
5334
5347
  }
5335
5348
  }
5336
5349
  @supports not (x: if(else:red)) {
@@ -5339,20 +5352,32 @@
5339
5352
  @container style(--picker-style: sheet) {}
5340
5353
  @container style(--picker-style: radio-group) {
5341
5354
  :where(picker-view:not([picker-style])) {
5342
- --picker--inputstack-gap: 1rem;
5355
+ --picker--inputstack-gap: var(--radio-group-picker-track-gap);
5343
5356
  }
5344
5357
  }
5345
5358
  @container style(--picker-style: palette) {
5346
5359
  :where(picker-view:not([picker-style])) {
5347
5360
  --picker--inputstack-display: flex;
5348
5361
  --picker--inputstack-flex-flow: row wrap;
5349
- --picker--inputstack-gap: 1rem;
5362
+ --picker--inputstack-gap: var(--palette-picker-track-gap);
5363
+ --picker--inputstack-justify-content: start;
5350
5364
  }
5351
5365
  }
5352
- @container style(--picker-style: segmented) {
5366
+ @container style(--picker-style: tabs) {
5353
5367
  :where(picker-view:not([picker-style])) {
5354
5368
  --picker--inputstack-grid-auto-flow: column;
5355
- --picker--inputstack-gap: 1rem;
5369
+ --picker--inputstack-gap: var(--tabs-picker-track-gap);
5370
+ --picker--inputstack-justify-self: center;
5371
+ --picker--inputstack-background: light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark));
5372
+ --picker--inputstack-backdrop-filter: var(--liquid-glass-backdrop-filter);
5373
+ --picker--inputstack-box-shadow: var(--liquid-glass-box-shadow);
5374
+ --picker--inputstack-border-radius: var(--tabs-picker-track-border-radius);
5375
+ --picker--inputstack-position: relative;
5376
+ --picker--inputstack-min-inline-size: calc(var(--tabs-picker-segment-min-inline-size) + 1rem);
5377
+ --picker--inputstack-block-size: var(--tabs-picker-track-block-size);
5378
+ --picker--inputstack-padding-inline: var(--tabs-picker-track-padding-inline);
5379
+ --picker--inputstack-padding-block: var(--tabs-picker-track-padding-block);
5380
+ --picker--inputstack-overflow: auto clip;
5356
5381
  }
5357
5382
  }
5358
5383
  @container style(--picker-style: menu) {
@@ -5425,18 +5450,10 @@
5425
5450
  --picker--host-border: var(--itemborder, );
5426
5451
  }
5427
5452
  }
5428
- @container style(--picker-style: segmented) {
5453
+ @container style(--picker-style: tabs) {
5429
5454
  :where(form picker-view:not([picker-style])) {
5430
5455
  --picker--labelstack-display: grid;
5431
5456
  --picker--inputstack-text-align: start;
5432
- --picker--inputstack-background: var(--segented-picker-track-bg);
5433
- --picker--inputstack-border-radius: var(--segented-picker-track-border-radius);
5434
- --picker--inputstack-position: relative;
5435
- --picker--inputstack-min-inline-size: calc(var(--segented-picker-button-min-inline-size) + 1rem);
5436
- --picker--inputstack-block-size: var(--segented-picker-track-block-size);
5437
- --picker--inputstack-padding-inline: var(--segented-picker-track-padding-inline);
5438
- --picker--inputstack-padding-block: var(--segented-picker-track-padding-block);
5439
- --picker--inputstack-overflow: auto clip;
5440
5457
  --picker--host-row-gap: var(--labeled-content-row-gap);
5441
5458
  --picker--host-column-gap: var(--labeled-content-column-gap);
5442
5459
  --picker--host-padding-inline: var(--itempadistart, ) var(--itempadiend, );
@@ -5494,7 +5511,7 @@
5494
5511
  }
5495
5512
  :where(picker-view[picker-style=radio-group]) {
5496
5513
  --picker-style: radio-group;
5497
- --picker--inputstack-gap: 1rem;
5514
+ --picker--inputstack-gap: var(--radio-group-picker-track-gap);
5498
5515
  }
5499
5516
  :where(form picker-view[picker-style=radio-group]) {
5500
5517
  --picker--labelstack-display: grid;
@@ -5512,7 +5529,8 @@
5512
5529
  --picker-style: palette;
5513
5530
  --picker--inputstack-display: flex;
5514
5531
  --picker--inputstack-flex-flow: row wrap;
5515
- --picker--inputstack-gap: 1rem;
5532
+ --picker--inputstack-gap: var(--palette-picker-track-gap);
5533
+ --picker--inputstack-justify-content: start;
5516
5534
  }
5517
5535
  :where(form picker-view[picker-style=palette]) {
5518
5536
  --picker--labelstack-display: grid;
@@ -5526,22 +5544,25 @@
5526
5544
  --picker--host-color: var(--itemtext, );
5527
5545
  --picker--host-border: var(--itemborder, );
5528
5546
  }
5529
- :where(picker-view[picker-style=segmented]) {
5530
- --picker-style: segmented;
5547
+ :where(picker-view[picker-style=tabs]) {
5548
+ --picker-style: tabs;
5531
5549
  --picker--inputstack-grid-auto-flow: column;
5532
- --picker--inputstack-gap: 1rem;
5550
+ --picker--inputstack-gap: var(--tabs-picker-track-gap);
5551
+ --picker--inputstack-justify-self: center;
5552
+ --picker--inputstack-background: light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark));
5553
+ --picker--inputstack-backdrop-filter: var(--liquid-glass-backdrop-filter);
5554
+ --picker--inputstack-box-shadow: var(--liquid-glass-box-shadow);
5555
+ --picker--inputstack-border-radius: var(--tabs-picker-track-border-radius);
5556
+ --picker--inputstack-position: relative;
5557
+ --picker--inputstack-min-inline-size: calc(var(--tabs-picker-segment-min-inline-size) + 1rem);
5558
+ --picker--inputstack-block-size: var(--tabs-picker-track-block-size);
5559
+ --picker--inputstack-padding-inline: var(--tabs-picker-track-padding-inline);
5560
+ --picker--inputstack-padding-block: var(--tabs-picker-track-padding-block);
5561
+ --picker--inputstack-overflow: auto clip;
5533
5562
  }
5534
- :where(form picker-view[picker-style=segmented]) {
5563
+ :where(form picker-view[picker-style=tabs]) {
5535
5564
  --picker--labelstack-display: grid;
5536
5565
  --picker--inputstack-text-align: start;
5537
- --picker--inputstack-background: var(--segented-picker-track-bg);
5538
- --picker--inputstack-border-radius: var(--segented-picker-track-border-radius);
5539
- --picker--inputstack-position: relative;
5540
- --picker--inputstack-min-inline-size: calc(var(--segented-picker-button-min-inline-size) + 1rem);
5541
- --picker--inputstack-block-size: var(--segented-picker-track-block-size);
5542
- --picker--inputstack-padding-inline: var(--segented-picker-track-padding-inline);
5543
- --picker--inputstack-padding-block: var(--segented-picker-track-padding-block);
5544
- --picker--inputstack-overflow: auto clip;
5545
5566
  --picker--host-row-gap: var(--labeled-content-row-gap);
5546
5567
  --picker--host-column-gap: var(--labeled-content-column-gap);
5547
5568
  --picker--host-padding-inline: var(--itempadistart, ) var(--itempadiend, );
@@ -5556,6 +5577,30 @@
5556
5577
  --picker--inputstack-display: flex;
5557
5578
  --picker--inputstack-flex-flow: row wrap;
5558
5579
  }
5580
+ :where(picker-view[js-init-tabs]) {
5581
+ --tabbar-after-tabreveal-duration: 0s;
5582
+ }
5583
+ @container style(--picker-style: tabs) {
5584
+ :where(picker-view)::part(picker-input-stack)::after {
5585
+ content: "";
5586
+ display: block;
5587
+ position: absolute;
5588
+ background-color: rgba(0, 0, 0, 0.4);
5589
+ pointer-events: none;
5590
+ touch-action: none;
5591
+ position-anchor: --anchor-id;
5592
+ inset: anchor(--anchor-id top) auto auto anchor(--anchor-id left);
5593
+ inline-size: anchor-size();
5594
+ block-size: anchor-size();
5595
+ border-radius: var(--pill-border-radius);
5596
+ z-index: -1;
5597
+ }
5598
+ @media (prefers-reduced-motion: no-preference) {
5599
+ :where(picker-view)::part(picker-input-stack)::after {
5600
+ transition: block-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete, inline-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete, inset var(--tabbar-after-tabreveal-duration) ease-out allow-discrete;
5601
+ }
5602
+ }
5603
+ }
5559
5604
  @container style(--picker-style: radio-group) {
5560
5605
  picker-view > label:not([slot]) input[type=radio] {
5561
5606
  min-inline-size: 20px;
@@ -5581,22 +5626,31 @@
5581
5626
  block-size: 2rem;
5582
5627
  border-radius: 0.4rem;
5583
5628
  pointer-events: none;
5629
+ background-size: cover;
5584
5630
  transition: outline 100ms ease-out;
5585
5631
  }
5586
5632
  :where(picker-view > label:not([slot]) input[type=radio]):checked {
5587
5633
  outline: var(--accentColor) solid 0.3rem;
5588
- outline-offset: 0.1rem;
5634
+ outline-offset: 0.15rem;
5589
5635
  }
5590
5636
  }
5591
- @container style(--picker-style: segmented) {
5637
+ @container style(--picker-style: tabs) {
5592
5638
  :where(picker-view > label:not([slot])) {
5639
+ --label-line-limit: 1;
5640
+ --label-truncation-mode: tail;
5593
5641
  --label-font: callout;
5594
5642
  color: var(--secondary);
5595
- min-inline-size: var(--segented-picker-button-min-inline-size);
5596
- background-color: blue;
5597
- border-radius: inherit;
5643
+ place-content: center;
5644
+ padding-inline: var(--tabs-picker-segment-padding-inline, );
5645
+ padding-block: var(--tabs-picker-segment-padding-block, );
5646
+ min-inline-size: var(--tabs-picker-segment-min-inline-size, );
5647
+ max-inline-size: var(--tabs-picker-segment-max-inline-size, );
5648
+ border-radius: var(--tabs-picker-track-border-radius);
5598
5649
  inline-size: fit-content;
5599
- block-size: calc(var(--segented-picker-track-block-size) - var(--segented-picker-track-padding-block) * 2);
5650
+ block-size: calc(var(--tabs-picker-track-block-size) - var(--tabs-picker-track-padding-block) * 2);
5651
+ }
5652
+ :where(picker-view > label:not([slot])[aria-selected=true]) {
5653
+ anchor-name: --anchor-id;
5600
5654
  }
5601
5655
  :where(picker-view > label:not([slot]):has(input[type=radio]:not(:disabled))) {
5602
5656
  cursor: pointer;
@@ -5608,15 +5662,9 @@
5608
5662
  :where(picker-view > label:not([slot]) input[type=radio]) {
5609
5663
  appearance: none;
5610
5664
  margin: 0;
5611
- inline-size: 2rem;
5612
- block-size: 2rem;
5613
- border-radius: 0.4rem;
5665
+ visibility: collapse;
5666
+ position: absolute;
5614
5667
  pointer-events: none;
5615
- transition: outline 100ms ease-out;
5616
- }
5617
- :where(picker-view > label:not([slot]) input[type=radio]):checked {
5618
- outline: var(--accentColor) solid 0.3rem;
5619
- outline-offset: 0.1rem;
5620
5668
  }
5621
5669
  }
5622
5670
  }
package/html-data/en.json CHANGED
@@ -36,7 +36,7 @@
36
36
  "name": "title-key"
37
37
  }
38
38
  ],
39
- "description": "A control that starts an action. Styled with a standard border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface BorderedButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderedButton extends HTMLButtonElement<BorderedButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'bordered-button' // <button is=\"bordered-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Creating a bordered button:**\n```html\n<button is=\"bordered-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
39
+ "description": "A control that starts an action. Styled with a standard border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface BorderedButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderedButton extends HTMLButtonElement<BorderedButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'bordered-button' // <button is=\"bordered-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a bordered button:**\n```html\n<button is=\"bordered-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
40
40
  },
41
41
  {
42
42
  "name": "bordered-prominent-button",
@@ -63,7 +63,7 @@
63
63
  "name": "title-key"
64
64
  }
65
65
  ],
66
- "description": "A control that starts an action. Styled with a prominent border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface BorderedProminentButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderedProminentButton extends HTMLButtonElement<BorderedProminentButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'bordered-prominent-button' // <button is=\"bordered-prominent-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Creating a prominent bordered button:**\n```html\n<button is=\"bordered-prominent-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
66
+ "description": "A control that starts an action. Styled with a prominent border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface BorderedProminentButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderedProminentButton extends HTMLButtonElement<BorderedProminentButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'bordered-prominent-button' // <button is=\"bordered-prominent-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a bordered prominent button:**\n```html\n<button is=\"bordered-prominent-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
67
67
  },
68
68
  {
69
69
  "name": "borderless-button",
@@ -90,7 +90,7 @@
90
90
  "name": "title-key"
91
91
  }
92
92
  ],
93
- "description": "A control that starts an action. Styled without any borders.\n---\n\n```ts\ninterface BorderlessButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderlessButton extends HTMLButtonElement<BorderlessButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'borderless-button' // <button is=\"borderless-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a `borderless-button`:**\n```html\n<button is=\"borderless-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
93
+ "description": "A control that starts an action. Styled without any borders.\n---\n\n```ts\ninterface BorderlessButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass BorderlessButton extends HTMLButtonElement<BorderlessButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'borderless-button' // <button is=\"borderless-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a borderless button:**\n```html\n<button is=\"borderless-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
94
94
  },
95
95
  {
96
96
  "name": "color-scheme",
@@ -218,7 +218,7 @@
218
218
  "description": "Value Type: boolean\nDescription: The status of this element"
219
219
  }
220
220
  ],
221
- "description": "A view that shows or hides another view when the user opens or closes it.\n---\n\n```ts\ninterface DisclosureGroupSignature {\n Attributes: {\n open?: boolean // The status of this element\n }\n}\n\nclass DisclosureGroup extends HTMLDetailsElement<DisclosureGroupSignature> {}\n\ninterface GlobalEventMap<\n Targets = HTMLElementEventMap | DocumentEventMap | WindowEventMap,\n> {\n 'is-expanded': CustomEvent\n 'is-collapsed': CustomEvent\n}\n\ndeclare global {\n interface HTMLDetailsElement {\n is: 'disclosure-group' // <details is=\"disclosure-group\"></details>\n }\n}\n\n```\n\n### **Examples:**\n**Example:**\n```html\n<details is=\"disclosure-group\">\n <summary><label-view title=\"Items\"></label-view></summary>\n <label-view title=\"Item 1\"></label-view>\n <label-view title=\"Item 2\"></label-view>\n <details is=\"disclosure-group\">\n <summary><label-view title=\"Sub-items\"></label-view></summary>\n <label-view title=\"Sub-item 1\"></label-view>\n </details>\n</details>\n\n```\n"
221
+ "description": "A view that shows or hides another view when the user opens or closes it.\n---\n\n```ts\ninterface DisclosureGroupSignature {\n Attributes: {\n open?: boolean // The status of this element\n }\n}\n\nclass DisclosureGroup extends HTMLDetailsElement<DisclosureGroupSignature> {}\n\ninterface GlobalEventMap<\n Targets = HTMLElementEventMap | DocumentEventMap | WindowEventMap,\n> {\n 'is-expanded': CustomEvent\n 'is-collapsed': CustomEvent\n}\n\ndeclare global {\n interface HTMLDetailsElement {\n is: 'disclosure-group' // <details is=\"disclosure-group\"></details>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to convert a `details` element into a disclosure group:**\n```html\n<details is=\"disclosure-group\">\n <summary><label-view title=\"Items\"></label-view></summary>\n <label-view title=\"Item 1\"></label-view>\n <label-view title=\"Item 2\"></label-view>\n <details is=\"disclosure-group\">\n <summary><label-view title=\"Sub-items\"></label-view></summary>\n <label-view title=\"Sub-item 1\"></label-view>\n </details>\n</details>\n\n```\n"
222
222
  },
223
223
  {
224
224
  "name": "fine-tooltip",
@@ -276,7 +276,7 @@
276
276
  "name": "title-key"
277
277
  }
278
278
  ],
279
- "description": "A control that starts an action. Styled with a glass border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface GlassButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass GlassButton extends HTMLButtonElement<GlassButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'glass-button' // <button is=\"glass-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Creating a glass button:**\n```html\n<button is=\"glass-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
279
+ "description": "A control that starts an action. Styled with a glass border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface GlassButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass GlassButton extends HTMLButtonElement<GlassButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'glass-button' // <button is=\"glass-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a glass button:**\n```html\n<button is=\"glass-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
280
280
  },
281
281
  {
282
282
  "name": "glass-prominent-button",
@@ -303,7 +303,7 @@
303
303
  "name": "title-key"
304
304
  }
305
305
  ],
306
- "description": "A control that starts an action. Styled with a prominent glass border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface GlassProminentButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass GlassProminentButton extends HTMLButtonElement<GlassProminentButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'glass-prominent-button' // <button is=\"glass-prominent-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Creating a prominent glass button:**\n```html\n<button is=\"glass-prominent-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
306
+ "description": "A control that starts an action. Styled with a prominent glass border, adapting to the button’s surroundings.\n---\n\n```ts\ninterface GlassProminentButtonSignature {\n Attributes: {\n role?: 'destructive' | 'confirm' // A value that describes the purpose of a button\n 'title-key'?: string\n }\n\n Slots: {\n overlay: HTMLElement[]\n }\n}\n\nclass GlassProminentButton extends HTMLButtonElement<GlassProminentButtonSignature> {}\n\ndeclare global {\n interface HTMLButtonElement {\n is: 'glass-prominent-button' // <button is=\"glass-prominent-button\"></button>\n }\n}\n\n```\n\n### **Examples:**\n**Use the `is` attribute to style a `button` as a prominent glass button:**\n```html\n<button is=\"glass-prominent-button\">\n <label-view system-image=\"hand-tap\" title=\"Tap Me\"></label-view>\n</button>\n\n```\n"
307
307
  },
308
308
  {
309
309
  "name": "h-divider",
@@ -657,7 +657,7 @@
657
657
  "description": "Value Type: boolean"
658
658
  }
659
659
  ],
660
- "description": "A control that selects one value from a set of options.\n---\n\n```ts\ninterface PickerViewSignature {\n Attributes: {\n 'label-value-placement'?: 'vertical' | 'horizontal' | 'auto'\n 'horizontal-radio-group-layout'?: boolean\n prompt?: string\n 'prompt-icon'?: string\n label?: string\n name?: string\n 'picker-style'?:\n | 'menu'\n | 'inline'\n | 'navigation-link'\n | 'sheet'\n | 'automatic'\n selection?: string\n searchable?: boolean\n 'current-value-label'?: string\n 'current-value-icon'?: string\n help?: string // Adds a help tooltip to the trigger of the picker, if style supports one\n dictionary?: Array<DictEntry> // Renders all options using this array\n required?: boolean\n }\n\n Slots: {\n default: HTMLElement[] // The default slot\n label: HTMLElement[]\n list: HTMLElement[]\n 'validity-options': HTMLOptionElement[]\n }\n}\n\nclass PickerView extends HTMLElement<PickerViewSignature> {\n static formAssociated = true\n\n selection: string\n readonly template: DocumentFragment\n readonly pickerStyle:\n | 'automatic'\n | 'menu'\n | 'inline'\n | 'navigation-link'\n | 'sheet'\n | 'radio-group'\n | 'palette'\n | 'segmented'\n readonly name: string // Form participation property\n\n setValidity(): void\n setCustomValidity(): void\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'picker-view': PickerView // <picker-view></picker-view>\n }\n}\n\n```\n"
660
+ "description": "A control that selects one value from a set of options.\n---\n\n```ts\ninterface PickerViewSignature {\n Attributes: {\n 'label-value-placement'?: 'vertical' | 'horizontal' | 'auto'\n 'horizontal-radio-group-layout'?: boolean\n prompt?: string\n 'prompt-icon'?: string\n label?: string\n name?: string\n 'picker-style'?:\n | 'menu'\n | 'inline'\n | 'navigation-link'\n | 'sheet'\n | 'automatic'\n selection?: string\n searchable?: boolean\n 'current-value-label'?: string\n 'current-value-icon'?: string\n help?: string // Adds a help tooltip to the trigger of the picker, if style supports one\n dictionary?: Array<DictEntry> // Renders all options using this array\n required?: boolean\n }\n\n Slots: {\n default: HTMLElement[] // The default slot\n label: HTMLElement[]\n list: HTMLElement[]\n 'validity-options': HTMLOptionElement[]\n }\n}\n\nclass PickerView extends HTMLElement<PickerViewSignature> {\n static formAssociated = true\n\n selection: string\n readonly template: DocumentFragment\n readonly pickerStyle:\n | 'automatic'\n | 'menu'\n | 'inline'\n | 'navigation-link'\n | 'sheet'\n | 'radio-group'\n | 'palette'\n | 'tabs'\n readonly name: string // Form participation property\n\n setValidity(): void\n setCustomValidity(): void\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'picker-view': PickerView // <picker-view></picker-view>\n }\n}\n\n```\n"
661
661
  },
662
662
  {
663
663
  "name": "plain-button",
@@ -2701,4 +2701,4 @@
2701
2701
  ]
2702
2702
  }
2703
2703
  ]
2704
- }
2704
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@swiftwc/ui",
3
- "version": "1.0.0-canary.4",
3
+ "version": "1.0.1-canary.0",
4
4
  "description": "Elegant SwiftUI-inspired web components for standalone web apps and web extensions.",
5
5
  "publishConfig": {
6
6
  "access": "public"
package/scss/_maps.scss CHANGED
@@ -1,4 +1,4 @@
1
- $picker-styles-names: menu, navigation-link, sheet, radio-group, palette, segmented;
1
+ $picker-styles-names: menu, navigation-link, sheet, radio-group, palette, tabs;
2
2
  $label-styles-names: icon-only, title-only, title-and-icon;
3
3
  $list-styles-names: inset, inset-grouped, sidebar;
4
4
  $form-styles-names: inset, inset-grouped, sidebar;
@@ -244,12 +244,18 @@
244
244
 
245
245
  --toggle-dot-box-shadow: var(--control-clear-glass-box-shadow);
246
246
 
247
- --segented-picker-track-bg: red;
248
- --segented-picker-track-border-radius: var(--pill-border-radius);
249
- --segented-picker-track-block-size: 3rem;
250
- --segented-picker-track-padding-inline: 0.1rem;
251
- --segented-picker-track-padding-block: 0.1rem;
252
- --segented-picker-button-min-inline-size: 3rem;
247
+ --tabs-picker-track-gap: 0rem;
248
+ --palette-picker-track-gap: 1rem;
249
+ --radio-group-picker-track-gap: 0.2rem;
250
+
251
+ --tabs-picker-track-border-radius: var(--pill-border-radius);
252
+ --tabs-picker-track-block-size: 3rem;
253
+ --tabs-picker-track-padding-inline: 0.1rem;
254
+ --tabs-picker-track-padding-block: 0.1rem;
255
+ --tabs-picker-segment-min-inline-size: 2rem;
256
+ --tabs-picker-segment-max-inline-size: min(20rem, 100svw);
257
+ --tabs-picker-segment-padding-inline: 1rem;
258
+ --tabs-picker-segment-padding-block: 0.5rem;
253
259
 
254
260
  // @media (prefers-color-scheme: dark) {
255
261
  // @include dark-theme;
@@ -5,17 +5,31 @@
5
5
  @use '../mixins';
6
6
 
7
7
  $picker-ifs: (
8
- segmented: (
8
+ tabs: (
9
9
  --picker--inputstack-grid-auto-flow: column,
10
- --picker--inputstack-gap: 1rem,
10
+ --picker--inputstack-gap: var(--tabs-picker-track-gap),
11
+ --picker--inputstack-justify-self: center,
12
+ // copied from tabbar -> @mixin make-floating-tabbar
13
+ --picker--inputstack-background: light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark)),
14
+ --picker--inputstack-backdrop-filter: var(--liquid-glass-backdrop-filter),
15
+ --picker--inputstack-box-shadow: var(--liquid-glass-box-shadow),
16
+ //
17
+ --picker--inputstack-border-radius: var(--tabs-picker-track-border-radius),
18
+ --picker--inputstack-position: relative,
19
+ --picker--inputstack-min-inline-size: calc(var(--tabs-picker-segment-min-inline-size) + 1rem),
20
+ --picker--inputstack-block-size: var(--tabs-picker-track-block-size),
21
+ --picker--inputstack-padding-inline: var(--tabs-picker-track-padding-inline),
22
+ --picker--inputstack-padding-block: var(--tabs-picker-track-padding-block),
23
+ --picker--inputstack-overflow: auto clip,
11
24
  ),
12
25
  palette: (
13
26
  --picker--inputstack-display: flex,
14
27
  --picker--inputstack-flex-flow: row wrap,
15
- --picker--inputstack-gap: 1rem,
28
+ --picker--inputstack-gap: var(--palette-picker-track-gap),
29
+ --picker--inputstack-justify-content: start,
16
30
  ),
17
31
  radio-group: (
18
- --picker--inputstack-gap: 1rem,
32
+ --picker--inputstack-gap: var(--radio-group-picker-track-gap),
19
33
  ),
20
34
  menu: (),
21
35
  navigation-link: (),
@@ -24,17 +38,9 @@ $picker-ifs: (
24
38
  $picker-elses: ();
25
39
 
26
40
  $picker-inform-ifs: (
27
- segmented: (
41
+ tabs: (
28
42
  --picker--labelstack-display: grid,
29
43
  --picker--inputstack-text-align: start,
30
- --picker--inputstack-background: var(--segented-picker-track-bg),
31
- --picker--inputstack-border-radius: var(--segented-picker-track-border-radius),
32
- --picker--inputstack-position: relative,
33
- --picker--inputstack-min-inline-size: calc(var(--segented-picker-button-min-inline-size) + 1rem),
34
- --picker--inputstack-block-size: var(--segented-picker-track-block-size),
35
- --picker--inputstack-padding-inline: var(--segented-picker-track-padding-inline),
36
- --picker--inputstack-padding-block: var(--segented-picker-track-padding-block),
37
- --picker--inputstack-overflow: auto clip,
38
44
  // copy from labeled-content
39
45
  --picker--host-row-gap: var(--labeled-content-row-gap),
40
46
  --picker--host-column-gap: var(--labeled-content-column-gap),
@@ -232,6 +238,8 @@ $picker-inform-elses: (
232
238
  display: var(--picker--inputstack-display, grid);
233
239
 
234
240
  text-align: var(--picker--inputstack-text-align,);
241
+ justify-content: var(--picker--inputstack-justify-content,);
242
+ justify-self: var(--picker--inputstack-justify-self,);
235
243
 
236
244
  gap: var(--picker--inputstack-gap,);
237
245
 
@@ -248,6 +256,9 @@ $picker-inform-elses: (
248
256
  padding-block: var(--picker--inputstack-padding-block,); //0.1rem;
249
257
  overflow: var(--picker--inputstack-overflow,); //auto clip;
250
258
 
259
+ backdrop-filter: var(--picker--inputstack-backdrop-filter,);
260
+ box-shadow: var(--picker--inputstack-box-shadow,);
261
+
251
262
  // flex-shrink: var(--picker--inputstack-flex-shrink,); //none;
252
263
 
253
264
  // max-width: var(--picker--inputstack-max-width,); //70%;
@@ -399,6 +410,28 @@ $picker-inform-elses: (
399
410
  }
400
411
  }
401
412
 
413
+ :where(&[js-init-tabs]) {
414
+ // transition: all var(--tabbar-after-tabreveal-duration) ease-out allow-discrete;
415
+ --tabbar-after-tabreveal-duration: 0s;
416
+ }
417
+
418
+ @container style(--picker-style: tabs) {
419
+ :where(&)::part(picker-input-stack) {
420
+ // outline: green solid 4px;
421
+
422
+ @include mixins.make-pseudo-tracking-thumb(--anchor-id);
423
+
424
+ &::after {
425
+ @media (prefers-reduced-motion: no-preference) {
426
+ transition:
427
+ block-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete,
428
+ inline-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete,
429
+ inset var(--tabbar-after-tabreveal-duration) ease-out allow-discrete;
430
+ }
431
+ }
432
+ }
433
+ }
434
+
402
435
  > label:not([slot]) {
403
436
  @container style(--picker-style: radio-group) {
404
437
  input[type='radio'] {
@@ -440,12 +473,14 @@ $picker-inform-elses: (
440
473
 
441
474
  pointer-events: none;
442
475
 
476
+ background-size: cover;
477
+
443
478
  transition: outline 100ms ease-out;
444
479
 
445
480
  &:checked {
446
481
  outline: var(--accentColor) solid 0.3rem;
447
482
 
448
- outline-offset: 0.1rem;
483
+ outline-offset: 0.15rem;
449
484
  }
450
485
  }
451
486
  }
@@ -464,18 +499,37 @@ $picker-inform-elses: (
464
499
  // }
465
500
  }
466
501
 
467
- @container style(--picker-style: segmented) {
502
+ @container style(--picker-style: tabs) {
468
503
  :where(&) {
504
+ --label-line-limit: 1;
505
+ --label-truncation-mode: tail;
506
+
469
507
  --label-font: callout;
470
508
 
471
509
  color: var(--secondary);
472
510
 
473
- min-inline-size: var(--segented-picker-button-min-inline-size);
474
- background-color: blue;
475
- border-radius: inherit;
511
+ place-content: center;
512
+
513
+ padding-inline: var(--tabs-picker-segment-padding-inline,);
514
+
515
+ padding-block: var(--tabs-picker-segment-padding-block,);
516
+
517
+ min-inline-size: var(--tabs-picker-segment-min-inline-size,);
518
+
519
+ max-inline-size: var(--tabs-picker-segment-max-inline-size,);
520
+
521
+ border-radius: var(--tabs-picker-track-border-radius);
476
522
 
477
523
  inline-size: fit-content;
478
- block-size: calc(var(--segented-picker-track-block-size) - calc(var(--segented-picker-track-padding-block) * 2));
524
+
525
+ block-size: calc(var(--tabs-picker-track-block-size) - calc(var(--tabs-picker-track-padding-block) * 2));
526
+ }
527
+
528
+ // &:has(input:checked) {
529
+ &[aria-selected='true'] {
530
+ :where(&) {
531
+ anchor-name: --anchor-id;
532
+ }
479
533
  }
480
534
 
481
535
  &:has(input[type='radio']:not(:disabled)) {
@@ -495,21 +549,14 @@ $picker-inform-elses: (
495
549
  input[type='radio'] {
496
550
  :where(&) {
497
551
  appearance: none;
498
- margin: 0;
499
552
 
500
- inline-size: 2rem;
501
- block-size: 2rem;
502
- border-radius: 0.4rem;
553
+ margin: 0;
503
554
 
504
- pointer-events: none;
555
+ visibility: collapse;
505
556
 
506
- transition: outline 100ms ease-out;
557
+ position: absolute;
507
558
 
508
- &:checked {
509
- outline: var(--accentColor) solid 0.3rem;
510
-
511
- outline-offset: 0.1rem;
512
- }
559
+ pointer-events: none;
513
560
  }
514
561
  }
515
562
 
@@ -1,27 +1,27 @@
1
1
  @use '../vars';
2
2
  @use '../mixins';
3
3
 
4
- @mixin make-pseudo-tracking-thumb($anchor-name) {
5
- :where(&)::after {
6
- content: '';
7
- display: block;
8
- position: absolute;
9
- background-color: rgba(0, 0, 0, 0.4);
10
- pointer-events: none;
11
- touch-action: none;
4
+ // @mixin make-pseudo-tracking-thumb($anchor-name) {
5
+ // :where(&)::after {
6
+ // content: '';
7
+ // display: block;
8
+ // position: absolute;
9
+ // background-color: rgba(0, 0, 0, 0.4);
10
+ // pointer-events: none;
11
+ // touch-action: none;
12
12
 
13
- position-anchor: #{$anchor-name};
14
- // position-area: center;
15
- inset: anchor(#{$anchor-name} top) auto auto anchor(#{$anchor-name} left);
13
+ // position-anchor: #{$anchor-name};
14
+ // // position-area: center;
15
+ // inset: anchor(#{$anchor-name} top) auto auto anchor(#{$anchor-name} left);
16
16
 
17
- inline-size: anchor-size();
18
- block-size: anchor-size();
17
+ // inline-size: anchor-size();
18
+ // block-size: anchor-size();
19
19
 
20
- border-radius: var(--pill-border-radius);
20
+ // border-radius: var(--pill-border-radius);
21
21
 
22
- z-index: -1;
23
- }
24
- }
22
+ // z-index: -1;
23
+ // }
24
+ // }
25
25
 
26
26
  @mixin make-floating-tabbar {
27
27
  background: light-dark(
@@ -166,7 +166,9 @@
166
166
  }
167
167
 
168
168
  > [is='form-view'] {
169
- @include make-pseudo-tracking-thumb(--tab-view-tabbar-selection); // NOTE: before is already taken!
169
+ :where(&) {
170
+ @include mixins.make-pseudo-tracking-thumb(--tab-view-tabbar-selection); // NOTE: before is already taken!
171
+ }
170
172
 
171
173
  :where(&) {
172
174
  @include mixins.contain-overscroll;
@@ -240,7 +242,9 @@
240
242
  // ANCHOR
241
243
 
242
244
  tab-view > [is='sidebar-view'] > scroll-view {
243
- @include make-pseudo-tracking-thumb(--tab-view-sidebar-selection); // NOTE: before is already taken!
245
+ :where(&) {
246
+ @include mixins.make-pseudo-tracking-thumb(--tab-view-sidebar-selection); // NOTE: before is already taken!
247
+ }
244
248
 
245
249
  :where(&)::after {
246
250
  background-color: white;
@@ -4,6 +4,28 @@
4
4
  @use '../vars';
5
5
  @use '../functions';
6
6
 
7
+ @mixin make-pseudo-tracking-thumb($anchor-name) {
8
+ &::after {
9
+ content: '';
10
+ display: block;
11
+ position: absolute;
12
+ background-color: rgba(0, 0, 0, 0.4);
13
+ pointer-events: none;
14
+ touch-action: none;
15
+
16
+ position-anchor: #{$anchor-name};
17
+ // position-area: center;
18
+ inset: anchor(#{$anchor-name} top) auto auto anchor(#{$anchor-name} left);
19
+
20
+ inline-size: anchor-size();
21
+ block-size: anchor-size();
22
+
23
+ border-radius: var(--pill-border-radius);
24
+
25
+ z-index: -1;
26
+ }
27
+ }
28
+
7
29
  @mixin span-all {
8
30
  grid-column: 1 / -1; // span all columns
9
31
  grid-row: 1 / -1; // span all rows