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
24 changes: 6 additions & 18 deletions .github/workflows/code-connect.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ on:
paths:
- "packages/raystack/figma/**"
- "packages/raystack/figma.config.json"
- "packages/raystack/scripts/generate-icons-code-connect.js"
- ".github/workflows/code-connect.yaml"

# Avoid overlapping publishes racing against the same Figma file.
Expand Down Expand Up @@ -41,28 +40,17 @@ jobs:
- name: Install Dependencies 🔧
run: pnpm install --frozen-lockfile

# Redact the Figma file keys from all subsequent step logs. The publish
# Redact the Figma file key from all subsequent step logs. The publish
# command prints every mapped node URL; masking turns the file key into
# *** so links read https://figma.com/file/***/?node-id=... in CI logs.
- name: Mask Figma file keys 🔒
- name: Mask Figma file key 🔒
env:
FIGMA_FILE_URL: ${{ secrets.FIGMA_FILE_URL }}
FIGMA_ICONS_FILE_URL: ${{ secrets.FIGMA_ICONS_FILE_URL }}
run: |
for url in "$FIGMA_FILE_URL" "$FIGMA_ICONS_FILE_URL"; do
key=$(printf '%s' "$url" | sed -E 's#.*/(design|file)/([^/?]+).*#\2#')
if [ -n "$key" ] && [ "$key" != "$url" ]; then
echo "::add-mask::$key"
fi
done

# Generate the per-icon batch JSON from the Figma icons file.
- name: Generate icon mappings 🎨
working-directory: ./packages/raystack
env:
FIGMA_ACCESS_TOKEN: ${{ secrets.FIGMA_ACCESS_TOKEN }}
FIGMA_ICONS_FILE_URL: ${{ secrets.FIGMA_ICONS_FILE_URL }}
run: pnpm figma:generate-icons
key=$(printf '%s' "$FIGMA_FILE_URL" | sed -E 's#.*/(design|file)/([^/?]+).*#\2#')
if [ -n "$key" ] && [ "$key" != "$FIGMA_FILE_URL" ]; then
echo "::add-mask::$key"
fi

# Substitute the real Figma file URL into figma.config.json.
- name: Update Figma config 🔧
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,3 @@ yarn-error.log*

# npm pack artifacts
*.tgz

# generated Code Connect batch file (created by figma:generate-icons at publish time)
packages/raystack/figma/icons.figma.batch.json
16 changes: 13 additions & 3 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,11 +191,21 @@ pnpm lint

# Clean build artifacts
pnpm clean

# Build icon components
pnpm build:icons
```

### Icons

The icons live in one committed file, `packages/raystack/icons/icons.tsx`: one
`createIcon` call per key, 31 of them. There is no generator and no build step —
to add, remove, or repoint an icon, edit that file.

`icons/types.ts` derives `IconName` from its exports with `keyof typeof icons`,
so the union cannot drift and nothing needs to be kept in step by hand.

`icons/__tests__/bundle.test.ts` is the test that matters here. It bundles a
three-icon fixture with the real rollup and asserts the other 28 keys and their
lucide imports are gone. That is what keeps one file from becoming one bundle.

## Testing

Apsara uses Vitest with React Testing Library for testing:
Expand Down
1 change: 0 additions & 1 deletion apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"format": "biome format --write ."
},
"dependencies": {
"@radix-ui/react-icons": "^1.3.2",
"@raystack/apsara": "workspace:*",
"@types/mdast": "^4.0.4",
"class-variance-authority": "^0.7.1",
Expand Down
28 changes: 22 additions & 6 deletions apps/www/src/components/dataview-demo.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
'use client';

import { ListBulletIcon, RowsIcon, TransformIcon } from '@radix-ui/react-icons';
import {
Avatar,
Badge,
Expand All @@ -18,6 +17,7 @@ import {
type TimelineCardContext,
useDataView
} from '@raystack/apsara';
import { Frame, LayoutList, Rows3 } from 'lucide-react';
import { useMemo, useRef, useState } from 'react';

type Person = {
Expand Down Expand Up @@ -243,8 +243,16 @@ export function DataViewSearchDemo() {
export function DataViewMultiViewDemo() {
const views = useMemo(
() => [
{ value: 'table', label: 'Table', leadingIcon: <RowsIcon /> },
{ value: 'list', label: 'List', leadingIcon: <ListBulletIcon /> }
{
value: 'table',
label: 'Table',
leadingIcon: <Rows3 size={16} strokeWidth={1.5} />
},
{
value: 'list',
label: 'List',
leadingIcon: <LayoutList size={16} strokeWidth={1.5} />
}
],
[]
);
Expand Down Expand Up @@ -525,8 +533,16 @@ export function DataViewLoadingDemo() {
export function DataViewPerViewFieldsDemo() {
const views = useMemo(
() => [
{ value: 'table', label: 'Table', leadingIcon: <RowsIcon /> },
{ value: 'list', label: 'List', leadingIcon: <ListBulletIcon /> }
{
value: 'table',
label: 'Table',
leadingIcon: <Rows3 size={16} strokeWidth={1.5} />
},
{
value: 'list',
label: 'List',
leadingIcon: <LayoutList size={16} strokeWidth={1.5} />
}
],
[]
);
Expand Down Expand Up @@ -611,7 +627,7 @@ function SelectionBar() {
variant='outline'
size='large'
color='neutral'
leadingIcon={<TransformIcon />}
leadingIcon={<Frame size={16} strokeWidth={1.5} />}
isDismissible
onDismiss={() => table.resetRowSelection()}
>
Expand Down
27 changes: 16 additions & 11 deletions apps/www/src/components/demo/demo-controls.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import {
InfoCircledIcon,
Pencil2Icon,
PlusIcon,
TransformIcon,
UploadIcon
} from '@radix-ui/react-icons';
import {
Field,
Flex,
IconButton,
InfoIcon,
Input,
PlusIcon,
Select,
Switch,
Text
} from '@raystack/apsara';
import { cx } from 'class-variance-authority';
import { Frame, Pencil, Upload } from 'lucide-react';
import { camelCaseToWords } from '@/lib/utils';
import styles from './styles.module.css';
import {
Expand All @@ -32,10 +28,19 @@ type PropControlsProps = {

const ICONS_MAP = {
plus: { icon: <PlusIcon />, value: '<PlusIcon />' },
transform: { icon: <TransformIcon />, value: '<TransformIcon />' },
pencil: { icon: <Pencil2Icon />, value: '<Pencil2Icon />' },
info: { icon: <InfoCircledIcon />, value: '<InfoCircledIcon />' },
upload: { icon: <UploadIcon />, value: '<UploadIcon />' }
transform: {
icon: <Frame size={16} strokeWidth={1.5} />,
value: '<Frame size={16} strokeWidth={1.5} />'
},
pencil: {
icon: <Pencil size={16} strokeWidth={1.5} />,
value: '<Pencil size={16} strokeWidth={1.5} />'
},
info: { icon: <InfoIcon />, value: '<InfoIcon />' },
upload: {
icon: <Upload size={16} strokeWidth={1.5} />,
value: '<Upload size={16} strokeWidth={1.5} />'
}
};

export default function DemoControls({
Expand Down
9 changes: 4 additions & 5 deletions apps/www/src/components/demo/demo-playground.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use client';

import { Cross2Icon } from '@radix-ui/react-icons';
import { Dialog, Flex, IconButton } from '@raystack/apsara';
import { ResetIcon } from '@raystack/apsara/icons';
import { Dialog, Flex, IconButton, XIcon } from '@raystack/apsara';
import { cx } from 'class-variance-authority';
import { RotateCcw } from 'lucide-react';
import {
ReadonlyURLSearchParams,
useRouter,
Expand Down Expand Up @@ -114,14 +113,14 @@ export default function DemoPlayground({
onClick={resetProps}
aria-label='Reset to default props'
>
<ResetIcon />
<RotateCcw size={16} strokeWidth={1.5} />
</IconButton>
<IconButton
size={2}
onClick={() => setOpenPlayground(false)}
aria-label='Close playground'
>
<Cross2Icon />
<XIcon />
</IconButton>
</Flex>
</Dialog.Header>
Expand Down
122 changes: 60 additions & 62 deletions apps/www/src/components/demo/demo.tsx
Original file line number Diff line number Diff line change
@@ -1,39 +1,36 @@
'use client';

import {
BorderSolidIcon,
CheckCircledIcon,
ColorWheelIcon,
Component1Icon,
FileIcon,
FontBoldIcon,
FontFamilyIcon,
FontItalicIcon,
InfoCircledIcon,
LayersIcon,
OpenInNewWindowIcon,
Pencil2Icon,
PlusIcon,
ShadowIcon,
Share2Icon,
SpaceBetweenHorizontallyIcon,
TextAlignCenterIcon,
TextAlignLeftIcon,
TextAlignRightIcon,
TransformIcon,
UnderlineIcon,
UploadIcon
} from '@radix-ui/react-icons';
import * as Apsara from '@raystack/apsara';
import {
BellIcon,
FilterIcon,
OrganizationIcon,
ShoppingBagFilledIcon,
SidebarIcon
} from '@raystack/apsara/icons';
import dayjs from 'dayjs';
import { Home, Info, Laugh, X } from 'lucide-react';
import {
AlignCenter,
AlignLeft,
AlignRight,
Bell,
Bold,
Building2,
Component,
Contrast,
ExternalLink,
Frame,
Home,
Info,
Italic,
Laugh,
Layers,
LayoutList,
Minus,
Palette,
Pencil,
Rows3,
Share2,
ShoppingBag,
StretchHorizontal,
Type,
Underline,
Upload,
X
} from 'lucide-react';
import NextLink from 'next/link';
import { Suspense } from 'react';
import ChipInputDemo from '../chip-input-demo';
Expand Down Expand Up @@ -64,13 +61,13 @@ import { DemoProps } from './types';
export default function Demo(props: DemoProps) {
const {
data,
// `...Apsara` carries the 31 icons Apsara publishes, so none of those needs
// its own entry — and nothing below may repeat one of their keys, because a
// later key shadows the spread. A demo that needs any other glyph names a
// lucide component from the block above and sizes it at the call site,
// which is exactly what an application does.
scope = {
...Apsara,
BellIcon,
FilterIcon,
ShoppingBagFilledIcon,
OrganizationIcon,
SidebarIcon,
DataViewTableDemo,
DataViewListDemo,
DataViewMultiViewDemo,
Expand All @@ -90,33 +87,34 @@ export default function Demo(props: DemoProps) {
LinearMenuDemo,
PopoverColorPicker,
TourDemo,
Info,
X,
NextLink,
AlignCenter,
AlignLeft,
AlignRight,
Bell,
Bold,
Building2,
Component,
Contrast,
ExternalLink,
Frame,
Home,
Info,
Italic,
Laugh,
NextLink,
PlusIcon,
TransformIcon,
CheckCircledIcon,
Pencil2Icon,
InfoCircledIcon,
UploadIcon,
FontBoldIcon,
FontItalicIcon,
UnderlineIcon,
TextAlignLeftIcon,
TextAlignCenterIcon,
TextAlignRightIcon,
Component1Icon,
FileIcon,
FontFamilyIcon,
LayersIcon,
OpenInNewWindowIcon,
Share2Icon,
BorderSolidIcon,
ColorWheelIcon,
ShadowIcon,
SpaceBetweenHorizontallyIcon,
LayoutList,
Layers,
Minus,
Palette,
Pencil,
Rows3,
Share2,
ShoppingBag,
StretchHorizontal,
Type,
Underline,
Upload,
X,
dayjs
}
} = props;
Expand Down
6 changes: 3 additions & 3 deletions apps/www/src/components/docs/footer.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ArrowLeftIcon, ArrowRightIcon } from '@radix-ui/react-icons';
import { Button, Flex, Link } from '@raystack/apsara';
import { findNeighbour } from 'fumadocs-core/page-tree';
import { ArrowLeft, ArrowRight } from 'lucide-react';
import { docs } from '@/lib/source';

type DocsFooterProps = {
Expand All @@ -17,7 +17,7 @@ export default function DocsFooter({ url }: DocsFooterProps) {
variant='outline'
color='neutral'
size='normal'
leadingIcon={<ArrowLeftIcon />}
leadingIcon={<ArrowLeft size={16} strokeWidth={1.5} />}
>
{neighbours.previous.name}
</Button>
Expand All @@ -31,7 +31,7 @@ export default function DocsFooter({ url }: DocsFooterProps) {
variant='outline'
color='neutral'
size='normal'
trailingIcon={<ArrowRightIcon />}
trailingIcon={<ArrowRight size={16} strokeWidth={1.5} />}
>
{neighbours.next.name}
</Button>
Expand Down
Loading
Loading