{"id":31698743,"url":"https://github.com/callum-gander/nine-slice-frame","last_synced_at":"2026-05-06T03:34:09.591Z","repository":{"id":317552835,"uuid":"1067757898","full_name":"callum-gander/nine-slice-frame","owner":"callum-gander","description":"A modern nine-slice scaling component for React, Vue, Svelte, and Solid. Zero dependencies, tiny bundle sizes (~1KB), and native CSS performance. Perfect for scalable UI frames, borders, and pixel art interfaces.","archived":false,"fork":false,"pushed_at":"2025-10-01T17:23:40.000Z","size":118,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-08T19:11:39.785Z","etag":null,"topics":["9-slice","border-image","game-ui","nine-slice","pixel-art","react","solidjs","svelte","typescript","ui-components","vue"],"latest_commit_sha":null,"homepage":"https://callum-gander.github.io/nine-slice-frame/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/callum-gander.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-01T10:48:58.000Z","updated_at":"2025-10-01T17:23:43.000Z","dependencies_parsed_at":"2025-10-01T17:40:22.278Z","dependency_job_id":null,"html_url":"https://github.com/callum-gander/nine-slice-frame","commit_stats":null,"previous_names":["callum-gander/nine-slice-frame"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/callum-gander/nine-slice-frame","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/callum-gander%2Fnine-slice-frame","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/callum-gander%2Fnine-slice-frame/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/callum-gander%2Fnine-slice-frame/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/callum-gander%2Fnine-slice-frame/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/callum-gander","download_url":"https://codeload.github.com/callum-gander/nine-slice-frame/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/callum-gander%2Fnine-slice-frame/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32677928,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-06T02:33:58.958Z","status":"ssl_error","status_checked_at":"2026-05-06T02:33:39.611Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["9-slice","border-image","game-ui","nine-slice","pixel-art","react","solidjs","svelte","typescript","ui-components","vue"],"created_at":"2025-10-08T19:10:34.775Z","updated_at":"2026-05-06T03:34:09.558Z","avatar_url":"https://github.com/callum-gander.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# nine-slice-frame\n\n[![npm version](https://img.shields.io/npm/v/@nine-slice-frame/react.svg)](https://www.npmjs.com/package/@nine-slice-frame/react)\n[![npm version](https://img.shields.io/npm/v/@nine-slice-frame/vue.svg)](https://www.npmjs.com/package/@nine-slice-frame/vue)\n[![npm version](https://img.shields.io/npm/v/@nine-slice-frame/svelte.svg)](https://www.npmjs.com/package/@nine-slice-frame/svelte)\n[![npm version](https://img.shields.io/npm/v/@nine-slice-frame/solid.svg)](https://www.npmjs.com/package/@nine-slice-frame/solid)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\nModern nine-slice scaling components for React, Vue, Svelte, and Solid using CSS `border-image`.\n\n🎯 **[Live Demo \u0026 Tester Tool](https://callum-gander.github.io/nine-slice-frame/)**\n\n## What is Nine-Slice Scaling?\n\nNine-slice scaling divides an image into 9 sections, allowing it to scale to any size while preserving corner details and preventing distortion. Perfect for UI frames, borders, panels, and buttons that need to scale dynamically.\n\n```\n┌─────────┬───────────┬─────────┐\n│ Corner  │ Top Edge  │ Corner  │\n│ (Fixed) │ (Scale H) │ (Fixed) │\n├─────────┼───────────┼─────────┤\n│  Left   │  Center   │  Right  │\n│  Edge   │ (Scale    │  Edge   │\n│(Scale V)│  Both)    │(Scale V)│\n├─────────┼───────────┼─────────┤\n│ Corner  │ Bottom    │ Corner  │\n│ (Fixed) │   Edge    │ (Fixed) │\n└─────────┴───────────┴─────────┘\n```\n\n## Why Nine-Slice Scaling?\n\n**The Problem:** Traditional image scaling stretches the entire image uniformly, distorting corners, borders, and decorative elements. This makes UI elements look unprofessional and breaks visual consistency.\n\n**The Solution:** Nine-slice scaling keeps corners and edges crisp while only stretching the middle sections. This means:\n\n- **Single image, infinite sizes** - One asset works for buttons, dialogs, and panels of any dimension\n- **Pixel-perfect corners** - Ornate borders and rounded corners stay sharp at any scale\n- **Smaller file sizes** - No need for multiple image variants for different sizes\n- **Ideal for pixel art** - Preserves the crisp aesthetic of retro-style UIs\n- **CSS-native performance** - Uses browser-native `border-image`, no canvas or WebGL overhead\n\n**Common Use Cases:**\n\n- Game UI frames and dialog boxes\n- Decorative borders and panels\n- Scalable buttons with ornate edges\n- Retro/pixel art interfaces\n- Dynamic content containers\n\n## Why This Library?\n\n**Zero Dependencies** - No runtime dependencies beyond your framework of choice. Each package only requires its respective framework as a peer dependency.\n\n**Incredibly Small** - Minimal bundle impact with tiny package sizes:\n\n- **React**: ~881B (ESM)\n- **Vue**: 1.33KB / 0.67KB gzipped\n- **Svelte**: 1.18KB / 0.62KB gzipped\n- **Solid**: 3.09KB / 1.28KB gzipped\n\n**Native Performance** - Uses browser-native CSS `border-image` property, not canvas rendering or heavy image manipulation libraries. Fast, efficient, and hardware-accelerated.\n\n**Framework-Agnostic API** - Same simple, consistent API across React, Vue, Svelte, and Solid. Learn once, use everywhere.\n\n## Installation\n\n### React\n\n```bash\nnpm install @nine-slice-frame/react\n# or\npnpm add @nine-slice-frame/react\n# or\nyarn add @nine-slice-frame/react\n```\n\n### Vue\n\n```bash\nnpm install @nine-slice-frame/vue\n# or\npnpm add @nine-slice-frame/vue\n# or\nyarn add @nine-slice-frame/vue\n```\n\n### Svelte\n\n```bash\nnpm install @nine-slice-frame/svelte\n# or\npnpm add @nine-slice-frame/svelte\n# or\nyarn add @nine-slice-frame/svelte\n```\n\n### Solid\n\n```bash\nnpm install @nine-slice-frame/solid\n# or\npnpm add @nine-slice-frame/solid\n# or\nyarn add @nine-slice-frame/solid\n```\n\n## Usage\n\n#### React\n\n```tsx\nimport { NineSliceFrame } from '@nine-slice-frame/react';\n\nfunction App() {\n  return (\n    \u003cNineSliceFrame\n      imagePath=\"/ui/frame.png\"\n      slice={7}\n      borderWidth={5}\n      repeat=\"stretch\"\n      fill={true}\n      pixelated={true}\n    \u003e\n      \u003cp\u003eYour content here\u003c/p\u003e\n    \u003c/NineSliceFrame\u003e\n  );\n}\n```\n\n#### Vue\n\n```vue\n\u003cscript setup lang=\"ts\"\u003e\nimport { NineSliceFrame } from '@nine-slice-frame/vue';\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cNineSliceFrame\n    image-path=\"/ui/frame.png\"\n    :slice=\"7\"\n    :border-width=\"5\"\n    repeat=\"stretch\"\n    :fill=\"true\"\n    :pixelated=\"true\"\n  \u003e\n    \u003cp\u003eYour content here\u003c/p\u003e\n  \u003c/NineSliceFrame\u003e\n\u003c/template\u003e\n```\n\n#### Svelte\n\n```svelte\n\u003cscript lang=\"ts\"\u003e\n  import { NineSliceFrame } from '@nine-slice-frame/svelte';\n\u003c/script\u003e\n\n\u003cNineSliceFrame\n  imagePath=\"/ui/frame.png\"\n  slice={7}\n  borderWidth={5}\n  repeat=\"stretch\"\n  fill={true}\n  pixelated={true}\n\u003e\n  \u003cp\u003eYour content here\u003c/p\u003e\n\u003c/NineSliceFrame\u003e\n```\n\n#### Solid\n\n```tsx\nimport { NineSliceFrame } from '@nine-slice-frame/solid';\n\nfunction App() {\n  return (\n    \u003cNineSliceFrame\n      imagePath=\"/ui/frame.png\"\n      slice={7}\n      borderWidth={5}\n      repeat=\"stretch\"\n      fill={true}\n      pixelated={true}\n    \u003e\n      \u003cp\u003eYour content here\u003c/p\u003e\n    \u003c/NineSliceFrame\u003e\n  );\n}\n```\n\n### Props\n\n| Prop          | Type                                          | Default     | Description                                                                       |\n| ------------- | --------------------------------------------- | ----------- | --------------------------------------------------------------------------------- |\n| `imagePath`   | `string`                                      | required    | Path to the image (relative to public folder)                                     |\n| `slice`       | `number \\| object`                            | `8`         | Slice values - number for uniform, or `{ top, right, bottom, left }` for per-edge |\n| `borderWidth` | `number`                                      | `5`         | Visual border width in pixels                                                     |\n| `repeat`      | `'stretch' \\| 'repeat' \\| 'round' \\| 'space'` | `'stretch'` | Border repeat mode                                                                |\n| `fill`        | `boolean`                                     | `true`      | Use 'fill' to show center of image as background                                  |\n| `pixelated`   | `boolean`                                     | `true`      | Use pixelated rendering for pixel art                                             |\n| `className`   | `string`                                      | `''`        | Additional CSS class names                                                        |\n| `style`       | `React.CSSProperties`                         | `{}`        | Additional inline styles                                                          |\n\n### Advanced: Different Slice Values Per Edge\n\n```tsx\n\u003cNineSliceFrame\n  imagePath=\"/ui/fancy-frame.png\"\n  slice={{ top: 10, right: 8, bottom: 10, left: 8 }}\n  borderWidth={6}\n\u003e\n  Content with asymmetric border\n\u003c/NineSliceFrame\u003e\n```\n\n## Development\n\nThis is a monorepo managed with pnpm workspaces.\n\n```bash\n# Install dependencies\npnpm install\n\n# Build all packages\npnpm build\n\n# Build React package only\npnpm build:react\n\n# Run demo site locally\npnpm demo:serve\n```\n\n## Roadmap\n\n- [x] React component\n- [x] Vue component\n- [x] Svelte component\n- [x] Solid component\n- [x] Interactive demo/tester tool\n\n## Contributing\n\nContributions are welcome! Here's how you can help:\n\n1. **Fork the repository** and create your branch from `main`\n2. **Make your changes** in your forked repository\n3. **Test your changes** - Run `pnpm build` and `pnpm test` to ensure everything works\n4. **Submit a pull request** with a clear description of your changes\n\n### Development Setup\n\n```bash\n# Clone the repository\ngit clone https://github.com/callum-gander/nine-slice-frame.git\ncd nine-slice-frame\n\n# Install dependencies\npnpm install\n\n# Build all packages\npnpm build\n\n# Run tests\npnpm test\n\n# Type checking\npnpm typecheck\n```\n\n### Reporting Issues\n\nFound a bug or have a feature request? Please [open an issue](https://github.com/callum-gander/nine-slice-frame/issues) with:\n\n- A clear description of the problem or suggestion\n- Steps to reproduce (for bugs)\n- Expected vs actual behavior\n- Screenshots or code examples if applicable\n\n## Resources\n\n- 🎮 [Live Demo \u0026 Tester](https://callum-gander.github.io/nine-slice-frame/)\n\n## License\n\nMIT © Callum Gander\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcallum-gander%2Fnine-slice-frame","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcallum-gander%2Fnine-slice-frame","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcallum-gander%2Fnine-slice-frame/lists"}