design token

Border Radius

Consistent rounded corner styles from sharp edges to fully rounded elements.

Consistent rounded corner styles from sharp edges to fully rounded elements. All values use rem units for scalability.

Scale

scale · border radius
xs 0.4rem
sm 0.6rem
md 0.8rem
lg 1.2rem
xl 1.6rem
2xl 2.4rem
3xl 3.2rem
4xl 4.0rem
5xl 4.8rem
6xl 6.4rem
full 9999px

Inner Radii

Semantic inner radius tokens are auto-generated for nested elements. They ensure an inner element’s radius looks proportional to its parent by computing max(4px, calc(outerRadius - spacing)):

// Example: a card with lg radius and md padding
// The inner element uses the inner radius token
<div className={css({ borderRadius: "lg", padding: "md" })}>
  <div className={css({ borderRadius: "inner.lg.md" })}>
    Inner content with proportional rounding
  </div>
</div>

Basic Usage

Card (lg)

Card content with large border radius

Button (md)

Badge/Pill (full)

Badge
---
import { css } from "@pindoba/styled-system/css";

// Common styles using css.raw()
const containerStyle = css({
  display: "flex",
  flexDirection: "column",
  gap: "lg",
  width: "full",
});

const subsectionTitleStyle = css.raw({
  fontSize: "sm",
  fontWeight: "bold",
  color: "neutral.text.bold",
});

const sectionStyle = css.raw({
  display: "flex",
  flexDirection: "column",
  gap: "md",
});

const sectionContentStyle = css.raw({
  display: "flex",
  flexDirection: "column",
  alignItems: "flex-start",
  gap: "2xs",
  backgroundColor: "neutral.surface.soft",
  borderRadius: "lg",
  padding: "lg",
  border: "1px solid",
  borderColor: "neutral.border.muted",
});

// Static border radius styles
const borderRadiusStyles = {
  lg: css.raw({ borderRadius: "lg" }),
  md: css.raw({ borderRadius: "md" }),
  full: css.raw({ borderRadius: "full" }),
} as const;

// Base component styles
const baseCardStyle = css.raw({
  backgroundColor: "neutral.surface.step.2",
  padding: "md",
  border: "1px solid",
  borderColor: "neutral.border.muted",
});

const baseButtonStyle = css.raw({
  backgroundColor: "primary.surface.deep",
  color: "primary.text.contrast",
  padding: "sm md",
  border: "none",
  cursor: "pointer",
  px: "sm",
  py: "xs",
});

const baseBadgeStyle = css.raw({
  display: "inline-flex",
  backgroundColor: "success.surface.deep",
  color: "success.text.contrast",
  px: "xs",
  py: "2xs",
  fontSize: "xs",
  fontWeight: "bold",
  borderRadius: "full",
});

// Component examples data
const examples = [
  {
    title: "Card (lg)",
    content: "Card content with large border radius",
    style: baseCardStyle,
    borderRadius: "lg" as const,
  },
  {
    title: "Button (md)",
    content: "Button",
    style: baseButtonStyle,
    borderRadius: "md" as const,
  },
  {
    title: "Badge/Pill (full)",
    content: "Badge",
    style: baseBadgeStyle,
    borderRadius: "full" as const,
  },
];
---

<div class={containerStyle}>
  <!-- Basic Border Radius -->
  <div class={css(sectionStyle)}>
    {
      examples.map((example) => (
        <div class={css(sectionContentStyle)}>
          <h4 class={css(subsectionTitleStyle)}>{example.title}</h4>
          {example.title.includes("Button") ? (
            <button
              class={css(
                example.style,
                borderRadiusStyles[example.borderRadius],
              )}
            >
              {example.content}
            </button>
          ) : (
            <div
              class={css(
                example.style,
                borderRadiusStyles[example.borderRadius],
              )}
            >
              {example.content}
            </div>
          )}
        </div>
      ))
    }
  </div>
</div>

Directional Border Radius

Directional Border Radius

Top rounded
borderTopRadius: "lg"
Bottom rounded
borderBottomRadius: "lg"
Left rounded
borderLeftRadius: "lg"
Right rounded
borderRightRadius: "lg"
Asymmetric rounding
TL: xl, TR: sm, BR: xl, BL: sm
---
import { css } from "@pindoba/styled-system/css";

// Common styles using css.raw()
const containerStyle = css({
  display: "flex",
  flexDirection: "column",
  gap: "lg",
});

const sectionStyle = css.raw({
  backgroundColor: "neutral.surface.soft",
  borderRadius: "lg",
  padding: "lg",
  border: "1px solid",
  borderColor: "neutral.border.muted",
});

const sectionTitleStyle = css.raw({
  fontSize: "md",
  fontWeight: "bold",
  marginBottom: "md",
  color: "neutral.text.bold",
});

const gridStyle = css.raw({
  display: "grid",
  gridTemplateColumns: "repeat(auto-fit, minmax(200px, 1fr))",
  gap: "md",
});

const itemContainerStyle = css.raw({
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  gap: "sm",
});

const baseBoxStyle = css.raw({
  padding: "md",
  width: "full",
  textAlign: "center",
  border: "1px solid",
});

const labelStyle = css.raw({
  fontSize: "xs",
  color: "neutral.text",
  fontFamily: "mono",
});

const specialItemStyle = css.raw({
  display: "flex",
  flexDirection: "column",
  alignItems: "center",
  gap: "sm",
  gridColumn: "1 / -1",
});

const specialBoxStyle = css.raw({
  padding: "md",
  textAlign: "center",
  border: "1px solid",
  borderColor: "info.border.muted",
  maxWidth: "sm",
  width: "full",
});

// Directional border radius styles
const directionalBorderRadiusStyles = {
  top: css.raw({
    borderTopLeftRadius: "lg",
    borderTopRightRadius: "lg",
  }),
  bottom: css.raw({
    borderBottomLeftRadius: "lg",
    borderBottomRightRadius: "lg",
  }),
  left: css.raw({
    borderTopLeftRadius: "lg",
    borderBottomLeftRadius: "lg",
  }),
  right: css.raw({
    borderTopRightRadius: "lg",
    borderBottomRightRadius: "lg",
  }),
  mixed: css.raw({
    borderTopLeftRadius: "xl",
    borderTopRightRadius: "sm",
    borderBottomRightRadius: "xl",
    borderBottomLeftRadius: "sm",
  }),
} as const;

// Component data
const directionalExamples = [
  {
    direction: "top" as const,
    text: "Top rounded",
    bgColor: "primary.surface",
    borderColor: "primary.border.muted",
    label: 'borderTopRadius: "lg"',
  },
  {
    direction: "bottom" as const,
    text: "Bottom rounded",
    bgColor: "success.surface",
    borderColor: "success.border.muted",
    label: 'borderBottomRadius: "lg"',
  },
  {
    direction: "left" as const,
    text: "Left rounded",
    bgColor: "warning.surface",
    borderColor: "warning.border.muted",
    label: 'borderLeftRadius: "lg"',
  },
  {
    direction: "right" as const,
    text: "Right rounded",
    bgColor: "danger.surface",
    borderColor: "danger.border.muted",
    label: 'borderRightRadius: "lg"',
  },
];
---

<div class={containerStyle}>
  <!-- Directional Border Radius -->
  <div class={css(sectionStyle)}>
    <h3 class={css(sectionTitleStyle)}>Directional Border Radius</h3>
    <div class={css(gridStyle)}>
      {
        directionalExamples.map((example) => (
          <div class={css(itemContainerStyle)}>
            <div
              class={css(
                baseBoxStyle,
                directionalBorderRadiusStyles[example.direction],
                {
                  backgroundColor: example.bgColor,
                  borderColor: example.borderColor,
                },
              )}
            >
              {example.text}
            </div>
            <span class={css(labelStyle)}>{example.label}</span>
          </div>
        ))
      }

      <!-- Mixed Radius Values -->
      <div class={css(specialItemStyle)}>
        <div
          class={css(specialBoxStyle, directionalBorderRadiusStyles.mixed, {
            backgroundColor: "info.surface",
          })}
        >
          Asymmetric rounding
        </div>
        <span
          class={css(labelStyle, {
            textAlign: "center",
          })}
        >
          TL: xl, TR: sm, BR: xl, BL: sm
        </span>
      </div>
    </div>
  </div>
</div>

Responsive & Interactive

Responsive Border Radius

Responsive Radius

Radius changes with screen size

Mobile: sm → Tablet: md → Desktop: lg

Interactive Radius (Hover)

Hover to change radius

Default: md → Hover: xl

Focus State Radius

Focus changes radius from sm to lg

Active State Radius

Active state reduces radius from lg to sm

---
import { css } from "@pindoba/styled-system/css";

// Common styles using css()
const containerStyle = css({
  display: "flex",
  flexDirection: "column",
  gap: "lg",
});

const sectionStyle = css({
  backgroundColor: "neutral.surface.soft",
  borderRadius: "lg",
  padding: "lg",
  border: "1px solid",
  borderColor: "neutral.border.muted",
});

const sectionTitleStyle = css({
  fontSize: "md",
  fontWeight: "bold",
  marginBottom: "md",
  color: "neutral.text.bold",
});

const sectionContentStyle = css({
  display: "flex",
  flexDirection: "column",
  gap: "lg",
});

const subsectionTitleStyle = css({
  fontSize: "sm",
  fontWeight: "medium",
  marginBottom: "sm",
  color: "neutral.text.bold",
});

const baseBoxStyle = css.raw({
  padding: "md",
  border: "1px solid",
  textAlign: "center",
});

const baseDescriptionStyle = css({
  margin: "0",
  fontSize: "sm",
});

const primarySubDescriptionStyle = css({
  margin: "0",
  fontSize: "xs",
  marginTop: "xs",
  color: "primary.text",
});

const successSubDescriptionStyle = css({
  margin: "0",
  fontSize: "xs",
  marginTop: "xs",
  color: "success.text",
});

const baseButtonStyle = css.raw({
  border: "2px solid",
  fontSize: "sm",
  cursor: "pointer",
  py: "md",
  px: "lg",
});

const buttonDescriptionStyle = css({
  margin: "0",
  fontSize: "xs",
  color: "neutral.text",
  marginTop: "xs",
});

const responsiveRadiusBoxStyle = css.raw({
  borderRadius: {
    base: "sm",
    md: "md",
    lg: "lg",
  },
  backgroundColor: "primary.surface",
  borderColor: "primary.border.muted",
});

const interactiveRadiusBoxStyle = css.raw({
  borderRadius: "md",
  backgroundColor: "success.surface",
  borderColor: "success.border.muted",
  transition: "all 0.3s ease",
  cursor: "pointer",
  "&:hover": {
    borderRadius: "xl",
  },
});

const focusButtonStyle = css.raw({
  borderRadius: "sm",
  backgroundColor: "warning.surface",
  borderColor: "warning.border.muted",
  transition: "all 0.2s ease",
  "&:focus": {
    borderRadius: "lg",
    borderColor: "warning.border",
    outline: "none",
  },
});

const activeButtonStyle = css.raw({
  borderRadius: "lg",
  backgroundColor: "info.surface",
  borderColor: "info.border.muted",
  transition: "all 0.1s ease",
  "&:active": {
    borderRadius: "sm",
    transform: "scale(0.98)",
  },
});
---

<div class={containerStyle}>
  <!-- Responsive Border Radius -->
  <div class={sectionStyle}>
    <h3 class={sectionTitleStyle}>Responsive Border Radius</h3>
    <div class={sectionContentStyle}>
      <div>
        <h4 class={subsectionTitleStyle}>Responsive Radius</h4>
        <div class={css(baseBoxStyle, responsiveRadiusBoxStyle)}>
          <p class={baseDescriptionStyle}>Radius changes with screen size</p>
          <p class={primarySubDescriptionStyle}>
            Mobile: sm → Tablet: md → Desktop: lg
          </p>
        </div>
      </div>

      <div>
        <h4 class={subsectionTitleStyle}>Interactive Radius (Hover)</h4>
        <div class={css(baseBoxStyle, interactiveRadiusBoxStyle)}>
          <p class={baseDescriptionStyle}>Hover to change radius</p>
          <p class={successSubDescriptionStyle}>Default: md → Hover: xl</p>
        </div>
      </div>

      <div>
        <h4 class={subsectionTitleStyle}>Focus State Radius</h4>
        <button class={css(baseButtonStyle, focusButtonStyle)}>
          Click to focus
        </button>
        <p class={buttonDescriptionStyle}>Focus changes radius from sm to lg</p>
      </div>

      <div>
        <h4 class={subsectionTitleStyle}>Active State Radius</h4>
        <button class={css(baseButtonStyle, activeButtonStyle)}>
          Press me
        </button>
        <p class={buttonDescriptionStyle}>
          Active state reduces radius from lg to sm
        </p>
      </div>
    </div>
  </div>
</div>

Best Practices

  • none — sharp edges for technical designs
  • xssm — subtle rounding for small elements, form inputs
  • md — standard buttons, inputs, small cards
  • lgxl — cards, panels, content containers
  • 2xl6xl — large components, hero sections
  • full — pills, circular buttons, badges
  • Use inner.* tokens for nested elements to maintain proportional rounding