ADDED: Card sub-components

TODO: Complete styles for card sub-components and section button
This commit is contained in:
2024-02-03 23:52:25 +04:00
committed by doryan
parent a942d22151
commit 9ee845fbba
22 changed files with 1239 additions and 873 deletions

View File

@@ -13,14 +13,14 @@ export const ButtonLayout = forwardRef<HTMLButtonElement, ButtonLayoutProps>(
buttonId = useId(),
events = useRippleEffect(ripplesRef, setIsActive);
const classes =
const extraClassStyles =
`m3${isActive ? ' is-active' : ''} ${props.className ?? ''}`.trimEnd();
return (
<button
{...props}
{...events}
className={classes}
className={extraClassStyles}
disabled={props.disabled}
id={buttonId}
ref={ref}

View File

@@ -30,11 +30,11 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
icon: toggled ? toggled.unselected ?? 'add_circle' : 'add_circle',
});
const classes = `m3-icon-button ${toggleIcon.state} ${variant} ${toggled ? 'toggled' : ''} ${className}`;
const extraClassStyles = `m3-icon-button ${toggleIcon.state} ${variant} ${toggled ? 'toggled' : ''} ${className}`;
const toggle = (classes: string, icon: string) => {
const toggle = (extraClassStyles: string, icon: string) => {
setToggleIcon({
state: classes,
state: extraClassStyles,
icon: icon,
});
};
@@ -60,7 +60,7 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
<ButtonLayout
{...props}
centralRipple={centralRipple}
className={classes}
className={extraClassStyles}
disabled={disabled}
onClick={callback}
ref={buttonRef}

View File

@@ -14,14 +14,14 @@ export const CardActionArea = forwardRef<HTMLDivElement, CardActionAreaProps>(
setIsActive,
ripples,
);
const classes =
const extraClassStyles =
`m3 m3-card-action-area${isActive ? ' is-active' : ''} ${props.className ?? ''}`.trimEnd();
return (
<div
{...props}
{...CardActionAreaEvents}
className={classes}
className={extraClassStyles}
ref={ref}
>
<div className={'m3 m3-card-action-area-content'}>

View File

@@ -1,7 +0,0 @@
import React from 'react';
export function CardActions(props) {
return (
<div></div>
);
}

View File

@@ -0,0 +1,14 @@
import React, { forwardRef, HTMLAttributes } from 'react';
export const CardBody = forwardRef<HTMLElement, HTMLAttributes<HTMLElement>>(
(props, ref) => {
const extraClassStyles =
`m3 m3-card-body ${props.className ?? ''}`.trimEnd();
return (
<section {...props} className={extraClassStyles} ref={ref}>
{props.children}
</section>
);
},
);

View File

@@ -1,7 +0,0 @@
import React from 'react';
export function CardContent(props) {
return (
<div></div>
);
}

View File

@@ -0,0 +1,15 @@
import React, { forwardRef, HTMLAttributes } from 'react';
export const CardFooter = forwardRef<
HTMLDivElement,
HTMLAttributes<HTMLDivElement>
>((props, ref) => {
const extraClassStyles =
`m3 m3-card-footer ${props.className ?? ''}`.trimEnd();
return (
<div {...props} className={extraClassStyles} ref={ref}>
{props.children}
</div>
);
});

View File

@@ -1,7 +1,15 @@
import React from 'react';
import React, { forwardRef, HTMLAttributes } from 'react';
export const CardHeader = forwardRef<
HTMLHeadElement,
HTMLAttributes<HTMLHeadElement>
>((props, ref) => {
const extraClassStyles =
`m3 m3-card-header ${props.className ?? ''}`.trimEnd();
export function CardHeader(props) {
return (
<div></div>
<header {...props} className={extraClassStyles} ref={ref}>
{props.children}
</header>
);
}
});

View File

@@ -1,33 +1,19 @@
import Image from 'next/image';
import React, { forwardRef } from 'react';
import { createElement, forwardRef } from 'react';
import { CardMediaProps, CardMediaType } from './card.types';
export const CardMedia = forwardRef<CardMediaType, CardMediaProps>(
(
{
alt,
src,
type,
quality = 80,
rounded = true,
preview = true,
className = '',
...props
},
ref,
) => {
const classes =
`m3 m3-card-media${rounded ? ' m3-rounded' : ''}${preview ? ' m3-preview' : ''} ${className}`.trimEnd();
({ type, rounded = true, className = '', ...props }, ref) => {
const extraClassStyles =
`m3 m3-card-media${rounded ? ' m3-rounded' : ''} ${className}`.trimEnd();
switch (type) {
case 'img':
return <Image alt={alt} quality={quality} src={src} />;
default:
return React.createElement(type, {
...props,
className: classes,
ref: ref,
});
}
return createElement(
type,
{
...props,
className: extraClassStyles,
ref: ref,
},
props.children,
);
},
);

View File

@@ -4,12 +4,12 @@ import { Container } from '../container/container';
export const Card = forwardRef<HTMLDivElement, CardProps>(
({ variant = 'filled', ...props }, ref) => {
const classes = `m3-card m3-card-${variant} ${props.className ?? ''}`;
const extraClassStyles = `m3-card m3-card-${variant} ${props.className ?? ''}`;
return (
<Container
{...props}
className={classes}
className={extraClassStyles}
ref={ref}
variant={variant}
>

View File

@@ -1,26 +1,22 @@
import { HTMLAttributes } from 'react';
import { HTMLProps } from 'react';
import { ContainerProps } from '../container/container.types';
import { RipplePropsForComponents } from '../ripple/ripple.types';
export interface CardProps extends ContainerProps {}
export interface CardActionAreaProps
extends RipplePropsForComponents<HTMLDivElement> {
ripples?: boolean;
}
export interface CardProps extends ContainerProps {}
export interface CardMediaProps extends HTMLAttributes<CardMediaType> {
alt: string;
src: string;
quality?: number;
export interface CardMediaProps extends HTMLProps<CardMediaType> {
rounded?: boolean;
preview?: boolean;
type: 'img' | 'video' | 'picture' | 'iframe' | 'audio';
}
export type CardMediaType = HTMLImageElement &
HTMLVideoElement &
HTMLPictureElement &
HTMLMediaElement &
HTMLIFrameElement &
HTMLAudioElement;
export type CardMediaType =
| HTMLImageElement
| HTMLVideoElement
| HTMLPictureElement
| HTMLIFrameElement
| HTMLAudioElement;

View File

@@ -3,11 +3,11 @@ import { ContainerProps } from './container.types';
export const Container = forwardRef<HTMLDivElement, ContainerProps>(
({ variant = 'filled', ...props }, ref) => {
const classes =
const extraClassStyles =
`m3 m3-container m3-container-${variant} ${props.className ?? ''}`.trimEnd();
return (
<div {...props} className={classes} ref={ref}>
<div {...props} className={extraClassStyles} ref={ref}>
{props.children}
</div>
);

View File

@@ -21,7 +21,7 @@ export const CheckBoxLayout = forwardRef<HTMLInputElement, CheckboxLayoutProps>(
const classesType = typeInput || type;
const classes =
const extraClassStyles =
props.className !== undefined
? `m3 m3-${type} ${props.className}`
: `m3 m3-${classesType}`;
@@ -30,7 +30,7 @@ export const CheckBoxLayout = forwardRef<HTMLInputElement, CheckboxLayoutProps>(
<input
ref={checkboxRef}
{...props}
className={classes.trimEnd()}
className={extraClassStyles.trimEnd()}
type={type}
/>
);

View File

@@ -26,7 +26,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
checkboxRef = useRef(null),
events = useRippleEffect(ripplesRef, setIsActive);
const classes =
const extraClassStyles =
`m3 m3-checkbox-label ${isActive === true ? 'visible' : ''}`.trimEnd();
useImperativeHandle(ref, () => checkboxRef.current);
@@ -36,7 +36,7 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
}, [checkboxRef.current?.checked]);
return (
<label {...events} className={classes}>
<label {...events} className={extraClassStyles}>
<CheckBoxLayout
{...props}
indeterminate={props.indeterminate}

View File

@@ -18,11 +18,11 @@ export const Radio = forwardRef<HTMLInputElement, RadioProps>(
ripplesRef = useRef(null),
events = useRippleEffect(ripplesRef, setIsActive);
const classes =
const extraClassStyles =
`m3 m3-radio ${isActive === true ? 'visible' : ''}`.trimEnd();
return (
<div {...events} className={classes}>
<div {...events} className={extraClassStyles}>
<CheckBoxLayout {...props} ref={ref} type={'radio'} />
<span className={'m3 m3-radio-state-layer'} />
<svg height={'20px'} viewBox={'0 0 20 20'} width={'20px'}>

View File

@@ -24,7 +24,7 @@ const RippleArea = forwardRef(
uniqueKey = useRef<number>(0),
uniqueId = useId();
const classes = props.className
const extraClassStyles = props.className
? `m3 m3-ripple-domain ${props.className}`.trimEnd()
: 'm3 m3-ripple-domain';
@@ -121,7 +121,7 @@ const RippleArea = forwardRef(
);
return (
<span className={classes} id={uniqueId} ref={rippleDomain}>
<span className={extraClassStyles} id={uniqueId} ref={rippleDomain}>
<rippleAreaContext.Provider value={clicked.current}>
<Ripples>{ripples}</Ripples>
</rippleAreaContext.Provider>

View File

@@ -1,8 +1,28 @@
@import 'mixins/m3-mixins'
div.m3.m3-card-action-area
$padding: 16px
.m3:not(:first-child):is(.m3-card)
padding: $padding
:is(div.m3-card-footer, header.m3-card-header, section.m3-card-body).m3
padding: $padding
display: block
box-sizing: border-box
.m3.m3-card-media
&.m3-rounded
border-radius: 12px
width: 100%
height: 100%
display: block
contain: content
position: relative
box-sizing: border-box
div.m3.m3-card-action-area
display: block
cursor: pointer
contain: content
position: relative
@@ -10,9 +30,12 @@ div.m3.m3-card-action-area
transition: box-shadow .2s cubic-bezier(0.2, 0, 0, 1)
& > div.m3.m3-card-action-area-content
position: absolute
top: 0
width: 100%
position: relative
& > span.m3.m3-card-state-layer
& > span.m3:is(.m3-card-state-layer, .m3-ripple-domain)
top: 0
width: 100%
height: 100%
position: absolute

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long