Skip to content

Commit

Permalink
Merge pull request #8 from squidit/feature/add-more-components
Browse files Browse the repository at this point in the history
✨ Add Banner component
  • Loading branch information
wandersonsales-dev authored Apr 2, 2024
2 parents 791613a + f9ec51c commit c7f86af
Show file tree
Hide file tree
Showing 76 changed files with 1,665 additions and 21 deletions.
6 changes: 1 addition & 5 deletions .storybook/squid.theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,8 @@ import { create } from '@storybook/theming/create'
export default create({
base: 'light',

// Typography
// fontBase: '"Open Sans", sans-serif',
// fontCode: 'monospace',

brandTitle: 'Squid',
brandUrl: 'https://css.squidit.com.br/',
brandUrl: '/',
brandImage: 'https://squidit.com.br/wp-content/themes/squid/assets/img/logo.svg',
brandTarget: '_self',

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@squidit/react-css",
"version": "0.0.7",
"version": "0.0.8",
"scripts": {
"format": "prettier --write --parser typescript '**/*.{ts,tsx}'",
"lint": "eslint src --ext js,ts,tsx",
Expand Down
4 changes: 4 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ export * from './sq-tab'
export * from './sq-tabs'
export * from './sq-infinity-scroll'
export * from './inputs/sq-input'
export * from './sq-banner'
export * from './sq-bar-chart'
export * from './sq-metric-chart'
export * from './sq-border-with-icon'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Loader from '@components/sq-loader/sq-loader.component'
import ColorsHelper from '@helpers/sq-colors.helper'
import ObjectHelper from '@helpers/sq-object.helper'
import ColorsHelper from '@/helpers/sq-colors/sq-colors.helper'
import ObjectHelper from '@/helpers/sq-object/sq-object.helper'
import { useEffect, useState } from 'react'

import './sq-input-file.component.scoped.scss'
Expand Down
2 changes: 1 addition & 1 deletion src/components/inputs/sq-input/sq-input.component.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import SqLoader from '@components/sq-loader/sq-loader.component'
import SqValidatorHelper from '@helpers/sq-validator.helper'
import SqValidatorHelper from '@/helpers/sq-validator/sq-validator.helper'
import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'

import './sq-input.component.scoped.scss'
Expand Down
19 changes: 19 additions & 0 deletions src/components/sq-banner/__docs__/sq-banner.component.example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import SqBannerExample, { Props } from '../banner.component'

const SqBanner = ({ children, ...props }: Props) => {
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
}}
>
<SqBannerExample {...props}>{children}</SqBannerExample>
</div>
)
}

export default SqBanner
24 changes: 24 additions & 0 deletions src/components/sq-banner/__docs__/sq-banner.component.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Meta, StoryObj } from '@storybook/react'
import SqBannerExample from './sq-banner.component.example'

const meta: Meta<typeof SqBannerExample> = {
title: 'Components/SqBanner',
parameters: {
docs: {
description: {
component: 'A simple Banner component',
},
},
},
component: SqBannerExample,
tags: ['autodocs'],
}

export default meta
type Story = StoryObj<typeof SqBannerExample>

export const Default: Story = {
args: {
children: 'This is a banner',
},
}
35 changes: 35 additions & 0 deletions src/components/sq-banner/banner.component.scoped.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.banner-container {
width: 100%;
display: flex;
justify-content: space-between;
margin: 2rem 0;
border-color: transparent;
border-radius: 5px;
padding: 1rem;
gap: 1rem;
.banner-figure {
width: calc(150px);
display: flex;
justify-content: center;
align-items: center;
flex-grow: 0;
flex-shrink: 0;
}
.content {
width: 100%;
.title {
font-size: 2rem;
font-weight: 300;
margin: 0;
padding: 0;
}
.text {
font-size: 0.9rem;
font-weight: 400;
}
}

@media (max-width: 500px) {
margin: 2rem auto;
}
}
30 changes: 30 additions & 0 deletions src/components/sq-banner/banner.component.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { describe, it, expect } from 'vitest'
import { render, screen } from '@testing-library/react'
import Banner from '@/components/sq-banner/banner.component'

describe('Banner Component', () => {
const bannerComponent = (
<Banner figure={<img src="https://github.com/wandersonsales-dev.png" alt="Alt banner" />} title="Title tests" textColor="var(--yellow)">
Text
</Banner>
)

it('should render without errors', () => {
render(bannerComponent)

const imageBanner = screen.getByRole('img', {
name: /alt banner/i,
})
const titleBanner = screen.getByRole('heading', {
name: /title tests/i,
})
const textBanner = screen.getByText(/text/i)

expect(imageBanner).toBeInTheDocument()
expect(imageBanner).toHaveAttribute('src', 'https://github.com/wandersonsales-dev.png')
expect(titleBanner).toBeInTheDocument()
expect(titleBanner).toHaveTextContent('Title tests')
expect(textBanner).toBeInTheDocument()
expect(textBanner).toHaveTextContent('Text')
})
})
30 changes: 30 additions & 0 deletions src/components/sq-banner/banner.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React, { PropsWithChildren } from 'react'
import './banner.component.scoped.scss'

export interface Props extends PropsWithChildren<React.HTMLAttributes<HTMLDivElement>> {
title: any
backgroundColor?: string
figure: any
textColor: string
}

export default ({
children,
title,
backgroundColor = 'var(--background)',
figure,
textColor = 'var(--text_color)',
className = '',
style,
}: Props) => {
return (
<section className={`banner-container ${className}`} style={{ backgroundColor, color: textColor, ...style }}>
<div className="banner-figure">{figure}</div>

<div className="content">
<h5 className="title">{title}</h5>
<div className="text">{children}</div>
</div>
</section>
)
}
1 change: 1 addition & 0 deletions src/components/sq-banner/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as SqBanner } from './banner.component'
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from 'react'
import SqBarChartExample, { Props } from '../sq-bar-chart.component'

const SqBarChart = ({ ...props }: Props) => {
return (
<div
style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
height: '100%',
}}
>
<SqBarChartExample {...props} />
</div>
)
}

export default SqBarChart
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Meta, StoryObj } from '@storybook/react'
import SqBarChartExample from './sq-bar-chart.component.example'

const meta: Meta<typeof SqBarChartExample> = {
title: 'Components/SqBarChart',
parameters: {
docs: {
description: {
component: 'A simple BarChart component',
},
},
},
component: SqBarChartExample,
tags: ['autodocs'],
}

export default meta
type Story = StoryObj<typeof SqBarChartExample>

export const Default: Story = {
args: {
labelPin: 'Pin',
percentage: false,
pinValue: 50,
total: 100,
value: 75,
},
argTypes: {
colorBar: {
control: {
type: 'color',
},
},
},
}
1 change: 1 addition & 0 deletions src/components/sq-bar-chart/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as SqBarChart } from './sq-bar-chart.component'
77 changes: 77 additions & 0 deletions src/components/sq-bar-chart/sq-bar-chart.component.scoped.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
.bar-chart {
height: 0.8rem;
background-color: var(--gray_light);
border-radius: 1rem;
display: flex;
position: relative;

.value-bar {
position: absolute;
background-color: var(--primary_color);
border-radius: 1rem;
height: 100%;
top: 0;
left: 0;
animation: loadbar 2s ease-in-out;
}

.pin-bar-chart {
position: absolute;
height: calc(100% + 1rem);
top: 0;
left: 0;
display: flex;
justify-content: flex-end;
align-items: center;
animation: loadbar 2s ease-in-out;
color: var(--gray);

.pin-container {
position: relative;
top: -5px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
align-self: baseline;

.pin-bar-chart-content {
background-color: var(--background_secondary);
padding: 0 2px;

.pin {
width: 3px;
height: 22px;
background-color: var(--gray);
border-radius: 10px;
margin: 0 2px;
position: relative;

.description-pin {
top: 3rem;
transform: translate(0%, -50%);
position: absolute;
display: flex;
flex-wrap: nowrap;
white-space: nowrap;
gap: 5px;
font-size: 0.9rem;
display: flex;
align-items: baseline;
color: var(--text_color);

span {
font-size: 0.9rem;
}
}
}
}
}
}

@keyframes loadbar {
from {
width: 0;
}
}
}
64 changes: 64 additions & 0 deletions src/components/sq-bar-chart/sq-bar-chart.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useLayoutEffect, useMemo, useRef } from 'react'
import SqNumbersHelper from '@/helpers/sq-numbers/sq-numbers.helper'
import useRect from '@/hooks/use-sq-rect/use-sq-rect.hook'

import './sq-bar-chart.component.scoped.scss'

export interface Props {
value: number
pinValue?: number
total: number
labelPin?: any
percentage: boolean
colorBar?: string
}

const BarChart = ({ value, pinValue = value, total, percentage = false, labelPin = null, colorBar = 'var(--primary_color)' }: Props) => {
const totalBar = useMemo(() => total || (percentage ? 1 : 100), [percentage, total])
const numbersHelper = useMemo(() => new SqNumbersHelper(), [])
const { formatCompactNumber, formatPercent } = numbersHelper
const refLabelPin = useRef<HTMLDivElement>(null)
const refValueBar = useRef<HTMLDivElement>(null)

const contentRectLabelPin = useRect(refLabelPin)
const contentRectMetricChartBody = useRect(refValueBar)

const definePercentage = (value: number, maxValue: number): string => {
return ((value * 100) / maxValue).toFixed(0)
}

const maxNumber = totalBar
const widthUserBar = definePercentage(value, maxNumber)
const widthInfluencerAverageBar = definePercentage(pinValue, maxNumber)

useLayoutEffect(() => {
const { left: leftDescription, width: widthDescription } = contentRectLabelPin
const { left: leftMetricChart, width: widthMetricChart } = contentRectMetricChartBody

if (refLabelPin.current && leftDescription < leftMetricChart && widthMetricChart <= widthDescription) {
refLabelPin.current.style.transform = `translate(-${widthMetricChart}px, -50%)`
}
})

return (
<div className="bar-chart">
<div className="value-bar" style={{ width: `${parseInt(widthUserBar)}%`, backgroundColor: colorBar }}></div>
<div className="pin-bar-chart" style={{ width: `${parseInt(widthInfluencerAverageBar)}%` }} ref={refValueBar}>
<div className="pin-container">
<div className="pin-bar-chart-content">
<div className="pin">
<div className="description-pin" ref={refLabelPin}>
{labelPin}
<span className="text-bold">
{percentage ? formatPercent(pinValue) : formatCompactNumber({ lang: 'en', number: pinValue })}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
)
}

export default BarChart
Loading

0 comments on commit c7f86af

Please sign in to comment.