Skip to content
Open
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
119 changes: 119 additions & 0 deletions v2/pink-sb/src/lib/CompoundTag/Child.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<script lang="ts">
import type { HTMLButtonAttributes } from 'svelte/elements';
import { createEventDispatcher, getContext } from 'svelte';

type $$Props = HTMLButtonAttributes & {
variant?: 'default' | 'code';
selected?: boolean;
disabled?: boolean;
dismiss?: boolean;
};

export let variant: $$Props['variant'] = 'default';
export let selected: $$Props['selected'] = false;
export let disabled: $$Props['disabled'] = false;
export let dismiss: $$Props['dismiss'] = false;

const dispatch = createEventDispatcher();
const dismissFn = getContext<() => void>('compound-tag-dismiss');
const size = getContext<'s' | 'm'>('compound-tag-size');
</script>

<button
class:code={variant === 'code'}
class:selected
class:s={size === 's'}
on:click
on:click|capture={() => {
if (dismiss) {
dismissFn?.();
dispatch('dismiss');
}
}}
type="button"
{disabled}
{...$$restProps}
>
<slot />
</button>

<style lang="scss">
@use '../../scss/mixins/transitions';

button {
@include transitions.common;

--p-compound-tag-child-font-family:
var(--badge-font-family, var(--font-family-sansserif)), var(--sans-fallbacks);
--p-compound-tag-child-font-size: var(--badge-font-size, var(--font-size-s));
--p-compound-tag-child-padding-block: var(--badge-padding-block, var(--space-5));
--p-compound-tag-child-padding-inline: var(--badge-padding-inline, var(--space-5));
--p-compound-tag-child-gap: var(--badge-gap, var(--space-3));
--p-compound-tag-child-color: var(--tag-color, var(--fgcolor-neutral-secondary));
--p-compound-tag-child-background-color: var(
--tag-background-color,
var(--bgcolor-neutral-default)
);
--p-compound-tag-child-border-color: var(--border-neutral);
--p-compound-tag-child-divider-color: var(--border-neutral);

display: inline-flex;
align-items: center;
justify-content: center;
padding-block: var(--p-compound-tag-child-padding-block);
padding-inline: var(--p-compound-tag-child-padding-inline);
gap: var(--p-compound-tag-child-gap);
min-height: 100%;

color: var(--p-compound-tag-child-color);
background-color: transparent;
border: none;
border-right: var(--border-width-s) solid var(--p-compound-tag-child-divider-color);

font-family: var(--p-compound-tag-child-font-family);
font-size: var(--p-compound-tag-child-font-size);
font-style: normal;
font-weight: 500;
line-height: 140%;

cursor: pointer;

&:last-child {
border-right: none;
}

&:hover {
background-color: var(--bgcolor-neutral-secondary);
}

&:active {
background-color: var(--bgcolor-neutral-secondary);
}

&:focus-visible {
outline: var(--border-width-l) solid var(--border-focus);
outline-offset: -2px;
}

&:disabled {
background-color: var(--bgcolor-neutral-primary);
opacity: 0.4;
cursor: not-allowed;
}

&.code {
--p-compound-tag-child-font-family: var(--font-family-code), var(--mono-fallbacks);
}

&.selected {
--p-compound-tag-child-background-color: var(--bgcolor-neutral-secondary);
border: var(--border-width-s) solid var(--border-neutral-stronger);
}

/* size variants */
&.s {
--p-compound-tag-child-padding-block: var(--space-2);
--p-compound-tag-child-padding-inline: var(--space-3);
}
}
</style>
57 changes: 57 additions & 0 deletions v2/pink-sb/src/lib/CompoundTag/CompoundTag.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<script lang="ts">
type $$Props = {
size?: 's' | 'm';
};

import { setContext } from 'svelte';

export let size: $$Props['size'] = 'm';

let visible = true;
function handleDismiss() {
visible = false;
}

setContext('compound-tag-dismiss', handleDismiss);
setContext('compound-tag-size', size);
</script>

{#if visible}
<div class="compound-tag" class:s={size === 's'} role="group">
<slot />
</div>
{/if}

<style lang="scss">
@use '../../scss/mixins/transitions';

.compound-tag {
@include transitions.common;

--p-compound-tag-font-family:
var(--badge-font-family, var(--font-family-sansserif)), var(--sans-fallbacks);
--p-compound-tag-font-size: var(--badge-font-size, var(--font-size-s));
--p-compound-tag-padding-block: var(--badge-padding-block, var(--space-5));
--p-compound-tag-padding-inline: var(--badge-padding-inline, var(--space-5));
--p-compound-tag-gap: var(--badge-gap, var(--space-3));
--p-compound-tag-color: var(--tag-color, var(--fgcolor-neutral-secondary));
--p-compound-tag-background-color: var(
--tag-background-color,
var(--bgcolor-neutral-default)
);
--p-compound-tag-border-color: var(--border-neutral);
--p-compound-tag-divider-color: var(--border-neutral);

display: inline-flex;
align-items: stretch;
background-color: var(--p-compound-tag-background-color);
border: var(--border-width-s) solid var(--p-compound-tag-border-color);
border-radius: var(--border-radius-XS, 6px);
overflow: hidden;

&.s {
--p-compound-tag-padding-block: var(--space-2);
--p-compound-tag-padding-inline: var(--space-3);
}
}
</style>
3 changes: 3 additions & 0 deletions v2/pink-sb/src/lib/CompoundTag/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as CompoundTag } from './CompoundTag.svelte';
export { default as Child } from './Child.svelte';
export { default } from './CompoundTag.svelte';
2 changes: 2 additions & 0 deletions v2/pink-sb/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export { default as InteractiveText } from './InteractiveText.svelte';
export { default as Root } from './Root.svelte';
export { default as Status } from './Status.svelte';
export { default as Tag } from './Tag.svelte';
export * as CompoundTag from './CompoundTag/index.js';
export { CompoundTag as CompoundTagRoot, Child as CompoundTagChild } from './CompoundTag/index.js';
export { default as ToggleButton } from './ToggleButton.svelte';
export { default as ProgressCircle } from './ProgressCircle.svelte';
export { default as Tooltip } from './Tooltip.svelte';
Expand Down
173 changes: 173 additions & 0 deletions v2/pink-sb/src/stories/CompoundTag.stories.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
<script context="module" lang="ts">
import { CompoundTagRoot, CompoundTagChild } from '$lib/index.js';
import type { MetaProps } from '@storybook/addon-svelte-csf';

export const meta: MetaProps = {
title: 'Components/CompoundTag',
component: CompoundTagRoot
};
</script>

<script>
import Icon from '$lib/Icon.svelte';
import Popover from '$lib/Popover.svelte';
import ActionMenu from '$lib/action-menu/index.js';
import { Story, Template } from '@storybook/addon-svelte-csf';
import {
IconXCircle,
IconFilter,
IconCheck,
IconX,
IconInfo,
IconChevronDoubleRight,
IconDuplicate
} from '@appwrite.io/pink-icons-svelte';
</script>

<Template let:args>
<CompoundTagRoot {...args} />
</Template>

<Story name="Default" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked Status')}>Status</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked is')}>is</CompoundTagChild>
<CompoundTagChild selected on:click={() => console.log('Clicked Active')}
>Active</CompoundTagChild
>
<CompoundTagChild aria-label="Dismiss" dismiss>
<Icon size="s" icon={IconX} />
</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="Action" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild>
<Icon icon={IconDuplicate} />
Action
</CompoundTagChild>
<CompoundTagChild aria-label="Dismiss" dismiss>
<Icon size="s" icon={IconX} />
</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="Filter Example" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked field')}>
<Icon icon={IconFilter} />
Build duration
</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked operator')}>is</CompoundTagChild>
<CompoundTagChild selected on:click={() => console.log('Clicked value')}
>more than 2 minutes</CompoundTagChild
>
<CompoundTagChild on:click={() => console.log('Clicked remove')}>
<Icon icon={IconXCircle} />
</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="Status Example" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked type')}>Status</CompoundTagChild>
<CompoundTagChild selected on:click={() => console.log('Clicked status')}>
<Icon icon={IconCheck} />
Completed
</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked action')}>
<Icon icon={IconXCircle} />
</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="Sizes">
<div
style="display: flex; flex-direction: column; gap: var(--space-6); align-items: flex-start;"
>
<CompoundTagRoot size="s">
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked is')}>is</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild dismiss on:click={() => console.log('Clicked close')}
><Icon icon={IconX} size="s" /></CompoundTagChild
>
</CompoundTagRoot>
<CompoundTagRoot size="m">
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked is')}>is</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild dismiss on:click={() => console.log('Clicked close')}
><Icon icon={IconX} size="s" /></CompoundTagChild
>
</CompoundTagRoot>
</div>
</Story>

<Story name="With Disabled Child" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked is')}>is</CompoundTagChild>
<CompoundTagChild disabled on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild
>
<CompoundTagChild on:click={() => console.log('Clicked close')}>×</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="Code Variant" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked function')}
>function</CompoundTagChild
>
<CompoundTagChild variant="code" on:click={() => console.log('Clicked name')}
>getUserData</CompoundTagChild
>
<CompoundTagChild on:click={() => console.log('Clicked params')}>()</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked return')}>return</CompoundTagChild>
</CompoundTagRoot>
</Story>

<Story name="With Action Menu" let:args>
<CompoundTagRoot size={args.size}>
<CompoundTagChild on:click={() => console.log('Clicked Tag')}>Tag</CompoundTagChild>
<CompoundTagChild on:click={() => console.log('Clicked is')}>is</CompoundTagChild>
<Popover let:toggle placement="bottom-start" padding="none">
<CompoundTagChild selected on:click={toggle}>Actions</CompoundTagChild>
<svelte:fragment slot="tooltip">
<ActionMenu.Root>
<ActionMenu.Item.Button
leadingIcon={IconInfo}
trailingIcon={IconChevronDoubleRight}
badge="1"
>
Default
</ActionMenu.Item.Button>
<ActionMenu.Item.Button
leadingIcon={IconInfo}
trailingIcon={IconChevronDoubleRight}
badge="1"
>
Default with a very long text
</ActionMenu.Item.Button>
<ActionMenu.Item.Button
leadingIcon={IconInfo}
trailingIcon={IconChevronDoubleRight}
disabled
>
Disabled
</ActionMenu.Item.Button>
<ActionMenu.Item.Button leadingIcon={IconInfo} status="danger">
Danger
</ActionMenu.Item.Button>
<ActionMenu.Item.Button leadingIcon={IconInfo} status="danger" disabled>
Danger Disabled
</ActionMenu.Item.Button>
</ActionMenu.Root>
</svelte:fragment>
</Popover>
<CompoundTagChild dismiss on:click={() => console.log('Clicked close')}>
<Icon icon={IconX} />
</CompoundTagChild>
</CompoundTagRoot>
</Story>