Skip to content

Commit

Permalink
fix(shell): update shell to correctly position calcite shell panel at…
Browse files Browse the repository at this point in the history
… shell's bottom (#9748)

**Related Issue:**
[#8269](#8269)

## Summary
Update `calcite-shell` to correctly position `calcite-shell-panel` with
`slot="panel-bottom"` at calcite-shell's bottom, when there is no
`calcite-shell-panel` with `slot="panel-top"`.
  • Loading branch information
aPreciado88 authored and github-actions[bot] committed Jul 30, 2024
1 parent d4448de commit 5959db7
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const CSS = {
main: "main",
content: "content",
contentBehind: "content--behind",
contentBottom: "content-bottom",
contentNonInteractive: "content--non-interactive",
footer: "footer",
positionedSlotWrapper: "positioned-slot-wrapper",
Expand Down
18 changes: 18 additions & 0 deletions packages/calcite-components/src/components/shell/shell.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,4 +121,22 @@ describe("calcite-shell", () => {
const panelTop = await contentNode.find(`slot[name="${SLOTS.panelTop}"]`);
expect(panelTop).toBeNull();
});

it("should position panel-bottom slot at content's bottom when no other panels exist", async () => {
const page = await newE2EPage();

await page.setContent(
html`<calcite-shell>
<calcite-shell-panel slot="${SLOTS.panelBottom}" display-mode="float" layout="horizontal">
<p>Primary Content</p>
</calcite-shell-panel>
</calcite-shell>`,
);

await page.waitForChanges();

const contentBottom = await page.find(`calcite-shell >>> .${CSS.contentBottom}`);

expect(contentBottom).not.toBeNull();
});
});
5 changes: 5 additions & 0 deletions packages/calcite-components/src/components/shell/shell.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

.content {
@apply overflow-auto;
justify-content: space-between;
}

.content ::slotted(calcite-shell-center-row),
Expand Down Expand Up @@ -97,6 +98,10 @@ slot[name="panel-bottom"]::slotted(calcite-shell-center-row:not([detached])) {
min-inline-size: 0;
}

.content-bottom {
justify-content: flex-end;
}

::slotted(calcite-shell-center-row) {
flex: none;
align-self: stretch;
Expand Down
30 changes: 30 additions & 0 deletions packages/calcite-components/src/components/shell/shell.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ const centerRowHTML = html`
</calcite-panel>
`;

const bottomPanelHTML = html`
<calcite-panel heading="Panel bottom content">
<div>Content</div>
</calcite-panel>
`;

const centerRowWithActionBarHTML = html`
<calcite-action-bar slot="action-bar">
<calcite-action-group>
Expand Down Expand Up @@ -842,6 +848,30 @@ export const slottedPanelTop_TestOnly = (): string =>
</calcite-shell>
`);

export const contentBehindPanelBottom = (): string =>
html(`
<calcite-shell
content-behind
style="
width:700px;
height:700px;
position:relative;
"
>
<div
style="
width:100%;
height:100%;
background-image: linear-gradient(45deg, #ccc 25%, transparent 25%),
linear-gradient(-45deg, #ccc 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, #ccc 75%),
linear-gradient(-45deg, transparent 75%, #ccc 75%);
background-size: 20px 20px;
background-position: 0 0, 0 10px, 10px -10px, -10px 0px;"></div>
<calcite-shell-panel slot="panel-bottom" display-mode="float" layout="horizontal">${bottomPanelHTML}</calcite-shell-panel>
</calcite-shell>
`);

export const slottedPanelBottom_TestOnly = (): string =>
html(`
<calcite-shell
Expand Down
46 changes: 41 additions & 5 deletions packages/calcite-components/src/components/shell/shell.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Element, Fragment, h, Listen, Prop, State, VNode } from "@stencil/core";
import { Component, Element, Fragment, h, Listen, Prop, State, VNode, Watch } from "@stencil/core";
import {
ConditionalSlotComponent,
connectConditionalSlotComponent,
Expand Down Expand Up @@ -74,8 +74,20 @@ export class Shell implements ConditionalSlotComponent {

@State() hasSheets = false;

@State() hasPanelTop = false;

@State() hasPanelBottom = false;

@State() hasOnlyPanelBottom = false;

@State() panelIsResizing = false;

@Watch("hasPanelTop")
@Watch("hasPanelBottom")
updateHasOnlyPanelBottom(): void {
this.hasOnlyPanelBottom = !this.hasPanelTop && this.hasPanelBottom;
}

// --------------------------------------------------------------------------
//
// Lifecycle
Expand Down Expand Up @@ -131,6 +143,14 @@ export class Shell implements ConditionalSlotComponent {
});
};

handlePanelTopChange = (event: Event): void => {
this.hasPanelTop = slotChangeHasAssignedElement(event);
};

handlePanelBottomChange = (event: Event): void => {
this.hasPanelBottom = slotChangeHasAssignedElement(event);
};

// --------------------------------------------------------------------------
//
// Render Methods
Expand Down Expand Up @@ -188,8 +208,16 @@ export class Shell implements ConditionalSlotComponent {
const deprecatedCenterRowSlotNode: VNode = (
<slot key="center-row-slot" name={SLOTS.centerRow} />
);
const panelBottomSlotNode: VNode = <slot key="panel-bottom-slot" name={SLOTS.panelBottom} />;
const panelTopSlotNode: VNode = <slot key="panel-top-slot" name={SLOTS.panelTop} />;
const panelBottomSlotNode: VNode = (
<slot
key="panel-bottom-slot"
name={SLOTS.panelBottom}
onSlotchange={this.handlePanelBottomChange}
/>
);
const panelTopSlotNode: VNode = (
<slot key="panel-top-slot" name={SLOTS.panelTop} onSlotchange={this.handlePanelTopChange} />
);

const contentContainerKey = "content-container";

Expand All @@ -204,14 +232,22 @@ export class Shell implements ConditionalSlotComponent {
>
{defaultSlotContainerNode}
</div>,
<div class={CSS.contentBehindCenterContent}>
<div
class={{
[CSS.contentBehindCenterContent]: true,
[CSS.contentBottom]: this.hasOnlyPanelBottom,
}}
>
{panelTopSlotNode}
{panelBottomSlotNode}
{deprecatedCenterRowSlotNode}
</div>,
]
: [
<div class={CSS.content} key={contentContainerKey}>
<div
class={{ [CSS.content]: true, [CSS.contentBottom]: this.hasOnlyPanelBottom }}
key={contentContainerKey}
>
{panelTopSlotNode}
{defaultSlotContainerNode}
{panelBottomSlotNode}
Expand Down

0 comments on commit 5959db7

Please sign in to comment.