Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cs 7896 try to change loading text indicator into loadingindicatoricon #2150

2 changes: 2 additions & 0 deletions packages/boxel-ui/addon/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import ResizablePanelGroup, {
ResizeHandle,
} from './components/resizable-panel-group/index.gts';
import BoxelSelect from './components/select/index.gts';
import SkeletonPlaceholder from './components/skeleton-placeholder/index.gts';
import Switch from './components/switch/index.gts';
import TabbedHeader from './components/tabbed-header/index.gts';
import Tooltip from './components/tooltip/index.gts';
Expand Down Expand Up @@ -106,6 +107,7 @@ export {
ResizablePanel,
ResizablePanelGroup,
ResizeHandle,
SkeletonPlaceholder,
Switch,
TabbedHeader,
Tooltip,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import Component from '@glimmer/component';

interface Signature {
Args: {
animation?: 'wave' | 'pulse' | 'none';
};
Element: HTMLDivElement;
}

export default class SkeletonPlaceholder extends Component<Signature> {
get animationClass(): string {
return this.args.animation ?? 'wave';
}

<template>
<div
class='boxel-skeleton-placeholder {{this.animationClass}}'
data-test-boxel-skeleton-placeholder
...attributes
/>

<style scoped>
.boxel-skeleton-placeholder {
--skeleton-background: var(
--boxel-skeleton-background,
var(--boxel-light-200)
);
--skeleton-highlight: var(
--boxel-skeleton-highlight,
var(--boxel-light-100)
);
--skeleton-width: var(--boxel-skeleton-width, 100%);
--skeleton-height: var(--boxel-skeleton-height, 1.5em);
--skeleton-border-radius: var(
--boxel-skeleton-border-radius,
var(--boxel-border-radius-sm)
);
width: var(--skeleton-width);
height: var(--skeleton-height);
border-radius: var(--skeleton-border-radius);
background-color: var(--skeleton-background);
position: relative;
overflow: hidden;
}

.wave::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
animation: wave 1.6s linear 0.5s infinite;
background: linear-gradient(
90deg,
transparent,
var(--skeleton-highlight),
transparent
);
transform: translateX(-100%);
}

.pulse {
animation: pulse 1.5s ease-in-out 0.5s infinite;
}

@keyframes wave {
0% {
transform: translateX(-200%);
}
100% {
transform: translateX(100%);
}
}

@keyframes pulse {
0% {
opacity: 1;
}
50% {
opacity: 0.4;
}
100% {
opacity: 1;
}
}
</style>
</template>
}
102 changes: 102 additions & 0 deletions packages/boxel-ui/addon/src/components/skeleton-placeholder/usage.gts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { array, fn } from '@ember/helper';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import FreestyleUsage from 'ember-freestyle/components/freestyle/usage';
import {
type CSSVariableInfo,
cssVariable,
} from 'ember-freestyle/decorators/css-variable';

import { cssVar } from '../../helpers/css-var.ts';
import SkeletonPlaceholder from './index.gts';

export default class SkeletonPlaceholderUsage extends Component {
@tracked width = '200px';
@tracked height = '20px';
@tracked borderRadius = '4px';
@tracked animation: 'wave' | 'pulse' | 'none' = 'wave';

@cssVariable({ cssClassName: 'skeleton-freestyle-container' })
declare boxelSkeletonBackground: CSSVariableInfo;
@cssVariable({ cssClassName: 'skeleton-freestyle-container' })
declare boxelSkeletonHighlight: CSSVariableInfo;
@cssVariable({ cssClassName: 'skeleton-freestyle-container' })
declare boxelSkeletonWidth: CSSVariableInfo;
@cssVariable({ cssClassName: 'skeleton-freestyle-container' })
declare boxelSkeletonHeight: CSSVariableInfo;
@cssVariable({ cssClassName: 'skeleton-freestyle-container' })
declare boxelSkeletonBorderRadius: CSSVariableInfo;

<template>
<div
class='skeleton-freestyle-container'
style={{cssVar
boxel-skeleton-background=this.boxelSkeletonBackground.value
boxel-skeleton-highlight=this.boxelSkeletonHighlight.value
boxel-skeleton-width=this.boxelSkeletonWidth.value
boxel-skeleton-height=this.boxelSkeletonHeight.value
boxel-skeleton-border-radius=this.boxelSkeletonBorderRadius.value
}}
>
<FreestyleUsage @name='Skeleton Placeholder'>
<:description>
A skeleton placeholder component to show loading states
</:description>
<:example>
<SkeletonPlaceholder @animation={{this.animation}} />
</:example>
<:api as |Args|>
<Args.String
@name='animation'
@value={{this.animation}}
@options={{array 'wave' 'pulse' 'none'}}
@description='Animation type for the skeleton'
@onInput={{fn (mut this.animation)}}
/>
</:api>
<:cssVars as |Css|>
<Css.Basic
@name='boxel-skeleton-width'
@type='string'
@description='Width of the skeleton (px or %)'
@defaultValue={{this.boxelSkeletonWidth.defaults}}
@value={{this.boxelSkeletonWidth.value}}
@onInput={{this.boxelSkeletonWidth.update}}
/>
<Css.Basic
@name='boxel-skeleton-height'
@type='string'
@description='Height of the skeleton (px or %)'
@defaultValue={{this.boxelSkeletonHeight.defaults}}
@value={{this.boxelSkeletonHeight.value}}
@onInput={{this.boxelSkeletonHeight.update}}
/>
<Css.Basic
@name='boxel-skeleton-border-radius'
@type='string'
@description='Border radius of the skeleton'
@defaultValue={{this.boxelSkeletonBorderRadius.defaults}}
@value={{this.boxelSkeletonBorderRadius.value}}
@onInput={{this.boxelSkeletonBorderRadius.update}}
/>
<Css.Basic
@name='boxel-skeleton-background'
@type='color'
@description='Background color of the skeleton'
@defaultValue={{this.boxelSkeletonBackground.defaults}}
@value={{this.boxelSkeletonBackground.value}}
@onInput={{this.boxelSkeletonBackground.update}}
/>
<Css.Basic
@name='boxel-skeleton-highlight'
@type='color'
@description='Highlight color for the wave animation (only applies when animation=wave)'
@defaultValue={{this.boxelSkeletonHighlight.defaults}}
@value={{this.boxelSkeletonHighlight.value}}
@onInput={{this.boxelSkeletonHighlight.update}}
/>
</:cssVars>
</FreestyleUsage>
</div>
</template>
}
2 changes: 2 additions & 0 deletions packages/boxel-ui/addon/src/usage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import RadioInputUsage from './components/radio-input/usage.gts';
import RealmIconUsage from './components/realm-icon/usage.gts';
import ResizablePanelGroupUsage from './components/resizable-panel-group/usage.gts';
import SelectUsage from './components/select/usage.gts';
import SkeletonPlaceholderUsage from './components/skeleton-placeholder/usage.gts';
import SwitchUsage from './components/switch/usage.gts';
import TabbedHeaderUsage from './components/tabbed-header/usage.gts';
import TooltipUsage from './components/tooltip/usage.gts';
Expand Down Expand Up @@ -75,6 +76,7 @@ export const ALL_USAGE_COMPONENTS = [
['RealmIcon', RealmIconUsage],
['ResizablePanelGroup', ResizablePanelGroupUsage],
['Select', SelectUsage],
['SkeletonPlaceholder', SkeletonPlaceholderUsage],
['Switch', SwitchUsage],
['TabbedHeader', TabbedHeaderUsage],
['Tooltip', TooltipUsage],
Expand Down
55 changes: 31 additions & 24 deletions packages/experiments-realm/crm/account.gts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ import AccountHeader from '../components/account-header';
import { WebsiteField } from '../website';
import TrendingUp from '@cardstack/boxel-icons/trending-up';
import ContactIcon from '@cardstack/boxel-icons/contact';
import { BoxelButton } from '@cardstack/boxel-ui/components';
import {
BoxelButton,
SkeletonPlaceholder,
} from '@cardstack/boxel-ui/components';
import PlusIcon from '@cardstack/boxel-icons/plus';
import { Pill } from '@cardstack/boxel-ui/components';
import { Query } from '@cardstack/runtime-common/query';
Expand Down Expand Up @@ -437,16 +440,19 @@ class IsolatedTemplate extends Component<typeof Account> {
</:icon>
<:content>
{{#if this.lifetimeValueDeals.isLoading}}
<h3 class='summary-highlight'>Loading...</h3>
<p class='description'>Loading...</p>
<SkeletonPlaceholder
class='skeleton-placeholder-deal-summary-highlight'
/>
<SkeletonPlaceholder
class='skeleton-placeholder-deal-description'
/>
{{else}}
<h3 class='summary-highlight'>
{{this.formattedLifetimeTotal}}
</h3>
<p class='description'>
{{this.formattedCurrentYearValue}}
</p>

{{/if}}
</:content>
</SummaryCard>
Expand All @@ -460,8 +466,12 @@ class IsolatedTemplate extends Component<typeof Account> {
</:icon>
<:content>
{{#if this.deals.isLoading}}
<h3 class='summary-highlight'>Loading...</h3>
<p class='description'>Loading...</p>
<SkeletonPlaceholder
class='skeleton-placeholder-deal-summary-highlight'
/>
<SkeletonPlaceholder
class='skeleton-placeholder-deal-description'
/>
{{else}}
<h3 class='summary-highlight'>{{this.activeDealsCount}}</h3>
<p class='description'>{{this.totalDealsValue}}</p>
Expand Down Expand Up @@ -506,7 +516,7 @@ class IsolatedTemplate extends Component<typeof Account> {
</:icon>
<:content>
{{#if this.activeTasks.isLoading}}
<div class='loading-skeleton'>Loading...</div>
<SkeletonPlaceholder class='skeleton-placeholder-task' />
{{else}}
{{#if this.hasActiveTasks}}
{{#each this.activeTasks.instances as |task|}}
Expand Down Expand Up @@ -636,14 +646,16 @@ class IsolatedTemplate extends Component<typeof Account> {
--profile-avatar-icon-border: 0px;
flex-shrink: 0;
}
.loading-skeleton {
height: 60px;
width: 100%;
background-color: var(--boxel-100);
border-radius: var(--boxel-border-radius-sm);
display: flex;
align-items: center;
justify-content: center;
/* Skeleton Placeholder */
.skeleton-placeholder-deal-summary-highlight {
--skeleton-width: 50%;
--skeleton-height: 22px;
}
.skeleton-placeholder-deal-description {
--skeleton-height: 13px;
}
.skeleton-placeholder-task {
--skeleton-height: 55px;
}

@container tasks-summary-card (max-width: 447px) {
Expand Down Expand Up @@ -959,7 +971,7 @@ class EmbeddedTemplate extends Component<typeof Account> {
<article>
<label>PRIORITY TASKS</label>
{{#if this.activeTasks.isLoading}}
<div class='loading-skeleton'>Loading...</div>
<SkeletonPlaceholder class='skeleton-placeholder-task' />
{{else}}
<div class='task-container'>
{{#if this.hasActiveTasks}}
Expand Down Expand Up @@ -1107,14 +1119,9 @@ class EmbeddedTemplate extends Component<typeof Account> {
--task-card-padding: var(--boxel-sp) 0;
border-top: 1px solid var(--boxel-200);
}
.loading-skeleton {
height: 60px;
width: 100%;
background: var(--boxel-light-300);
border-radius: var(--boxel-border-radius-sm);
display: flex;
align-items: center;
justify-content: center;
/* Skeleton Placeholder */
.skeleton-placeholder-task {
--skeleton-height: 55px;
}

@container account-page-layout-embedded (max-width: 447px) {
Expand Down
12 changes: 10 additions & 2 deletions packages/experiments-realm/crm/deal.gts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
Pill,
BoxelButton,
FieldContainer,
SkeletonPlaceholder,
} from '@cardstack/boxel-ui/components';
import { cn, not } from '@cardstack/boxel-ui/helpers';
import Info from '@cardstack/boxel-icons/info';
Expand Down Expand Up @@ -367,7 +368,9 @@ class IsolatedTemplate extends Component<typeof Deal> {
Current Value
<@fields.computedValue class='highlight-value' @format='atom' />
{{#if this.query.isLoading}}
Loading...
<SkeletonPlaceholder
class='skeleton-placeholder-deal-description'
/>
{{else if this.query.instances}}
{{#let
(this.dealSizeSummary this.query.instances)
Expand Down Expand Up @@ -532,7 +535,8 @@ class IsolatedTemplate extends Component<typeof Deal> {
</:icon>
<:content>
{{#if this.activeTasks.isLoading}}
<div class='loading-skeleton'>Loading...</div>
<SkeletonPlaceholder />
<SkeletonPlaceholder />
{{else}}
{{#if this.hasActiveTasks}}
{{#each this.activeTasks.instances as |task|}}
Expand Down Expand Up @@ -712,6 +716,10 @@ class IsolatedTemplate extends Component<typeof Deal> {
gap: var(--boxel-sp-sm);
font-weight: 600;
}
/* Skeleton Placeholder */
.skeleton-placeholder-deal-description {
--skeleton-height: var(--boxel-font-sm);
}
@container (max-width: 447px) {
.progress-container {
flex-direction: column-reverse;
Expand Down