---
title: Design Philosophy
description: "AsheeUI abstracts the HTML element and the utility classes, so a component copied into a project works the way it did where it was copied from."
type: concept
section: Core concepts
order: 0
---

AsheeUI exists so that a component can be written once and used everywhere: copied out of
the documentation into a project, imported from the package, or written by the CLI's
template. That promise holds only if a component owns two things, which is why the
framework abstracts both.

---

## The idea

A component brings its own element and its own styling. You write `<Button>`, and the
component decides whether that is a `<button>` or an `<a>`, which variant and size it
carries, and what a colour role resolves to. You do not write the element, and you do not
write the classes.

Everything on this page is a consequence of that:

- The **element** is the component's decision, because one call has to render a control in
  one place and a navigation in another.
- The **styling** is the theme's decision, because a copied component has to arrive looking
  right in a project it has never seen.
- The **layout** is a component too, because needing a wrapper is the most common reason a
  project starts writing markup by hand.

---

## What is abstracted

**The HTML element.** `Button` renders a `<button>`, or an `<a>` when it is given an `href`
or a link. `Card` renders a `div`, or the link component you name. `Link` renders an anchor,
or your router's link. The element follows what the component was asked to do, and it is
written once, inside the framework.

**The utility classes.** A variant, a size, a colour role, a radius and a spacing step are
props rather than class strings. `<Badge color="primary" variant="faded">` is the whole
styling decision: the component resolves the pair to one static class string that the theme
produced. Nothing in your application has to name a Tailwind utility to make an AsheeUI
component look the way it is supposed to look.

**The layout.** `Container`, `Section`, `Grid`, `Stack`, `HStack`, `VStack` and `Centered`
exist so that composition does not fall back to markup with classes. A band of a page is a
`Section` with a spacing step, not a `div` with padding utilities.

---

## How it resolves

Every option a component takes resolves through one cascade, in the same order:

1. the prop on the component, such as `color="danger"`
2. the component's configuration, such as `components.badge.color` in `asheeui.config.ts`
3. the application's defaults on the provider, such as `defaultRadius`
4. the framework's fallback

Because the styling is resolved rather than written, the same copied component renders
correctly in a project whose theme is not the theme it was copied from: the component asks
the theme what `primary` is there, and the theme answers.

---

## Your router and image components still work

Abstraction is not isolation. A link still has to be your router's link and an image still
has to be your application framework's image, or the application gives up prefetching, the
image pipeline and everything else that framework is for.

So the components that render one take a substitution:

```tsx
import { Link } from "asheeui";
import NextLink from "next/link";

export function DashboardLink() {
  return (
    <Link href="/dashboard" component={NextLink} componentProps={{ prefetch: true }}>
      Dashboard
    </Link>
  );
}
```

`component` names the component to render in place of the native element, and
`componentProps` carries what it needs. What you name renders **inside** the AsheeUI
component, and that is the whole point: the router keeps the navigation, the image component
keeps the loading, and AsheeUI keeps the styling, the states and the accessibility. The same
pair works on `Image` for a framework's image component and on `Form` for its form
component, and the components that render a link or an image themselves take it as well:
`Card`, `Button`, `Avatar`, `Breadcrumb`, `Navbar`, `Footer` and `Testimonials`.

This is the strongest argument for writing the component instead of the element. An
`<a href>` written by hand cannot become a router link later; a `<Link href>` can.

---

## In practice

- The CLI writes an application whose provider, styles and configuration are already in
  place.
- A component is copied out of these pages, or imported from the package.
- The theme decides what its colours, radii and spacing resolve to.
- The framework's routing and images arrive through substitution, so the application keeps
  its own navigation and its own image pipeline.

---

## What to avoid

**Hand-written markup and utility classes for something the framework provides.** It is the
one habit that works against the reason to use the framework at all:

- What you write is not in the theme, so it cannot follow a change to the theme.
- It is not part of the cascade, so a project default cannot reach it.
- It does not travel. A copied file that leans on utilities you added reads differently
  where those utilities are not in use, or are overridden.
- It cannot take a substitution. Framework components arrive through `component` and
  `componentProps`, which is how your router's link and your application framework's image
  get in. An anchor written by hand has nowhere to put them, so it stays a plain anchor
  while the rest of the application navigates through the router and loads images through
  the framework's pipeline.
- It becomes a second source of truth for something the component already decides.

There is an escape hatch, and it is deliberate: every component accepts `className`, because
the framework is Tailwind-native and a genuine one-off is a real thing. The recommendation
is to reach for it last, after a prop and a token and the configuration have each been
considered, and never as the way an application's screens are built.

When something needs to exist in its own right, build it from AsheeUI components and give it
a name. That is a component which travels, inherits the theme and takes a substitution,
which is the same standard the framework holds itself to.

---

## Related

- [Configuration](/docs/configuration): the cascade, written down.
- [Theming](/docs/theming): the tokens a component resolves its colours against.
- [Components](/docs/components): what each component abstracts, and what it takes.
- [Getting Started](/docs/getting-started): the three ways a component arrives.

