Skip to content

Commit

Permalink
Merge pull request #474 from sima-land/472-gradients-and-colors-upd
Browse files Browse the repository at this point in the history
 Шаг 2 #472 Добавить css-свойства для цветов и градиентов
  • Loading branch information
krutoo authored Aug 29, 2024
2 parents 5af7592 + 7099a2b commit bc15568
Show file tree
Hide file tree
Showing 7 changed files with 225 additions and 140 deletions.
31 changes: 1 addition & 30 deletions docs/stories/tokens/colors/usage.m.scss
Original file line number Diff line number Diff line change
@@ -1,40 +1,11 @@
@use 'pkg:@sima-land/ui-nucleons/colors';

.section + .section {
margin-top: 32px;
}

.imports {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 32px;
> * {
width: 100%;
}
}

.colors {
display: flex;
gap: 4px;
flex-direction: column;
}

.color {
padding: 8px;
display: flex;
align-items: center;
gap: 16px;
border-radius: 4px;
&:hover {
background: colors.$basic-gray4;
}
.circle {
flex-shrink: 0;
width: 32px;
height: 32px;
border-radius: 50%;
}
.title {
margin-right: auto;
}
}
129 changes: 20 additions & 109 deletions docs/stories/tokens/colors/usage.tsx
Original file line number Diff line number Diff line change
@@ -1,123 +1,34 @@
import { COLORS } from '@sima-land/ui-nucleons/colors';
import { useEffect, useRef, useState } from 'react';
import ClipboardJS from 'clipboard';
import { Button } from '@sima-land/ui-nucleons/button';
import { Input } from '@sima-land/ui-nucleons/input';
import { TextButton } from '@sima-land/ui-nucleons/text-button';
import CopySVG from '@sima-land/ui-quarks/icons/16x16/Stroked/Copy';
import CopyBigSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/Copy';
import { CardGrid, ImportField, TokenCard } from '../gradients/usage';
import styles from './usage.m.scss';

export function ColorsPicker() {
return (
<>
<h2>Токены цветов</h2>
<h2>Цвета</h2>

<p>Библиотека предоставляет утилиты для использования цветов дизайн-системы.</p>

<div className={styles.section}>
<div className={styles.imports}>
<ImportField label='Импорт SCSS' value="@use '@sima-land/ui-nucleons/colors';" />
<ImportField
label='Импорт JS'
value="import { COLORS } from '@sima-land/ui-nucleons/colors';"
/>
</div>
<div className={styles.imports}>
<ImportField label='Импорт SCSS' value="@use 'pkg:@sima-land/ui-nucleons/colors';" />
<ImportField
label='Импорт JS'
value="import { COLORS } from '@sima-land/ui-nucleons/colors';"
/>
</div>

<div className={styles.section}>
<div className={styles.colors}>
{[...COLORS.entries()].map(([name, value], index) => (
<ColorView key={index} {...{ name, value }} />
))}
</div>
</div>
<CardGrid>
{[...COLORS.entries()].map(([name, value], index) => (
<TokenCard
key={index}
name={name}
value={value}
usageToken={`color/${name}`}
usageScss={`colors.$${name}`}
usageJs={`COLORS.get('${name}')`}
/>
))}
</CardGrid>
</>
);
}

function ImportField({ value, label }: { value: string; label: string }) {
const inputRef = useRef<HTMLInputElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [copied, setCopied] = useState(false);

useEffect(() => {
if (buttonRef.current) {
const clipboard = new ClipboardJS(buttonRef.current, { text: () => value });

clipboard.on('success', () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});

return () => clipboard.destroy();
}
}, []);

return (
<Input
label={label}
value={copied ? 'Скопировано' : value}
disabled={copied}
inputRef={inputRef}
readOnly
adornmentEnd={
<TextButton
disabled={copied}
color='basic-gray87'
buttonRef={buttonRef}
onMouseDown={e => e.preventDefault()}
>
<CopyBigSVG fill='currentColor' />
</TextButton>
}
/>
);
}

function ColorView({ name, value }: { name: string; value: string }) {
return (
<div className={styles.color}>
<span className={styles.circle} style={{ background: value }} />
<span className={styles.title}>{name}</span>
<span>{value}</span>

<CopyButton title='SCSS' value={`colors.$${name}`} />
<CopyButton title='JS' value={`COLORS.get('${name}')`} />
</div>
);
}

function CopyButton({ title, value }: { title: string; value: string }) {
const buttonRef = useRef<HTMLButtonElement>(null);
const [copied, setCopied] = useState(false);

useEffect(() => {
if (buttonRef.current) {
const clipboard = new ClipboardJS(buttonRef.current, {
text: () => value,
});

clipboard.on('success', () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});

return () => clipboard.destroy();
}
}, []);

return (
<div>
<Button
ref={buttonRef}
size='xs'
viewType='secondary'
icon={!copied ? CopySVG : undefined}
disabled={copied}
>
{copied ? 'Скопировано' : title}
</Button>
</div>
);
}
3 changes: 3 additions & 0 deletions docs/stories/tokens/gradients.story.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { GradientPicker } from './gradients/usage.tsx';

<GradientPicker />
1 change: 1 addition & 0 deletions docs/stories/tokens/gradients.story.meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "title": "Градиенты", "category": "Токены" }
53 changes: 53 additions & 0 deletions docs/stories/tokens/gradients/usage.m.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@use 'pkg:@sima-land/ui-nucleons/colors';

.imports {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 32px;
> * {
width: 100%;
}
}

.grid {
display: flex;
flex-wrap: wrap;
gap: 12px;
container-type: inline-size;
}

.card {
width: calc((100% - 24px) / 3);
display: flex;
flex-direction: column;
border-radius: 8px;
box-shadow: inset 0 0 0 1px #ddd;
@container (max-width: 960px) {
width: calc((100% - 12px) / 2);
}
@container (max-width: 600px) {
width: calc((100%));
}
.sample {
margin: 16px 16px 0;
aspect-ratio: 2 / 1;
border-radius: 4px;
}
.info {
padding: 16px;
display: flex;
flex-direction: column;
gap: 4px;
.title {
font-weight: bold;
}
}
.controls {
padding: 16px;
padding-top: 0;
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
}
}
146 changes: 146 additions & 0 deletions docs/stories/tokens/gradients/usage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
import { GRADIENTS } from '@sima-land/ui-nucleons/gradients';
import { ReactNode, useEffect, useRef, useState } from 'react';
import ClipboardJS from 'clipboard';
import { Button } from '@sima-land/ui-nucleons/button';
import { Input } from '@sima-land/ui-nucleons/input';
import { TextButton } from '@sima-land/ui-nucleons/text-button';
import CopySVG from '@sima-land/ui-quarks/icons/16x16/Stroked/Copy';
import CopyBigSVG from '@sima-land/ui-quarks/icons/24x24/Stroked/Copy';
import styles from './usage.m.scss';

export function GradientPicker() {
return (
<>
<h2>Градиенты</h2>

<p>Библиотека предоставляет утилиты для использования градиентов дизайн-системы.</p>

<div className={styles.imports}>
<ImportField label='Импорт SCSS' value="@use 'pkg:@sima-land/ui-nucleons/gradients';" />
<ImportField
label='Импорт JS'
value="import { GRADIENTS } from '@sima-land/ui-nucleons/gradients';"
/>
</div>

<CardGrid>
{[...GRADIENTS.entries()].map(([name, value], index) => (
<TokenCard
key={index}
name={name}
value={value}
usageToken={`gradient/${name}`}
usageScss={`gradients.$${name}`}
usageJs={`GRADIENTS.get('${name}')`}
/>
))}
</CardGrid>
</>
);
}

export function ImportField({ value, label }: { value: string; label: string }) {
const inputRef = useRef<HTMLInputElement>(null);
const buttonRef = useRef<HTMLButtonElement>(null);
const [copied, setCopied] = useState(false);

useEffect(() => {
if (buttonRef.current) {
const clipboard = new ClipboardJS(buttonRef.current, { text: () => value });

clipboard.on('success', () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});

return () => clipboard.destroy();
}
}, []);

return (
<Input
label={label}
value={copied ? 'Скопировано' : value}
disabled={copied}
inputRef={inputRef}
readOnly
adornmentEnd={
<TextButton
disabled={copied}
color='basic-gray87'
buttonRef={buttonRef}
onMouseDown={e => e.preventDefault()}
>
<CopyBigSVG fill='currentColor' />
</TextButton>
}
/>
);
}

export function CardGrid({ children }: { children: ReactNode }) {
return <div className={styles.grid}>{children}</div>;
}

export function TokenCard({
name,
value,
usageToken: token,
usageScss: scss,
usageJs: js,
}: {
name: string;
value: string;
usageToken: string;
usageScss: string;
usageJs: string;
}) {
return (
<div className={styles.card}>
<div className={styles.sample} style={{ background: value }}></div>

<div className={styles.info}>
<span className={styles.title}>{name}</span>
<span className={styles.value}>{value}</span>
</div>

<div className={styles.controls}>
<CopyButton title='Токен' value={token} />
<CopyButton title='SCSS' value={scss} />
<CopyButton title='JS' value={js} />
</div>
</div>
);
}

function CopyButton({ title, value }: { title: string; value: string }) {
const buttonRef = useRef<HTMLButtonElement>(null);
const [copied, setCopied] = useState(false);

useEffect(() => {
if (buttonRef.current) {
const clipboard = new ClipboardJS(buttonRef.current, {
text: () => value,
});

clipboard.on('success', () => {
setCopied(true);
setTimeout(() => setCopied(false), 2000);
});

return () => clipboard.destroy();
}
}, []);

return (
<Button
ref={buttonRef}
size='xs'
viewType='secondary'
icon={!copied ? CopySVG : undefined}
disabled={copied}
>
{copied ? 'Скопировано' : title}
</Button>
);
}
Loading

0 comments on commit bc15568

Please sign in to comment.