Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"fumadocs-mdx": "13.0.5",
"fumadocs-typescript": "^4.0.6",
"fumadocs-ui": "16.0.7",
"lucide-react": "^0.548.0",
"lucide-react": "^1.45.0",
"next": "16.0.7",
"next-themes": "^0.4.4",
"prettier": "^2.8.8",
Expand Down
24 changes: 24 additions & 0 deletions apps/www/src/components/docs/github-mark.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { SVGProps } from 'react';

/**
* The GitHub mark, drawn here rather than imported.
*
* lucide dropped its brand icons in 1.0, so `Github` no longer exists. A brand
* mark is the one kind of icon a general icon set can't carry — the shape
* belongs to its owner, not to the set — so it lives with the one link that
* uses it.
*/
export function GithubMark(props: SVGProps<SVGSVGElement>) {
return (
<svg
width={12}
height={12}
viewBox='0 0 24 24'
fill='currentColor'
aria-hidden='true'
{...props}
>
<path d='M12 .5C5.73.5.5 5.73.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56 0-.28-.01-1.02-.02-2-3.2.7-3.88-1.54-3.88-1.54-.52-1.33-1.28-1.69-1.28-1.69-1.05-.71.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.18 1.18a11 11 0 0 1 5.8 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.12 3.05.74.8 1.18 1.83 1.18 3.09 0 4.42-2.69 5.4-5.25 5.68.41.36.78 1.06.78 2.14 0 1.55-.01 2.79-.01 3.17 0 .31.2.67.79.56A11.51 11.51 0 0 0 23.5 12C23.5 5.73 18.27.5 12 .5Z' />
</svg>
);
}
7 changes: 3 additions & 4 deletions apps/www/src/components/docs/navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
import { Breadcrumb, Button, CopyIcon } from '@raystack/apsara';
import { useBreadcrumb } from 'fumadocs-core/breadcrumb';
import { Root } from 'fumadocs-core/page-tree';
import { Component, Github } from 'lucide-react';
import { Component } from 'lucide-react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Fragment, useState } from 'react';
import { SourceType } from '@/lib/types';
import { useDemoContext } from '../demo/demo-context';
import { GithubMark } from './github-mark';
import styles from './navbar.module.css';

const cache = new Map<string, string>();
Expand Down Expand Up @@ -114,9 +115,7 @@ export default function DocsNavbar({
variant='outline'
color='neutral'
size='small'
leadingIcon={
<Github size={12} strokeWidth={1.5} className={styles.icon} />
}
leadingIcon={<GithubMark className={styles.icon} />}
>
View source
</Button>
Expand Down
6 changes: 3 additions & 3 deletions apps/www/src/content/docs/(overview)/upgrading.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ names `@raystack/apsara/icons` exports have changed.
npm install lucide-react
```

The range is wide, `>=0.500.0 <1.0.0`, so your app picks the version. If a
lucide release changes a drawing you care about, replace that one icon (step 5)
rather than pinning the whole library.
The range is wide, `>=0.500.0 <2.0.0`, so your app picks the version — both the
0.x and 1.x lines satisfy it. If a lucide release changes a drawing you care
about, replace that one icon (step 5) rather than pinning the whole library.

<Callout type="grey">
`@radix-ui/react-icons` is no longer a dependency of Apsara. If your own code
Expand Down
6 changes: 4 additions & 2 deletions packages/raystack/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ and [Icons](https://apsara.raystack.io/docs/theme/icons).

#### Breaking changes

- **`lucide-react` is a new peer dependency**, range `>=0.500.0 <1.0.0`.
Install it.
- **`lucide-react` is a new peer dependency**, range `>=0.500.0 <2.0.0`,
so both the 0.x and 1.x lines satisfy it. Install it. Note that lucide
dropped its brand icons in 1.0, so a name like `Github` no longer
exists there — none of Apsara's 31 keys draw one.
- **`@radix-ui/react-icons` is no longer a dependency.** If your own code
imports from it, keep it in your own `dependencies`.
- **`@raystack/apsara/icons` exports icon components, not raw SVG
Expand Down
54 changes: 54 additions & 0 deletions packages/raystack/icons/__tests__/lucide-contract.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { readFileSync } from 'node:fs';
import { resolve } from 'node:path';
import { render } from '@testing-library/react';
import * as lucide from 'lucide-react';
import { describe, expect, it } from 'vitest';
import { CheckIcon } from '../icons';

/**
* The peer range spans two lucide majors (`>=0.500.0 <2.0.0`), so what Apsara
* relies on has to hold across both. It relies on three things only, and this
* file pins each one:
*
* 1. every drawing it imports is still exported under that name,
* 2. `width` / `height` / `strokeWidth` are plain SVG props, and
* 3. the viewBox is 24 units, which is what makes `strokeWidth={1.5}` a 1px
* stroke at 16px.
*
* A lucide release that breaks any of them fails here rather than in a
* consumer's app.
*/

/** vitest runs with the package root as the cwd. */
const ICONS_SRC = resolve(process.cwd(), 'icons/icons.tsx');

/** The lucide names `icons.tsx` imports, read from its own import block. */
function importedNames(): string[] {
const src = readFileSync(ICONS_SRC, 'utf8');
const block = src.match(/import \{([\s\S]*?)\} from 'lucide-react';/);
if (!block) throw new Error('no lucide import block in icons.tsx');
return block[1]
.split(',')
.map(name => name.trim())
.filter(Boolean);
}

describe('lucide contract', () => {
it('exports every drawing icons.tsx imports', () => {
const names = importedNames();

expect(names.length).toBeGreaterThan(0);
expect(names.filter(name => !(name in lucide))).toEqual([]);
});

it('takes size and stroke as SVG props, on a 24-unit viewBox', () => {
const { container } = render(<CheckIcon />);
const svg = container.querySelector('svg');

expect(svg).toHaveAttribute('width', '16');
expect(svg).toHaveAttribute('height', '16');
expect(svg).toHaveAttribute('stroke-width', '1.5');
// Not 0 0 16 16: the rendered stroke is strokeWidth x size / 24.
expect(svg).toHaveAttribute('viewBox', '0 0 24 24');
});
});
4 changes: 2 additions & 2 deletions packages/raystack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"dotenv": "^17.2.2",
"identity-obj-proxy": "^3.0.0",
"jsdom": "^26.1.0",
"lucide-react": "^0.548.0",
"lucide-react": "^1.45.0",
"postcss": "^8.4.24",
"postcss-import": "^16.1.0",
"postcss-modules": "^6.0.0",
Expand Down Expand Up @@ -135,7 +135,7 @@
},
"peerDependencies": {
"@types/react": "^19",
"lucide-react": ">=0.500.0 <1.0.0",
"lucide-react": ">=0.500.0 <2.0.0",
"react": "^19",
"react-dom": "^19"
},
Expand Down
32 changes: 16 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading