Skip to content

Commit

Permalink
Add more components
Browse files Browse the repository at this point in the history
  • Loading branch information
caro401 committed Dec 18, 2023
1 parent 3b08083 commit 63cd257
Show file tree
Hide file tree
Showing 16 changed files with 415 additions and 2 deletions.
48 changes: 48 additions & 0 deletions src/lib/components/base/Button.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import type { Meta, StoryObj } from '@storybook/svelte';

import Button from './Button.svelte';

// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const meta = {
title: 'Base/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
size: {
control: { type: 'select' },
options: ['small', 'medium', 'large']
}
}
} satisfies Meta<Button>;

export default meta;
type Story = StoryObj<typeof meta>;

// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
export const Primary: Story = {
args: {
primary: true,
label: 'Button'
}
};

export const Secondary: Story = {
args: {
label: 'Button'
}
};

export const Large: Story = {
args: {
size: 'large',
label: 'Button'
}
};

export const Small: Story = {
args: {
size: 'small',
label: 'Button'
}
};
65 changes: 65 additions & 0 deletions src/lib/components/base/Button.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<script lang="ts">
/**
* Is this the principal call to action on the page?
*/
export let primary = false;
/**
* What background color to use
*/
export let backgroundColor: string | undefined = undefined;
/**
* How large should the button be?
*/
export let size: 'small' | 'medium' | 'large' = 'medium';
/**
* Button contents
*/
export let label: string = '';
$: mode = primary ? 'storybook-button--primary' : 'storybook-button--secondary';
$: style = backgroundColor ? `background-color: ${backgroundColor}` : '';
</script>

<button
type="button"
class={['storybook-button', `storybook-button--${size}`, mode].join(' ')}
{style}
on:click
>
{label}
</button>

<style>
.storybook-button {
font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-weight: 700;
border: 0;
border-radius: 3em;
cursor: pointer;
display: inline-block;
line-height: 1;
}
.storybook-button--primary {
color: white;
background-color: #1ea7fd;
}
.storybook-button--secondary {
color: #333;
background-color: transparent;
box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
}
.storybook-button--small {
font-size: 12px;
padding: 10px 16px;
}
.storybook-button--medium {
font-size: 14px;
padding: 11px 20px;
}
.storybook-button--large {
font-size: 16px;
padding: 12px 24px;
}
</style>
31 changes: 31 additions & 0 deletions src/lib/components/display/Code.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script context="module">
import Code from './Code.svelte';
export const meta = {
title: 'Display/Code',
component: Code,
tags: ['autodocs'],
argTypes: {
code: { control: 'text', description: 'Python code to be highlighted', type: 'string' }
},
parameters: {
docs: {
description: {
component:
'This component uses Shiki to apply syntax highlighting to the provided Python code'
}
}
}
};
</script>

<script>
import { Story, Template } from '@storybook/addon-svelte-csf';
const code =
'class DeserializeTableModule(DeserializeValueModule):\n\n _module_type_name = "load.tables"\n\n @classmethod\n def retrieve_supported_target_profiles(cls) -> Mapping[str, Type]:\n return {"python_object": KiaraTables}\n\n @classmethod\n def retrieve_serialized_value_type(cls) -> str:\n return "tables"\n\n @classmethod\n def retrieve_supported_serialization_profile(cls) -> str:\n return "feather"\n\n def to__python_object(self, data: SerializedData, **config: Any):\n\n import pyarrow as pa\n\n tables: Dict[str, Any] = {}\n\n for column_id in data.get_keys():\n\n if TABLE_COLUMN_SPLIT_MARKER not in column_id:\n raise KiaraException(\n f"Invalid serialized \'tables\' data, key must contain \'{TABLE_COLUMN_SPLIT_MARKER}\': {column_id}"\n )\n table_id, column_name = column_id.split(\n TABLE_COLUMN_SPLIT_MARKER, maxsplit=1\n )\n\n chunks = data.get_serialized_data(column_id)\n\n # TODO: support multiple chunks\n assert chunks.get_number_of_chunks() == 1\n files = list(chunks.get_chunks(as_files=True, symlink_ok=True))\n assert len(files) == 1\n\n file = files[0]\n with pa.memory_map(file, "r") as column_chunk:\n loaded_arrays: pa.Table = pa.ipc.open_file(column_chunk).read_all()\n column = loaded_arrays.column(column_name)\n tables.setdefault(table_id, {})[column_name] = column\n\n table = KiaraTables.create_tables(tables)\n return table\n';
</script>

<Template let:args>
<Code {...args} />
</Template>
<Story name="Default" args={{ code: code }} />
14 changes: 14 additions & 0 deletions src/lib/components/display/Code.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<script lang="ts">
export let code: string;
import { highlightPythonCode } from '../../syntax-highlight.js';
const displayCode = highlightPythonCode(code);
</script>

<pre>{@html displayCode}</pre>

<style lang="postcss">
/* hex code from shiki's nord theme */
pre {
@apply bg-[#2e3440] text-sm p-6 rounded-md w-fit;
}
</style>
46 changes: 46 additions & 0 deletions src/lib/components/display/Doc.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Meta, StoryObj } from '@storybook/svelte';
import Doc from './Doc.svelte';

const meta = {
title: 'Display/Doc',
component: Doc,
tags: ['autodocs']
} satisfies Meta<Doc>;

const minimalDoc = {
description: '-- n/a --',
doc: null
};

const docWithMarkdown = {
description: 'The description field of a Doc, summarising what the item does.',
doc: 'The Doc field of a doc, which can contain markdown.\n\nThe markdown should be rendered to inlude\n[links](https://github.com/DHARPA-project/kiara) and other **formatting things**. '
};

export default meta;
type Story = StoryObj<typeof meta>;

/**
* You'll probably want to wrap this component in `<section class="prose">` to make it look good
*/
export const Default: Story = {
args: {
doc: docWithMarkdown
}
};

export const JustSummary: Story = {
args: {
doc: docWithMarkdown,
verbose: false
}
};

/**
* items with description = '-- n/a --' are just not rendered, because this information isn't useful to show to end users
*/
export const Minimal: Story = {
args: {
doc: minimalDoc
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import sanitizeHtml from 'sanitize-html';
import { marked } from 'marked';
/**
* The Documentation from a kiara item, an object with keys description (summarising the item) and doc (detailed documentation in markdown)
*/
export let doc: Documentation;
/**
* Whether to show the full markdown documentation of the item, or just the summary
Expand Down
37 changes: 37 additions & 0 deletions src/lib/components/display/Foldable.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script context="module">
import Foldable from './Foldable.svelte';
import { userEvent, within } from '@storybook/testing-library';
import { expect } from '@storybook/jest';
export const meta = {
title: 'Display/Foldable',
component: Foldable,
tags: ['autodocs']
};
</script>

<script>
import { Story, Template } from '@storybook/addon-svelte-csf';
const content = "Here's some content that goes inside the foldable, and isn't shown by default";
</script>

<Template let:args>
<Foldable {...args}>
<p>{content}</p>
</Foldable>
</Template>

<Story
name="Default"
args={{ title: "Foldable thing's title" }}
play={async ({ canvasElement }) => {
const canvas = within(canvasElement);
// Content hidden by default
await expect(canvas.queryByText(content)).not.toBeVisible();
await userEvent.click(canvas.getByRole('button'));
// click button, content visible
await expect(canvas.getByText(content)).toBeVisible();
await userEvent.click(canvas.getByRole('button'));
// click button again, content hidden
await expect(canvas.getByText(content)).not.toBeVisible();
}}
/>
49 changes: 49 additions & 0 deletions src/lib/components/display/Foldable.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<script lang="ts">
export let title: string;
let expanded = false;
</script>

<section data-accordion {...$$restProps}>
<div data-accordion-item>
<button
type="button"
aria-expanded={expanded}
on:click={() => {
expanded = !expanded;
}}
>
<h2>{title}</h2>
<span class:rotate-180={expanded}>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
<path
d="M201.4 374.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 306.7 86.6 169.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z"
></path>
</svg>
</span>
</button>
<div role="region" hidden={!expanded}>
<slot />
</div>
</div>
</section>

<style lang="postcss">
section[data-accordion] {
@apply w-full flex items-center space-x-4 py-2 px-4;
}
div[data-accordion-item] {
@apply w-full;
}
button {
@apply w-full inline-flex justify-between items-center;
}
h2 {
@apply text-left flex-grow my-2;
}
span {
@apply fill-current w-3 transition-transform duration-[100ms];
}
</style>
52 changes: 52 additions & 0 deletions src/lib/components/display/GitHubLink.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<script context="module">
import GitHubLink from './GitHubLink.svelte';
export const meta = {
title: 'Display/GitHub Link',
component: GitHubLink,
tags: ['autodocs'],
argTypes: {
href: { control: 'text', description: 'Link to relevant code on GitHub', type: 'string' }
},
parameters: {
docs: {
description: {
component:
'This component uses Shiki to apply syntax highlighting to the provided Python code'
}
}
}
};
</script>

<script>
import { Story, Template } from '@storybook/addon-svelte-csf';
import { userEvent, within } from '@storybook/testing-library';
</script>

<Template let:args>
<GitHubLink {...args} />
</Template>
<Story
name="Default"
args={{ href: 'https://github.com/DHARPA-project/kiara-svelte-components' }}
play={async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.hover(canvas.getByRole('link'));
}}
/>

<Story
name="Styled"
parameters={{
docs: {
description: {
story:
'Optionally provide styling via tailwind classes. You\'ll need to specify "fill" to change the icon colour'
}
}
}}
args={{
href: 'https://github.com/DHARPA-project/kiara-svelte-components',
classes: 'text-purple-500 hover:fill-red-500 fill-purple-500'
}}
/>
28 changes: 28 additions & 0 deletions src/lib/components/display/GitHubLink.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts">
/**
* Link to GitHub
*/
export let href: string;
/**
* Optionally provide additional classes for styling
*/
export let classes: string = '';
</script>

<a {href} class={classes}>
<svg aria-hidden="true" viewBox="0 0 16 16">
<path
d="M8 0c4.42 0 8 3.58 8 8a8.013 8.013 0 0 1-5.45 7.59c-.4.08-.55-.17-.55-.38 0-.27.01-1.13.01-2.2 0-.75-.25-1.23-.54-1.48 1.78-.2 3.65-.88 3.65-3.95 0-.88-.31-1.59-.82-2.15.08-.2.36-1.02-.08-2.12 0 0-.67-.22-2.2.82-.64-.18-1.32-.27-2-.27-.68 0-1.36.09-2 .27-1.53-1.03-2.2-.82-2.2-.82-.44 1.1-.16 1.92-.08 2.12-.51.56-.82 1.28-.82 2.15 0 3.06 1.86 3.75 3.64 3.95-.23.2-.44.55-.51 1.07-.46.21-1.61.55-2.33-.66-.15-.24-.6-.83-1.23-.82-.67.01-.27.38.01.53.34.19.73.9.82 1.13.16.45.68 1.31 2.69.94 0 .67.01 1.3.01 1.49 0 .21-.15.45-.55.38A7.995 7.995 0 0 1 0 8c0-4.42 3.58-8 8-8Z"
></path>
</svg>
<span>View code on GitHub</span>
</a>

<style lang="postcss">
svg {
@apply inline w-6 h-6 hover:opacity-70 focus-visible:opacity-70 focus-visible:border-2;
}
span {
@apply sr-only;
}
</style>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest';
import { Doc } from '../index.js';
import { Doc } from '../../index.js';
import { render, screen } from '@testing-library/svelte';

describe('Doc', () => {
Expand Down
Loading

0 comments on commit 63cd257

Please sign in to comment.