Skip to content

Commit

Permalink
feat: add storybook text
Browse files Browse the repository at this point in the history
  • Loading branch information
driss-chelouati committed Sep 5, 2023
1 parent 853eac2 commit 6b0f05c
Show file tree
Hide file tree
Showing 7 changed files with 345 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import plugin from 'tailwindcss/plugin'
import { defu } from 'defu'
import { type PluginOption, defaultPluginOptions } from '../options'
import { type PluginOption, defaultPluginOptions } from '../../options'

const defaultTextConfig = {
export const defaultTextConfig = {
textXS: 'xs',
textSM: 'sm',
textMD: 'base',
Expand Down
32 changes: 32 additions & 0 deletions src/plugins/components/text/text.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { html } from 'lit'
import { spread } from '@open-wc/lit-helpers'

import type { TextAttrs } from './text.types'
import * as variants from './text.variants'

/**
* Primary UI component for user interaction
*/
export const Text = ({
size = 'sm',
weight = 'normal',
lead = 'normal',
children,
...attrs
}: TextAttrs) => {
return html`
<span
class=${[
'nui-text',
size && variants.size[size],
weight && variants.weight[weight],
lead && variants.lead[lead],
]
.filter(Boolean)
.join(' ')}
${spread(attrs)}
>
${children}
</span>
`
}
75 changes: 75 additions & 0 deletions src/plugins/components/text/text.doc.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Meta, Primary, Controls, Story } from '@storybook/blocks'
import * as TextStories from './text.stories'
import { defaultTextConfig } from '.'

<Meta of={TextStories} />

# Text

Text spans are an important part of any website or application and are often referred as part of the "Typography". They help creating structure and consistency accross the page and your content.

<Primary />

## Props

<Controls />

## Variants

<br />

### Sizes

Use the Text component to display some content or a subtitle. You can use various props to customize the size, weight, the line-height and the Html tag used to render the text span.

<div className="bg-slate-100 dark:bg-slate-900 p-6 rounded-sm">
<Story of={TextStories.Size2Xl} />
<br />
<Story of={TextStories.SizeXl} />
<br />
<Story of={TextStories.SizeLg} />
<br />
<Story of={TextStories.SizeMd} />
<br />
<Story of={TextStories.SizeSm} />
<br />
<Story of={TextStories.SizeXs} />
</div>

<br />
<br />

## Customization

### Default config

<div class="relative">
<details class="relative bg-slate-50 border border-slate-200 rounded-lg p-4 [&>summary>svg]:open:-rotate-180">
<summary class="list-none cursor-pointer">
<span class="font-sans text-slate-500">View configuration options</span>
<svg
class="w-5 h-5 text-slate-500 absolute top-5 end-4 transition-transform duration-300"
xmlns="http://www.w3.org/2000/svg"
width="32"
height="32"
viewBox="0 0 24 24"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m6 9l6 6l6-6"
/>
</svg>
</summary>

<div class="!mt-4">
<pre >
{JSON.stringify(defaultTextConfig, null, 2)}
</pre>
</div>

</details>
</div>
137 changes: 137 additions & 0 deletions src/plugins/components/text/text.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import type { Meta, StoryObj } from '@storybook/web-components'
import { html } from 'lit'

import type { TextAttrs } from './text.types'
import { Text } from './text.component'

// More on how to set up stories at: https://storybook.js.org/docs/web-components/writing-stories/introduction
const meta = {
title: 'Shuriken UI/Typography/Text',
// tags: ['autodocs'],
render: (args) => Text(args),
argTypes: {
size: {
control: { type: 'select' },
options: [
'xs',
'sm',
'md',
'lg',
'xl',
'2xl',
'3xl',
'4xl',
'5xl',
'6xl',
'7xl',
'8xl',
'9xl',
],
defaultValue: 'sm',
},
weight: {
control: { type: 'select' },
options: ['light', 'normal', 'medium', 'semibold', 'bold', 'extrabold'],
defaultValue: 'normal',
},
lead: {
control: { type: 'select' },
options: ['none', 'tight', 'snug', 'normal', 'relaxed', 'loose'],
defaultValue: 'normal',
},
},
} satisfies Meta<TextAttrs>

export default meta
type Story = StoryObj<TextAttrs>

// first export is the Primary story

// #region Main
export const Main: Story = {
name: 'Main example',
args: {
// set default values used for UI preview
size: 'sm',
weight: 'normal',
lead: 'none',
children: html`
This is a nice content text span.
`,
},
}
// #endregion

// #region Variants
export const Size2Xl: Story = {
name: 'Size: 2xl',
args: {
size: '2xl',
weight: 'normal',
lead: 'none',
children: html`
Iam a 2xl text span
`,
},
}

export const SizeXl: Story = {
name: 'Size: xl',
args: {
size: 'xl',
weight: 'normal',
lead: 'none',
children: html`
Iam a xl text span
`,
},
}

export const SizeLg: Story = {
name: 'Size: lg',
args: {
size: 'lg',
weight: 'normal',
lead: 'none',
children: html`
Iam a lg text span
`,
},
}

export const SizeMd: Story = {
name: 'Size: md',
args: {
size: 'md',
weight: 'normal',
lead: 'none',
children: html`
Iam a md text span
`,
},
}

export const SizeSm: Story = {
name: 'Size: sm',
args: {
size: 'sm',
weight: 'normal',
lead: 'none',
children: html`
Iam a sm text span
`,
},
}

export const SizeXs: Story = {
name: 'Size: xs',
args: {
size: 'xs',
weight: 'normal',
lead: 'none',
children: html`
Iam a xs text span
`,
},
}
// #endregion
35 changes: 35 additions & 0 deletions src/plugins/components/text/text.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { axe } from 'vitest-axe'
import { expect, test, describe } from 'vitest'
import { render, html } from 'lit'

import { Text } from './text.component'

describe('Text', () => {
test('Should render slot', () => {
const text = Text({
children: html`
<span>Hello world</span>
`,
})

render(text, document.body)

expect(document.body.querySelector('.nui-text')?.outerHTML)?.toContain(
'Hello world',
)
})

test('Should have no axe violations', async () => {
const text = Text({
children: html`
<span>Hello world</span>
`,
})

render(text, document.body)

expect(
await axe(document.body.querySelector('.nui-text')!.outerHTML),
)?.toHaveNoViolations()
})
})
29 changes: 29 additions & 0 deletions src/plugins/components/text/text.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type { PropertyVariant } from '~/types/utils'

export interface TextProps extends Record<string, unknown> {
size?:
| 'xs'
| 'sm'
| 'md'
| 'lg'
| 'xl'
| '2xl'
| '3xl'
| '4xl'
| '5xl'
| '6xl'
| '7xl'
| '8xl'
| '9xl'
weight?: 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold'
lead?: 'none' | 'tight' | 'snug' | 'normal' | 'relaxed' | 'loose'
}

export interface TextEvents {}

export interface TextSlots {
children: any
}

export type TextAttrs = TextProps & TextEvents & TextSlots
export type TextVariant<T> = PropertyVariant<T, TextProps>
35 changes: 35 additions & 0 deletions src/plugins/components/text/text.variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { TextVariant } from './text.types'

export const size = {
xs: 'nui-content-xs',
sm: 'nui-content-sm',
md: 'nui-content-md',
lg: 'nui-content-lg',
xl: 'nui-content-xl',
'2xl': 'nui-content-2xl',
'3xl': 'nui-content-3xl',
'4xl': 'nui-content-4xl',
'5xl': 'nui-content-5xl',
'6xl': 'nui-content-6xl',
'7xl': 'nui-content-7xl',
'8xl': 'nui-content-8xl',
'9xl': 'nui-content-9xl',
} as const satisfies TextVariant<'size'>

export const weight = {
light: 'nui-weight-light',
normal: 'nui-weight-normal',
medium: 'nui-weight-medium',
semibold: 'nui-weight-semibold',
bold: 'nui-weight-bold',
extrabold: 'nui-weight-extrabold',
} as const satisfies TextVariant<'weight'>

export const lead = {
none: 'nui-lead-none',
tight: 'nui-lead-tight',
snug: 'nui-lead-snug',
normal: 'nui-lead-normal',
relaxed: 'nui-lead-relaxed',
loose: 'nui-lead-loose',
} as const satisfies TextVariant<'lead'>

0 comments on commit 6b0f05c

Please sign in to comment.