UNPKG

raft-ui

Version:

React UI components for Raft.

317 lines (279 loc) • 11.1 kB
/* FloatButton pure CSS styling following pattern/Button.css architecture - Local CSS variables (--r-float-button-*) declared on component root - Modifier classes rebind local variables - Component styles strictly consume local variables - An icon button: surface + 1.5px ink edge, control radius on every shape, no shadow, press overlay, focus ring. */ /* ───────────────────────────────────────────────────────────────────────── 1. Local Variable Definitions & Modifier Overrides ───────────────────────────────────────────────────────────────────────── */ .r-float-button { --r-float-button-size: 32px; --r-float-button-width: var(--r-float-button-size); --r-float-button-padding-x: 0px; --r-float-button-border-radius: 8px; --r-float-button-border-width: 1.5px; --r-float-button-border-style: solid; --r-float-button-border-color: var(--line-strong); --r-float-button-bg: var(--layer-card); --r-float-button-bg-hover: var(--layer-card); --r-float-button-press: var(--fill-pressed); --r-float-button-text-color: var(--foreground); --r-float-button-text-hover-color: var(--foreground); --r-float-button-text-disabled-color: var(--foreground-disabled); --r-float-button-box-shadow: none; --r-float-button-shadow-hover: none; --r-float-button-shadow-active: none; --r-float-button-transform-hover: none; --r-float-button-transform-active: none; --r-float-button-outline: 2px solid var(--line-strong); --r-float-button-outline-offset: 2px; --r-float-button-font-size: 12px; --r-float-button-font-weight: 700; --r-float-button-desc-font-size: 10px; --r-float-button-icon-size: 16px; --r-float-button-opacity-disabled: 1; /* Sizes: xs (24px), sm (28px), md (32px), lg (36px) */ &.r-float-button--xs { --r-float-button-size: 24px; --r-float-button-icon-size: 12px; --r-float-button-font-size: 11px; --r-float-button-desc-font-size: 8px; --r-float-button-padding-x: 8px; } &.r-float-button--sm { --r-float-button-size: 28px; --r-float-button-icon-size: 14px; --r-float-button-font-size: 12px; --r-float-button-desc-font-size: 9px; --r-float-button-padding-x: 10px; } &.r-float-button--md { --r-float-button-size: 32px; --r-float-button-icon-size: 16px; --r-float-button-font-size: 12px; --r-float-button-desc-font-size: 10px; --r-float-button-padding-x: 12px; } &.r-float-button--lg { --r-float-button-size: 36px; --r-float-button-icon-size: 18px; --r-float-button-font-size: 14px; --r-float-button-desc-font-size: 11px; --r-float-button-padding-x: 14px; } /* Extended with text (adaptive width & horizontal padding) */ &.r-float-button--with-text { --r-float-button-width: auto; } /* Shapes: every shape takes the control radius; a pill sizes to its text. */ &.r-float-button--pill { --r-float-button-width: auto; padding-left: var(--r-float-button-padding-x); padding-right: var(--r-float-button-padding-x); } /* Variants: default and outline are the base surface. Filled variants are stickers: ink edge and ink text on the fill, pressed with the sticker overlay. */ &.r-float-button--primary, &.r-float-button--accent { --r-float-button-border-color: var(--sticker-ink); --r-float-button-bg: var(--accent-400); --r-float-button-bg-hover: var(--accent-400); --r-float-button-press: var(--sticker-pressed); --r-float-button-text-color: var(--sticker-ink); --r-float-button-text-hover-color: var(--sticker-ink); } &.r-float-button--warning { --r-float-button-border-color: var(--sticker-ink); --r-float-button-bg: var(--warning); --r-float-button-bg-hover: var(--warning); --r-float-button-press: var(--sticker-pressed); --r-float-button-text-color: var(--sticker-ink); --r-float-button-text-hover-color: var(--sticker-ink); } &.r-float-button--danger { --r-float-button-border-color: var(--sticker-ink); --r-float-button-bg: var(--danger); --r-float-button-bg-hover: var(--danger); --r-float-button-press: var(--sticker-pressed); --r-float-button-text-color: var(--sticker-ink); --r-float-button-text-hover-color: var(--sticker-ink); } &.r-float-button--ghost { --r-float-button-border-color: transparent; --r-float-button-bg: transparent; --r-float-button-bg-hover: var(--fill-pressed); --r-float-button-press: transparent; } } /* ───────────────────────────────────────────────────────────────────────── 2. Base Element Rules Consuming Local Variables ───────────────────────────────────────────────────────────────────────── */ .r-float-button { position: relative; display: inline-flex; flex-shrink: 0; align-items: center; justify-content: center; user-select: none; cursor: pointer; box-sizing: border-box; padding: 0; width: var(--r-float-button-width, var(--r-float-button-size)); min-width: var(--r-float-button-size); height: var(--r-float-button-size); border-radius: var(--r-float-button-border-radius); border-width: var(--r-float-button-border-width); border-style: var(--r-float-button-border-style); border-color: var(--r-float-button-border-color); background-color: var(--r-float-button-bg); color: var(--r-float-button-text-color); box-shadow: var(--r-float-button-box-shadow); font-size: var(--r-float-button-font-size); font-weight: var(--r-float-button-font-weight); outline: none; transition: transform 150ms cubic-bezier(0.4, 0, 0.2, 1), box-shadow 150ms cubic-bezier(0.4, 0, 0.2, 1), background-color 150ms cubic-bezier(0.4, 0, 0.2, 1), border-color 150ms cubic-bezier(0.4, 0, 0.2, 1), color 150ms cubic-bezier(0.4, 0, 0.2, 1); @media (prefers-reduced-motion: reduce) { transition: none; } &.r-float-button--with-text, &.r-float-button--pill { padding-left: var(--r-float-button-padding-x); padding-right: var(--r-float-button-padding-x); } &:hover:not(:disabled) { background-color: var(--r-float-button-bg-hover); color: var(--r-float-button-text-hover-color); box-shadow: var(--r-float-button-shadow-hover); transform: var(--r-float-button-transform-hover); } &:active:not(:disabled) { box-shadow: var(--r-float-button-shadow-active); transform: var(--r-float-button-transform-active); } &:focus-visible { outline: var(--r-float-button-outline); outline-offset: var(--r-float-button-outline-offset); } /* Press feedback lays one overlay over the resting fill instead of swapping it. */ &:is(:hover, :active):not(:disabled) { background-image: linear-gradient(var(--r-float-button-press), var(--r-float-button-press)); } /* Disabled is the sunken surface, not an opacity fade. */ &:disabled { pointer-events: none; opacity: var(--r-float-button-opacity-disabled); cursor: not-allowed; border-color: var(--line-muted); background-color: var(--fill-muted); background-image: none; color: var(--r-float-button-text-disabled-color); } &.r-float-button--ghost:disabled { border-color: transparent; background-color: transparent; } & svg { pointer-events: none; flex-shrink: 0; width: var(--r-float-button-icon-size); height: var(--r-float-button-icon-size); } & > .r-float-button__content { display: inline-flex; align-items: center; justify-content: center; gap: 6px; white-space: nowrap; &.r-float-button__content--with-desc { flex-direction: column; gap: 2px; } } &.r-float-button--square.r-float-button--with-desc { padding-top: 2px; padding-bottom: 2px; } & .r-float-button__text { display: inline-flex; align-items: center; line-height: 1; white-space: nowrap; } & .r-float-button__desc { font-size: var(--r-float-button-desc-font-size); text-align: center; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } /* ───────────────────────────────────────────────────────────────────────── 3. FloatButtonGroup ───────────────────────────────────────────────────────────────────────── */ .r-float-button-group { --r-float-button-group-gap: 10px; display: inline-flex; align-items: center; user-select: none; box-sizing: border-box; gap: var(--r-float-button-group-gap); &.r-float-button-group--vertical { flex-direction: column; } &.r-float-button-group--horizontal { flex-direction: row; } &.r-float-button-group--attached { --r-float-button-group-gap: 0px; gap: 0; } /* Attached: seamless borders */ &.r-float-button-group--attached.r-float-button-group--vertical > .r-float-button:not(:last-child) { border-bottom-width: 0; } &.r-float-button-group--attached.r-float-button-group--vertical > .r-float-button:not(:first-child):not(:last-child) { border-radius: 0; } &.r-float-button-group--attached.r-float-button-group--horizontal > .r-float-button:not(:last-child) { border-right-width: 0; } &.r-float-button-group--attached.r-float-button-group--horizontal > .r-float-button:not(:first-child):not(:last-child) { border-radius: 0; } /* Attached square: square corners on every button; the outer-corner rules below round the ends of a run of two or more. */ &.r-float-button-group--attached.r-float-button-group--square > .r-float-button { border-radius: 0; } /* Attached: control radius on the outer corners, whatever the shape */ &.r-float-button-group--attached.r-float-button-group--vertical > .r-float-button:first-child:not(:last-child) { border-radius: 8px 8px 0 0; } &.r-float-button-group--attached.r-float-button-group--vertical > .r-float-button:last-child:not(:first-child) { border-radius: 0 0 8px 8px; } &.r-float-button-group--attached.r-float-button-group--horizontal > .r-float-button:first-child:not(:last-child) { border-radius: 8px 0 0 8px; } &.r-float-button-group--attached.r-float-button-group--horizontal > .r-float-button:last-child:not(:first-child) { border-radius: 0 8px 8px 0; } }