Skip to content

Commit

Permalink
component: error state
Browse files Browse the repository at this point in the history
  • Loading branch information
shyakadavis committed Jul 19, 2024
1 parent 11c72e1 commit a765cf2
Show file tree
Hide file tree
Showing 17 changed files with 901 additions and 15 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"shiki": "^1.10.3",
"svelte": "^4.2.18",
"svelte-check": "^3.8.4",
"svelte-exmarkdown": "^3.0.5",
"svelte-meta-tags": "^3.1.2",
"tailwindcss": "^3.4.6",
"tslib": "^2.6.3",
Expand Down
651 changes: 651 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,10 @@ html.dark .shiki span {
font-weight: var(--shiki-dark-font-weight) !important;
text-decoration: var(--shiki-dark-text-decoration) !important;
}

/*
The styles for ``
*/
.prose code:not(pre > code) {
@apply rounded-md border border-gray-300 bg-gray-100 px-[3.6px] py-0.5 font-mono text-sm before:content-[''] after:content-[''];
}
3 changes: 3 additions & 0 deletions src/lib/assets/icons/chart-bar-peak.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 67 additions & 0 deletions src/lib/assets/icons/error-states.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/lib/assets/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import Bell from './bell.svg?component';
import Box from './box.svg?component';
import BrandAssets from './brand-assets.svg?component';
import CharBarMiddle from './chart-bar-middle.svg?component';
import ChartBarPeak from './chart-bar-peak.svg?component';
import CharTrendingDown from './chart-trending-down.svg?component';
import Check from './check.svg?component';
import ChevronLeft from './chevron-left.svg?component';
Expand All @@ -15,6 +16,7 @@ import CodeBracket from './code-bracket.svg?component';
import Command from './command.svg?component';
import Copy from './copy.svg?component';
import Database from './database.svg?component';
import ErrorStates from './error-states.svg?component';
import External from './external.svg?component';
import FileText from './file-text.svg?component';
import Flag from './flag.svg?component';
Expand Down Expand Up @@ -56,6 +58,7 @@ export const Icons = {
Box,
BrandAssets,
CharBarMiddle,
ChartBarPeak,
CharTrendingDown,
Check,
ChevronLeft,
Expand All @@ -66,6 +69,7 @@ export const Icons = {
Command,
Copy,
Database,
ErrorStates,
External,
FileText,
Flag,
Expand Down
9 changes: 0 additions & 9 deletions src/lib/components/shared/demo-utils.ts

This file was deleted.

12 changes: 9 additions & 3 deletions src/lib/components/shared/demo.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
import { Icons } from '$lib/assets/icons';
import { cn } from '$lib/utils';
import { onMount } from 'svelte';
import Markdown from 'svelte-exmarkdown';
import { scale } from 'svelte/transition';
import Accordion from './accordion-animation';
import { format_string, parse_back_ticks } from './demo-utils';
import { get_highlighted_code } from './shiki';
let class_name: string | undefined = undefined;
Expand All @@ -13,6 +13,11 @@
export let subtitle: string | undefined = undefined;
export { class_name as class };
// e.g. "with-icons" -> "With Icons"
function format_string(str: string) {
return str.replace(/-/g, ' ').replace(/\b\w/g, (char) => char.toUpperCase());
}
// Show/hide code details animation
const accordions: Accordion[] = [];
onMount(() => {
Expand Down Expand Up @@ -58,9 +63,10 @@
</a>
{#if subtitle}
<p
class="mt-2 leading-6 text-gray-900 xl:mt-4 [&>code]:rounded-md [&>code]:border [&>code]:border-gray-300 [&>code]:bg-gray-100 [&>code]:px-[3.6px] [&>code]:py-0.5 [&>code]:font-mono [&>code]:text-sm"
class="prose prose-neutral mt-2 max-w-none text-gray-900 dark:prose-invert marker:content-['-'] prose-strong:font-normal prose-strong:text-gray-1000 xl:mt-4"
>
{@html parse_back_ticks(subtitle)}
<Markdown md={subtitle} />
<slot name="image"></slot>
</p>
{/if}
<div
Expand Down
2 changes: 1 addition & 1 deletion src/lib/components/ui/badge/badge.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{...$$restProps}
>
{#if icon}
<svelte:component this={icon} class="size-4" />
<svelte:component this={icon} aria-hidden="true" class="size-4" />
{/if}
<slot />
</svelte:element>
32 changes: 32 additions & 0 deletions src/lib/components/ui/empty-state/empty-state.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts">
import { cn } from '$lib/utils.js';
import { type Props, badge_variants } from './index.js';
type $$Props = Props;
let class_name: string | undefined | null = undefined;
export let variant: $$Props['variant'] = undefined;
export let title: $$Props['title'];
export let description: $$Props['description'];
export let icon_size: $$Props['icon_size'] = 32;
export { class_name as class };
export let icon: $$Props['icon'] = undefined;
$: icon_parent_size = icon_size ? icon_size + 28 : 32;
</script>

<div class={cn(badge_variants({ variant, className: class_name }))} {...$$restProps}>
{#if icon}
<span
class="grid place-items-center rounded-lg border border-gray-alpha-400 bg-background-100 p-[14px]"
style="width: {icon_parent_size}px; height: {icon_parent_size}px;"
>
<svelte:component this={icon} aria-hidden="true" width={icon_size} height={icon_size} />
</span>
{/if}
<div class="grid place-items-center gap-2">
<p class="text-lg font-medium text-gray-1000">{title}</p>
<p class="text-balance text-sm">{description}</p>
</div>
<slot></slot>
</div>
22 changes: 22 additions & 0 deletions src/lib/components/ui/empty-state/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Icons } from '$lib/assets/icons';
import { type VariantProps, tv } from 'tailwind-variants';

export { default as EmptyState } from './empty-state.svelte';

export const badge_variants = tv({
base: 'grid place-items-center gap-4 text-gray-900',
variants: {
variant: {}
},
defaultVariants: {}
});

type Variant = VariantProps<typeof badge_variants>['variant'];

export type Props = {
variant?: Variant;
icon?: typeof Icons.Shield;
title: string;
description: string;
icon_size?: number;
};
2 changes: 1 addition & 1 deletion src/lib/config/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export const aside_items: Aside = {
{
title: 'Empty State',
href: '/empty-state',
status: 'soon'
status: 'draft'
},
{
title: 'Error',
Expand Down
43 changes: 42 additions & 1 deletion src/routes/empty-state/+page.svelte
Original file line number Diff line number Diff line change
@@ -1 +1,42 @@
<h1>empty-state</h1>
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import Demo from '$lib/components/shared/demo.svelte';
import PageWrapper from '$lib/components/shared/page-wrapper.svelte';
import BlankSlate from './blank-slate.svelte';
import blank_slate_code from './blank-slate.svelte?raw';
import EmptyStateDesignFramework from './empty-state-design-framework.svelte';
import empty_state_design_framework_code from './empty-state-design-framework.svelte?raw';
import Informational from './informational.svelte';
import informational_code from './informational.svelte?raw';
export let data;
const empty_state_design_framework_subtitle =
'When designed thoughtfully, empty states become an essential part of a smooth user experience, providing enough context to keep users working in a productive way. There are several approaches to explore that will match the needs a developer in different situations:\n- __Blank Slate__ - Basic empty state for first run experience\n- __Informational__ - Alternative for first use empty state, including in-line CTAs and supplemental documentation links\n- __Educational__ - Launch a contextual onboarding flow to gain deeper understanding about that area of the app\n- __Guide__ - Starter content that allows users to interact with data and learn the system by tinkering or setting up their environment';
const informational_subtitle =
'Help users by clearly explaining the benefit and utility of a product or feature, with a call to action and link to more information to help users progress.\n\nDefault to showing rather than telling the value of a feature. Certain entry points to a product may call for a unique empty state and a call to upgrade. Informational empty states will include a call to action.';
</script>

<PageWrapper title={data.title} description={data.description}>
<Demo
id="empty-state-design-framework"
subtitle={empty_state_design_framework_subtitle}
code={empty_state_design_framework_code}
>
<Icons.ErrorStates aria-hidden="true" slot="image" />
<EmptyStateDesignFramework />
</Demo>

<Demo
id="blank-slate"
subtitle="The most basic empty state should convey the state of the view."
code={blank_slate_code}
>
<BlankSlate />
</Demo>

<Demo id="informational" subtitle={informational_subtitle} code={informational_code}>
<Informational />
</Demo>
</PageWrapper>
22 changes: 22 additions & 0 deletions src/routes/empty-state/+page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { MetaTagsProps } from 'svelte-meta-tags';

export function load() {
const title = 'Empty State';
const description =
'Fill spaces when no content has been added yet, or is temporarily empty due to the nature of the feature and should be designed to prevent confusion.';

const pageMetaTags = Object.freeze({
title,
description,
openGraph: {
title,
description
}
}) satisfies MetaTagsProps;

return {
pageMetaTags,
title,
description
};
}
11 changes: 11 additions & 0 deletions src/routes/empty-state/blank-slate.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { EmptyState } from '$lib/components/ui/empty-state';
</script>

<EmptyState
title="Title"
description="A message conveying the state of the product."
icon={Icons.ChartBarPeak}
icon_size={32}
/>
11 changes: 11 additions & 0 deletions src/routes/empty-state/empty-state-design-framework.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { EmptyState } from '$lib/components/ui/empty-state';
</script>

<EmptyState
title="Title"
description="A message conveying the state of the product."
icon={Icons.ChartBarPeak}
icon_size={32}
/>
17 changes: 17 additions & 0 deletions src/routes/empty-state/informational.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script lang="ts">
import { Icons } from '$lib/assets/icons';
import { Button } from '$lib/components/ui/button';
import { EmptyState } from '$lib/components/ui/empty-state';
</script>

<EmptyState
description="This should detail the actions you can take on this screen, as well as why it's valuable."
icon={Icons.ChartBarPeak}
icon_size={32}
title="Title"
>
<Button variant="secondary">Primary Action</Button>
<!-- <Link external href="/" variant="secondary">
Learn more
</Link> -->
</EmptyState>

0 comments on commit a765cf2

Please sign in to comment.