mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
add sync
This commit is contained in:
@@ -770,6 +770,112 @@ const App = () => {
|
||||
};
|
||||
```
|
||||
|
||||
### Syncing with the Anchor's Dimensions
|
||||
|
||||
Use the `sync` attribute to make the popup the same width or height as the anchor element. This is useful for controls that need the popup to stay the same width or height as the trigger.
|
||||
|
||||
```html preview
|
||||
<div class="popup-match">
|
||||
<sl-popup placement="top" sync="width" active>
|
||||
<span slot="anchor"></span>
|
||||
<div class="box"></div>
|
||||
</sl-popup>
|
||||
|
||||
<sl-select value="width" label="Sync">
|
||||
<sl-menu-item value="width">Width</sl-menu-item>
|
||||
<sl-menu-item value="height">Height</sl-menu-item>
|
||||
<sl-menu-item value="both">Both</sl-menu-item>
|
||||
<sl-menu-item value="">None</sl-menu-item>
|
||||
</sl-select>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.popup-match span[slot='anchor'] {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: dashed 2px var(--sl-color-neutral-600);
|
||||
margin: 50px;
|
||||
}
|
||||
|
||||
.popup-match .box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
background: var(--sl-color-primary-600);
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
}
|
||||
|
||||
.popup-match sl-switch {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const container = document.querySelector('.popup-match');
|
||||
const popup = container.querySelector('sl-popup');
|
||||
const fixed = container.querySelector('sl-switch');
|
||||
const sync = container.querySelector('sl-select');
|
||||
|
||||
sync.addEventListener('sl-change', () => (popup.sync = sync.value));
|
||||
</script>
|
||||
```
|
||||
|
||||
```jsx react
|
||||
import { useState } from 'react';
|
||||
import { SlPopup, SlSelect, SlMenuItem } from '@shoelace-style/shoelace/dist/react';
|
||||
|
||||
const css = `
|
||||
.popup-match span[slot='anchor'] {
|
||||
display: inline-block;
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
border: dashed 2px var(--sl-color-neutral-600);
|
||||
margin: 50px;
|
||||
}
|
||||
|
||||
.popup-match .box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 50px;
|
||||
min-height: 50px;
|
||||
background: var(--sl-color-primary-600);
|
||||
border-radius: var(--sl-border-radius-medium);
|
||||
}
|
||||
|
||||
.popup-match sl-switch {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
`;
|
||||
|
||||
const App = () => {
|
||||
const [sync, setSync] = useState('width');
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="popup-match">
|
||||
<SlPopup placement="top" sync={sync} active>
|
||||
<span slot="anchor" />
|
||||
<div class="box" />
|
||||
</SlPopup>
|
||||
|
||||
<SlSelect value={sync} label="Sync" onSlChange={event => setSync(event.target.value)}>
|
||||
<SlMenuItem value="width">Width</SlMenuItem>
|
||||
<SlMenuItem value="height">Height</SlMenuItem>
|
||||
<SlMenuItem value="both">Both</SlMenuItem>
|
||||
<SlMenuItem value="">None</SlMenuItem>
|
||||
</SlSelect>
|
||||
|
||||
{sync}
|
||||
</div>
|
||||
|
||||
<style>{css}</style>
|
||||
</>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### Positioning Strategy
|
||||
|
||||
By default, the popup is positioned using an absolute positioning strategy. However, if your anchor is fixed or exists within a container that has `overflow: auto|hidden`, the popup risks being clipped. To work around this, you can use a fixed positioning strategy by setting the `strategy` attribute to `fixed`.
|
||||
|
||||
@@ -10,6 +10,7 @@ _During the beta period, these restrictions may be relaxed in the event of a mis
|
||||
|
||||
## Next
|
||||
|
||||
- Added the `sync` attribute to `<sl-popup>`
|
||||
- Fixed a bug in `<sl-tree>` where dynamically changing slotted items wouldn't update the tree properly
|
||||
- Fixed a bug in `<sl-split-panel>` that caused the panel to stack when clicking on the divider in mobile versions of Chrome [#862](https://github.com/shoelace-style/shoelace/issues/862)
|
||||
- Improved single selection in `<sl-tree>` so nodes expand and collapse and receive selection when clicking on the label
|
||||
|
||||
@@ -160,6 +160,9 @@ export default class SlPopup extends ShoelaceElement {
|
||||
/** When set, this will cause the popup to automatically resize itself to prevent it from overflowing. */
|
||||
@property({ attribute: 'auto-size', type: Boolean }) autoSize = false;
|
||||
|
||||
/** Syncs the popup's width or height to that of the anchor element. */
|
||||
@property() sync: 'width' | 'height' | 'both';
|
||||
|
||||
/**
|
||||
* The auto-size boundary describes clipping element(s) that overflow will be checked relative to when resizing. By
|
||||
* default, the boundary includes overflow ancestors that will cause the element to be clipped. If needed, you can
|
||||
@@ -277,7 +280,25 @@ export default class SlPopup extends ShoelaceElement {
|
||||
offset({ mainAxis: this.distance, crossAxis: this.skidding })
|
||||
];
|
||||
|
||||
// First we flip
|
||||
// First we sync width/height
|
||||
if (this.sync) {
|
||||
middleware.push(
|
||||
size({
|
||||
apply: ({ rects }) => {
|
||||
const syncWidth = this.sync === 'width' || this.sync === 'both';
|
||||
const syncHeight = this.sync === 'height' || this.sync === 'both';
|
||||
this.popup.style.width = syncWidth ? `${rects.reference.width}px` : '';
|
||||
this.popup.style.height = syncHeight ? `${rects.reference.height}px` : '';
|
||||
}
|
||||
})
|
||||
);
|
||||
} else {
|
||||
// Cleanup styles if we're not matching width/height
|
||||
this.popup.style.width = '';
|
||||
this.popup.style.height = '';
|
||||
}
|
||||
|
||||
// Then we flip
|
||||
if (this.flip) {
|
||||
middleware.push(
|
||||
flip({
|
||||
|
||||
Reference in New Issue
Block a user