Comments 14
Очень интересный подход! А как передать не булево свойство внутрь?
И более менее сложный лэйаут будет требовать десятка дивов, импорты превратятся в Div as ComponentWrapper.
Я бы посмотрел в сторону чего-то такого:
div#Wrapper { // возможность указать тэг
color: green;
.dangerous { // булево
color: red;
}
background: attr(background); // получаем значение из проперти. к слову, это можно вообще нативно через дата аттрибут сделать, но вроде как там возможности пока что сильно лимитированны
}
Вроде в рамках нормального css (sass), но гибче.
А как передать не булево свойство внутрь?
Внутрь ничего передавать не нужно, расценивайте это не как улучшение styled-components, а больше как улучшение css-modules, т.е. мы избавились от использования библиотек типа `classnames` и ручной генерации значения свойства `className`, а всё остальное осталось как и было, т.е.
.avatar {
width: 40px;
height: 40px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border-radius: 50%;
}
import { Div } from './styles.css'
function Avatar(props){
return <Div avatar style={{backgroundImage: `url(${props.src})`}} />
}
И более менее сложный лэйаут будет требовать десятка дивов, импорты превратятся в Div as ComponentWrapper.
В том то и дело, что всё будет гораздо проще :)
import { Div } from './styles.css'
function Layout(props){
return <Div wrapper>
<Div header />
<Div aside />
<Div content>{props.children}</Div>
<Div footer />
</Div>
}
при этом в стилях у нас
.wrapper{}
.header{}
.aside{}
.content{}
.footer{}
Синтетический пример, но думаю замысел понятен :)
получаем значение из проперти. к слову, это можно вообще нативно через дата аттрибут сделать, но вроде как там возможности пока что сильно лимитированны
кстати спасибо за идею! обязательно покопаю в эту сторону, дабы упростить подобное
style={{backgroundImage: `url(${props.src})`}}
А как передать не булево свойство внутрь?
изначально не правильно понял ваш замысел, подумал что вы хотите пробрасывать свойства внутрь, как в styled-components, поэтому исправляюсь и прошу первый абзац моего ответа изложить в следующей редакции:
для динамического определения какого-то свойства компонента необходимо использовать подход css-modules, а именно передачу через свойство `style`
спасибо)
получаем значение из проперти. к слову, это можно вообще нативно через дата аттрибут сделать, но вроде как там возможности пока что сильно лимитированны
развивая эту тему - можно заюзать установку значений переменных через атрибут style, т.е. например (тут нужно соглашение) все свойства, начинающиеся с двойного нижнего подчеркивания
<Div name __fontSize="14px">John</Div>
конвертировать в переменные, получая на выходе
<div class="name" style="--fontSize: 14px">John</div>
доступ к которым получать через `var(...)`
.name {
font-size: var(--fontSize);
}
что я собственно и сделал
Цсс-модули и стайлед-компоненты хорошо стыкуются с пользовательскими компонентами, у которых есть подпорка className (бывают, правда, ещё пропсы вроде anotherClassName, с которыми стайледы почти не дружат).
Как с этим обстоит дело у сабжа?
Тут всё хорошо :)
<Div root red className="anotherClassName" />
на выходе даст, что-то типа
<div class="_root_78bp722 _red_53ds782 anotherClassName"></div>
т.е. значение свойства `className`, если оно определено, будет проброшено до целевого компонента
Я немного о другом. Вот допустим календарь - кастомный компонент. У него есть пропсы className и tileClassName. Как их задать через Candy?
аа, вот вы о чем )
сейчас это можно сделать, например, так: в файле стилей определить
/* style.css */
:global .calendar_custom_classname {
color: rebeccapurple;
}
:global .calendar_custom_tile_classname {
color: red;
}
затем
import './style.css'
function MyApp() {
return (
<Calendar
className="calendar_custom_classname"
tileClassName="calendar_custom_tile_classname" />
)
}
можно конечно рассмотреть вопрос о том, чтобы `candy-loader` помимо компонентов-тегов экспортировал ссылки на локальные названия классов, тогда можно будет сочетать подход css-modules, типа
/* style.css */
.calendar_custom_classname {
color: rebeccapurple;
}
.calendar_custom_tile_classname {
color: red;
}
import {calendar_custom_classname, calendar_custom_tile_classname} from './style.css'
function MyApp() {
return (
<Calendar
className={calendar_custom_classname}
tileClassName={calendar_custom_tile_classname} />
)
}
тут `calendar_custom_classname` и `calendar_custom_tile_classname` будут содержать что-то типа "_calendar_custom_tile_classname_0ksfd33"
Здорово, мне очень понравилась идея
Если не сложно можно объяснить как работает red={props.red}, то есть он устанавливает класс, если props.red===true или я не правильно понял?
да, вы всё правильно поняли, с использованием css-modules это выглядело бы так
import styles from './styles.css'
function Component(props) {
let cn = styles.root
if(props.red) cn += ' ' + styles.red
return (
<div className={cn}>...</div>
)
}
с использованием, например, библиотеки classnames, так
import styles from './styles.css'
import classnames from 'çlassnames'
function Component(props) {
const cn = classnames({
[styles.root]: true,
[styles.red]: props.red
})
return (
<div className={cn}>...</div>
)
}
всё что делает candy - прячет работу по формированию свойства `className` под капот
import { Div } from './styles.css'
function Component(props) {
return (
<Div root red={props.red}>...</Div>
)
}
во всём остальном на выходе мы получаем тоже что и в css-modules, что-то типа
<div class="root_23sadsd red_32423xad2">...</div>
На компонентах размера побольше хорошо заметна разница в читабельности кода
Для сравнения css-modules:
const Post = (props) => {
/* ... */
return (
<div className={styles.post}>
<div className={styles.cover} style={{ backgroundImage: `url(${cover})` }} />
<div className={styles.info}>
<div className={styles.title}>{title}</div>
<div className={styles.stats}>
<span className={styles.comments}>{commentsCount}</span>
<span className={styles.likes}>{likesCount}</span>
</div>
</div>
</div>
)
}
candy:
const Post = (props) => {
/* ... */
return (
<Div post>
<Div cover __src={`url(${cover})`} />
<Div info>
<Div title>{title}</Div>
<Div stats>
<Span comments>{commentsCount}</Span>
<Span likes>{likesCount}</Span>
</Div>
</Div>
</Div>
)
}
В такой верстке сразу видно и используемые теги, и используемые стили. Это чище на вид и легче для восприятия, если знаешь правила по, которым создан и работает код.
Будем честны - в большинстве случаев при верстке у тегов мы максимум, что определяем - обработчики событий типа `onClick` и свойство `className`. Думаю нет ничего сложного в том, чтобы распознать, что `<Span comments>` это тег `span` со стилем class="comments"
`. Откуда этот стиль берется видно по импорту, typescript плагин также подсветит ошибку при её наличии.
но даже тут постоянный бойлерплейт вида className={cn(...)} начинает порядком надоедать
Проблема была решена еще в 2018ом
Пару слов о стилизации React компонентов