Files
cinny/src/app/styles/CustomHtml.css.ts
litruv c286501be8 Improve timeline scroll, media layout, avatars, and emoji coverage.
Remember room scroll position across switches, reserve image/video heights from Matrix dimensions, cache authenticated media blobs for avatars, restore jumbo emoji-only messages, and extend emoji font unicode-range for Unicode 15 glyphs.
2026-07-22 20:00:14 +10:00

310 lines
6.4 KiB
TypeScript

import { style } from '@vanilla-extract/css';
import { recipe } from '@vanilla-extract/recipes';
import { color, config, DefaultReset, toRem } from 'folds';
import { ContainerColor } from './ContainerColor.css';
export const MarginSpaced = style({
marginBottom: config.space.S200,
marginTop: config.space.S200,
selectors: {
'&:first-child': {
marginTop: 0,
},
'&:last-child': {
marginBottom: 0,
},
},
});
export const Paragraph = style([
DefaultReset,
{
overflow: 'hidden',
lineHeight: '1.5',
},
]);
export const Heading = style([
DefaultReset,
MarginSpaced,
{
marginTop: config.space.S400,
overflow: 'hidden',
lineHeight: '1.5',
selectors: {
'&:first-child': {
marginTop: 0,
},
},
},
]);
export const BlockQuote = style([
DefaultReset,
MarginSpaced,
{
paddingLeft: config.space.S200,
borderLeft: `${config.borderWidth.B700} solid ${color.SurfaceVariant.ContainerLine}`,
fontStyle: 'italic',
overflow: 'hidden',
lineHeight: '1.5',
},
]);
const BaseCode = style({
color: color.SurfaceVariant.OnContainer,
background: color.SurfaceVariant.Container,
border: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
borderRadius: config.radii.R300,
});
const CodeFont = style({
fontFamily: 'monospace',
});
export const InlineCodeWrapper = style({
position: 'relative',
display: 'inline-block',
});
export const Code = style([
DefaultReset,
BaseCode,
CodeFont,
{
padding: `0 ${config.space.S100}`,
display: 'inline',
overflow: 'hidden',
lineHeight: '1.5',
},
]);
export const InlineCodeCopyButton = style({
position: 'absolute',
top: 0,
right: 0,
transform: 'translateY(-100%)',
opacity: 0,
transition: 'opacity 0.15s ease-in-out',
background: color.SurfaceVariant.Container,
border: `${config.borderWidth.B300} solid ${color.SurfaceVariant.ContainerLine}`,
borderBottom: 'none',
borderTopLeftRadius: config.radii.R300,
borderTopRightRadius: config.radii.R300,
padding: `${config.space.S200} ${config.space.S300}`,
cursor: 'pointer',
fontSize: toRem(11),
color: color.SurfaceVariant.OnContainer,
fontWeight: config.fontWeight.W500,
whiteSpace: 'nowrap',
zIndex: 1,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
selectors: {
[`${InlineCodeWrapper}:hover &`]: {
opacity: 1,
},
'&:hover': {
background: color.SurfaceVariant.ContainerHover,
},
'&:active': {
background: color.SurfaceVariant.ContainerActive,
},
},
});
export const Spoiler = recipe({
base: [
DefaultReset,
{
padding: `0 ${config.space.S100}`,
backgroundColor: color.SurfaceVariant.ContainerActive,
borderRadius: config.radii.R300,
overflow: 'hidden',
lineHeight: '1.5',
selectors: {
'&[aria-pressed=true]': {
color: 'transparent',
},
},
},
],
variants: {
active: {
true: {
color: 'transparent',
},
},
},
});
export const CodeBlock = style([
DefaultReset,
BaseCode,
MarginSpaced,
{
fontStyle: 'normal',
position: 'relative',
overflow: 'hidden',
lineHeight: '1.5',
},
]);
export const CodeBlockHeader = style([
ContainerColor({ variant: 'Surface' }),
{
padding: `0 ${config.space.S200} 0 ${config.space.S300}`,
borderBottomWidth: config.borderWidth.B300,
gap: config.space.S200,
},
]);
export const CodeBlockInternal = style([
CodeFont,
{
padding: `${config.space.S200} ${config.space.S200} 0`,
minWidth: toRem(200),
},
]);
export const CodeBlockBottomShadow = style({
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
pointerEvents: 'none',
height: config.space.S400,
background: `linear-gradient(to top, #00000022, #00000000)`,
});
export const List = style([
DefaultReset,
MarginSpaced,
{
padding: `0 ${config.space.S100}`,
paddingLeft: config.space.S600,
overflow: 'hidden',
lineHeight: '1.5',
},
]);
export const Img = style([
DefaultReset,
MarginSpaced,
{
maxWidth: toRem(296),
borderRadius: config.radii.R300,
},
]);
export const InlineChromiumBugfix = style({
fontSize: 0,
lineHeight: 0,
});
export const Mention = recipe({
base: [
DefaultReset,
{
backgroundColor: color.SurfaceVariant.Container,
color: color.SurfaceVariant.OnContainer,
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.ContainerLine}`,
padding: `0 ${toRem(2)}`,
borderRadius: config.radii.R300,
fontWeight: config.fontWeight.W500,
overflow: 'hidden',
lineHeight: '1.5',
},
],
variants: {
highlight: {
true: {
backgroundColor: color.Success.Container,
color: color.Success.OnContainer,
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.Success.ContainerLine}`,
},
},
focus: {
true: {
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.OnContainer}`,
},
},
},
});
export const Command = recipe({
base: [
DefaultReset,
{
padding: `0 ${toRem(2)}`,
borderRadius: config.radii.R300,
fontWeight: config.fontWeight.W500,
overflow: 'hidden',
lineHeight: '1.5',
},
],
variants: {
focus: {
true: {
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.Warning.OnContainer}`,
},
},
active: {
true: {
backgroundColor: color.Warning.Container,
color: color.Warning.OnContainer,
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.Warning.ContainerLine}`,
},
},
},
});
export const EmoticonBase = style([
DefaultReset,
{
display: 'inline-block',
verticalAlign: '-0.1em',
lineHeight: 1,
height: 'auto',
padding: 0,
},
]);
export const Emoticon = recipe({
base: [
DefaultReset,
{
display: 'inline',
fontSize: '1.2em',
lineHeight: 1,
verticalAlign: 'inherit',
},
],
variants: {
focus: {
true: {
boxShadow: `0 0 0 ${config.borderWidth.B300} ${color.SurfaceVariant.OnContainer}`,
},
},
},
});
export const EmoticonImg = style([
DefaultReset,
{
display: 'block',
height: '1.2em',
width: '1.2em',
cursor: 'default',
},
]);
export const highlightText = style([
DefaultReset,
{
backgroundColor: 'yellow',
color: 'black',
overflow: 'hidden',
lineHeight: '1.5',
},
]);