@taprootio/espalier 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/custom-elements.json +7707 -5044
- package/dist/breadcrumbs/esp-breadcrumbs.d.ts +1 -1
- package/dist/breadcrumbs/esp-breadcrumbs.js +6 -9
- package/dist/button/action-state-lightness.js +1 -0
- package/dist/button/esp-button.js +22 -10
- package/dist/data-cell/esp-data-cell.js +1 -1
- package/dist/footer/esp-footer-link-group.d.ts +40 -0
- package/dist/footer/esp-footer-link-group.js +57 -0
- package/dist/footer/esp-footer.d.ts +186 -0
- package/dist/footer/esp-footer.js +300 -0
- package/dist/footer/index.d.ts +2 -0
- package/dist/footer/index.js +1 -0
- package/dist/header/esp-header.js +10 -11
- package/dist/image/esp-image.js +8 -8
- package/dist/image/image-dimensions.js +1 -0
- package/dist/image-upload/esp-image-upload.js +20 -22
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/lightbox/esp-lightbox.d.ts +4 -3
- package/dist/lightbox/esp-lightbox.js +250 -235
- package/dist/menu/esp-menu.d.ts +14 -1
- package/dist/menu/esp-menu.js +3 -4
- package/dist/page/esp-page.d.ts +9 -6
- package/dist/page/esp-page.js +33 -11
- package/dist/progress/esp-progress.d.ts +2 -1
- package/dist/progress/esp-progress.js +13 -7
- package/dist/shared/configured-brand.js +4 -0
- package/dist/shared/slot-content.js +1 -0
- package/dist/slider/esp-slider.js +2 -2
- package/espalier.token-manifest.json +146 -2
- package/package.json +10 -1
|
@@ -35,7 +35,7 @@ export * from "./esp-breadcrumb.js";
|
|
|
35
35
|
* @customElement esp-breadcrumbs
|
|
36
36
|
* @slot - `<esp-breadcrumb>` items to display.
|
|
37
37
|
* @cssprop --esp-breadcrumb-separator-color - Set the color of the separator. It defaults
|
|
38
|
-
* to
|
|
38
|
+
* to the semantic heading color so navigation structure stays visible in light and dark themes.
|
|
39
39
|
*
|
|
40
40
|
* ```html
|
|
41
41
|
* <style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var c=function(o,s,e,t){var r=arguments.length,l=r<3?s:t===null?t=Object.getOwnPropertyDescriptor(s,e):t,
|
|
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">
|
|
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" />
|
|
@@ -7,19 +7,16 @@ var c=function(o,s,e,t){var r=arguments.length,l=r<3?s:t===null?t=Object.getOwnP
|
|
|
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
|
|
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`
|
|
11
11
|
<div class="crumbs">
|
|
12
|
-
<slot ${
|
|
12
|
+
<slot ${d(this.itemsSlot)}></slot>
|
|
13
13
|
</div>
|
|
14
|
-
`}};
|
|
14
|
+
`}};a.styles=[...m.styles,p`
|
|
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(
|
|
21
|
-
--esp-breadcrumb-separator-color,
|
|
22
|
-
oklch(from var(--esp-color-complementary) var(--esp-l-accent) c h)
|
|
23
|
-
);
|
|
20
|
+
color: var(--esp-breadcrumb-separator-color, var(--esp-color-headings));
|
|
24
21
|
}
|
|
25
|
-
`],
|
|
22
|
+
`],a=c([u("esp-breadcrumbs")],a);export{a as EspalierBreadcrumbs};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const T=.9,N=.88,_=.8;export{_ as BUTTON_ICON_INTERACTION_LIGHTNESS_FACTOR,T as BUTTON_ICON_SPLIT_LIGHTNESS_FACTOR,N as BUTTON_INTERACTION_LIGHTNESS_FACTOR};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,r):e,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")n=Reflect.decorate(p,t,r,e);else for(var h=p.length-1;h>=0;h--)(l=p[h])&&(n=(s<3?l(n):s>3?l(t,r,n):l(t,r))||n);return s>3&&n&&Object.defineProperty(t,r,n),n};import{css as
|
|
1
|
+
var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,r):e,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")n=Reflect.decorate(p,t,r,e);else for(var h=p.length-1;h>=0;h--)(l=p[h])&&(n=(s<3?l(n):s>3?l(t,r,n):l(t,r))||n);return s>3&&n&&Object.defineProperty(t,r,n),n};import{css as f,html as d,nothing as c}from"lit";import{customElement as m,eventOptions as v,property as a,state as y}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{ref as k}from"lit/directives/ref.js";import{getIconHrefForHost as x}from"../shared/intent-values.js";import{SlottedIconController as T}from"../shared/slotted-icon-controller.js";import{renderSpriteIcon as w}from"../shared/svgs/render-sprite-icon.js";import{BUTTON_ICON_INTERACTION_LIGHTNESS_FACTOR as S,BUTTON_ICON_SPLIT_LIGHTNESS_FACTOR as g,BUTTON_INTERACTION_LIGHTNESS_FACTOR as $}from"./action-state-lightness.js";const N=d`<svg
|
|
2
2
|
xmlns="http://www.w3.org/2000/svg"
|
|
3
3
|
viewBox="0 0 24 24"
|
|
4
4
|
fill="none"
|
|
@@ -10,12 +10,12 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=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 o=class extends b{constructor(){super(...arguments),this.iconSlot=new
|
|
13
|
+
</svg>`;let o=class extends b{constructor(){super(...arguments),this.iconSlot=new T(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.label="",this.loading=!1,this.target="",this.rel="",this.formNoValidate=!1,this.buildIcon=t=>this.loading?d` <span>${N}</span> `:d`
|
|
14
14
|
<span>
|
|
15
|
-
<slot ${
|
|
15
|
+
<slot ${k(this.iconSlot.slotRef)} @slotchange=${this.iconSlot.handleSlotChange}></slot>
|
|
16
16
|
${!this.iconSlot.hasSlottedIcon(":scope > *")&&t?w(t):c}
|
|
17
17
|
</span>
|
|
18
|
-
`}static get observedAttributes(){return[...super.observedAttributes,"tabindex"]}attributeChangedCallback(t,r,e){if(super.attributeChangedCallback(t,r,e),t!=="tabindex"||this.neutralizingTabindex)return;const s=e===null?null:Number(e),n=s===null||Number.isNaN(s)?null:s;n!==null&&n>=0?(this.innerTabindex=n,this.writeHostTabindex(null)):n===null&&e!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=n}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("clicked",{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const r=this.closest("form");if(r){const e=document.createElement("button");e.type="submit",e.hidden=!0,this.formNoValidate&&(e.formNoValidate=!0),r.appendChild(e),r.requestSubmit(e),e.remove()}}else this.buttonType==="reset"&&this.closest("form")?.reset()}render(){const t=
|
|
18
|
+
`}static get observedAttributes(){return[...super.observedAttributes,"tabindex"]}attributeChangedCallback(t,r,e){if(super.attributeChangedCallback(t,r,e),t!=="tabindex"||this.neutralizingTabindex)return;const s=e===null?null:Number(e),n=s===null||Number.isNaN(s)?null:s;n!==null&&n>=0?(this.innerTabindex=n,this.writeHostTabindex(null)):n===null&&e!==null?(this.innerTabindex=null,this.writeHostTabindex(null)):this.innerTabindex=n}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("clicked",{detail:{},bubbles:!0,composed:!0})),this.buttonType==="submit"){const r=this.closest("form");if(r){const e=document.createElement("button");e.type="submit",e.hidden=!0,this.formNoValidate&&(e.formNoValidate=!0),r.appendChild(e),r.requestSubmit(e),e.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:e,iconOnly:s}=this,n=s?this.getAttribute("aria-label")||this.label||c:c,l={"esp-field":!0,"icon-only":s,incognito:this.incognito,"is-collapsed":e,"has-icon":r};return this.href.length?d`
|
|
19
19
|
<div part="wrapper" class=${u(l)}>
|
|
20
20
|
<a
|
|
21
21
|
?disabled=${this.disabled}
|
|
@@ -42,7 +42,7 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnP
|
|
|
42
42
|
${this.buildIcon(t)}
|
|
43
43
|
</button>
|
|
44
44
|
</div>
|
|
45
|
-
`}};o.styles=[...b.styles,
|
|
45
|
+
`}};o.styles=[...b.styles,f`
|
|
46
46
|
:host {
|
|
47
47
|
--_esp-button-radius: var(--esp-size-border-radius);
|
|
48
48
|
}
|
|
@@ -80,7 +80,10 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnP
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
> span:nth-child(2) {
|
|
83
|
-
background-color: oklch(
|
|
83
|
+
background-color: oklch(
|
|
84
|
+
from var(--esp-color-action-background)
|
|
85
|
+
calc(l * ${g}) c h
|
|
86
|
+
);
|
|
84
87
|
display: none;
|
|
85
88
|
place-content: center;
|
|
86
89
|
border-left: 1px dotted var(--esp-color-border);
|
|
@@ -131,12 +134,18 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnP
|
|
|
131
134
|
|
|
132
135
|
&:hover,
|
|
133
136
|
&:focus-within {
|
|
134
|
-
background-color: oklch(
|
|
137
|
+
background-color: oklch(
|
|
138
|
+
from var(--esp-color-action-background) calc(l * ${$})
|
|
139
|
+
c h
|
|
140
|
+
);
|
|
135
141
|
|
|
136
142
|
button,
|
|
137
143
|
a {
|
|
138
144
|
> span:nth-child(2) {
|
|
139
|
-
background-color: oklch(
|
|
145
|
+
background-color: oklch(
|
|
146
|
+
from var(--esp-color-action-background)
|
|
147
|
+
calc(l * ${S}) c h
|
|
148
|
+
);
|
|
140
149
|
border-color: oklch(from var(--esp-color-border) calc(l * 1.2) c h);
|
|
141
150
|
}
|
|
142
151
|
}
|
|
@@ -187,7 +196,10 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnP
|
|
|
187
196
|
button,
|
|
188
197
|
a {
|
|
189
198
|
> span:nth-child(2) {
|
|
190
|
-
background-color: oklch(
|
|
199
|
+
background-color: oklch(
|
|
200
|
+
from var(--esp-color-action-background)
|
|
201
|
+
calc(l * ${g}) c h
|
|
202
|
+
);
|
|
191
203
|
border-color: var(--esp-color-border);
|
|
192
204
|
}
|
|
193
205
|
}
|
|
@@ -210,4 +222,4 @@ var i=function(p,t,r,e){var s=arguments.length,n=s<3?t:e===null?e=Object.getOwnP
|
|
|
210
222
|
transform: rotate(360deg);
|
|
211
223
|
}
|
|
212
224
|
}
|
|
213
|
-
`],i([
|
|
225
|
+
`],i([y()],o.prototype,"innerTabindex",void 0),i([a({attribute:"button-type",type:String})],o.prototype,"buttonType",void 0),i([a({type:Boolean})],o.prototype,"collapsed",void 0),i([a({type:Boolean,reflect:!0})],o.prototype,"disabled",void 0),i([a({type:String})],o.prototype,"href",void 0),i([a({attribute:"icon-only",type:Boolean})],o.prototype,"iconOnly",void 0),i([a({type:Boolean,reflect:!0})],o.prototype,"incognito",void 0),i([a({type:String})],o.prototype,"icon",void 0),i([a({type:String})],o.prototype,"label",void 0),i([a({type:Boolean,reflect:!0})],o.prototype,"loading",void 0),i([a({type:String})],o.prototype,"target",void 0),i([a({type:String})],o.prototype,"rel",void 0),i([a({attribute:"formnovalidate",type:Boolean})],o.prototype,"formNoValidate",void 0),i([v({capture:!1,passive:!0})],o.prototype,"handleClick",null),o=i([m("esp-button")],o);export{o as EspalierButton};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var c=function(
|
|
1
|
+
var c=function(a,e,s,n){var r=arguments.length,t=r<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,s):n,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(a,e,s,n);else for(var i=a.length-1;i>=0;i--)(l=a[i])&&(t=(r<3?l(t):r>3?l(e,s,t):l(e,s))||t);return r>3&&t&&Object.defineProperty(e,s,t),t};import{css as h,html as m}from"lit";import{customElement as y,property as f,state as u}from"lit/decorators.js";import{classMap as g}from"lit/directives/class-map.js";import{createRef as S,ref as p}from"lit/directives/ref.js";import{EspalierElementBase as d}from"../shared/esp-element-base.js";import{SlottedIconController as v}from"../shared/slotted-icon-controller.js";import{slotHasContent as w}from"../shared/slot-content.js";let o=class extends d{constructor(){super(...arguments),this.iconSlot=new v(this),this.secondarySlot=S(),this.hasSecondary=!1,this.truncate=!1,this.handleSecondarySlotChange=()=>{this.hasSecondary=w(this.secondarySlot.value)}}firstUpdated(e){super.firstUpdated(e),this.iconSlot.handleSlotChange(),this.handleSecondarySlotChange()}render(){const e={cell:!0,"has-icon":this.iconSlot.hasAssignedSlotContent,"has-secondary":this.hasSecondary,truncate:this.truncate};return m`
|
|
2
2
|
<span part="cell" class=${g(e)}>
|
|
3
3
|
<span part="icon" class="icon">
|
|
4
4
|
<slot
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EspalierElementBase } from "../shared/esp-element-base.js";
|
|
2
|
+
/**
|
|
3
|
+
* A labelled group of related links inside [`<esp-footer>`](/components/footer/).
|
|
4
|
+
* Supply ordinary anchors in the default slot; the component provides the
|
|
5
|
+
* compact vertical rhythm and an accessible navigation landmark.
|
|
6
|
+
*
|
|
7
|
+
* ```html
|
|
8
|
+
* <esp-footer-link-group heading="Explore">
|
|
9
|
+
* <a href="/components">Components</a>
|
|
10
|
+
* <a href="/guides">Guides</a>
|
|
11
|
+
* <a href="/api">API</a>
|
|
12
|
+
* </esp-footer-link-group>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @customElement esp-footer-link-group
|
|
16
|
+
* @slot - Links belonging to the group. Native anchors are preferred because
|
|
17
|
+
* footer links do not need application-menu disclosure or drawer behavior.
|
|
18
|
+
* @csspart nav - The group's navigation landmark.
|
|
19
|
+
* @csspart heading - The visible heading used to label the navigation landmark.
|
|
20
|
+
* @csspart links - The link-list container.
|
|
21
|
+
* @docPageTitle Footer Link Group
|
|
22
|
+
* @docUrl /components/footer/link-group
|
|
23
|
+
* @menuGroup Navigation
|
|
24
|
+
* @menuIcon list-details
|
|
25
|
+
*/
|
|
26
|
+
export declare class EspalierFooterLinkGroup extends EspalierElementBase {
|
|
27
|
+
/**
|
|
28
|
+
* Visible heading for the link group. It also labels the navigation
|
|
29
|
+
* landmark. When omitted, the landmark receives the fallback label
|
|
30
|
+
* “Footer links” without rendering an empty heading.
|
|
31
|
+
*/
|
|
32
|
+
heading: string;
|
|
33
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
34
|
+
static styles: import("lit").CSSResult[];
|
|
35
|
+
}
|
|
36
|
+
declare global {
|
|
37
|
+
interface HTMLElementTagNameMap {
|
|
38
|
+
"esp-footer-link-group": EspalierFooterLinkGroup;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var d=function(t,o,r,n){var s=arguments.length,e=s<3?o:n===null?n=Object.getOwnPropertyDescriptor(o,r):n,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(t,o,r,n);else for(var a=t.length-1;a>=0;a--)(l=t[a])&&(e=(s<3?l(e):s>3?l(o,r,e):l(o,r))||e);return s>3&&e&&Object.defineProperty(o,r,e),e};import{css as v,html as f,nothing as p}from"lit";import{customElement as g,property as u}from"lit/decorators.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";const h="esp-footer-link-group-heading";let i=class extends c{constructor(){super(...arguments),this.heading=""}render(){return f`
|
|
2
|
+
<nav
|
|
3
|
+
part="nav"
|
|
4
|
+
aria-labelledby=${this.heading?h:p}
|
|
5
|
+
aria-label=${this.heading?p:"Footer links"}
|
|
6
|
+
>
|
|
7
|
+
${this.heading?f`<h2 part="heading" id=${h}>${this.heading}</h2>`:p}
|
|
8
|
+
<div part="links" class="links"><slot></slot></div>
|
|
9
|
+
</nav>
|
|
10
|
+
`}};i.styles=[...c.styles,v`
|
|
11
|
+
:host {
|
|
12
|
+
display: block;
|
|
13
|
+
min-inline-size: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
nav {
|
|
17
|
+
display: grid;
|
|
18
|
+
gap: var(--esp-footer-link-group-gap, var(--esp-size-small));
|
|
19
|
+
min-inline-size: 0;
|
|
20
|
+
color: var(--esp-footer-color, var(--esp-color-text));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h2 {
|
|
24
|
+
margin: 0;
|
|
25
|
+
color: var(--esp-footer-heading-color, var(--esp-color-headings));
|
|
26
|
+
font-family: var(--esp-font-headings);
|
|
27
|
+
font-size: var(--esp-type-normal);
|
|
28
|
+
font-weight: var(--esp-font-weight-headings);
|
|
29
|
+
line-height: 1.25;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.links {
|
|
33
|
+
display: grid;
|
|
34
|
+
gap: var(--esp-size-tiny);
|
|
35
|
+
min-inline-size: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
::slotted(a) {
|
|
39
|
+
inline-size: fit-content;
|
|
40
|
+
max-inline-size: 100%;
|
|
41
|
+
color: var(--esp-footer-link-color, var(--esp-color-link));
|
|
42
|
+
overflow-wrap: anywhere;
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
text-underline-offset: 0.18em;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::slotted(a:hover) {
|
|
48
|
+
color: var(--esp-footer-link-hover-color, var(--esp-color-link-hover));
|
|
49
|
+
text-decoration: underline;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
::slotted(a:focus-visible) {
|
|
53
|
+
border-radius: var(--esp-size-border-radius);
|
|
54
|
+
outline: var(--esp-footer-focus-outline, 2px solid var(--esp-color-link));
|
|
55
|
+
outline-offset: 3px;
|
|
56
|
+
}
|
|
57
|
+
`],d([u({type:String})],i.prototype,"heading",void 0),i=d([g("esp-footer-link-group")],i);export{i as EspalierFooterLinkGroup};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { type PropertyValues } from "lit";
|
|
2
|
+
import { EspalierElementBase } from "../shared/esp-element-base.js";
|
|
3
|
+
import "./esp-footer-link-group.js";
|
|
4
|
+
export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
|
|
5
|
+
/**
|
|
6
|
+
* A responsive site footer with structured spaces for branding, feature
|
|
7
|
+
* artwork, link groups, supporting actions, and legal or utility content.
|
|
8
|
+
* Its background remains full-bleed while its content automatically aligns
|
|
9
|
+
* to the surface of a containing [`<esp-page>`](/components/page/).
|
|
10
|
+
*
|
|
11
|
+
* Use [`<esp-footer-link-group>`](/components/footer/link-group/) children for
|
|
12
|
+
* ordinary navigation columns. `columns` is a maximum: the grid always drops
|
|
13
|
+
* columns when they no longer fit.
|
|
14
|
+
*
|
|
15
|
+
* ```html
|
|
16
|
+
* <esp-footer
|
|
17
|
+
* brand-logo="/assets/favicon.svg"
|
|
18
|
+
* brand-text="Espalier"
|
|
19
|
+
* brand-href="/"
|
|
20
|
+
* brand-alt="Espalier logo"
|
|
21
|
+
* columns="3">
|
|
22
|
+
* <esp-footer-link-group heading="Explore">
|
|
23
|
+
* <a href="/components">Components</a>
|
|
24
|
+
* <a href="/api">API</a>
|
|
25
|
+
* </esp-footer-link-group>
|
|
26
|
+
* <esp-footer-link-group heading="Learn">
|
|
27
|
+
* <a href="/guides/getting-started">Getting started</a>
|
|
28
|
+
* <a href="/guides/styling">Styling</a>
|
|
29
|
+
* </esp-footer-link-group>
|
|
30
|
+
* <p slot="aside">Themeable web components built on web standards.</p>
|
|
31
|
+
* <div slot="bottom">Copyright 2026 Example Organization</div>
|
|
32
|
+
* </esp-footer>
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* A slotted brand replaces configured branding, while the media slot accepts
|
|
36
|
+
* a responsive `picture`, native image, or `esp-image`. Media spans the
|
|
37
|
+
* surface-aligned content well; use the decorative background layer for
|
|
38
|
+
* edge-to-edge artwork:
|
|
39
|
+
*
|
|
40
|
+
* ```html
|
|
41
|
+
* <esp-footer columns="4">
|
|
42
|
+
* <picture slot="media">
|
|
43
|
+
* <source media="(prefers-color-scheme: dark)" srcset="/assets/canvas-bg-dark.jpg" />
|
|
44
|
+
* <img
|
|
45
|
+
* src="/assets/canvas-bg.jpg"
|
|
46
|
+
* alt="A colorful floral pattern"
|
|
47
|
+
* style="display: block; width: 100%; height: auto;" />
|
|
48
|
+
* </picture>
|
|
49
|
+
* <a slot="brand" href="/" aria-label="Espalier home">
|
|
50
|
+
* <img src="/assets/espalier-logo.svg" alt="Espalier" />
|
|
51
|
+
* </a>
|
|
52
|
+
* <esp-footer-link-group heading="Product">
|
|
53
|
+
* <a href="/components">Components</a>
|
|
54
|
+
* </esp-footer-link-group>
|
|
55
|
+
* </esp-footer>
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* Decorative art uses an image layer independent of the base color. The same
|
|
59
|
+
* API supports a repeating landscape band or one large cover image:
|
|
60
|
+
*
|
|
61
|
+
* ```html
|
|
62
|
+
* <style>
|
|
63
|
+
* esp-footer.mountains {
|
|
64
|
+
* --esp-footer-background: oklch(0.48 0.12 145);
|
|
65
|
+
* --esp-footer-background-image-opacity: 0.55;
|
|
66
|
+
* --esp-footer-background-image:
|
|
67
|
+
* linear-gradient(to bottom, transparent 8rem, oklch(0.48 0.12 145)),
|
|
68
|
+
* url("/assets/espalier-geometric-texture.png");
|
|
69
|
+
* --esp-footer-background-repeat: no-repeat, repeat-x;
|
|
70
|
+
* --esp-footer-background-position: 0 0, top;
|
|
71
|
+
* --esp-footer-background-size: 100% 100%, auto 10rem;
|
|
72
|
+
* --esp-footer-padding-block: 6rem;
|
|
73
|
+
* }
|
|
74
|
+
*
|
|
75
|
+
* esp-footer.photo {
|
|
76
|
+
* --esp-footer-background: oklch(0.2 0.04 216);
|
|
77
|
+
* --esp-footer-heading-color: white;
|
|
78
|
+
* --esp-footer-background-image:
|
|
79
|
+
* linear-gradient(oklch(0.1 0 0 / 0.55), oklch(0.1 0 0 / 0.55)),
|
|
80
|
+
* url("/assets/canvas-bg.jpg");
|
|
81
|
+
* --esp-footer-background-repeat: no-repeat;
|
|
82
|
+
* --esp-footer-background-position: center;
|
|
83
|
+
* --esp-footer-background-size: cover;
|
|
84
|
+
* }
|
|
85
|
+
* </style>
|
|
86
|
+
* <esp-footer class="mountains" brand-text="Mountain Studio"></esp-footer>
|
|
87
|
+
* <esp-footer class="photo" brand-text="Photo Studio"></esp-footer>
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* Surface alignment is automatic inside `esp-page`; opt out only when the
|
|
91
|
+
* footer's content should also span the entire bar:
|
|
92
|
+
*
|
|
93
|
+
* ```html
|
|
94
|
+
* <esp-page align="center" style="--esp-page-max-width: 36rem;">
|
|
95
|
+
* <main>Surface-aligned page content</main>
|
|
96
|
+
* <esp-footer slot="footer" brand-text="Aligned Studio" columns="3">
|
|
97
|
+
* <esp-footer-link-group heading="Explore">
|
|
98
|
+
* <a href="/work">Work</a>
|
|
99
|
+
* <a href="/about">About</a>
|
|
100
|
+
* </esp-footer-link-group>
|
|
101
|
+
* </esp-footer>
|
|
102
|
+
* </esp-page>
|
|
103
|
+
*
|
|
104
|
+
* <esp-footer full-bleed-content brand-text="Full-width Studio"></esp-footer>
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* @customElement esp-footer
|
|
108
|
+
* @slot media - Meaningful artwork spanning the surface-aligned content well,
|
|
109
|
+
* preferably responsive `<picture>` markup or an `esp-image` with appropriate
|
|
110
|
+
* alternative text.
|
|
111
|
+
* @slot brand - Custom brand identity. Overrides configured brand properties.
|
|
112
|
+
* @slot - `esp-footer-link-group` navigation columns.
|
|
113
|
+
* @slot aside - Supporting content such as a newsletter, call to action,
|
|
114
|
+
* contact details, social links, or locale controls.
|
|
115
|
+
* @slot bottom - Copyright, legal/utility links, attribution, accessibility
|
|
116
|
+
* controls, site credit, or a final wordmark.
|
|
117
|
+
* @csspart footer - The native footer landmark and full-bleed base surface.
|
|
118
|
+
* @csspart background - The independent decorative image layer.
|
|
119
|
+
* @csspart content - The surface-aligned content wrapper.
|
|
120
|
+
* @csspart media - The media region spanning the aligned content well.
|
|
121
|
+
* @csspart primary - The grid containing brand, link groups, and aside content.
|
|
122
|
+
* @csspart brand - The brand region.
|
|
123
|
+
* @csspart groups - The link-group grid.
|
|
124
|
+
* @csspart aside - The supporting-content region.
|
|
125
|
+
* @csspart bottom - The final legal/utility region.
|
|
126
|
+
* @cssprop --esp-footer-background - Base footer color. Defaults to `var(--esp-color-layer-2)`.
|
|
127
|
+
* @cssprop --esp-footer-color - Body text color. Defaults to `var(--esp-color-text)`.
|
|
128
|
+
* @cssprop --esp-footer-heading-color - Heading and configured-brand color. Defaults to `var(--esp-color-headings)`.
|
|
129
|
+
* @cssprop --esp-footer-link-color - Link color. Defaults to `var(--esp-color-link)`.
|
|
130
|
+
* @cssprop --esp-footer-link-hover-color - Hovered link color. Defaults to `var(--esp-color-link-hover)`.
|
|
131
|
+
* @cssprop --esp-footer-focus-outline - Focus-visible outline. Defaults to `2px solid var(--esp-color-link)`.
|
|
132
|
+
* @cssprop --esp-footer-border - Block-start footer border. Defaults to `1px solid var(--esp-color-border)`.
|
|
133
|
+
* @cssprop --esp-footer-padding-block - Content block padding. Defaults to `var(--esp-size-padding-page)`.
|
|
134
|
+
* @cssprop --esp-footer-padding-inline - Content inline padding. Defaults to `var(--esp-size-padding-page)`.
|
|
135
|
+
* @cssprop --esp-footer-section-gap - Gap between media, primary, and bottom regions. Defaults to `var(--esp-size-big)`.
|
|
136
|
+
* @cssprop --esp-footer-column-gap - Gap between link-group columns and major primary regions. Defaults to `var(--esp-size-padding-page)`.
|
|
137
|
+
* @cssprop --esp-footer-row-gap - Compact-layout row gap. Defaults to `var(--esp-size-big)`.
|
|
138
|
+
* @cssprop --esp-footer-link-group-min-width - Intrinsic minimum link-group column width. Defaults to `10rem`.
|
|
139
|
+
* @cssprop --esp-footer-link-group-gap - Space between a link-group heading and its links. Defaults to `var(--esp-size-small)`.
|
|
140
|
+
* @cssprop --esp-footer-brand-logo-size - Configured logo block size. Defaults to `3rem`.
|
|
141
|
+
* @cssprop --esp-footer-brand-logo-max-width - Configured logo maximum inline size. Defaults to `12rem`.
|
|
142
|
+
* @cssprop --esp-footer-background-image - Decorative image or gradient layer. Defaults to `none`.
|
|
143
|
+
* @cssprop --esp-footer-background-image-opacity - Decorative layer opacity. Defaults to `1`.
|
|
144
|
+
* @cssprop --esp-footer-background-repeat - Decorative layer repeat behavior. Defaults to `repeat`.
|
|
145
|
+
* @cssprop --esp-footer-background-position - Decorative layer position. Defaults to `0 0`.
|
|
146
|
+
* @cssprop --esp-footer-background-size - Decorative layer size. Defaults to `auto`.
|
|
147
|
+
* @cssprop --esp-footer-background-blend-mode - Decorative layer blend mode. Defaults to `normal`.
|
|
148
|
+
* @cssprop --esp-footer-content-max-width - Surface-alignment cap published by `esp-page`. Defaults to `100%`.
|
|
149
|
+
* @cssprop --esp-footer-content-lead - Fraction of surplus placed before content (`0`, `0.5`, or `1`). Defaults to `0`.
|
|
150
|
+
* @docPageTitle Footer
|
|
151
|
+
* @docUrl /components/footer
|
|
152
|
+
* @menuGroup Structure
|
|
153
|
+
* @menuLabel Footer
|
|
154
|
+
* @menuIcon layout
|
|
155
|
+
*/
|
|
156
|
+
export declare class EspalierFooter extends EspalierElementBase {
|
|
157
|
+
/** Configured brand text used when the `brand` slot is empty. */
|
|
158
|
+
brandText: string;
|
|
159
|
+
/** Configured brand logo URL used when the `brand` slot is empty. */
|
|
160
|
+
brandLogo: string;
|
|
161
|
+
/** Optional configured-brand link target. */
|
|
162
|
+
brandHref: string;
|
|
163
|
+
/** Accessible text for a configured logo. */
|
|
164
|
+
brandAlt: string;
|
|
165
|
+
/**
|
|
166
|
+
* Maximum number of link-group columns. Numeric values cap the wide layout;
|
|
167
|
+
* the intrinsic grid still renders fewer columns when space is limited.
|
|
168
|
+
*/
|
|
169
|
+
columns: FooterColumns;
|
|
170
|
+
/**
|
|
171
|
+
* Opt out of the `esp-page` surface-alignment contract and allow footer
|
|
172
|
+
* content to use the full bar width. The background is always full-bleed.
|
|
173
|
+
*/
|
|
174
|
+
fullBleedContent: boolean;
|
|
175
|
+
/** Optional accessible label for pages containing multiple footer landmarks. */
|
|
176
|
+
landmarkLabel: string;
|
|
177
|
+
protected willUpdate(changedProperties: PropertyValues): void;
|
|
178
|
+
protected firstUpdated(changedProperties: PropertyValues): void;
|
|
179
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
180
|
+
static styles: import("lit").CSSResult[];
|
|
181
|
+
}
|
|
182
|
+
declare global {
|
|
183
|
+
interface HTMLElementTagNameMap {
|
|
184
|
+
"esp-footer": EspalierFooter;
|
|
185
|
+
}
|
|
186
|
+
}
|