CHANGED: README

This commit is contained in:
doryan04 2024-02-02 14:39:02 +04:00
parent 231bdbec3a
commit d970f5a5b3
23 changed files with 206 additions and 102 deletions

View File

@ -7,14 +7,14 @@ This repository is including and will be including components, enumerates in tab
- [x] Icon - [x] Icon
- [x] FAB - [x] FAB
- [X] Radio - [X] Radio
- [ ] Segmented - [ ] Segmented (WIP)
- [X] Checkbox - [X] Checkbox
- [x] Text fields - [x] Text fields
- [X] Switches - [X] Switches
- [ ] Chips - [ ] Chips
- [x] Icon - [x] Icon
- [x] Ripple Effect - [x] Ripple Effect
- [x] Dividers - [ ] Dividers (WIP)
- [x] Badges - [x] Badges
- [ ] Select field - [ ] Select field
- [ ] Bottom sheets - [ ] Bottom sheets

View File

@ -12,9 +12,24 @@ export default function Buttons() {
); );
return ( return (
<div className={'m3 m3-wrapper'}> <div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}
>
<h1> Buttons </h1> <h1> Buttons </h1>
<div style={{ display: 'flex', flexDirection: 'row', gap: '2em' }}> <div
style={{
display: 'flex',
flexDirection: 'row',
gap: '2em',
width: '100%',
height: '100%',
}}
>
<div> <div>
<h2> Default buttons </h2> <h2> Default buttons </h2>
<div <div
@ -30,7 +45,7 @@ export default function Buttons() {
onClick={callback} onClick={callback}
variant={'filled'} variant={'filled'}
> >
Label + {state} Label
</Button> </Button>
<Button variant={'outlined'}>Label</Button> <Button variant={'outlined'}>Label</Button>
<Button variant={'tonal'}>Label</Button> <Button variant={'tonal'}>Label</Button>

View File

@ -5,7 +5,14 @@ import { IconButton } from '../../src/primitive-components/components';
function IconButtons() { function IconButtons() {
return ( return (
<div className={'m3 m3-wrapper'}> <div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
}}
>
<h1> Icon buttons </h1> <h1> Icon buttons </h1>
<div style={{ display: 'flex', flexDirection: 'row', gap: '2em' }}> <div style={{ display: 'flex', flexDirection: 'row', gap: '2em' }}>
<div> <div>

View File

@ -9,6 +9,7 @@ import IconButtons from './components/icon-buttons';
import { TextFields } from './components/text-fields'; import { TextFields } from './components/text-fields';
import { import {
ButtonLayout, ButtonLayout,
Divider,
SegmentedButtons, SegmentedButtons,
} from '../src/primitive-components/components'; } from '../src/primitive-components/components';
@ -35,23 +36,79 @@ export default function Page() {
alignItems: 'center', alignItems: 'center',
}} }}
> >
<Buttons /> <div className={'m3 m3-wrapper'}>
<IconButtons /> <div
style={{
display: 'flex',
flexDirection: 'row',
padding: '25px',
}}
>
<SegmentedButtons>
<ButtonLayout>Segment 1</ButtonLayout>
<ButtonLayout>Segment 2</ButtonLayout>
</SegmentedButtons>
</div>
</div>
<div
className={'m3 m3-wrapper'}
style={{
display: 'flex',
flexDirection: 'row',
gap: '0.5em',
justifyContent: 'space-evenly',
alignItems: 'center',
}}
>
<div
style={{
display: 'flex',
flexDirection: 'row',
padding: '25px',
}}
>
<Buttons />
</div>
<Divider
orientation={'vertical'}
variant={'middle-inset'}
/>
<div
style={{
display: 'flex',
flexDirection: 'row',
padding: '25px',
}}
>
<IconButtons />
</div>
</div>
<div
className={'m3 m3-wrapper'}
style={{
display: 'flex',
flexDirection: 'row',
gap: '0.5em',
justifyContent: 'space-evenly',
alignItems: 'center',
}}
>
<Checkboxes />
<Divider
orientation={'vertical'}
variant={'middle-inset'}
/>
<Radios />
<Divider
orientation={'vertical'}
variant={'middle-inset'}
/>
<Badges />
</div>
<Switches /> <Switches />
<Checkboxes />
<Radios />
<TextFields /> <TextFields />
<Fabs /> <Fabs />
<Badges />
</div> </div>
<SegmentedButtons>
<ButtonLayout>
<span>Segment 1</span>
</ButtonLayout>
<ButtonLayout>
<span>Segment 1</span>
</ButtonLayout>
</SegmentedButtons>
</div> </div>
</Fragment> </Fragment>
); );

View File

@ -7,15 +7,14 @@ import useRippleEffect from '../ripple/hooks/useRippleEffect';
import React, { forwardRef, useId, useRef, useState } from 'react'; import React, { forwardRef, useId, useRef, useState } from 'react';
export const ButtonLayout = forwardRef<HTMLButtonElement, ButtonLayoutProps>( export const ButtonLayout = forwardRef<HTMLButtonElement, ButtonLayoutProps>(
({ centralRipple = false, variant, ...props }, ref) => { ({ centralRipple = false, ...props }, ref) => {
const [isActive, setIsActive] = useState<boolean>(false), const [isActive, setIsActive] = useState<boolean>(false),
ripplesRef = useRef(null), ripplesRef = useRef(null),
buttonId = useId(), buttonId = useId(),
events = useRippleEffect(ripplesRef, setIsActive); events = useRippleEffect(ripplesRef, setIsActive);
const classes = props.className const classes =
? `m3 ${props.className} ${variant}${isActive ? ' is-active' : ''}` `m3${isActive ? ' is-active' : ''} ${props.className ?? ''}`.trimEnd();
: `m3 ${variant}${isActive ? ' is-active' : ''}`;
return ( return (
<button <button
@ -38,7 +37,6 @@ export const ButtonLayout = forwardRef<HTMLButtonElement, ButtonLayoutProps>(
); );
ButtonLayout.propTypes = { ButtonLayout.propTypes = {
variant: string,
centralRipple: bool,
children: string, children: string,
centralRipple: bool,
}; };

View File

@ -2,6 +2,4 @@ import { ButtonHTMLAttributes } from 'react';
import { RipplePropsForComponents } from '../ripple/ripple.types'; import { RipplePropsForComponents } from '../ripple/ripple.types';
export type ButtonLayoutProps = RipplePropsForComponents<HTMLButtonElement> & export type ButtonLayoutProps = RipplePropsForComponents<HTMLButtonElement> &
ButtonHTMLAttributes<HTMLButtonElement> & { ButtonHTMLAttributes<HTMLButtonElement>;
variant?: string;
};

View File

@ -4,6 +4,7 @@ import { forwardRef } from 'react';
import { Icon } from '../components'; import { Icon } from '../components';
import { ButtonProps } from './button.types'; import { ButtonProps } from './button.types';
import { ButtonLayout } from '../button-layout/button-layout'; import { ButtonLayout } from '../button-layout/button-layout';
import { bool, oneOf, string } from 'prop-types';
/** /**
* Button component * Button component
@ -12,18 +13,32 @@ import { ButtonLayout } from '../button-layout/button-layout';
export const Button = forwardRef<HTMLButtonElement, ButtonProps>( export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
( (
{ centralRipple = false, variant, disabled = false, icon, ...props }, {
icon,
className = '',
disabled = false,
variant = 'filled',
centralRipple = false,
...props
},
ref, ref,
) => ( ) => (
<ButtonLayout <ButtonLayout
{...props} {...props}
centralRipple={centralRipple} centralRipple={centralRipple}
className={`${variant} ${className}`}
disabled={disabled} disabled={disabled}
ref={ref} ref={ref}
variant={variant ? variant : 'filled'}
> >
{icon ? <Icon iconSize={20}>{icon}</Icon> : <></>} {icon ? <Icon iconSize={20}>{icon}</Icon> : <></>}
<span className={'label-large'}>{props.children}</span> <span className={'label-large'}>{props.children}</span>
</ButtonLayout> </ButtonLayout>
), ),
); );
Button.propTypes = {
icon: string,
children: string,
centralRipple: bool,
variant: oneOf(['filled', 'outlined', 'elevated', 'tonal', 'text']),
};

View File

@ -2,9 +2,10 @@ import { RipplePropsForComponents } from '../ripple/ripple.types';
import { ButtonHTMLAttributes } from 'react'; import { ButtonHTMLAttributes } from 'react';
export interface ButtonMainProps { export interface ButtonMainProps {
icon?: string;
children?: string;
disabled?: boolean; disabled?: boolean;
variant?: 'filled' | 'outlined' | 'elevated' | 'tonal' | 'text'; variant?: 'filled' | 'outlined' | 'elevated' | 'tonal' | 'text';
icon?: string;
} }
export type ButtonProps = RipplePropsForComponents<HTMLButtonElement> & export type ButtonProps = RipplePropsForComponents<HTMLButtonElement> &

View File

@ -38,7 +38,6 @@ export const CheckBoxLayout = forwardRef<HTMLInputElement, CheckboxLayoutProps>(
); );
CheckBoxLayout.propTypes = { CheckBoxLayout.propTypes = {
indeterminate: bool,
typeInput: string, typeInput: string,
type: string, indeterminate: bool,
}; };

View File

@ -1,7 +1,8 @@
import { oneOf } from 'prop-types';
import React, { forwardRef } from 'react'; import React, { forwardRef } from 'react';
import { DividerProps } from './divider.types'; import { DividerProps } from './divider.types';
const Divider = forwardRef<HTMLHRElement, DividerProps>( export const Divider = forwardRef<HTMLHRElement, DividerProps>(
({ orientation, variant, ...props }, ref) => ( ({ orientation, variant, ...props }, ref) => (
<hr <hr
{...props} {...props}
@ -11,4 +12,7 @@ const Divider = forwardRef<HTMLHRElement, DividerProps>(
), ),
); );
export { Divider }; Divider.propTypes = {
orientation: oneOf(['vertical', 'horizontal']),
variant: oneOf(['full-width', 'inset', 'middle-inset']),
};

View File

@ -3,6 +3,7 @@
import { forwardRef } from 'react'; import { forwardRef } from 'react';
import { Icon } from '../components'; import { Icon } from '../components';
import { FABProps } from './fab.types'; import { FABProps } from './fab.types';
import { bool, oneOf, string } from 'prop-types';
import { ButtonLayout } from '../button-layout/button-layout'; import { ButtonLayout } from '../button-layout/button-layout';
/** /**
@ -20,12 +21,13 @@ const sizes = {
export const FAB = forwardRef<HTMLButtonElement, FABProps>( export const FAB = forwardRef<HTMLButtonElement, FABProps>(
( (
{ {
variant, icon = 'edit',
disabled, className = '',
icon,
centralRipple = false,
size = 'default', size = 'default',
elevated, elevated = false,
disabled = false,
variant = 'surface',
centralRipple = false,
...props ...props
}, },
ref, ref,
@ -33,10 +35,9 @@ export const FAB = forwardRef<HTMLButtonElement, FABProps>(
<ButtonLayout <ButtonLayout
{...props} {...props}
centralRipple={centralRipple} centralRipple={centralRipple}
className={`m3-fab m3-${size}-fab ${!(elevated ?? false) && 'without-elevation'}`} className={`m3-fab m3-${size}-fab${!elevated ? ' without-elevation' : ''} ${variant} ${className}`}
disabled={disabled} disabled={disabled}
ref={ref} ref={ref}
variant={variant ? variant : 'surface'}
> >
<Icon iconSize={sizes[size]} svgSize={sizes[size]}> <Icon iconSize={sizes[size]} svgSize={sizes[size]}>
{icon} {icon}
@ -49,3 +50,11 @@ export const FAB = forwardRef<HTMLButtonElement, FABProps>(
</ButtonLayout> </ButtonLayout>
), ),
); );
FAB.propTypes = {
icon: string,
elevated: bool,
children: string,
size: oneOf(['small', 'default', 'large', 'extended']),
variant: oneOf(['surface', 'primary', 'secondary', 'tertiary']),
};

View File

@ -3,6 +3,7 @@ import { RipplePropsForComponents } from '../ripple/ripple.types';
export interface FABMainProps { export interface FABMainProps {
icon: string; icon: string;
children?: string;
disabled?: boolean; disabled?: boolean;
elevated?: boolean; elevated?: boolean;
size?: 'small' | 'default' | 'large' | 'extended'; size?: 'small' | 'default' | 'large' | 'extended';

View File

@ -1,9 +1,10 @@
'use client'; 'use client';
import { Icon } from '../components'; import { Icon } from '../components';
import { bool, oneOf, string } from 'prop-types';
import { ButtonLayout } from '../button-layout/button-layout'; import { ButtonLayout } from '../button-layout/button-layout';
import { IconButtonProps, StateToggleIconType } from './icon-button.types';
import { forwardRef, useImperativeHandle, useRef, useState } from 'react'; import { forwardRef, useImperativeHandle, useRef, useState } from 'react';
import { IconButtonProps, StateToggleIconType } from './icon-button.types';
/** /**
* Icon button-layout component * Icon button-layout component
@ -14,11 +15,12 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
( (
{ {
icon, icon,
variant, className = '',
disabled,
selected = false,
toggled = false, toggled = false,
centralRipple, disabled = false,
selected = false,
variant = 'default',
centralRipple = false,
...props ...props
}, },
ref, ref,
@ -28,6 +30,8 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
icon: toggled ? toggled.unselected ?? 'add_circle' : 'add_circle', icon: toggled ? toggled.unselected ?? 'add_circle' : 'add_circle',
}); });
const classes = `m3-icon-button ${toggleIcon.state} ${variant} ${toggled ? 'toggled' : ''} ${className}`;
const toggle = (classes: string, icon: string) => { const toggle = (classes: string, icon: string) => {
setToggleIcon({ setToggleIcon({
state: classes, state: classes,
@ -56,11 +60,10 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
<ButtonLayout <ButtonLayout
{...props} {...props}
centralRipple={centralRipple} centralRipple={centralRipple}
className={`m3-icon-button ${toggleIcon.state} ${toggled ? 'toggled' : ''}`.trimEnd()} className={classes}
disabled={disabled} disabled={disabled}
onClick={callback} onClick={callback}
ref={buttonRef} ref={buttonRef}
variant={variant ? variant : 'default'}
> >
<Icon <Icon
fillIcon={toggleIcon.state === 'selected' ? 1 : 0} fillIcon={toggleIcon.state === 'selected' ? 1 : 0}
@ -73,3 +76,10 @@ export const IconButton = forwardRef<HTMLButtonElement, IconButtonProps>(
); );
}, },
); );
IconButton.propTypes = {
icon: string,
selected: bool,
centralRipple: bool,
variant: oneOf(['default', 'filled', 'tonal', 'outlined']),
};

View File

@ -2,7 +2,7 @@ import { IconProps } from './icon.types';
import React, { forwardRef } from 'react'; import React, { forwardRef } from 'react';
import { number, oneOf, string } from 'prop-types'; import { number, oneOf, string } from 'prop-types';
const Icon = forwardRef<SVGSVGElement, IconProps>( export const Icon = forwardRef<SVGSVGElement, IconProps>(
( (
{ {
children = '', children = '',
@ -52,5 +52,3 @@ Icon.propTypes = {
type: oneOf(['outlined', 'rounded', 'sharp']), type: oneOf(['outlined', 'rounded', 'sharp']),
weight: oneOf([100, 200, 300, 400, 500, 600, 700]), weight: oneOf([100, 200, 300, 400, 500, 600, 700]),
}; };
export { Icon };

View File

@ -1,11 +1,11 @@
'use client'; 'use client';
import { bool, string } from 'prop-types';
import { RadioProps } from './radio.types'; import { RadioProps } from './radio.types';
import { RippleArea } from '../ripple/ripple-area'; import { RippleArea } from '../ripple/ripple-area';
import { forwardRef, useRef, useState } from 'react'; import { forwardRef, useRef, useState } from 'react';
import useRippleEffect from '../ripple/hooks/useRippleEffect'; import useRippleEffect from '../ripple/hooks/useRippleEffect';
import { CheckBoxLayout } from '../checkbox-layout/check-box-layout'; import { CheckBoxLayout } from '../checkbox-layout/check-box-layout';
import { bool, string } from 'prop-types';
/** /**
* Radio component * Radio component

View File

@ -1,8 +1,8 @@
'use client'; 'use client';
import isEmpty from './utils/utils'; import isEmpty from './utils/utils';
import { RippleProps, RipplesProps } from './ripple.types';
import { rippleAreaContext } from './ripple-area'; import { rippleAreaContext } from './ripple-area';
import { RippleProps, RipplesProps } from './ripple.types';
import RippleEffectBuild from './utils/ripple-effect-builder'; import RippleEffectBuild from './utils/ripple-effect-builder';
import React, { import React, {
ReactElement, ReactElement,
@ -18,7 +18,7 @@ const Ripples = (props: RipplesProps) => {
const firstRender = useRef<boolean>(true); const firstRender = useRef<boolean>(true);
const [pending, startTransition] = useTransition(); const [pending, startTransition] = useTransition();
const LifetimeEnd = (child: ReactElement) => { const endLifetime = (child: ReactElement) => {
if (child.props.endLifetime) { if (child.props.endLifetime) {
child.props.endLifetime(); child.props.endLifetime();
} }
@ -34,11 +34,11 @@ const Ripples = (props: RipplesProps) => {
if (props.children.length > 0 && !pending) { if (props.children.length > 0 && !pending) {
startTransition(() => { startTransition(() => {
if (firstRender.current || isEmpty(ripples)) { if (firstRender.current || isEmpty(ripples)) {
setRipples(RippleEffectBuild(props.children, LifetimeEnd)); setRipples(RippleEffectBuild(props.children, endLifetime));
firstRender.current = false; firstRender.current = false;
} else { } else {
setRipples( setRipples(
RippleEffectBuild(props.children, LifetimeEnd, ripples), RippleEffectBuild(props.children, endLifetime, ripples),
); );
} }
}); });

View File

@ -6,8 +6,7 @@ export const SegmentedButtons = forwardRef<
SegmentedButtonProps SegmentedButtonProps
>(({ children, ...props }, ref) => { >(({ children, ...props }, ref) => {
if (children.length <= 1) { if (children.length <= 1) {
console.error('You must build segmented button with 2 or more buttton'); throw 'You must build segmented button with 2 or more buttton';
return <></>;
} }
return ( return (

View File

@ -1,5 +1,6 @@
'use client'; 'use client';
import { bool } from 'prop-types';
import React, { forwardRef } from 'react'; import React, { forwardRef } from 'react';
import { SwitchMainProps } from './switch.types'; import { SwitchMainProps } from './switch.types';
import { CheckBoxLayout } from '../checkbox-layout/check-box-layout'; import { CheckBoxLayout } from '../checkbox-layout/check-box-layout';
@ -34,3 +35,8 @@ export const Switch = forwardRef<
</svg> </svg>
</div> </div>
)); ));
Switch.propTypes = {
icon: bool,
selected: bool,
};

View File

@ -92,8 +92,6 @@ export const TextField = forwardRef<HTMLInputElement, TextFieldInterface>(
TextField.propTypes = { TextField.propTypes = {
children: string, children: string,
className: string,
placeholder: string,
withAfterIcon: bool, withAfterIcon: bool,
withBeforeIcon: bool, withBeforeIcon: bool,
supportingText: string, supportingText: string,

View File

@ -1,26 +1,26 @@
hr.m3.m3-divider hr.m3.m3-divider
display: flex
align-items: end
box-sizing: border-box
border: none border: none
outline: 0.5px solid var(--md-sys-color-outline-variant) outline: 0.5px solid var(--md-sys-color-outline-variant)
margin: 4px margin-inline: 4px
position: relative
&.vertical &.vertical
writing-mode: tb-rl height: 100%
&, &.full-width
height: 100%
&.inset &.inset
align-self: end margin-top: 16px
height: calc(100% - 16px)
&.middle-inset &.middle-inset
height: calc(100% - (2 * 16px)) margin-bottom: 16px
margin-top: 16px
&.horizontal &.horizontal
&, &.full-width width: 100%
width: 100%
&.inset &.inset
align-self: end margin-left: 16px
width: calc(100% - 16px)
&.middle-inset &.middle-inset
width: calc(100% - (2 * 16px)) margin-left: 16px
margin-right: 16px

View File

@ -694,35 +694,30 @@ div.m3.m3-switch > input.m3:checked:disabled + svg > rect.m3.m3-switch-track {
} }
hr.m3.m3-divider { hr.m3.m3-divider {
display: flex;
align-items: end;
box-sizing: border-box;
border: none; border: none;
outline: 0.5px solid var(--md-sys-color-outline-variant); outline: 0.5px solid var(--md-sys-color-outline-variant);
margin: 4px; margin-inline: 4px;
position: relative;
} }
hr.m3.m3-divider.vertical { hr.m3.m3-divider.vertical {
writing-mode: tb-rl;
}
hr.m3.m3-divider.vertical, hr.m3.m3-divider.vertical.full-width {
height: 100%; height: 100%;
} }
hr.m3.m3-divider.vertical.inset { hr.m3.m3-divider.vertical.inset {
align-self: end; margin-top: 16px;
height: calc(100% - 16px);
} }
hr.m3.m3-divider.vertical.middle-inset { hr.m3.m3-divider.vertical.middle-inset {
height: calc(100% - 32px); margin-bottom: 16px;
margin-top: 16px;
} }
hr.m3.m3-divider.horizontal, hr.m3.m3-divider.horizontal.full-width { hr.m3.m3-divider.horizontal {
width: 100%; width: 100%;
} }
hr.m3.m3-divider.horizontal.inset { hr.m3.m3-divider.horizontal.inset {
align-self: end; margin-left: 16px;
width: calc(100% - 16px);
} }
hr.m3.m3-divider.horizontal.middle-inset { hr.m3.m3-divider.horizontal.middle-inset {
width: calc(100% - 32px); margin-left: 16px;
margin-right: 16px;
} }
label.m3.m3-checkbox-label { label.m3.m3-checkbox-label {
@ -1197,13 +1192,10 @@ html {
.m3.m3-wrapper { .m3.m3-wrapper {
width: 100%; width: 100%;
position: relative;
display: block;
background-color: var(--md-sys-color-surface); background-color: var(--md-sys-color-surface);
border-radius: 25px; border-radius: 25px;
padding: 25px;
display: flex;
align-items: center;
flex-direction: column;
height: min-content;
} }
/*# sourceMappingURL=generics.css.map */ /*# sourceMappingURL=generics.css.map */

File diff suppressed because one or more lines are too long

View File

@ -26,11 +26,8 @@ html
.m3.m3-wrapper .m3.m3-wrapper
width: 100% width: 100%
position: relative
display: block
background-color: var(--md-sys-color-surface) background-color: var(--md-sys-color-surface)
border-radius: 25px border-radius: 25px
padding: 25px
display: flex
align-items: center
flex-direction: column
height: min-content