@coyalabs/bts-style
v1.3.10
Published
BTS Theme Svelte component templates
Downloads
4,424
Maintainers
Readme
@coyalabs/bts-style
Coya Behind the Scenes - A Svelte 4 component library with a serif 1920s aesthetic.
Installation
npm install @coyalabs/bts-styleQuick Start
<script>
import { BasePage, Button, BaseText } from '@coyalabs/bts-style';
</script>
<BasePage>
<BaseText variant="title">Hello BTS Theme!</BaseText>
<Button theme="primary">Click Me</Button>
</BasePage>Design System
Colors
- Background:
#0B070D- Deep dark page background - Default Text:
#E3D8D8- Light text and icons - Toned:
#A18F8F- Muted icons and accents - Accent:
#FFEFF6- Interactive elements
Fonts
The package uses fonts from Google Fonts and Fontshare (loaded via CDN):
- Noto Serif KR (900) - Titles and button text
- Satoshi (400, 500, 700, 900) - Content and UI text
Theme Variants
All container-based components support these themes:
full- Standard glass container with subtle backgroundprimary- Slightly more prominent glass effectsecondary- Alternative glass stylingvague- Subtle thingfilled- Use for solid container sections (customizable)
Components
Base Components
BasePage
Root page component with automatic favicon setup, dark background, and decorative background elements.
Props:
favicon?: string | null- Custom favicon URL (defaults to BTS theme icon)showBGDetails?: boolean- Show/hide decorative background elements (default:true)chainColor?: string- Color of the animated chain (default:"#130F15")
Example:
<BasePage favicon="/custom-icon.svg">
<!-- Your app content -->
</BasePage>
<!-- Without background decorations -->
<BasePage showBGDetails={false}>
<!-- Clean page without gears/chains -->
</BasePage>
<!-- Custom chain color -->
<BasePage chainColor="#1a1520">
<!-- Content with custom chain color -->
</BasePage>Features:
- Sets min-height: 100vh
- Applies #0B070D background
- Automatically injects BTS favicon unless overridden
- Resets body/html margins
- Decorative BGDetails layer with animated gears and swinging chain
Background Details (BGDetails):
The BGDetails component renders decorative 1920s-style animated elements:
- Chain - A physics-simulated swinging chain in the top-left corner
- Gears - Rotating interlocked gears in the top-right corner
- Single Gear - A slowly rotating gear in the bottom-left corner
These elements are purely decorative (pointer-events: none) and sit behind your content. Disable with showBGDetails={false}.
BaseContainer
Container with customizable corners and themes.
Props:
theme?: 'full' | 'primary' | 'secondary' | 'filled'- Visual theme (default:'full')padding?: string- CSS padding value (default:'1.5rem')borderRadiusTopLeft?: string- Top-left corner radius (default:'25px')borderRadiusTopRight?: string- Top-right corner radius (default:'25px')borderRadiusBottomLeft?: string- Bottom-left corner radius (default:'25px')borderRadiusBottomRight?: string- Bottom-right corner radius (default:'25px')
Example:
<BaseContainer theme="primary" borderRadiusTopLeft="35px">
<slot />
</BaseContainer>BaseText
Typography component with three text variants.
Props:
variant: 'title' | 'content' | 'button'- Text style variant
Variants:
title- Noto Serif KR 900, 30px - For headingscontent- Satoshi 700, 18px - For body textbutton- Noto Serif KR 900, 17px - For button labels
Example:
<BaseText variant="title">Page Title</BaseText>
<BaseText variant="content">This is content text.</BaseText>BaseIcon
SVG icon wrapper with color variants.
Props:
svg: string- SVG markup stringvariant?: 'default' | 'toned'- Color variant (default:'default')size?: string- Icon size (default:'18px')
Example:
<script>
import { BaseIcon, icons } from '@coyalabs/bts-style';
</script>
<BaseIcon svg={icons.folder} variant="toned" size="24px" />Structure Components
TextHeader
Header component with title and optional subtitle.
Props:
title: string- Main heading textsubtitle?: string- Optional subheading
Example:
<TextHeader
title="Welcome"
subtitle="Get started with BTS Theme"
/>Interactive Components
Button
Clickable button extending BaseContainer with icon support.
Props:
theme?: 'full' | 'primary' | 'secondary' | 'filled'- Button themeicon?: string- Left icon SVGactionIcon?: string | null- Right icon SVG (default: arrow, null to hide)iconRotation?: number- Left icon rotation in degreesactionIconRotation?: number- Right icon rotation in degreesiconSize?: string- Left icon size (default:'18px')actionIconSize?: string- Right icon size (default:'18px')- All BaseContainer corner radius props
Events:
- Forwards all events including
on:click
Example:
<script>
import { Button, icons } from '@coyalabs/bts-style';
</script>
<Button
theme="primary"
icon={icons.folder}
actionIconRotation={-45}
on:click={() => console.log('Clicked!')}
>
Open Folder
</Button>
<!-- Button without action icon -->
<Button actionIcon={null} theme="secondary">
Simple Button
</Button>States:
- Hover: Subtle background lightening
- Active/Pressed: Visual feedback
IconButton
Circular icon-only button with hover effects.
Props:
svg: string- Icon SVG markupvariant?: 'default' | 'toned'- Icon color variantsize?: string- Button size (default:'20px')
Events:
- Forwards all events including
on:click
Example:
<script>
import { IconButton, icons } from '@coyalabs/bts-style';
</script>
<IconButton
svg={icons.cross}
variant="toned"
on:click={() => closeModal()}
/>Effects:
- Hover: Scale 1.1, subtle background
- Active: Scale 0.95
InputBox
Text input field with icon support and theme matching.
Props:
value?: string- Input value (bindable)placeholder?: string- Placeholder texttype?: string- Input type (default:'text')theme?: 'full' | 'primary' | 'secondary' | 'filled'- Visual themeicon?: string- Left icon SVG- All BaseContainer corner radius props
Example:
<script>
import { InputBox, icons } from '@coyalabs/bts-style';
let username = '';
</script>
<InputBox
bind:value={username}
placeholder="Enter username..."
icon={icons.pen}
theme="primary"
/>Toggle
Animated toggle switch with on/off states.
Props:
checked?: boolean- Toggle state (bindable)
Example:
<script>
import { Toggle } from '@coyalabs/bts-style';
let enabled = false;
</script>
<Toggle bind:checked={enabled} />
<p>State: {enabled ? 'On' : 'Off'}</p>Tooltip
Hover tooltip that displays above or below an icon.
Props:
icon: string- Icon SVG markuptext: string- Tooltip text contenticonSize?: string- Icon size (default:'18px')
Example:
<script>
import { Tooltip, icons } from '@coyalabs/bts-style';
</script>
<Tooltip
icon={icons.folder}
text="This is a helpful explanation"
iconSize="20px"
/>Features:
- Automatic positioning to fit on screen
- Min width 150px, max width 300px
TabBar
Vertical tab navigation with support for categorized groups.
Props:
tabs: Array<TabItem>- Array of tabs and separatorsactiveTab: string- Currently active tab ID (bindable)onTabChange?: (tabId: string) => void- Callback when tab changes
TabItem Type:
type TabItem = {
id?: string; // Required for tabs, omit for separators
label: string; // Tab/separator text
icon?: string; // Optional icon SVG
type?: 'tab' | 'separator'; // Default: 'tab'
}Example:
<script>
import { TabBar, icons } from '@coyalabs/bts-style';
let currentTab = 'home';
const tabs = [
{ type: 'separator', label: 'Navigation' },
{ id: 'home', label: 'Home', icon: icons.folder },
{ id: 'about', label: 'About' },
{ type: 'separator', label: 'Account' },
{ id: 'settings', label: 'Settings' },
{ id: 'profile', label: 'Profile' }
];
</script>
<TabBar
{tabs}
bind:activeTab={currentTab}
onTabChange={(id) => console.log('Tab:', id)}
/>Features:
- Vertical layout, 175px fixed width
- Active tab uses
primarytheme, inactive usessecondary - Adaptive corner radius: 25px at group boundaries, 18px for middle tabs
- Text separators for grouping tabs into categories
- Categories have 1rem spacing between them
- Buttons within categories have 4px spacing
Corner Radius Behavior:
- First tab in a group: top corners 25px
- Last tab in a group: bottom corners 25px
- Middle tabs: all corners 18px
- Separators create group boundaries
TreeDirectory
Expandable file/folder tree with recursive structure.
Props:
items: Array<TreeItem>- Tree data structureshowCount?: boolean- Show item counts in folders (default:false)itemIcon?: string- Custom icon for itemstopFoldersExpanded?: boolean- Expand top-level folders initially (default:false)draggable?: boolean- Enable drag and drop functionality (default:false)currentPath?: string- Current folder path for nested items (default:'')level?: number- Internal: Current nesting level (default:0)
TreeItem Type:
type TreeItem = {
name: string;
type: 'file' | 'folder';
children?: TreeItem[];
data?: any; // Custom data attached to item
variant?: 'full' | 'primary' | 'secondary' | 'filled' | 'special-filled'; // Theme variant
suffixIcon?: string; // SVG icon displayed on the right
}Events:
on:itemClick- Fired when any item is clickedevent.detail.item- The clicked item objectevent.detail.type- Either'file'or'folder'
on:rightClick- Fired when any item is right-clickedevent.detail.item- The right-clicked item objectevent.detail.type- Either'file'or'folder'event.detail.event- The original mouse event (for positioning context menus)
on:dragStart- Fired when dragging a file starts (requiresdraggable={true})event.detail.item- The dragged item objectevent.detail.sourcePath- Path of the source folder
on:itemDrop- Fired when a file is dropped (requiresdraggable={true})event.detail.item- The dropped item dataevent.detail.sourcePath- Original folder pathevent.detail.targetPath- Destination folder path
Example:
<script>
import { TreeDirectory, icons } from '@coyalabs/bts-style';
const fileTree = [
{
name: 'src',
type: 'folder',
variant: 'primary',
children: [
{
name: 'App.svelte',
type: 'file',
variant: 'secondary',
suffixIcon: icons.pen
},
{ name: 'main.js', type: 'file' }
]
},
{
name: 'README.md',
type: 'file',
suffixIcon: '<svg>...</svg>'
}
];
function handleItemClick(event) {
const { item, type } = event.detail;
console.log(`Clicked ${type}:`, item.name);
}
function handleRightClick(event) {
const { item, type, event: mouseEvent } = event.detail;
console.log(`Right-clicked ${type}:`, item.name);
// Use mouseEvent.clientX and mouseEvent.clientY for positioning context menus
}
function handleDrop(event) {
const { item, sourcePath, targetPath } = event.detail;
console.log(`Moved ${item.name} from ${sourcePath} to ${targetPath}`);
}
</script>
<TreeDirectory
items={fileTree}
showCount={true}
topFoldersExpanded={true}
draggable={true}
on:itemClick={handleItemClick}
on:rightClick={handleRightClick}
on:itemDrop={handleDrop}
/>Methods:
<script>
let tree;
// Get current state
const state = tree.getState();
// Restore state
tree.setState(state);
// Expand all folders
tree.expandAll();
// Collapse all folders
tree.collapseAll();
</script>
<TreeDirectory bind:this={tree} items={fileTree} />Features:
- Slide animations (150ms, skipped on initial render)
- Recursive item counting
- State persistence
- Event forwarding for click handling
- Initial expansion option for top-level folders
- Adaptive corner radius based on nesting
- Padding increases with depth
- Per-item theme variants (override default folder/file themes)
- Suffix icon support for displaying icons on the right side
- Optional drag and drop functionality for files
- Visual feedback during drag operations (folder highlight)
- Path tracking for nested folder structures
Drag and Drop:
When draggable={true}:
- Only files can be dragged (folders are drop targets)
- Dragged files show reduced opacity
- Folders highlight when dragged over
- Drop on folders to move files into them
- Drop on empty space to move to current level
on:itemDropevent provides source and target paths for handling moves
Customization:
Item Variants:
Each item can have a custom variant to override the default theme:
- Folders default to
'primary' - Files default to
'secondary' - Set
varianton any item to use a different theme
Suffix Icons: Display additional icons on the right side of items:
{
name: 'config.json',
type: 'file',
suffixIcon: '<svg>...</svg>' // Any SVG string
}Popup System
Popup
Global modal popup overlay (singleton).
Usage:
<script>
import { Popup, popupStore } from '@coyalabs/bts-style';
</script>
<!-- Place once at app root -->
<Popup />Features:
- Fade overlay (250ms)
- Fly dialog animation (300ms, backOut easing)
- Close button with toned icon
- ESC key support (built-in)
popupStore
Writable store for controlling the popup.
Methods:
open()
popupStore.open(
title: string,
component: SvelteComponent,
props?: object,
subtitle?: string
)Opens popup with custom component.
Example:
<script>
import { popupStore } from '@coyalabs/bts-style';
import MyCustomPopup from './MyCustomPopup.svelte';
</script>
<button on:click={() =>
popupStore.open(
'Settings',
MyCustomPopup,
{ userId: 123 },
'Configure your preferences'
)
}>
Open Settings
</button>confirm()
popupStore.confirm(
title: string,
message: string,
options?: {
onConfirm?: () => void,
onCancel?: () => void,
confirmText?: string,
cancelText?: string
}
)Shows confirmation dialog.
Example:
<button on:click={() =>
popupStore.confirm(
'Delete Item',
'Are you sure? This cannot be undone.',
{
onConfirm: () => deleteItem(),
onCancel: () => console.log('Cancelled'),
confirmText: 'Delete',
cancelText: 'Keep'
}
)
}>
Delete
</button>alert()
popupStore.alert(
title: string,
message: string,
options?: {
onOk?: () => void,
okText?: string
}
)Shows alert dialog.
Example:
popupStore.alert(
'Success',
'Your changes have been saved!',
{
onOk: () => navigateToHome(),
okText: 'Got it'
}
);prompt()
popupStore.prompt(
title: string,
message: string,
options?: {
onSubmit?: (value: string) => void,
onCancel?: () => void,
placeholder?: string,
submitText?: string,
cancelText?: string
}
)Shows input prompt dialog.
Example:
popupStore.prompt(
'Enter Name',
'Please provide your display name:',
{
onSubmit: (name) => updateProfile(name),
placeholder: 'Your name...',
submitText: 'Save',
cancelText: 'Skip'
}
);close()
popupStore.close()Closes the current popup.
Popup Presets
The popup system includes three pre-built popup components that can be triggered via popupStore methods.
ConfirmPopup
A two-button confirmation dialog with confirm and cancel actions.
Features:
- Primary theme confirm button (left)
- Secondary theme cancel button (right)
- Callbacks:
onConfirm,onCancel - Customizable button text
Triggered via:
popupStore.confirm(title, message, options)Visual Layout:
- Message text displayed as subtitle
- Two buttons side-by-side
- Confirm button uses primary theme
- Cancel button uses secondary theme
AlertPopup
A single-button alert dialog for notifications.
Features:
- Single OK button with primary theme
- Callback:
onOk - Customizable button text
- Auto-closes on OK click
Triggered via:
popupStore.alert(title, message, options)Visual Layout:
- Message text displayed as subtitle
- Single centered OK button
- Primary theme button
PromptPopup
An input dialog that prompts the user for text input.
Features:
- InputBox component for text entry
- Submit button (primary theme)
- Cancel button (secondary theme)
- Callbacks:
onSubmit(value),onCancel - Customizable placeholder and button text
Triggered via:
popupStore.prompt(title, message, options)Visual Layout:
- Message text displayed as subtitle
- InputBox with customizable placeholder
- Two buttons: Submit (primary) and Cancel (secondary)
- Submit returns the input value to callback
Example with all options:
popupStore.prompt(
'Rename File',
'Enter a new name for this file:',
{
placeholder: 'filename.txt',
submitText: 'Rename',
cancelText: 'Cancel',
onSubmit: (newName) => {
console.log('New name:', newName);
renameFile(newName);
},
onCancel: () => console.log('Rename cancelled')
}
);Toast System
Toast
Global toast notification container (singleton).
Usage:
<script>
import { Toast, toastStore } from '@coyalabs/bts-style';
</script>
<!-- Place once at app root -->
<Toast />Features:
- Bottom-right stacking
- Smooth slide animations (300ms in, 200ms out)
- Auto-dismiss with configurable duration
- Manual dismiss via close button
- Non-blocking, less intrusive than popups
toastStore
Writable store for controlling toast notifications.
Methods:
show()
toastStore.show(
message: string,
duration?: number // Default: 4000ms, 0 = no auto-dismiss
): string // Returns toast IDShows a toast notification.
Example:
<script>
import { toastStore } from '@coyalabs/bts-style';
</script>
<button on:click={() => toastStore.show('File saved successfully!')}>
Save
</button>
<!-- Custom duration -->
<button on:click={() => toastStore.show('Processing...', 2000)}>
Process
</button>
<!-- No auto-dismiss -->
<button on:click={() => toastStore.show('Important message', 0)}>
Important
</button>dismiss()
toastStore.dismiss(id: string)Dismisses a specific toast by ID.
Example:
<script>
const toastId = toastStore.show('Click to dismiss', 0);
</script>
<button on:click={() => toastStore.dismiss(toastId)}>
Dismiss Toast
</button>dismissAll()
toastStore.dismissAll()Dismisses all active toasts.
Example:
<button on:click={() => toastStore.dismissAll()}>
Clear All Toasts
</button>Visual Design:
- Uses Button component with secondary theme
- Help icon on the left (info indicator)
- Close icon (crossb) on the right
- Stacks vertically with 0.75rem gap
- Slides in from right, slides out to right
- Fixed position at bottom-right (2rem from edges)
- Z-index 10000 (above popups)
Best Practices:
Place <Toast /> once at your app root alongside <Popup />:
<!-- App.svelte -->
<script>
import { BasePage, Popup, Toast } from '@coyalabs/bts-style';
</script>
<BasePage>
<!-- App content -->
</BasePage>
<Popup />
<Toast />Special Components
Glowy components with unique styling and animations.
SpecialAction
A special-themed button with gradient background and optional tooltip.
Props:
label: string- Button texttooltipText?: string- Optional tooltip text displayed on the right
Example:
<script>
import { SpecialAction } from '@coyalabs/bts-style';
</script>
<SpecialAction
label="AI Generate"
tooltipText="Uses AI to generate content"
/>Features:
- Purple gradient background (
special-filledtheme) - AI icon on the left
- Tooltip positioned at far right (when provided)
- Enhanced hover effect with brighter gradient
- Pressed state with darker gradient
For?
- AI actions.
Styling:
- Background: Linear gradient purple tones
- Enhanced glow effects on hover
- User-select disabled for better UX
SpecialParagraph
Animated text component that reveals words sequentially with fade and blur effects.
Props:
text: string- The text content to animatewordDelay?: number- Delay between each word appearing in ms (default:50)startDelay?: number- Initial delay before animation starts in ms (default:0)animationDuration?: number- Animation duration for each word in ms (default:300)variant?: 'title' | 'content' | 'button'- Text styling variant (default:'content')textModifier?: string- Font size adjustment (default:'0px')autoPlay?: boolean- Start animation automatically on mount (default:true)
Methods:
play()- Start/restart the animationreset()- Reset to hidden stateshowAll()- Show all words immediately
Example:
<script>
import { SpecialParagraph } from '@coyalabs/bts-style';
let paragraph;
</script>
<!-- Auto-playing paragraph -->
<SpecialParagraph
text="This text will animate in word by word with smooth effects"
wordDelay={80}
variant="content"
/>
<!-- Manual control -->
<SpecialParagraph
bind:this={paragraph}
text="Click the button to animate!"
autoPlay={false}
/>
<button on:click={() => paragraph.play()}>Play Animation</button>Animation Effects:
- Each word fades in from opacity 0 to 1
- Slides up from 8px translateY offset
- Blur transitions from 4px to 0
- Smooth easing transitions
For?
- Fancier AI.
Use Cases:
- Intro text animations
- Loading state messages
- Drawing attention to important content
- Storytelling and narrative interfaces
ContextMenu
Categorized menu component with separator support, similar to TabBar layout.
Props:
items: Array<ContextMenuItem>- Array of menu items and separatorsselectedValue?: any- Currently selected item valueonSelect?: (value: any) => void- Callback when item is selected
ContextMenuItem Type:
type ContextMenuItem = {
label: string;
value?: any; // Required for items, omit for separators
disabled?: boolean;
type?: 'item' | 'separator'; // Default: 'item'
}Example:
<script>
import { ContextMenu } from '@coyalabs/bts-style';
let selectedValue = 'cut';
const menuItems = [
{ label: 'Edit', type: 'separator' },
{ label: 'Cut', value: 'cut' },
{ label: 'Copy', value: 'copy' },
{ label: 'Paste', value: 'paste', disabled: true },
{ label: 'View', type: 'separator' },
{ label: 'Zoom In', value: 'zoomIn' },
{ label: 'Zoom Out', value: 'zoomOut' }
];
</script>
<ContextMenu
items={menuItems}
{selectedValue}
onSelect={(val) => handleAction(val)}
/>Features:
- Category grouping with separator labels
- Selected item highlighting
- Disabled item support with reduced opacity
- Hover effects on enabled items
- Filled theme container
- Automatic category spacing and borders
- Text ellipsis for long labels
Visual Layout:
- Categories separated by labeled dividers
- First category has no top border
- Subsequent categories have subtle top border
- 0.5rem padding around separators
- 4px spacing between items
Dropdown
Select dropdown with collapsible options menu.
Props:
label: string- Default button text before selectionicon?: string- Optional left icon SVGtheme?: 'full' | 'primary' | 'secondary'- Button theme (default:'full')width?: string- Fixed width for dropdown (default:'200px')options: Array<DropdownOption>- Array of selectable optionsvalue?: any- Currently selected value (bindable)onChange?: (value: any) => void- Callback when selection changes- All BaseContainer corner radius props
DropdownOption Type:
type DropdownOption = {
label: string;
value: any;
disabled?: boolean;
type?: 'item' | 'separator'; // Optional: use for category separation
}Example:
<script>
import { Dropdown, icons } from '@coyalabs/bts-style';
let selectedValue = 'option1';
const options = [
{ label: 'Basic', type: 'separator' },
{ label: 'Option 1', value: 'option1' },
{ label: 'Option 2', value: 'option2' },
{ label: 'Advanced', type: 'separator' },
{ label: 'Option 3', value: 'option3' },
{ label: 'Disabled', value: 'option4', disabled: true }
];
</script>
<Dropdown
label="Select an option"
icon={icons.folder}
theme="primary"
width="250px"
{options}
bind:value={selectedValue}
onChange={(val) => console.log('Selected:', val)}
/>Features:
- Fixed width with text truncation (ellipsis)
- Expand icon rotates 180° when open
- Slide animation for menu (150ms)
- Click outside to close
- Uses ContextMenu component internally
- Support for category separators
- Selected item highlighted
- Disabled items shown with reduced opacity
LinearList
Vertical list component with customizable actions for each item.
Props:
items: Array<ListItem>- Array of list items
ListItem Type:
type CustomAction = {
label: string;
actionIcon?: string;
}
type ListItem = {
data?: any; // Custom data attached to item
customActions?: CustomAction[];
removeButton?: boolean;
}Events:
on:action- Fired when any custom action is clickedevent.detail.index- Item indexevent.detail.actionLabel- Action label that was clickedevent.detail.item- The item object
on:remove- Fired when remove button is clickedevent.detail.index- Item indexevent.detail.item- The item object
Example:
<script>
import { LinearList, icons } from '@coyalabs/bts-style';
const items = [
{
data: { id: 1, name: 'First Item' },
customActions: [
{ label: 'Edit', actionIcon: icons.pen },
{ label: 'View' }
],
removeButton: true
},
{
data: { id: 2, name: 'Second Item' },
customActions: [
{ label: 'Download' }
],
removeButton: true
}
];
function handleAction(event) {
const { index, actionLabel, item } = event.detail;
console.log(`${actionLabel} clicked on item ${index}`, item);
}
function handleRemove(event) {
const { index, item } = event.detail;
console.log(`Remove item ${index}`, item);
}
</script>
<LinearList
{items}
on:action={handleAction}
on:remove={handleRemove}
>
{#snippet children({ item, index })}
<div>{item.data.name}</div>
{/snippet}
</LinearList>Features:
- Left-aligned content slot with
itemandindexprops - Right-aligned action buttons (horizontal)
- Optional remove button (icon-only, toned variant)
- 1px bottom border separator (rgba(161, 143, 143, 0.24))
- No border on last item
- 10px vertical padding per item
- No horizontal padding
- No spacing between items
- Event-based action handling
Visual Layout:
- Each item is a flex row with space-between
- Content on the left, actions on the right
- Actions have 0.5rem gap between them
- Remove button appears at the end of actions
- Borders are internal strokes (bottom edge only)
Separator
Decorative SVG separator with tiled middle section.
Props:
height?: string- Separator height (default:'12px')width?: string- Separator width (default:'100%')margin?: string- CSS margin (default:'2rem 0')
Example:
<script>
import { Separator } from '@coyalabs/bts-style';
</script>
<Separator />
<Separator height="20px" margin="3rem 0" />Features:
- Three-part design: left piece, tiled middle, right piece
- Inline SVG data URLs for performance
- Scales to container width
- Elegant visual break between sections
Icons
The package exports a collection of built-in SVG icons.
Usage:
<script>
import { icons, BaseIcon } from '@coyalabs/bts-style';
</script>
<BaseIcon svg={icons.arrow} />
<BaseIcon svg={icons.folder} />
<BaseIcon svg={icons.icon_expand} />
<BaseIcon svg={icons.cross} />
<BaseIcon svg={icons.pen} />Available Icons:
arrow- Right arrow navigationfolder- Folder iconicon_expand- Expand/collapse chevroncross- Close/dismiss Xpen- Edit/write pen
Custom Icons:
You can use any SVG string with icon-supporting components:
<script>
const myIcon = '<svg>...</svg>';
</script>
<Button icon={myIcon}>Custom Icon</Button>
<BaseIcon svg={myIcon} />Styling
Corner Radius Customization
All components extending BaseContainer support individual corner radius props:
<Button
borderRadiusTopLeft="35px"
borderRadiusTopRight="35px"
borderRadiusBottomLeft="15px"
borderRadiusBottomRight="15px"
theme="primary"
>
Asymmetric Button
</Button>Theme Customization
You can customize filled theme backgrounds by targeting CSS variables or extending components.
Best Practices
Layout
<BasePage>
<main style="max-width: 900px; margin: 0 auto; padding: 3rem 2rem;">
<TextHeader title="My App" subtitle="Welcome" />
<!-- Your content -->
</main>
</BasePage>Popup Management
Place <Popup /> once at your app root:
<!-- App.svelte -->
<script>
import { BasePage, Popup } from '@coyalabs/bts-style';
</script>
<BasePage>
<!-- App content -->
</BasePage>
<Popup />Icons
For consistent styling, prefer using BaseIcon over raw SVG:
<!-- Good -->
<BaseIcon svg={myIcon} variant="toned" />
<!-- Less ideal -->
{@html myIcon}Development
Local Development
Link the package locally for testing:
# In the package directory
cd @bts-theme/bts-theme
npm run package
npm link
# In your project
npm link @coyalabs/bts-styleAfter making changes:
npm run packageNote: You may need to clear Vite cache after rebuilding:
rm -rf node_modules/.vitePublishing
npm run release # Bumps version, packages, and publishesTypeScript Support
All components include TypeScript definitions. Import types as needed:
import type { TreeItem } from '@coyalabs/bts-style';Package Structure
@coyalabs/bts-style/
├── dist/ # Compiled package
├── public/ # Static assets
│ ├── favicon.svg # Default BTS favicon
│ └── PLACE_YOUR_IMAGES_HERE.txt
├── src/
│ ├── Base/ # Base components
│ ├── Components/ # Interactive components
│ ├── Structure/ # Layout components
│ ├── icons.js # Icon definitions
│ └── index.ts # Main export
└── package.jsonLicense
MIT
Repository
github.com/sparklescoya/svelte-bts-theme
Credits
Created with ❤️ using Svelte 5
