Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Implement interactive component documentation #128

Merged
merged 10 commits into from
Mar 4, 2025
Prev Previous commit
Next Next commit
fix: Fixed an issue that would prevent components from accepting inli…
…ne styles
  • Loading branch information
spuxx-dev committed Mar 4, 2025
commit ed4919a8afe75411c1e9bb2606d43ae756e7c782
Original file line number Diff line number Diff line change
@@ -71,4 +71,10 @@ describe('Button', () => {
button.click();
expect(onClick).not.toHaveBeenCalled();
});

it('should accept inline styles', () => {
const { getByRole } = render(() => <Button style={{ width: '1337px' }}>Click me</Button>);
const button = getByRole('button');
expect(button).toHaveStyle({ width: '1337px' });
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JSX, Show, type Component } from 'solid-js';
import { ButtonProps } from './button.types';
import { Icon, IconifyIcon } from '@iconify-icon/solid';
import { classNames } from '@src/main';
import { attributes, classNames } from '@src/main';

export const Button: Component<ButtonProps> = (props) => {
const { variant = 'contained', color = 'primary', rounded, loading } = props;
@@ -10,7 +10,7 @@ export const Button: Component<ButtonProps> = (props) => {
return (
<button
type="button"
{...props.attrs}
{...attributes(props)}
title={props.title}
spx-variant={variant}
spx-color={color}
Original file line number Diff line number Diff line change
@@ -41,4 +41,9 @@ describe('Container', () => {
expect(container).toHaveAttribute('spx-no-padding');
expect(container).toHaveAttribute('id', 'container');
});

it('should accept inline styles', () => {
const { container } = render(() => <Container style={{ width: '1337px' }}>Content</Container>);
expect(container.firstChild).toHaveStyle({ width: '1337px' });
});
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Dynamic } from 'solid-js/web';
import { Component } from 'solid-js';
import { ContainerProps } from './container.types';
import { classNames } from '@src/main';
import { attributes, classNames } from '@src/main';

/**
* A container component. Very flexible and can be used for most layout purposes.
@@ -12,7 +12,7 @@ export const Container: Component<ContainerProps> = (props) => {

return (
<Dynamic
{...props.attrs}
{...attributes(props)}
component={tag}
spx-variant={variant}
spx-color={color}
Original file line number Diff line number Diff line change
@@ -35,4 +35,9 @@ describe('Divider', () => {
expect(divider).toHaveAttribute('spx-vertical');
expect(divider).toHaveAttribute('id', 'foo');
});

it('should accept inline styles', () => {
const { container } = render(() => <Divider style={{ width: '1337px' }} />);
expect(container.firstChild).toHaveStyle({ width: '1337px' });
});
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Component } from 'solid-js';
import { DividerProps } from './divider.types';
import { classNames } from '@src/main';
import { attributes, classNames } from '@src/main';

/**
* A divider component. Can be used to separate content. Supports vertical orientation.
@@ -13,7 +13,7 @@ export const Divider: Component<DividerProps> = (props) => {

return (
<hr
{...props.attrs}
{...attributes(props)}
spx-color={color}
spx-variant={variant}
spx-vertical={vertical}
Original file line number Diff line number Diff line change
@@ -58,4 +58,23 @@ describe('Heading', () => {
expect(heading).toHaveClass('spx-heading');
expect(heading.tagName.toLowerCase()).toBe('h6');
});

it('should accept inline styles', () => {
const { container } = render(() => (
<>
<Heading level={1} style={{ width: '1px' }} />
<Heading level={2} style={{ width: '2px' }} />
<Heading level={3} style={{ width: '3px' }} />
<Heading level={4} style={{ width: '4px' }} />
<Heading level={5} style={{ width: '5px' }} />
<Heading level={6} style={{ width: '6px' }} />
</>
));
expect(container.children[0]).toHaveStyle({ width: '1px' });
expect(container.children[1]).toHaveStyle({ width: '2px' });
expect(container.children[2]).toHaveStyle({ width: '3px' });
expect(container.children[3]).toHaveStyle({ width: '4px' });
expect(container.children[4]).toHaveStyle({ width: '5px' });
expect(container.children[5]).toHaveStyle({ width: '6px' });
});
});
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
import { type Component } from 'solid-js';
import { HeadingProps } from './heading.types';
import { classNames } from '@src/main';
import { attributes, classNames } from '@src/main';

export const Heading: Component<HeadingProps> = (props) => {
const { level } = props;
return (
<>
{level === 1 && (
<h1 {...props} {...classNames('spx-heading', props.class)}>
<h1 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h1>
)}
{level === 2 && (
<h2 {...props} {...classNames('spx-heading', props.class)}>
<h2 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h2>
)}
{level === 3 && (
<h3 {...props} {...classNames('spx-heading', props.class)}>
<h3 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h3>
)}
{level === 4 && (
<h4 {...props} {...classNames('spx-heading', props.class)}>
<h4 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h4>
)}
{level === 5 && (
<h5 {...props} {...classNames('spx-heading', props.class)}>
<h5 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h5>
)}
{level === 6 && (
<h6 {...props} {...classNames('spx-heading', props.class)}>
<h6 {...attributes(props)} {...classNames('spx-heading', props.class)}>
{props.children}
</h6>
)}
22 changes: 22 additions & 0 deletions packages/solid/src/utils/component.utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
import { ComponentProps } from '@src/main';

/**
* Joins multiple class names together.
* @param classes The class names to join.
* @returns The joined class names.
* @example
* export const MyComponent: Component<Props> = (props) => {
* return <div {...classNames('my-class', props.class)}></div>;
* }
*/
export const classNames = (...classes: (string | undefined)[]): { class: string } => {
const classNames = ['spx', ...classes.filter(Boolean)];
return { class: classNames.join(' ') };
};

/**
* Extracts all attributes from the given {@link ComponentProps}.
* @param props The component properties to extract attributes from.
* @returns A flat object containing all attributes.
* @example
* export const MyComponent: Component<Props> = (props) => {
* return <div {...attributes(props)}></div>;
* }
*/
export const attributes = (props: ComponentProps<any>) => {
return {
style: props.style,
...props.attrs,
};
};