@swiftwc/ui 1.0.0-canary.4 → 1.0.0-canary.5

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.
@@ -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: 1rem;
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: 3rem;
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,7 @@
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, );
5278
5284
  gap: var(--picker--inputstack-gap, );
5279
5285
  flex-flow: var(--picker--inputstack-flex-flow, );
5280
5286
  grid-auto-flow: var(--picker--inputstack-grid-auto-flow, );
@@ -5286,6 +5292,8 @@
5286
5292
  padding-inline: var(--picker--inputstack-padding-inline, );
5287
5293
  padding-block: var(--picker--inputstack-padding-block, );
5288
5294
  overflow: var(--picker--inputstack-overflow, );
5295
+ backdrop-filter: var(--picker--inputstack-backdrop-filter, );
5296
+ box-shadow: var(--picker--inputstack-box-shadow, );
5289
5297
  }
5290
5298
  :where(picker-view)::part(picker-label-stack) {
5291
5299
  display: var(--picker--labelstack-display, none);
@@ -5307,30 +5315,33 @@
5307
5315
  }
5308
5316
  @supports (x: if(else:red)) {
5309
5317
  :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; );
5318
+ --picker--inputstack-grid-auto-flow: if(style(--picker-style: tabs): column; );
5319
+ --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); );
5320
+ --picker--inputstack-justify-content: if(style(--picker-style: tabs): start; style(--picker-style: palette): start; );
5321
+ --picker--inputstack-background: if(style(--picker-style: tabs): light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark)); );
5322
+ --picker--inputstack-backdrop-filter: if(style(--picker-style: tabs): var(--liquid-glass-backdrop-filter); );
5323
+ --picker--inputstack-box-shadow: if(style(--picker-style: tabs): var(--liquid-glass-box-shadow); );
5324
+ --picker--inputstack-border-radius: if(style(--picker-style: tabs): var(--tabs-picker-track-border-radius); );
5325
+ --picker--inputstack-position: if(style(--picker-style: tabs): relative; );
5326
+ --picker--inputstack-min-inline-size: if(style(--picker-style: tabs): calc(var(--tabs-picker-segment-min-inline-size) + 1rem); );
5327
+ --picker--inputstack-block-size: if(style(--picker-style: tabs): var(--tabs-picker-track-block-size); );
5328
+ --picker--inputstack-padding-inline: if(style(--picker-style: tabs): var(--tabs-picker-track-padding-inline); );
5329
+ --picker--inputstack-padding-block: if(style(--picker-style: tabs): var(--tabs-picker-track-padding-block); );
5330
+ --picker--inputstack-overflow: if(style(--picker-style: tabs): auto clip; );
5312
5331
  --picker--inputstack-display: if(style(--picker-style: palette): flex; );
5313
5332
  --picker--inputstack-flex-flow: if(style(--picker-style: palette): row wrap; );
5314
5333
  }
5315
5334
  :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, ); );
5335
+ --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 ;);
5336
+ --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; );
5337
+ --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); );
5338
+ --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); );
5339
+ --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, ); );
5340
+ --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, ); );
5341
+ --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, ); );
5342
+ --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, ); );
5343
+ --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, ); );
5344
+ --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
5345
  }
5335
5346
  }
5336
5347
  @supports not (x: if(else:red)) {
@@ -5339,20 +5350,32 @@
5339
5350
  @container style(--picker-style: sheet) {}
5340
5351
  @container style(--picker-style: radio-group) {
5341
5352
  :where(picker-view:not([picker-style])) {
5342
- --picker--inputstack-gap: 1rem;
5353
+ --picker--inputstack-gap: var(--radio-group-picker-track-gap);
5343
5354
  }
5344
5355
  }
5345
5356
  @container style(--picker-style: palette) {
5346
5357
  :where(picker-view:not([picker-style])) {
5347
5358
  --picker--inputstack-display: flex;
5348
5359
  --picker--inputstack-flex-flow: row wrap;
5349
- --picker--inputstack-gap: 1rem;
5360
+ --picker--inputstack-gap: var(--palette-picker-track-gap);
5361
+ --picker--inputstack-justify-content: start;
5350
5362
  }
5351
5363
  }
5352
- @container style(--picker-style: segmented) {
5364
+ @container style(--picker-style: tabs) {
5353
5365
  :where(picker-view:not([picker-style])) {
5354
5366
  --picker--inputstack-grid-auto-flow: column;
5355
- --picker--inputstack-gap: 1rem;
5367
+ --picker--inputstack-gap: var(--tabs-picker-track-gap);
5368
+ --picker--inputstack-justify-content: start;
5369
+ --picker--inputstack-background: light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark));
5370
+ --picker--inputstack-backdrop-filter: var(--liquid-glass-backdrop-filter);
5371
+ --picker--inputstack-box-shadow: var(--liquid-glass-box-shadow);
5372
+ --picker--inputstack-border-radius: var(--tabs-picker-track-border-radius);
5373
+ --picker--inputstack-position: relative;
5374
+ --picker--inputstack-min-inline-size: calc(var(--tabs-picker-segment-min-inline-size) + 1rem);
5375
+ --picker--inputstack-block-size: var(--tabs-picker-track-block-size);
5376
+ --picker--inputstack-padding-inline: var(--tabs-picker-track-padding-inline);
5377
+ --picker--inputstack-padding-block: var(--tabs-picker-track-padding-block);
5378
+ --picker--inputstack-overflow: auto clip;
5356
5379
  }
5357
5380
  }
5358
5381
  @container style(--picker-style: menu) {
@@ -5425,18 +5448,10 @@
5425
5448
  --picker--host-border: var(--itemborder, );
5426
5449
  }
5427
5450
  }
5428
- @container style(--picker-style: segmented) {
5451
+ @container style(--picker-style: tabs) {
5429
5452
  :where(form picker-view:not([picker-style])) {
5430
5453
  --picker--labelstack-display: grid;
5431
5454
  --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
5455
  --picker--host-row-gap: var(--labeled-content-row-gap);
5441
5456
  --picker--host-column-gap: var(--labeled-content-column-gap);
5442
5457
  --picker--host-padding-inline: var(--itempadistart, ) var(--itempadiend, );
@@ -5494,7 +5509,7 @@
5494
5509
  }
5495
5510
  :where(picker-view[picker-style=radio-group]) {
5496
5511
  --picker-style: radio-group;
5497
- --picker--inputstack-gap: 1rem;
5512
+ --picker--inputstack-gap: var(--radio-group-picker-track-gap);
5498
5513
  }
5499
5514
  :where(form picker-view[picker-style=radio-group]) {
5500
5515
  --picker--labelstack-display: grid;
@@ -5512,7 +5527,8 @@
5512
5527
  --picker-style: palette;
5513
5528
  --picker--inputstack-display: flex;
5514
5529
  --picker--inputstack-flex-flow: row wrap;
5515
- --picker--inputstack-gap: 1rem;
5530
+ --picker--inputstack-gap: var(--palette-picker-track-gap);
5531
+ --picker--inputstack-justify-content: start;
5516
5532
  }
5517
5533
  :where(form picker-view[picker-style=palette]) {
5518
5534
  --picker--labelstack-display: grid;
@@ -5526,22 +5542,25 @@
5526
5542
  --picker--host-color: var(--itemtext, );
5527
5543
  --picker--host-border: var(--itemborder, );
5528
5544
  }
5529
- :where(picker-view[picker-style=segmented]) {
5530
- --picker-style: segmented;
5545
+ :where(picker-view[picker-style=tabs]) {
5546
+ --picker-style: tabs;
5531
5547
  --picker--inputstack-grid-auto-flow: column;
5532
- --picker--inputstack-gap: 1rem;
5548
+ --picker--inputstack-gap: var(--tabs-picker-track-gap);
5549
+ --picker--inputstack-justify-content: start;
5550
+ --picker--inputstack-background: light-dark(var(--liquid-glass-bg), var(--liquid-glass-bg-dark));
5551
+ --picker--inputstack-backdrop-filter: var(--liquid-glass-backdrop-filter);
5552
+ --picker--inputstack-box-shadow: var(--liquid-glass-box-shadow);
5553
+ --picker--inputstack-border-radius: var(--tabs-picker-track-border-radius);
5554
+ --picker--inputstack-position: relative;
5555
+ --picker--inputstack-min-inline-size: calc(var(--tabs-picker-segment-min-inline-size) + 1rem);
5556
+ --picker--inputstack-block-size: var(--tabs-picker-track-block-size);
5557
+ --picker--inputstack-padding-inline: var(--tabs-picker-track-padding-inline);
5558
+ --picker--inputstack-padding-block: var(--tabs-picker-track-padding-block);
5559
+ --picker--inputstack-overflow: auto clip;
5533
5560
  }
5534
- :where(form picker-view[picker-style=segmented]) {
5561
+ :where(form picker-view[picker-style=tabs]) {
5535
5562
  --picker--labelstack-display: grid;
5536
5563
  --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
5564
  --picker--host-row-gap: var(--labeled-content-row-gap);
5546
5565
  --picker--host-column-gap: var(--labeled-content-column-gap);
5547
5566
  --picker--host-padding-inline: var(--itempadistart, ) var(--itempadiend, );
@@ -5556,6 +5575,30 @@
5556
5575
  --picker--inputstack-display: flex;
5557
5576
  --picker--inputstack-flex-flow: row wrap;
5558
5577
  }
5578
+ :where(picker-view[js-init-tabs]) {
5579
+ --tabbar-after-tabreveal-duration: 0s;
5580
+ }
5581
+ @container style(--picker-style: tabs) {
5582
+ :where(picker-view)::part(picker-input-stack)::after {
5583
+ content: "";
5584
+ display: block;
5585
+ position: absolute;
5586
+ background-color: rgba(0, 0, 0, 0.4);
5587
+ pointer-events: none;
5588
+ touch-action: none;
5589
+ position-anchor: --anchor-id;
5590
+ inset: anchor(--anchor-id top) auto auto anchor(--anchor-id left);
5591
+ inline-size: anchor-size();
5592
+ block-size: anchor-size();
5593
+ border-radius: var(--pill-border-radius);
5594
+ z-index: -1;
5595
+ }
5596
+ @media (prefers-reduced-motion: no-preference) {
5597
+ :where(picker-view)::part(picker-input-stack)::after {
5598
+ 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;
5599
+ }
5600
+ }
5601
+ }
5559
5602
  @container style(--picker-style: radio-group) {
5560
5603
  picker-view > label:not([slot]) input[type=radio] {
5561
5604
  min-inline-size: 20px;
@@ -5588,15 +5631,23 @@
5588
5631
  outline-offset: 0.1rem;
5589
5632
  }
5590
5633
  }
5591
- @container style(--picker-style: segmented) {
5634
+ @container style(--picker-style: tabs) {
5592
5635
  :where(picker-view > label:not([slot])) {
5636
+ --label-line-limit: 1;
5637
+ --label-truncation-mode: tail;
5593
5638
  --label-font: callout;
5594
5639
  color: var(--secondary);
5595
- min-inline-size: var(--segented-picker-button-min-inline-size);
5596
- background-color: blue;
5597
- border-radius: inherit;
5640
+ place-content: center;
5641
+ padding-inline: var(--tabs-picker-segment-padding-inline, );
5642
+ padding-block: var(--tabs-picker-segment-padding-block, );
5643
+ min-inline-size: var(--tabs-picker-segment-min-inline-size);
5644
+ max-inline-size: var(--tabs-picker-segment-max-inline-size);
5645
+ border-radius: var(--tabs-picker-track-border-radius);
5598
5646
  inline-size: fit-content;
5599
- block-size: calc(var(--segented-picker-track-block-size) - var(--segented-picker-track-padding-block) * 2);
5647
+ block-size: calc(var(--tabs-picker-track-block-size) - var(--tabs-picker-track-padding-block) * 2);
5648
+ }
5649
+ :where(picker-view > label:not([slot])[aria-selected=true]) {
5650
+ anchor-name: --anchor-id;
5600
5651
  }
5601
5652
  :where(picker-view > label:not([slot]):has(input[type=radio]:not(:disabled))) {
5602
5653
  cursor: pointer;
@@ -5608,15 +5659,9 @@
5608
5659
  :where(picker-view > label:not([slot]) input[type=radio]) {
5609
5660
  appearance: none;
5610
5661
  margin: 0;
5611
- inline-size: 2rem;
5612
- block-size: 2rem;
5613
- border-radius: 0.4rem;
5662
+ visibility: collapse;
5663
+ position: absolute;
5614
5664
  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
5665
  }
5621
5666
  }
5622
5667
  }
package/html-data/en.json CHANGED
@@ -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",
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.0-canary.5",
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: 1rem;
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: 3rem;
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-content: start,
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,7 @@ $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,);
235
242
 
236
243
  gap: var(--picker--inputstack-gap,);
237
244
 
@@ -248,6 +255,9 @@ $picker-inform-elses: (
248
255
  padding-block: var(--picker--inputstack-padding-block,); //0.1rem;
249
256
  overflow: var(--picker--inputstack-overflow,); //auto clip;
250
257
 
258
+ backdrop-filter: var(--picker--inputstack-backdrop-filter,);
259
+ box-shadow: var(--picker--inputstack-box-shadow,);
260
+
251
261
  // flex-shrink: var(--picker--inputstack-flex-shrink,); //none;
252
262
 
253
263
  // max-width: var(--picker--inputstack-max-width,); //70%;
@@ -399,6 +409,28 @@ $picker-inform-elses: (
399
409
  }
400
410
  }
401
411
 
412
+ :where(&[js-init-tabs]) {
413
+ // transition: all var(--tabbar-after-tabreveal-duration) ease-out allow-discrete;
414
+ --tabbar-after-tabreveal-duration: 0s;
415
+ }
416
+
417
+ @container style(--picker-style: tabs) {
418
+ :where(&)::part(picker-input-stack) {
419
+ // outline: green solid 4px;
420
+
421
+ @include mixins.make-pseudo-tracking-thumb(--anchor-id);
422
+
423
+ &::after {
424
+ @media (prefers-reduced-motion: no-preference) {
425
+ transition:
426
+ block-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete,
427
+ inline-size var(--tabbar-after-tabreveal-duration) ease-out allow-discrete,
428
+ inset var(--tabbar-after-tabreveal-duration) ease-out allow-discrete;
429
+ }
430
+ }
431
+ }
432
+ }
433
+
402
434
  > label:not([slot]) {
403
435
  @container style(--picker-style: radio-group) {
404
436
  input[type='radio'] {
@@ -464,18 +496,37 @@ $picker-inform-elses: (
464
496
  // }
465
497
  }
466
498
 
467
- @container style(--picker-style: segmented) {
499
+ @container style(--picker-style: tabs) {
468
500
  :where(&) {
501
+ --label-line-limit: 1;
502
+ --label-truncation-mode: tail;
503
+
469
504
  --label-font: callout;
470
505
 
471
506
  color: var(--secondary);
472
507
 
473
- min-inline-size: var(--segented-picker-button-min-inline-size);
474
- background-color: blue;
475
- border-radius: inherit;
508
+ place-content: center;
509
+
510
+ padding-inline: var(--tabs-picker-segment-padding-inline,);
511
+
512
+ padding-block: var(--tabs-picker-segment-padding-block,);
513
+
514
+ min-inline-size: var(--tabs-picker-segment-min-inline-size);
515
+
516
+ max-inline-size: var(--tabs-picker-segment-max-inline-size);
517
+
518
+ border-radius: var(--tabs-picker-track-border-radius);
476
519
 
477
520
  inline-size: fit-content;
478
- block-size: calc(var(--segented-picker-track-block-size) - calc(var(--segented-picker-track-padding-block) * 2));
521
+
522
+ block-size: calc(var(--tabs-picker-track-block-size) - calc(var(--tabs-picker-track-padding-block) * 2));
523
+ }
524
+
525
+ // &:has(input:checked) {
526
+ &[aria-selected='true'] {
527
+ :where(&) {
528
+ anchor-name: --anchor-id;
529
+ }
479
530
  }
480
531
 
481
532
  &:has(input[type='radio']:not(:disabled)) {
@@ -495,21 +546,14 @@ $picker-inform-elses: (
495
546
  input[type='radio'] {
496
547
  :where(&) {
497
548
  appearance: none;
498
- margin: 0;
499
549
 
500
- inline-size: 2rem;
501
- block-size: 2rem;
502
- border-radius: 0.4rem;
550
+ margin: 0;
503
551
 
504
- pointer-events: none;
552
+ visibility: collapse;
505
553
 
506
- transition: outline 100ms ease-out;
554
+ position: absolute;
507
555
 
508
- &:checked {
509
- outline: var(--accentColor) solid 0.3rem;
510
-
511
- outline-offset: 0.1rem;
512
- }
556
+ pointer-events: none;
513
557
  }
514
558
  }
515
559
 
@@ -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