Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-pillows-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solidmaterial/landing-page': minor
---

Add action button to EmptyState component
5 changes: 5 additions & 0 deletions .changeset/dirty-icons-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@solidmaterial/material': minor
---

Add supporting-pane canonical layout
12 changes: 12 additions & 0 deletions apps/landing-page/src/components/empty-state/EmptyState.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,16 @@
place-content: center;
justify-items: center;
text-align: center;

& > md-icon {
padding-bottom: var(--md-user-spacing-xs);
}

& > span {
padding-top: var(--md-user-spacing-xs);
}

& > sm-button {
padding-top: var(--md-user-spacing-lg);
}
}
6 changes: 5 additions & 1 deletion apps/landing-page/src/components/empty-state/EmptyState.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { JSX, VoidComponent } from 'solid-js';
import type { MaterialButtonProps } from '@solidmaterial/material/components/button';
import type { FlowProps, JSX, VoidComponent } from 'solid-js';

import { MaterialButton } from '@solidmaterial/material/components/button';
import { MaterialIcon } from '@solidmaterial/material/components/icon';
import { H1, Span } from '@solidmaterial/material/components/typography';
import { Show } from 'solid-js';
Expand All @@ -10,6 +12,7 @@ export interface EmptyStateProps {
label: string;
supportingText?: string;
icon?: JSX.Element;
action?: FlowProps<MaterialButtonProps>;
}

export const EmptyState: VoidComponent<EmptyStateProps> = props => {
Expand All @@ -26,6 +29,7 @@ export const EmptyState: VoidComponent<EmptyStateProps> = props => {
{props.supportingText}
</Span>
</Show>
<Show when={props.action}>{action => <MaterialButton {...action()} />}</Show>
</main>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@
display: flex;
flex-direction: row;
gap: 12px;
padding-bottom: var(--md-user-spacing-md);

&:not(:empty) {
padding-bottom: var(--md-user-spacing-md);
}

& > h1 {
color: var(--md-sys-color-on-surface-variant);
Expand Down
10 changes: 6 additions & 4 deletions packages/material/src/layouts/body-layout/MaterialBodyLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import type { TwoPaneLayoutProps } from './pane-layouts/pane-layout.types';
import { SplitPaneLayout } from './layouts/split-pane-layout/SplitPaneLayout';
import { TwoPaneFixedFlexibleLayout } from './layouts/two-pane-fixed-flexible-layout/TwoPaneFixedFlexibleLayout';
import { TwoPaneFlexibleFixedLayout } from './layouts/two-pane-flexible-fixed-layout/TwoPaneFlexibleFixedLayout';
import { TwoFlexiblePanesLayout } from './pane-layouts/two-flexible-panes-layout/TwoFlexiblePanesLayout';

export type MaterialBodyLayoutVariant = 'split' | 'flexible-fixed' | 'fixed-flexible';
export type MaterialBodyLayoutVariant = 'split' | 'flexible-fixed' | 'fixed-flexible' | 'flexible-flexible';

export interface MaterialBodyLayoutProps extends MaterialBodyLayoutWithDragHandleProps {
variant: MaterialBodyLayoutVariant;
Expand All @@ -24,7 +25,8 @@ export interface MaterialBodyLayoutProps extends MaterialBodyLayoutWithDragHandl
const LAYOUTS: Record<MaterialBodyLayoutVariant, FlowComponent<TwoPaneLayoutProps>> = {
split: SplitPaneLayout,
'flexible-fixed': TwoPaneFlexibleFixedLayout,
'fixed-flexible': TwoPaneFixedFlexibleLayout
'fixed-flexible': TwoPaneFixedFlexibleLayout,
'flexible-flexible': TwoFlexiblePanesLayout
};

export const MaterialBodyLayout: FlowComponent<MaterialBodyLayoutProps> = props => {
Expand All @@ -37,8 +39,8 @@ export const MaterialBodyLayout: FlowComponent<MaterialBodyLayoutProps> = props
const railWidth = () => navigationRailWidth?.() ?? 0;

const margin = () => (Breakpoints.isCompactWidth() ? 16 : 24);
const marginLeft = () => (railWidth() === 0 && visiblePanes().length > 1 ? margin() : 0);
const marginRight = () => (railWidth() > 0 || visiblePanes().length > 1 ? margin() : 0);
const marginLeft = () => (railWidth() === 0 && visiblePanes().length > 1 && props.rounded !== false ? margin() : 0);
const marginRight = () => (visiblePanes().length > 1 && props.rounded !== false ? margin() : 0);

const windowSize = createWindowSize();
const maximumWidth = () => windowSize.width - marginLeft() - marginRight() - railWidth();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export type DragHandlePosition = {
};

export interface MaterialBodyLayoutWithDragHandleProps {
rounded?: boolean;
showDragHandle?: boolean;
dragHandleAriaLabel?: string;
dragHandleAriaValue?: (position: DragHandlePosition) => string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const SplitPaneLayout: FlowComponent<TwoPaneLayoutProps> = props => {
width={fixedPaneWidth()}
snapWidths={snapWidths()}
preferredWidth={visuallyCentered()}
rounded={props.rounded}
showDragHandle={showDragHandle()}
dragHandleAriaLabel={props.dragHandleAriaLabel}
dragHandleAriaValue={props.dragHandleAriaValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const TwoPaneFixedFlexibleLayout: FlowComponent<TwoPaneLayoutProps> = pro
width={fixedPaneWidth()}
snapWidths={snapWidths()}
preferredWidth={spacerVisuallyCentered()}
rounded={props.rounded}
showDragHandle={showDragHandle()}
dragHandleAriaLabel={props.dragHandleAriaLabel}
dragHandleAriaValue={props.dragHandleAriaValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export const TwoPaneFlexibleFixedLayout: FlowComponent<TwoPaneLayoutProps> = pro
width={fixedPaneWidth()}
snapWidths={snapWidths()}
preferredWidth={spacerVisuallyCentered()}
rounded={props.rounded}
showDragHandle={showDragHandle()}
dragHandleAriaLabel={props.dragHandleAriaLabel}
dragHandleAriaValue={props.dragHandleAriaValue}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
@layer material.components {
.layout {
display: flex;
contain: layout size;
height: 100%;

view-transition-name: sm-body-layout;

/* Do not apply transition to nested layout */
.layout {
view-transition-name: none;
}
}

.pane {
flex-grow: 1;
height: 100%;
contain: style;
overflow-y: auto;
}

.layout:not([data-rounded='false']) > .pane {
padding-block: var(--md-comp-pane-container-margin-block);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { FlowComponent } from 'solid-js';

import { Show, children, createMemo } from 'solid-js';

import styles from './TwoFlexiblePanesLayout.module.css';

export interface TwoFlexiblePanesLayoutProps {
rounded?: boolean;
margin: [number, number];
class?: string | undefined;
}

export const TwoFlexiblePanesLayout: FlowComponent<TwoFlexiblePanesLayoutProps> = props => {
const panes = children(() => props.children);
const visiblePanesCount = createMemo(() => panes.toArray().filter(item => item !== undefined).length);

return (
<sm-body-layout
attr:data-rounded={props.rounded}
classList={{
[styles['layout']!]: true,
[props.class ?? '']: props.class !== undefined
}}
style={{
'padding-inline-start': `${props.margin[0]}px`,
'padding-inline-end': `${props.margin[1]}px`
}}
>
<div class={styles['pane']}>{panes.toArray()[0]}</div>
<Show when={visiblePanesCount() > 1}>
<div class={styles['pane']}>{panes.toArray()[1]}</div>
</Show>
</sm-body-layout>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
}

view-transition-name: sm-body-layout;

/* Do not apply transition to nested layout */
.layout {
view-transition-name: none;
}
}

.spacer {
Expand All @@ -32,4 +37,8 @@
height: 100%;
contain: inline-size style;
}

.layout:is(:has(.spacer):not([data-rounded='false']), [data-rounded='true']) > .pane {
padding-block: var(--md-comp-pane-container-margin-block);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export const TwoPanesWithSpacerLayout: FlowComponent<TwoPanesWithSpacerLayoutPro
return (
<sm-body-layout
bool:data-dragging={isDraggingHandle()}
attr:data-rounded={props.rounded}
classList={{
[styles['layout']!]: true,
[props.class ?? '']: props.class !== undefined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
view-transition-name: none;

/* Apply the transition to just the detail pane (when 2 panes are visible) */
& > :last-child sm-pane > * {
& > :last-child > sm-pane > :first-child {
view-transition-name: sm-detail-pane;
height: 100%;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { FlowComponent } from 'solid-js';

import { Match, Show, Switch, createEffect, createSignal } from 'solid-js';

import { MaterialBottomSheet } from '../../../components/bottom-sheet';
import { MaterialSideSheet } from '../../../components/side-sheet/MaterialSideSheet';
import { Breakpoints } from '../../../utils';
import { MaterialPane } from '../../pane/MaterialPane';

export type MaterialSupportingPaneContainerVariant = 'standard' | 'modal';

export interface MaterialSupportingPaneProps {
variant: MaterialSupportingPaneContainerVariant;
title?: string;
dragHandle?: boolean;
dragHandleAriaLabel?: string;
open?: boolean;
onClose?: () => void;
}

export const MaterialSupportingPane: FlowComponent<MaterialSupportingPaneProps> = props => {
const isMobile = () => Breakpoints.isCompactWidth() || Breakpoints.isMediumWidth();

const [isOpen, setOpen] = createSignal(props.open ?? true);

createEffect(() => {
setOpen(props.open ?? true);
});

return (
<MaterialPane>
<Switch>
<Match when={isMobile()}>
<Show when={props.variant === 'modal'} fallback={<aside bool:data-open={isOpen()}>{props.children}</aside>}>
<MaterialBottomSheet
variant="modal"
dragHandle={props.dragHandle}
dragHandleAriaLabel={props.dragHandleAriaLabel}
open={isOpen()}
onClose={() => props.onClose?.()}
>
{props.children}
</MaterialBottomSheet>
</Show>
</Match>
<Match when={!isMobile()}>
<MaterialSideSheet
open={isOpen()}
variant={props.variant}
title={props.title}
onClickClose={props.onClose !== undefined || props.variant === 'modal' ? () => setOpen(false) : undefined}
onClose={() => props.onClose?.()}
>
{props.children}
</MaterialSideSheet>
</Match>
</Switch>
</MaterialPane>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@layer material.components {
:root {
--md-comp-layouts-supporting-pane-width: 360px;
}

.layout {
display: grid;
grid-template-columns: auto max-content;

--md-comp-side-sheet-width: var(--md-comp-layouts-supporting-pane-width);
transition-property: gap;

&:has(> :last-child > sm-pane > :is(dialog, aside)[data-open]:not(:modal)) {
gap: var(--md-user-spacing-lg);

/* Transition when entering the screen */
transition-duration: var(--md-sys-motion-duration-emphasized-decelerate);
transition-timing-function: var(--md-sys-motion-easing-emphasized-decelerate);
}

&:has(> :last-child > sm-pane > :is(dialog, aside):not([data-open])) {
gap: 0;

/* Transition when exiting the screen */
transition-duration: var(--md-sys-motion-duration-emphasized-accelerate);
transition-timing-function: var(--md-sys-motion-easing-emphasized-accelerate);
}

&:not(:has(> :last-child > sm-pane > dialog)) {
grid-template-columns: 1fr;
grid-template-rows: auto max-content;

& > *:not(:first-child) {
padding-block-start: unset;
}
& > *:not(:last-child) {
padding-block-end: unset;
}

& > :last-child > sm-pane {
transition-property: max-height;
interpolate-size: allow-keywords;

max-height: 0;
overflow-y: hidden;

/* Transition when exiting the screen */
transition-duration: var(--md-sys-motion-duration-emphasized-accelerate);
transition-timing-function: var(--md-sys-motion-easing-emphasized-accelerate);

&:has(> aside[data-open]) {
max-height: fit-content;

/* Transition when entering the screen */
transition-duration: var(--md-sys-motion-duration-emphasized-decelerate);
transition-timing-function: var(--md-sys-motion-easing-emphasized-decelerate);
}
}
}
}
}
Loading
Loading