Skip to content

Commit

Permalink
Merge pull request #74 from brainstormforce/storybook-tooltip
Browse files Browse the repository at this point in the history
SUR-277 Molecule: Implement Tooltip with label/icon
  • Loading branch information
vrundakansara authored Sep 23, 2024
2 parents 682168e + 3015abd commit 8559da2
Show file tree
Hide file tree
Showing 4 changed files with 187 additions and 8 deletions.
7 changes: 4 additions & 3 deletions src/components/button/button.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import React, { forwardRef } from 'react';
import { cn } from '@/utilities/functions';

const Button = ( props ) => {
const Button = forwardRef( ( props, ref ) => {
const {
variant = 'primary', // primary, secondary, outline, ghost, link
size = 'md', // xs, sm, md, lg
Expand Down Expand Up @@ -67,6 +67,7 @@ const Button = ( props ) => {
const Tag = tag;
return (
<Tag
ref={ ref }
type={ type }
className={ cn(
iconClass,
Expand All @@ -85,6 +86,6 @@ const Button = ( props ) => {
{ iconRight }
</Tag>
);
};
} );

export default Button;
8 changes: 5 additions & 3 deletions src/components/label/label.jsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { cn } from '@/utilities/functions';
import React, { forwardRef } from 'react';

/**
* Label component.
*/

const Label = ( {
const Label = forwardRef( ( {
children = null,
tag = 'label',
size = 'sm', // xs, sm, md
className = '',
variant = 'neutral', // neutral, help, error, disabled
required = false,
...props
} ) => {
}, ref ) => {
// Base classes. - Mandatory classes.
const baseClasses =
'font-medium text-field-label flex items-center gap-0.5';
Expand Down Expand Up @@ -48,6 +49,7 @@ const Label = ( {

return (
<Tag
ref={ ref }
className={ cn(
baseClasses,
sizeClasses[ size ],
Expand All @@ -60,6 +62,6 @@ const Label = ( {
{ children }
</Tag>
);
};
} );

export default Label;
4 changes: 2 additions & 2 deletions src/components/tooltip/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ The `Tooltips` are small, interactive pop-up boxes that provide brief, informati

### `variant`
- **Type:** `string`
- **Default:** `"light"`
- **Default:** `"dark"`
- **Description:** Defines the style variant of the tooltip. Options include:
- `"light"`
- `"dark"`

### `placement`
- **Type:** `string`
- **Default:** `"top"`
- **Default:** `"bottom"`
- **Description:** Defines the position of the tooltip. Options include:
- `"top"`
- `"top-start"`
Expand Down
176 changes: 176 additions & 0 deletions src/components/tooltip/tooltip.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import React, { useState } from 'react';
import Tooltip from './tooltip.jsx';
import { CircleHelp } from 'lucide-react';
import Label from '../label/label.jsx';

export default {
title: 'Molecules/Tooltip',
component: Tooltip,
parameters: {
layout: 'centered',
},
tags: [ 'autodocs' ],
argTypes: {
variant: {
description: 'Defines the style variant of the tooltip.',
control: { type: 'select' },
options: [ 'light', 'dark' ],
table: {
type: { summary: 'string' },
},
},
placement: {
description: 'The placement of the tooltip relative to the target.',
control: { type: 'select' },
options: [
'top', 'top-start', 'top-end',
'bottom', 'bottom-start', 'bottom-end',
'right', 'right-start', 'right-end',
'left', 'left-start', 'left-end',
],
table: {
type: { summary: 'string' },
},
},
title: {
description: 'Title for the tooltip.',
control: { type: 'text' },
table: {
type: { summary: 'string' },
},
},
content: {
description: 'Content of tooltip - description of tooltip in more detail.',
control: { type: 'text' },
table: {
type: { summary: 'string' },
},
},
arrow: {
description: 'Defines whether the tooltip is displayed with an arrow or not.',
control: { type: 'boolean' },
table: {
type: { summary: 'boolean' },
},
},
open: {
description: 'Controls the open state when controlled mode is used.',
control: { type: 'boolean' },
table: {
type: { summary: 'boolean' },
},
},
triggers: {
description: 'Triggers to open the tooltip (hover, focus, click).',
control: { type: 'select' },
options: [ 'click', 'hover', 'focus' ],
table: {
type: { summary: 'string' },
},
},
interactive: {
description: 'If set to true, the tooltip is interactive and will not close when the user hovers over the tooltip.',
control: { type: 'boolean' },
table: {
type: { summary: 'boolean' },
},
},
offset: {
description: 'Defines the offset of the tooltip from the target element.',
control: { type: 'number' },
table: {
type: { summary: 'number' },
},
},
tooltipPortalRoot: {
description: "Root element where the tooltip will be rendered. It's helpful when the tooltip is rendered outside the parent container and scopped Tailwind CSS styles.",
table: {
type: { summary: 'HTMLElement | null' },
},
},
tooltipPortalId: {
description: "Root element where the tooltip will be rendered. It's helpful when the tooltip is rendered outside the parent container and scopped Tailwind CSS styles.",
table: {
type: { summary: 'HTMLElement | null' },
},
},
boundary: {
description: 'The element that the tooltip is positioned relative to. When provided, the tooltip will be positioned within the boundary of the element.',
table: {
type: { summary: 'HTMLElement' },
},
},
strategy: {
description: 'Defines the positioning strategy of the tooltip. Options include: `absolute` and `fixed`. The `fixed` strategy is recommended for most use cases.',
table: {
type: { summary: 'string' },
},
},
},
};

export const DefaultTooltip = ( args ) => {
const [ isOpen, setIsOpen ] = useState( false );

return (
<div>
<Tooltip
{ ...args }
open={ args.open !== undefined ? args.open : isOpen }
setOpen={ args.open !== undefined ? setIsOpen : undefined }
>
<CircleHelp />
</Tooltip>
</div>
);
};

DefaultTooltip.args = {
variant: 'dark',
placement: 'bottom',
title: 'Tooltip Title',
content: 'This is the content of the tooltip.',
arrow: true,
triggers: [ 'hover', 'focus' ],
interactive: false,
};

export const DarkTooltipWithIcon = ( args ) => (
<div style={ { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '10px', justifyContent: 'center', padding: '20px' } }>
{ [ 'top-end', 'top', 'top-start', 'left', 'bottom', 'right' ].map( ( placement ) => (
<div style={ { display: 'flex', justifyContent: 'center', padding: '30px' } } key={ placement }>
<Tooltip key={ placement } { ...args } placement={ placement }>
<CircleHelp style={ { fontSize: '2rem', cursor: 'pointer' } } />
</Tooltip>
</div>
) ) }
</div>
);

DarkTooltipWithIcon.storyName = 'Tooltip with icon';

DarkTooltipWithIcon.args = {
variant: 'dark',
title: 'Tooltip',
arrow: true,
};

export const DarkTooltipWithLabel = ( args ) => (
<div style={ { display: 'grid', gridTemplateColumns: '1fr 1fr 1fr', gap: '10px', justifyContent: 'center', padding: '20px' } }>
{ [ 'top-end', 'top', 'top-start', 'left', 'bottom', 'right' ].map( ( placement ) => (
<div style={ { display: 'flex', justifyContent: 'center', padding: '30px' } } key={ placement }>
<Tooltip key={ placement } { ...args } placement={ placement }>
<Label size="md">Label</Label>
</Tooltip>
</div>
) ) }
</div>
);

DarkTooltipWithLabel.storyName = 'Tooltip with label';

DarkTooltipWithLabel.args = {
variant: 'dark',
title: 'Tooltip',
arrow: true,
};

0 comments on commit 8559da2

Please sign in to comment.