@taprootio/espalier 4.15.0 → 4.16.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.
@@ -4,8 +4,21 @@ import { LitElement } from "lit";
4
4
  * [esp-breadcrumbs](/components/breadcrumbs/) to show breadcrumb
5
5
  * navigation.
6
6
  *
7
- * @cssprop --esp-breadcrumb-color - The text color of the breadcrumb link.
8
- * @cssprop --esp-breadcrumb-hover-color - The text color on hover.
7
+ * @cssprop --esp-breadcrumb-color - The text color of the breadcrumb link. Defaults to
8
+ * `var(--esp-color-link)`, so a trail reads as navigation in the same ink as the links in
9
+ * the surrounding content.
10
+ * @cssprop --esp-breadcrumb-hover-color - The text color on hover. Defaults to
11
+ * `var(--esp-color-link-hover)`.
12
+ * @cssprop --esp-breadcrumb-hover-background - The background behind a hovered link.
13
+ * Defaults to `var(--esp-color-link-hover-bg)`.
14
+ * @cssprop --esp-breadcrumb-current-color - The text color of the current-page crumb, which
15
+ * is not a link. Defaults to `--esp-breadcrumb-color` when that is set, then to
16
+ * `var(--esp-color-headings)`, keeping the current page distinct from the links beside it.
17
+ * @cssprop --esp-breadcrumb-separator-color - The color of the separator icons. Defaults to
18
+ * `oklch(from var(--esp-color-link) l c calc(h + 90))`, an accent that takes the link ink's
19
+ * scheme-adapted lightness and chroma at a different hue, so the arrows are their own color
20
+ * rather than the heading color. Set it on `esp-breadcrumbs` to recolor a whole trail, or on
21
+ * one `esp-breadcrumb` to recolor a single arrow.
9
22
  * @docPageTitle Breadcrumb
10
23
  * @docUrl /components/breadcrumbs/breadcrumb
11
24
  * @menuGroup Navigation
@@ -26,8 +39,11 @@ export declare class EspalierBreadcrumb extends LitElement {
26
39
  */
27
40
  separator: string;
28
41
  /**
29
- * Used internally to render the item using a label
30
- * instead of a link.
42
+ * Marks this crumb as the end of the trail. The parent
43
+ * `esp-breadcrumbs` sets it to pick the down-arrow separator and
44
+ * the current-crumb styling. It does not decide link versus label —
45
+ * a crumb that carries a `url` stays clickable wherever it sits, so
46
+ * a trail can end at its deepest folder.
31
47
  * @type {boolean}
32
48
  */
33
49
  isLastElement: boolean;
@@ -1,4 +1,4 @@
1
- var i=function(s,r,o,a){var l=arguments.length,e=l<3?r:a===null?a=Object.getOwnPropertyDescriptor(r,o):a,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(s,r,o,a);else for(var c=s.length-1;c>=0;c--)(n=s[c])&&(e=(l<3?n(e):l>3?n(r,o,e):n(r,o))||e);return l>3&&e&&Object.defineProperty(r,o,e),e};import{LitElement as h,css as d,html as m}from"lit";import{customElement as u,property as p}from"lit/decorators.js";import{unsafeSVG as b}from"lit/directives/unsafe-svg.js";let t=class extends h{constructor(){super(...arguments),this.label="",this.url="",this.separator="",this.isLastElement=!1}_renderLink(){return this.isLastElement?m`<label>${this.label}</label>`:m`<a href=${this.url}>${this.label}</a>`}render(){return m`${this._renderLink()}${this.separator?b(this.separator):""}`}};t.styles=d`
1
+ var a=function(l,t,o,s){var i=arguments.length,e=i<3?t:s===null?s=Object.getOwnPropertyDescriptor(t,o):s,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(l,t,o,s);else for(var p=l.length-1;p>=0;p--)(n=l[p])&&(e=(i<3?n(e):i>3?n(t,o,e):n(t,o))||e);return i>3&&e&&Object.defineProperty(t,o,e),e};import{LitElement as d,css as m,html as h}from"lit";import{customElement as u,property as c}from"lit/decorators.js";import{unsafeSVG as b}from"lit/directives/unsafe-svg.js";let r=class extends d{constructor(){super(...arguments),this.label="",this.url="",this.separator="",this.isLastElement=!1}_renderLink(){return this.url?h`<a href=${this.url}>${this.label}</a>`:h`<label>${this.label}</label>`}render(){return h`${this._renderLink()}${this.separator?b(this.separator):""}`}};r.styles=m`
2
2
  :host {
3
3
  display: grid;
4
4
  grid-template-columns: min-content min-content;
@@ -6,9 +6,8 @@ var i=function(s,r,o,a){var l=arguments.length,e=l<3?r:a===null?a=Object.getOwnP
6
6
  align-items: center;
7
7
  }
8
8
 
9
- a,
10
- label {
11
- color: var(--esp-breadcrumb-color, var(--esp-color-headings));
9
+
10
+ :is(a, label) {
12
11
  font-weight: bold;
13
12
  width: min-content;
14
13
  text-decoration: none;
@@ -16,17 +15,32 @@ var i=function(s,r,o,a){var l=arguments.length,e=l<3?r:a===null?a=Object.getOwnP
16
15
  white-space: nowrap;
17
16
  }
18
17
 
18
+ a {
19
+ color: var(--esp-breadcrumb-color, var(--esp-color-link));
20
+ }
21
+
19
22
  a:hover {
20
- color: var(--esp-breadcrumb-hover-color, var(--esp-color-headings-hover));
23
+ background: var(--esp-breadcrumb-hover-background, var(--esp-color-link-hover-bg));
24
+ color: var(--esp-breadcrumb-hover-color, var(--esp-color-link-hover));
21
25
  text-decoration: underline;
22
26
  }
23
27
 
28
+
24
29
  label {
30
+ color: var(
31
+ --esp-breadcrumb-current-color,
32
+ var(--esp-breadcrumb-color, var(--esp-color-headings))
33
+ );
25
34
  font-style: italic;
26
35
  }
27
36
 
37
+
28
38
  svg {
39
+ color: var(
40
+ --esp-breadcrumb-separator-color,
41
+ oklch(from var(--esp-color-link) l c calc(h + 90))
42
+ );
29
43
  height: var(--esp-size-normal-to-medium);
30
44
  width: var(--esp-size-normal-to-medium);
31
45
  }
32
- `,i([p({type:String})],t.prototype,"label",void 0),i([p({type:String})],t.prototype,"url",void 0),i([p({type:String})],t.prototype,"separator",void 0),i([p({attribute:"is-last-element",type:Boolean})],t.prototype,"isLastElement",void 0),t=i([u("esp-breadcrumb")],t);export{t as EspalierBreadcrumb};
46
+ `,a([c({type:String})],r.prototype,"label",void 0),a([c({type:String})],r.prototype,"url",void 0),a([c({type:String})],r.prototype,"separator",void 0),a([c({attribute:"is-last-element",type:Boolean})],r.prototype,"isLastElement",void 0),r=a([u("esp-breadcrumb")],r);export{r as EspalierBreadcrumb};
@@ -16,6 +16,17 @@ export * from "./esp-breadcrumb.js";
16
16
  * </esp-breadcrumbs>
17
17
  * ```
18
18
  *
19
+ * Every crumb with a `url` is a link, including the last one — a trail
20
+ * may end at the deepest folder rather than at the current page. Leave
21
+ * `url` off a crumb to render it as the italic current-page label:
22
+ *
23
+ * ```html
24
+ * <esp-breadcrumbs>
25
+ * <esp-breadcrumb label="Code" url="/code"></esp-breadcrumb>
26
+ * <esp-breadcrumb label="This page"></esp-breadcrumb>
27
+ * </esp-breadcrumbs>
28
+ * ```
29
+ *
19
30
  * Custom separators can be specified in the `<esp-breadcrumb>`:
20
31
  *
21
32
  * ```html
@@ -34,8 +45,11 @@ export * from "./esp-breadcrumb.js";
34
45
  *
35
46
  * @customElement esp-breadcrumbs
36
47
  * @slot - `<esp-breadcrumb>` items to display.
37
- * @cssprop --esp-breadcrumb-separator-color - Set the color of the separator. It defaults
38
- * to the semantic heading color so navigation structure stays visible in light and dark themes.
48
+ * @cssprop --esp-breadcrumb-separator-color - The color of the separator icons. Defaults to
49
+ * `oklch(from var(--esp-color-link) l c calc(h + 90))`, an accent that takes the link ink's
50
+ * scheme-adapted lightness and chroma at a different hue, so the arrows are their own color
51
+ * rather than the heading color. Set it on `esp-breadcrumbs` to recolor a whole trail, or on
52
+ * one `esp-breadcrumb` to recolor a single arrow.
39
53
  *
40
54
  * ```html
41
55
  * <style>
@@ -1,22 +1,21 @@
1
- var c=function(o,s,e,t){var r=arguments.length,l=r<3?s:t===null?t=Object.getOwnPropertyDescriptor(s,e):t,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")l=Reflect.decorate(o,s,e,t);else for(var i=o.length-1;i>=0;i--)(n=o[i])&&(l=(r<3?n(l):r>3?n(s,e,l):n(s,e))||l);return r>3&&l&&Object.defineProperty(s,e,l),l};import{css as p,html as f}from"lit";import{customElement as u}from"lit/decorators.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{createRef as v,ref as d}from"lit/directives/ref.js";export*from"./esp-breadcrumb.js";const h=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
1
+ var f=function(l,e,t,s){var o=arguments.length,r=o<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,t):s,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(l,e,t,s);else for(var i=l.length-1;i>=0;i--)(a=l[i])&&(r=(o<3?a(r):o>3?a(e,t,r):a(e,t))||r);return o>3&&r&&Object.defineProperty(e,t,r),r};import{css as h,html as u}from"lit";import{customElement as v}from"lit/decorators.js";import{EspalierElementBase as m}from"../shared/esp-element-base.js";import{createRef as d,ref as g}from"lit/directives/ref.js";export*from"./esp-breadcrumb.js";const p=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
2
2
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
3
3
  <path
4
4
  d="M12.089 3.634a2 2 0 0 0 -1.089 1.78l-.001 2.586h-6.999a2 2 0 0 0 -2 2v4l.005 .15a2 2 0 0 0 1.995 1.85l6.999 -.001l.001 2.587a2 2 0 0 0 3.414 1.414l6.586 -6.586a2 2 0 0 0 0 -2.828l-6.586 -6.586a2 2 0 0 0 -2.18 -.434l-.145 .068z" />
5
- </svg>`,g=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
5
+ </svg>`,c=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
6
6
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
7
7
  <path
8
8
  d="M10 2l-.15 .005a2 2 0 0 0 -1.85 1.995v6.999l-2.586 .001a2 2 0 0 0 -1.414 3.414l6.586 6.586a2 2 0 0 0 2.828 0l6.586 -6.586a2 2 0 0 0 .434 -2.18l-.068 -.145a2 2 0 0 0 -1.78 -1.089l-2.586 -.001v-6.999a2 2 0 0 0 -2 -2h-4z"
9
9
  />
10
- </svg>`;let a=class extends m{constructor(){super(...arguments),this.itemsSlot=v()}firstUpdated(s){if(super.firstUpdated(s),!this.itemsSlot.value){console.warn("No items slot found for breadcrumbs.");return}const e=this.itemsSlot.value.assignedElements();for(let t=0;t<e.length;t++){const r=e[t];r.separator.length>0||(r.isLastElement=t===e.length-1,r.separator=r.isLastElement?g:h)}}render(){return f`
10
+ </svg>`;let n=class extends m{constructor(){super(...arguments),this.itemsSlot=d()}firstUpdated(e){if(super.firstUpdated(e),!this.itemsSlot.value){console.warn("No items slot found for breadcrumbs.");return}this.assignSeparators()}assignSeparators(){const e=this.itemsSlot.value?.assignedElements()??[];for(let t=0;t<e.length;t++){const s=e[t],o=t===e.length-1;s.isLastElement=o;const r=s.separator===p||s.separator===c;s.separator&&!r||(s.separator=o?c:p)}}render(){return u`
11
11
  <div class="crumbs">
12
- <slot ${d(this.itemsSlot)}></slot>
12
+ <slot ${g(this.itemsSlot)} @slotchange=${this.assignSeparators}></slot>
13
13
  </div>
14
- `}};a.styles=[...m.styles,p`
14
+ `}};n.styles=[...m.styles,h`
15
15
  div.crumbs {
16
16
  display: flex;
17
17
  align-items: center;
18
18
  gap: var(--esp-size-tiny-to-small);
19
19
  font-size: var(--esp-size-small-to-normal);
20
- color: var(--esp-breadcrumb-separator-color, var(--esp-color-headings));
21
20
  }
22
- `],a=c([u("esp-breadcrumbs")],a);export{a as EspalierBreadcrumbs};
21
+ `],n=f([v("esp-breadcrumbs")],n);export{n as EspalierBreadcrumbs};
@@ -1,4 +1,4 @@
1
- var n=function(h,t,r,o){var a=arguments.length,i=a<3?t:o===null?o=Object.getOwnPropertyDescriptor(t,r):o,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(h,t,r,o);else for(var p=h.length-1;p>=0;p--)(d=h[p])&&(i=(a<3?d(i):a>3?d(t,r,i):d(t,r))||i);return a>3&&i&&Object.defineProperty(t,r,i),i};import{css as f,html as c,nothing as l}from"lit";import{customElement as g,eventOptions as m,property as s,state as v}from"lit/decorators.js";import{classMap as u}from"lit/directives/class-map.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ESP_EVENTS as y}from"../shared/events.js";import{ref as w}from"lit/directives/ref.js";import{getIconHrefForHost as x}from"../shared/intent-values.js";import{SlottedIconController as k}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as T}from"../shared/svgs/render-sprite-icon.js";import{BUTTON_INTERACTION_LIGHTNESS_FACTOR as S}from"./action-state-lightness.js";const $=c`<svg
1
+ var n=function(h,t,s,i){var a=arguments.length,o=a<3?t:i===null?i=Object.getOwnPropertyDescriptor(t,s):i,d;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(h,t,s,i);else for(var c=h.length-1;c>=0;c--)(d=h[c])&&(o=(a<3?d(o):a>3?d(t,s,o):d(t,s))||o);return a>3&&o&&Object.defineProperty(t,s,o),o};import{css as g,html as p,nothing as l}from"lit";import{customElement as f,eventOptions as m,property as r,state as v}from"lit/decorators.js";import{classMap as u}from"lit/directives/class-map.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ESP_EVENTS as y}from"../shared/events.js";import{ref as w}from"lit/directives/ref.js";import{getIconHrefForHost as k}from"../shared/intent-values.js";import{SlottedIconController as x}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as T}from"../shared/svgs/render-sprite-icon.js";import{BUTTON_INTERACTION_LIGHTNESS_FACTOR as S}from"./action-state-lightness.js";const $=p`<svg
2
2
  xmlns="http://www.w3.org/2000/svg"
3
3
  viewBox="0 0 24 24"
4
4
  fill="none"
@@ -10,40 +10,40 @@ var n=function(h,t,r,o){var a=arguments.length,i=a<3?t:o===null?o=Object.getOwnP
10
10
  >
11
11
  <path stroke="none" d="M0 0h24v24H0z" fill="none" />
12
12
  <path d="M4.05 11a8 8 0 1 1 .5 4m-.5 5v-5h5" />
13
- </svg>`;let e=class extends b{constructor(){super(...arguments),this.iconSlot=new k(this),this.innerTabindex=null,this.neutralizingTabindex=!1,this.buttonType="button",this.collapsed=!1,this.disabled=!1,this.href="",this.iconOnly=!1,this.incognito=!1,this.icon="",this.iconPosition="right",this.label="",this.loading=!1,this.target="",this.rel="",this.formNoValidate=!1,this.buildIcon=t=>this.loading?c` <span>${$}</span> `:c`
13
+ </svg>`;let e=class extends b{constructor(){super(...arguments),this.iconSlot=new x(this),this.innerTabindex=null,this.neutralizingTabindex=!1,this.buttonType="button",this.collapsed=!1,this.disabled=!1,this.href="",this.iconOnly=!1,this.incognito=!1,this.icon="",this.iconPosition="right",this.label="",this.loading=!1,this.target="",this.rel="",this.formNoValidate=!1,this.buildIcon=t=>this.loading?p` <span>${$}</span> `:p`
14
14
  <span>
15
15
  <slot ${w(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
16
16
  ${!this.iconSlot.hasSlottedIcon(":scope > *")&&t?T(t):l}
17
17
  </span>
18
- `}static get observedAttributes(){return[...super.observedAttributes,"tabindex","aria-pressed"]}attributeChangedCallback(t,r,o){if(super.attributeChangedCallback(t,r,o),t==="aria-pressed"){this.requestUpdate();return}if(t!=="tabindex"||this.neutralizingTabindex)return;const a=o===null?null:Number(o),i=a===null||Number.isNaN(a)?null:a;i!==null&&i>=0?(this.innerTabindex=i,this.writeHostTabindex(null)):i===null&&o!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=i}writeHostTabindex(t){this.getAttribute("tabindex")!==t&&(this.neutralizingTabindex=!0,t===null?this.removeAttribute("tabindex"):this.setAttribute("tabindex",t),this.neutralizingTabindex=!1)}removeAttribute(t){super.removeAttribute(t),t==="tabindex"&&!this.neutralizingTabindex&&(this.innerTabindex=null)}focus(t){this.focusShadowElementAfterUpdate("button, a",t)}handleClick(t){if(this.dispatchEvent(new CustomEvent(y.CLICKED,{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const r=this.closest("form");if(r){const o=document.createElement("button");o.type="submit",o.hidden=!0,this.formNoValidate&&(o.formNoValidate=!0),r.appendChild(o),r.requestSubmit(o),o.remove()}}else this.buttonType==="reset"&&this.closest("form")?.reset()}render(){const t=x(this.icon,this),r=this.loading||this.iconSlot.hasSlottedIcon(":scope > *")||t.length>0,{collapsed:o,iconOnly:a}=this,i=a?this.getAttribute("aria-label")||this.label||l:l,d=this.getAttribute("aria-pressed")||l,p={"esp-field":!0,"icon-only":a,incognito:this.incognito,"is-collapsed":o,"has-icon":r,"icon-left":r&&!a&&this.iconPosition==="left"};return this.href.length?c`
19
- <div part="wrapper" class=${u(p)}>
18
+ `}static get observedAttributes(){return[...super.observedAttributes,"tabindex","aria-pressed"]}attributeChangedCallback(t,s,i){if(super.attributeChangedCallback(t,s,i),t==="aria-pressed"){this.requestUpdate();return}if(t!=="tabindex"||this.neutralizingTabindex)return;const a=i===null?null:Number(i),o=a===null||Number.isNaN(a)?null:a;o!==null&&o>=0?(this.innerTabindex=o,this.writeHostTabindex(null)):o===null&&i!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=o}writeHostTabindex(t){this.getAttribute("tabindex")!==t&&(this.neutralizingTabindex=!0,t===null?this.removeAttribute("tabindex"):this.setAttribute("tabindex",t),this.neutralizingTabindex=!1)}removeAttribute(t){super.removeAttribute(t),t==="tabindex"&&!this.neutralizingTabindex&&(this.innerTabindex=null)}focus(t){this.focusShadowElementAfterUpdate("button, a",t)}handleClick(t){if(this.dispatchEvent(new CustomEvent(y.CLICKED,{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const s=this.closest("form");if(s){const i=document.createElement("button");i.type="submit",i.hidden=!0,this.formNoValidate&&(i.formNoValidate=!0),s.appendChild(i),s.requestSubmit(i),i.remove()}}else this.buttonType==="reset"&&this.closest("form")?.reset()}render(){const t=k(this.icon,this),s=this.loading||this.iconSlot.hasSlottedIcon(":scope > *")||t.length>0,{collapsed:i,iconOnly:a}=this,o=a?this.getAttribute("aria-label")||this.label||l:l,d=this.getAttribute("aria-pressed")||l,c={"esp-field":!0,"icon-only":a,incognito:this.incognito,"is-collapsed":i,"has-icon":s,"icon-left":s&&!a&&this.iconPosition==="left"};return this.href.length?p`
19
+ <div part="wrapper" class=${u(c)}>
20
20
  <a
21
21
  ?disabled=${this.disabled}
22
22
  href=${this.href}
23
23
  target=${this.target}
24
24
  rel=${this.rel||l}
25
25
  tabindex=${this.innerTabindex??l}
26
- aria-label=${i}
26
+ aria-label=${o}
27
27
  >
28
28
  <span>${this.label??""}</span>
29
29
  ${this.buildIcon(t)}
30
30
  </a>
31
31
  </div>
32
- `:c`
33
- <div part="wrapper" class=${u(p)}>
32
+ `:p`
33
+ <div part="wrapper" class=${u(c)}>
34
34
  <button
35
35
  ?disabled=${this.disabled||this.loading}
36
36
  @click=${this.handleClick}
37
37
  type=${this.buttonType}
38
38
  tabindex=${this.innerTabindex??l}
39
- aria-label=${i}
39
+ aria-label=${o}
40
40
  aria-pressed=${d}
41
41
  >
42
42
  <span>${this.label??""}</span>
43
43
  ${this.buildIcon(t)}
44
44
  </button>
45
45
  </div>
46
- `}};e.styles=[...b.styles,f`
46
+ `}};e.styles=[...b.styles,g`
47
47
  :host {
48
48
  --_esp-button-radius: var(--esp-size-border-radius);
49
49
  }
@@ -112,6 +112,25 @@ var n=function(h,t,r,o){var a=arguments.length,i=a<3?t:o===null?o=Object.getOwnP
112
112
  display: grid;
113
113
  }
114
114
  }
115
+
116
+
117
+ &:where(:not(.icon-left)) {
118
+ button,
119
+ a {
120
+ > span:nth-child(1) {
121
+ padding-inline-end: 0;
122
+ }
123
+ }
124
+ }
125
+
126
+ &.icon-left {
127
+ button,
128
+ a {
129
+ > span:nth-child(1) {
130
+ padding-inline-start: 0;
131
+ }
132
+ }
133
+ }
115
134
  }
116
135
 
117
136
  &.is-collapsed,
@@ -213,4 +232,4 @@ var n=function(h,t,r,o){var a=arguments.length,i=a<3?t:o===null?o=Object.getOwnP
213
232
  transform: rotate(360deg);
214
233
  }
215
234
  }
216
- `],n([v()],e.prototype,"innerTabindex",void 0),n([s({attribute:"button-type",type:String})],e.prototype,"buttonType",void 0),n([s({type:Boolean})],e.prototype,"collapsed",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"disabled",void 0),n([s({type:String})],e.prototype,"href",void 0),n([s({attribute:"icon-only",type:Boolean})],e.prototype,"iconOnly",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"incognito",void 0),n([s({type:String})],e.prototype,"icon",void 0),n([s({attribute:"icon-position",type:String})],e.prototype,"iconPosition",void 0),n([s({type:String})],e.prototype,"label",void 0),n([s({type:Boolean,reflect:!0})],e.prototype,"loading",void 0),n([s({type:String})],e.prototype,"target",void 0),n([s({type:String})],e.prototype,"rel",void 0),n([s({attribute:"formnovalidate",type:Boolean})],e.prototype,"formNoValidate",void 0),n([m({capture:!1,passive:!0})],e.prototype,"handleClick",null),e=n([g("esp-button")],e);export{e as EspalierButton};
235
+ `],n([v()],e.prototype,"innerTabindex",void 0),n([r({attribute:"button-type",type:String})],e.prototype,"buttonType",void 0),n([r({type:Boolean})],e.prototype,"collapsed",void 0),n([r({type:Boolean,reflect:!0})],e.prototype,"disabled",void 0),n([r({type:String})],e.prototype,"href",void 0),n([r({attribute:"icon-only",type:Boolean})],e.prototype,"iconOnly",void 0),n([r({type:Boolean,reflect:!0})],e.prototype,"incognito",void 0),n([r({type:String})],e.prototype,"icon",void 0),n([r({attribute:"icon-position",type:String})],e.prototype,"iconPosition",void 0),n([r({type:String})],e.prototype,"label",void 0),n([r({type:Boolean,reflect:!0})],e.prototype,"loading",void 0),n([r({type:String})],e.prototype,"target",void 0),n([r({type:String})],e.prototype,"rel",void 0),n([r({attribute:"formnovalidate",type:Boolean})],e.prototype,"formNoValidate",void 0),n([m({capture:!1,passive:!0})],e.prototype,"handleClick",null),e=n([f("esp-button")],e);export{e as EspalierButton};
@@ -1,7 +1,7 @@
1
- var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,a):e,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(i,t,a,e);else for(var l=i.length-1;l>=0;l--)(r=i[l])&&(o=(s<3?r(o):s>3?r(t,a,o):r(t,a))||o);return s>3&&o&&Object.defineProperty(t,a,o),o};import{css as u,html as d,nothing as f}from"lit";import{customElement as v,property as m,state as g}from"lit/decorators.js";import{createRef as y,ref as w}from"lit/directives/ref.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";import{ESP_EVENTS as k}from"../shared/events.js";import{EspalierTab as p}from"./esp-tab.js";import{disabledControl as T}from"../shared/style-fragments.js";let n=class extends c{constructor(){super(...arguments),this.panelsSlot=y(),this.disabled=!1,this.tabData=[]}getTabs(){const t=this.panelsSlot.value?Array.from(this.panelsSlot.value.assignedElements()).filter(a=>a instanceof p):[];return t.length>0?t:Array.from(this.children).filter(a=>a instanceof p)}syncTabData(){const t=this.getTabs();if(t.length===0){this.tabData=[];return}const a=t.find(e=>e.active&&!e.disabled);if(a)for(const e of t)e!==a&&(e.active=!1);else{const e=t.find(s=>!s.disabled);e?e.active=!0:t[0].active=!0}this.tabData=t.map((e,s)=>{const o=`esp-tab-btn-${this.correlationId}-${s}`,r=`esp-tab-panel-${this.correlationId}-${s}`;return e.panelId=r,e.ariaLabelledBy=o,{label:e.label,active:e.active,disabled:this.disabled||e.disabled,buttonId:o,panelId:r}})}activateTab(t){const a=this.getTabs(),e=a[t];if(!(!e||e.disabled||this.disabled)){for(const s of a)s.active=s===e;this.syncTabData(),this.dispatchEvent(new CustomEvent(k.TAB_GROUP_CHANGED,{detail:{index:t,label:e.label},bubbles:!0,composed:!0}))}}handleTabClick(t){this.activateTab(t),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[t]?.buttonId)?.focus()})}handleKeyDown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;t.preventDefault();const e=this.tabData.map((l,h)=>({td:l,i:h})).filter(({td:l})=>!l.disabled).map(({i:l})=>l);if(e.length===0)return;const s=this.tabData.findIndex(l=>l.active),o=e.indexOf(s);let r;switch(t.key){case"ArrowRight":o===-1?r=e[0]:r=e[(o+1)%e.length];break;case"ArrowLeft":o===-1?r=e[e.length-1]:r=e[(o-1+e.length)%e.length];break;case"Home":r=e[0];break;case"End":r=e[e.length-1];break;default:return}this.activateTab(r),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[r]?.buttonId)?.focus()})}handleChildUpdated(){this.syncTabData()}handleSlotChange(){this.syncTabData()}connectedCallback(){super.connectedCallback(),this.syncTabData()}willUpdate(t){super.willUpdate(t),t.has("disabled")&&this.syncTabData()}render(){return d`
1
+ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,a):e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(l,t,a,e);else for(var n=l.length-1;n>=0;n--)(o=l[n])&&(r=(s<3?o(r):s>3?o(t,a,r):o(t,a))||r);return s>3&&r&&Object.defineProperty(t,a,r),r};import{css as u,html as c,nothing as v}from"lit";import{customElement as f,property as g,state as m}from"lit/decorators.js";import{createRef as y,ref as w}from"lit/directives/ref.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ESP_EVENTS as x}from"../shared/events.js";import{EspalierTab as p}from"./esp-tab.js";import{disabledControl as T}from"../shared/style-fragments.js";let i=class extends b{constructor(){super(...arguments),this.panelsSlot=y(),this.disabled=!1,this.tabData=[]}getTabs(){const t=this.panelsSlot.value?Array.from(this.panelsSlot.value.assignedElements()).filter(a=>a instanceof p):[];return t.length>0?t:Array.from(this.children).filter(a=>a instanceof p)}syncTabData(){const t=this.getTabs();if(t.length===0){this.tabData=[];return}const a=t.find(e=>e.active&&!e.disabled);if(a)for(const e of t)e!==a&&(e.active=!1);else{const e=t.find(s=>!s.disabled);e?e.active=!0:t[0].active=!0}this.tabData=t.map((e,s)=>{const r=`esp-tab-btn-${this.correlationId}-${s}`,o=`esp-tab-panel-${this.correlationId}-${s}`;return e.panelId=o,e.ariaLabelledBy=r,{label:e.label,active:e.active,disabled:this.disabled||e.disabled,buttonId:r,panelId:o}})}activateTab(t){const a=this.getTabs(),e=a[t];if(!(!e||e.disabled||this.disabled)){for(const s of a)s.active=s===e;this.syncTabData(),this.dispatchEvent(new CustomEvent(x.TAB_GROUP_CHANGED,{detail:{index:t,label:e.label},bubbles:!0,composed:!0}))}}handleTabClick(t){this.activateTab(t),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[t]?.buttonId)?.focus()})}handleKeyDown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;t.preventDefault();const e=this.tabData.map((n,h)=>({td:n,i:h})).filter(({td:n})=>!n.disabled).map(({i:n})=>n);if(e.length===0)return;const s=this.tabData.findIndex(n=>n.active),r=e.indexOf(s);let o;switch(t.key){case"ArrowRight":r===-1?o=e[0]:o=e[(r+1)%e.length];break;case"ArrowLeft":r===-1?o=e[e.length-1]:o=e[(r-1+e.length)%e.length];break;case"Home":o=e[0];break;case"End":o=e[e.length-1];break;default:return}this.activateTab(o),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[o]?.buttonId)?.focus()})}handleChildUpdated(){this.syncTabData()}handleSlotChange(){this.syncTabData()}connectedCallback(){super.connectedCallback(),this.syncTabData()}willUpdate(t){super.willUpdate(t),t.has("disabled")&&this.syncTabData()}render(){return c`
2
2
  <div class="tab-container">
3
3
  <div class="tab-list" role="tablist" part="tab-list" @keydown=${this.handleKeyDown}>
4
- ${this.tabData.map((t,a)=>d`
4
+ ${this.tabData.map((t,a)=>c`
5
5
  <button
6
6
  id=${t.buttonId}
7
7
  class="tab-button"
@@ -9,7 +9,7 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
9
9
  part="tab-button"
10
10
  aria-selected=${t.active?"true":"false"}
11
11
  aria-controls=${t.panelId}
12
- aria-disabled=${t.disabled?"true":f}
12
+ aria-disabled=${t.disabled?"true":v}
13
13
  tabindex=${t.active?"0":"-1"}
14
14
  ?disabled=${t.disabled}
15
15
  @click=${()=>this.handleTabClick(a)}
@@ -26,7 +26,7 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
26
26
  ></slot>
27
27
  </div>
28
28
  </div>
29
- `}};n.styles=[...c.styles,T(".tab-button[disabled]"),u`
29
+ `}};i.styles=[...b.styles,T(".tab-button[disabled]"),u`
30
30
  :host {
31
31
  display: block;
32
32
  --_esp-tab-resolved-button-hover: var(
@@ -43,6 +43,8 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
43
43
  }
44
44
 
45
45
  .tab-container {
46
+
47
+ --_esp-tab-inner-radius: max(0px, calc(var(--esp-size-border-radius) - 1px));
46
48
  background-color: var(--esp-tab-color-background, var(--esp-color-layer-1));
47
49
  border-radius: var(--esp-size-border-radius);
48
50
  box-shadow: 1px 1px 4px var(--esp-color-shadow);
@@ -50,11 +52,14 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
50
52
  overflow: hidden;
51
53
  }
52
54
 
55
+
53
56
  .tab-list {
54
57
  display: flex;
55
58
  overflow-x: auto;
56
59
  background-color: var(--esp-tab-color-strip-background, var(--esp-color-layer-1));
57
60
  border-bottom: 1px solid var(--esp-tab-color-border, var(--esp-color-border));
61
+ border-start-start-radius: var(--_esp-tab-inner-radius);
62
+ border-start-end-radius: var(--_esp-tab-inner-radius);
58
63
  }
59
64
 
60
65
  .tab-button {
@@ -90,6 +95,11 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
90
95
  cursor: default;
91
96
  }
92
97
 
98
+
99
+ .tab-button:first-child {
100
+ border-start-start-radius: var(--_esp-tab-inner-radius);
101
+ }
102
+
93
103
  .tab-button:first-child[aria-selected="true"] {
94
104
  border-left: none;
95
105
  }
@@ -109,4 +119,4 @@ var b=function(i,t,a,e){var s=arguments.length,o=s<3?t:e===null?e=Object.getOwnP
109
119
  .panels {
110
120
 
111
121
  }
112
- `],b([m({type:Boolean,reflect:!0})],n.prototype,"disabled",void 0),b([g()],n.prototype,"tabData",void 0),n=b([v("esp-tab-group")],n);export{n as EspalierTabGroup};
122
+ `],d([g({type:Boolean,reflect:!0})],i.prototype,"disabled",void 0),d([m()],i.prototype,"tabData",void 0),i=d([f("esp-tab-group")],i);export{i as EspalierTabGroup};
@@ -79,15 +79,23 @@
79
79
  },
80
80
  {
81
81
  "name": "--esp-breadcrumb-color",
82
- "description": "The text color of the breadcrumb link."
82
+ "description": "The text color of the breadcrumb link. Defaults to `var(--esp-color-link)`, so a trail reads as navigation in the same ink as the links in the surrounding content."
83
+ },
84
+ {
85
+ "name": "--esp-breadcrumb-current-color",
86
+ "description": "The text color of the current-page crumb, which is not a link. Defaults to `--esp-breadcrumb-color` when that is set, then to `var(--esp-color-headings)`, keeping the current page distinct from the links beside it."
87
+ },
88
+ {
89
+ "name": "--esp-breadcrumb-hover-background",
90
+ "description": "The background behind a hovered link. Defaults to `var(--esp-color-link-hover-bg)`."
83
91
  },
84
92
  {
85
93
  "name": "--esp-breadcrumb-hover-color",
86
- "description": "The text color on hover."
94
+ "description": "The text color on hover. Defaults to `var(--esp-color-link-hover)`."
87
95
  },
88
96
  {
89
97
  "name": "--esp-breadcrumb-separator-color",
90
- "description": "Set the color of the separator. It defaults to the semantic heading color so navigation structure stays visible in light and dark themes."
98
+ "description": "The color of the separator icons. Defaults to `oklch(from var(--esp-color-link) l c calc(h + 90))`, an accent that takes the link ink's scheme-adapted lightness and chroma at a different hue, so the arrows are their own color rather than the heading color. Set it on `esp-breadcrumbs` to recolor a whole trail, or on one `esp-breadcrumb` to recolor a single arrow."
91
99
  },
92
100
  {
93
101
  "name": "--esp-button-group-divider",
@@ -117,19 +117,31 @@
117
117
  "name": "--esp-breadcrumb-color",
118
118
  "category": "component",
119
119
  "component": "esp-breadcrumb",
120
- "description": "The text color of the breadcrumb link."
120
+ "description": "The text color of the breadcrumb link. Defaults to `var(--esp-color-link)`, so a trail reads as navigation in the same ink as the links in the surrounding content."
121
+ },
122
+ {
123
+ "name": "--esp-breadcrumb-current-color",
124
+ "category": "component",
125
+ "component": "esp-breadcrumb",
126
+ "description": "The text color of the current-page crumb, which is not a link. Defaults to `--esp-breadcrumb-color` when that is set, then to `var(--esp-color-headings)`, keeping the current page distinct from the links beside it."
127
+ },
128
+ {
129
+ "name": "--esp-breadcrumb-hover-background",
130
+ "category": "component",
131
+ "component": "esp-breadcrumb",
132
+ "description": "The background behind a hovered link. Defaults to `var(--esp-color-link-hover-bg)`."
121
133
  },
122
134
  {
123
135
  "name": "--esp-breadcrumb-hover-color",
124
136
  "category": "component",
125
137
  "component": "esp-breadcrumb",
126
- "description": "The text color on hover."
138
+ "description": "The text color on hover. Defaults to `var(--esp-color-link-hover)`."
127
139
  },
128
140
  {
129
141
  "name": "--esp-breadcrumb-separator-color",
130
142
  "category": "component",
131
- "component": "esp-breadcrumbs",
132
- "description": "Set the color of the separator. It defaults to the semantic heading color so navigation structure stays visible in light and dark themes."
143
+ "component": "esp-breadcrumb",
144
+ "description": "The color of the separator icons. Defaults to `oklch(from var(--esp-color-link) l c calc(h + 90))`, an accent that takes the link ink's scheme-adapted lightness and chroma at a different hue, so the arrows are their own color rather than the heading color. Set it on `esp-breadcrumbs` to recolor a whole trail, or on one `esp-breadcrumb` to recolor a single arrow."
133
145
  },
134
146
  {
135
147
  "name": "--esp-button-group-divider",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "4.15.0",
3
+ "version": "4.16.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",