Packages
Framework packages are found within the Skeleton monorepo in the following locations.
Package | Framework | App Framework |
---|---|---|
/packages/skeleton-svelte | Svelte 5 | SvelteKit |
/packages/skeleton-react | React | Vite/React |
The purpose of our component packages is two-fold. First, they house and export the full set of components available to that framework. Additionally, each project contains a dedicated app framework. This is used to test the components in their native environment. Use these projects as a sandbox to test and iterate before adding the components to the public facing Astro-base documentation website.
Dev Server
To run each app framework, change your directory to the respective package and run the following command.
Server Ports
The following represents the default localhost address and port for each project. This will be displayed in the terminal when starting each dev server.
- Documentation Site:
http://localhost:4321/
- Svelte Package App:
http://localhost:5173/
- React Package App:
http://localhost:5173/
You may run the documentation site and framework packages in parallel at the same time. If the server shares a port, this will increment by one for the next server (ex: 5174
, 5175
, etc). Keep your eye on the terminal to retrieve the specific local address.
Add Components
Components are housed in the following location per framework:
Framework | Directory |
---|---|
Svelte | /src/lib/components |
React | /src/components |
Use the following file path conventions when creating a new component:
Props
Skeleton designates the following categories of component properties. These should be maintained in the following order.
- Functional - these should be single instance props that directly affect the functionality of the component.
- Style - contain and accept Tailwind utility classes to affect the style of the component.
- Event - provide callback functions for external event handlers.
- Children - contain reference to React children, Svelte Snippets, or similar.
Style Prop Conventions
Style props implement sementic naming conventions to enable specificity and avoid naming conflicts. These are organized into three specific categories. Each should be maintained in the following order.
base
- houses the base utility classes, which enables faux-headless styling.- Replaces:
cBase
class definitions from Skeleton v2. - Parent base props are not prefixed, which helps maintain parity cross-framework
- Child base props are prefixed:
titleBase
,panelBase
,controlBase
.
- Replaces:
{property}
- individual style props that houses one or more “swappable” utility classes.- Naming should follow Tailwind convention, except for single letter descriptors (ex: use
padding
instead ofp
). - Parent props are not prefixed:
background
,margin
,border
. - Child props are prefixed:
titleBg
,controlMargin
,panelBorder
.
- Naming should follow Tailwind convention, except for single letter descriptors (ex: use
classes
- allows you to extend or override the class list with an arbitrary set of utility classes.- Replaces the inconsistent use of
slotX
andregionX
classes in Skeleton v2. - Uses
classes
(plural) to avoid conflict with the standardclass
attribute.- Parent instances are not prefixed:
classes
- Child instances are prefixed:
titleClasses
,controlClasses
,panelClasses
- Parent instances are not prefixed:
- Replaces the inconsistent use of
Here’s what this might look like in practice.
Dynamic Style Props
You may need to conditionally update or swap between one or more sets of style prop classes. For this, we will use an “interceptor” pattern as demonstrated below. The rx
naming convention denotes that the value will be derived in a reactive manner. This is simpler to distinguish in the template from standard style prop classes.
TIP: use this convention in React as well, but make use of a ternary,
useState
, oruseMemo
hooks as appropriate.
Type Definitions
All component props should be strongly typed using Typescript in a colocated types.ts
file. Each prop should be described using JSDoc. This provides additional context through Intellisense features of text editors and IDEs and helps generate automatic documentation for these features. Remember to keep the description short and semantic.
Context API
Svelte
Skeleton expands the Svelte Context API via a utility called createContext
, which handles the following:
- Generates a unique key using the
Symbol
API. - Ensure type safety when getting and setting context.
- Allows for a fallback when there is no context provided.
Here’s an example of how this can be used:
Which can then be used like so:
Form Components
When implementing form components (ex: Segment Control), please adhere to the following conventions:
- For components with a parent/child structure, pass all shared values through the parent.
- Data in should use a
value
prop, while data out should use anonChange
event handler. - When supported, use two-way binding on the
value
;onChange
is then optional. - Pass state that’s unique to the child components directly to each child item.
- When embedding form inputs within components for state management, always use
type="hidden"
.
See the examples per each framework below.
Svelte
React
Generating Schema
When you add or change component types.ts
data, please run pnpm schema
in the Astro documentation project to generate new component schema. This data is used to populate the API Reference information on each documentation page. In most cases you can just add the following component on the page and the available schema will automatically be consumed.
In rare cases you may need to specify the schema directly. To do so, import the schema JSON, then pass this via the schema
prop.
All generate schema files reside in the following directory.
Animations
Skeleton opts for what we feel is the most optimal solution for animations per framework. This means implementation and capabilities may differ slightly for each. Please refer to the Accordion component source code for a reference example.
Package | Solution |
---|---|
/packages/skeleton-svelte | Svelte Transition |
/packages/skeleton-react | Framer Motion |
Composed Pattern
To keep component syntax consistent cross-framework, we implement a composed pattern. Components are composed using a set of smaller components, named slots, or snippets - depending on the framework. This implementation differs per framework.
React
For React, this is handled via small components that implement the dot notation syntax.
Svelte
This is handled by pairing child components with Svelte Snippets.
Dot Notation Syntax
The implementation of this will differ per framework.
React
To implement this, we use Object.assign()
For example, for the accordion component
Svelte
Create a new index.ts
file colocated within the /component/<ComponentName>
directory:
Component Exports
Finally, make sure components are included in the package export list.
React
Found in /src/lib/index.ts
.
Svelte
Found in /src/components/index.ts
.
Additional Resources
- Component Party - easily compare features between each framework
- Svelte 5 Docs - the temporary home of Svelte 5 documentation
- Svelte 5 REPL - quickly test and share Svelte 5 code snippets