Skip to content
Vy logo
Guides

Component development

This section will cover how to develop new and maintain components in the design system. When creating a new component it is important for them to be consistent, accessible, and align with the design tokens.

Creating a new component

At Spor, everyone contributes! If your team needs a new component, it’s your responsibility to make it happen. This guide will walk you through the process.

📂 Where to Add Components

All components are located in packages/spor-react/src.

📁 Component Structure

Our folder structure closely mirrors the Figma component file, so you should easily find the correct location for your component.

  • Name your file the same as your component (e.g., Button.tsx).
  • If your component consists of multiple files, create a dedicated folder for it.

🌟 Best Practices

  • Keep components modular, reusable, and small.
  • Refer to the Chakra documentation as needed.
  • Avoid using raw HTML elements like <div> or <span>. Instead, use Chakra components to ensure design token compatibility.

📜 Component File: Key Considerations

📝 Writing Documentation in Code

  • Include a brief usage guide at the top of the file.
  • Add comments on props to explain their purpose, options, and default values.

🔀 Props vs. Composite Components

Decide whether to:

  1. Use props for customization – Best for simple components where users need minimal control.
  2. Break into smaller composite components – Ideal for complex components like Accordions, where different parts need independent control.

Tip

Providing a label prop for an input field is often better than requiring users to manually add a <label> element.

🔁 Handling Rest Props in Chakra Components

When using Chakra, be intentional about including rest props (...rest). Instead of automatically spreading all props onto the component, consider whether each prop should be exposed to users.

Why?

Prevents unwanted props from affecting styling or behavior.
Allows for better control over component API and defaults.
Reduces inconsistencies by limiting excessive customization.

Best Practice

If the component should allow additional props, include {...rest} in a controlled manner.
If not, explicitly define accepted props to keep the API clean.

Example:

const Button = ({ children, variant = "primary", ...rest }: ButtonProps) => {
return <ChakraButton colorScheme={variant} {...rest}>{children}</ChakraButton>;
};
  • Here, we intentionally allow additional Chakra props (rest), but control the variant prop.

Avoid blindly spreading props unless necessary, as it can expose the component to unintended behaviors.

📌 Recipe vs. Slot Recipe?

🎨 Use Design Tokens

Spor provides typed and exported design tokens for colors, spacing, sizing, and more. Always use these tokens instead of static values to ensure consistency across components.

🎭 Use Semantic Color Tokens

For colors, always use semantic tokens rather than aliases or raw color values. Semantic tokens automatically handle both light and dark mode, ensuring proper contrast and accessibility in different themes.

Good:

<Box backgroundColor="core.surface" />

Avoid:

<Box backgroundColor="darkTeal" />

📌 Defining Types

  • We prefer type over interface.
  • Add comments on props, especially if they have default values.
  • Stick to naming conventions. Avoid isDisabled, use disabled instead.

♿ Prioritizing Accessibility

Building accessible components benefits everyone, not just users with disabilities. Spor is committed to universal design, and you should be too!

✅ Use Semantic HTML

Whenever possible, use native HTML elements instead of divs and spans. This ensures built-in accessibility without extra effort.

Good:

<Button onClick={handleClick}>Button is semantic</Button>

Avoid:

<div onClick={handleClick} role="button" tabindex="0">Click me</div>

Semantic elements come with correct roles, keyboard support, and screen reader behavior by default—saving you time and effort!

🔊 Use ARIA Only When Needed

ARIA attributes (like aria-label, aria-labelledby, or aria-hidden) can enhance accessibility but should not replace semantic elements. Use them only when necessary.

Use aria-label when no visible label exists:

<IconButton aria-label="Close modal" icon={<CloseIcon />} onClick={closeModal} />

Don’t overuse ARIA when native elements work:

<div role="button" aria-label="Submit">Submit</div>

Instead, just use a <Button>.

🎯 Focus on Keyboard Navigation

  • Ensure all interactive elements are focusable (tabindex when necessary).
  • Use onKeyDown handlers where applicable (e.g., Enter for button-like elements).
  • Avoid removing outline styles—users rely on them for navigation!

By following these best practices, you'll create components that are usable by everyone—no extra work later to fix accessibility issues! 🚀

Tip

Mdn docsEkstern lenke contains a lot of tips for semantics and how your component should act when using keyboard navigation.

📤 Exporting Components

Every folder should have an index.ts file.

  • Export your new component inside index.ts to ensure it’s available in the package.

📚 Updating Documentation in Sanity

  • If you’ve created a new component, update the documentation in Sanity.
  • If you don’t have access, contact Team Kanaler on Slack.

⚠️ Other Things to Be Aware Of

🛠 Running Type Generation

If you add or modify a slot in a slot recipe, you must run:

npm run typegen

For live updates while developing, use:

npm run typegen:watch

🔄 Rebuilding Icons or Tokens

If you upload new icons or modify design tokens, run:

npm run build

This ensures your changes appear locally.

🔖 Summary Checklist

✔️ Place your component in the correct folder.

✔️ Follow best practices for modular and reusable code.

✔️ Decide between using props or composite components.

✔️ Use Chakra components instead of raw HTML elements.

✔️ Include documentation and comments on props.

✔️ Follow proper type definitions (type over interface).

✔️ Always use semantic tokens.

✔️ Prioritise accessibility

✔️ Export your component in index.ts.

✔️ Update Sanity documentation.

✔️ Run npm run typegen if you've changed a recipe.

✔️ Run npm run build if you modified icons or design tokens.