ADDED: Mozilla styles for slider
FIXED: Some typography issues and a ripple effect bug that appears in Firefox And some changes, about which I forget
This commit is contained in:
commit
cb04ae521a
11
README.md
11
README.md
|
@ -9,24 +9,25 @@ This repository is including and will be including components, enumerates in tab
|
|||
- [x] Icon
|
||||
- [x] FAB
|
||||
- [X] Radio
|
||||
- [ ] Segmented (WIP)
|
||||
- [X] Segmented
|
||||
- [X] Checkbox
|
||||
- [x] Text fields
|
||||
- [X] Switches
|
||||
- [ ] Chips
|
||||
- [x] Icon
|
||||
- [x] Ripple Effect
|
||||
- [X] Dividers
|
||||
- [x] Badges
|
||||
- [ ] Select field
|
||||
- [ ] Bottom sheets
|
||||
- [X] Cards
|
||||
- [X] Typography
|
||||
- [ ] Chips
|
||||
- [ ] Select field (WIP)
|
||||
- [ ] Bottom sheets
|
||||
- [ ] Menus
|
||||
- [ ] Navigation
|
||||
- [ ] Bars
|
||||
- [ ] Drawer
|
||||
- [ ] Rail
|
||||
- [ ] Sliders
|
||||
- [ ] Sliders (WIP)
|
||||
- [ ] Snackbar
|
||||
- [ ] Tabs
|
||||
- [ ] Bottom sheets
|
||||
|
|
41
app/page.tsx
41
app/page.tsx
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import testImage1 from './test-images/test-image-1.jpg';
|
||||
import { Card } from '../src/primitive-components/card/card';
|
||||
import {Checkbox, Radio} from '../src/primitive-components/components';
|
||||
import { Checkbox, IconButton } from '../src/primitive-components/components';
|
||||
import { CardBody } from '../src/primitive-components/card/card-body';
|
||||
import { CardMedia } from '../src/primitive-components/card/card-media';
|
||||
import { CardFooter } from '../src/primitive-components/card/card-footer';
|
||||
|
@ -9,7 +9,6 @@ import { CardHeader } from '../src/primitive-components/card/card-header';
|
|||
import { Typography } from '../src/primitive-components/typography/typography';
|
||||
import { CardActionArea } from '../src/primitive-components/card/card-action-area';
|
||||
import { Slider } from '../src/primitive-components/input-components/slider/slider';
|
||||
import { Button } from '../src/primitive-components/button-components/button/button';
|
||||
import { SegmentButton } from '../src/primitive-components/button-components/segmented-buttons/segment-button';
|
||||
import { SegmentedButtons } from '../src/primitive-components/button-components/segmented-buttons/segmented-buttons';
|
||||
|
||||
|
@ -25,15 +24,22 @@ export default function Page() {
|
|||
padding: '8px',
|
||||
}}
|
||||
>
|
||||
<div style={{ display: 'flex', gap: '8px', maxWidth: '1024px' }}>
|
||||
<div
|
||||
style={{ display: 'flex', gap: '8px', maxWidth: '1024px' }}
|
||||
>
|
||||
<Card variant={'outlined'}>
|
||||
<CardHeader>
|
||||
<Typography.h3> Header-3 </Typography.h3>
|
||||
<Typography role={'headline'} size={'large'}>
|
||||
Welcome to Material You for Next.js!
|
||||
</Typography>
|
||||
<Typography role={'body'} size={'large'}>
|
||||
{"It's UI kit for fast frontend development!"}
|
||||
</Typography>
|
||||
</CardHeader>
|
||||
<CardActionArea>
|
||||
<CardMedia src={testImage1.src} type={'img'} />
|
||||
<CardBody>
|
||||
<p>
|
||||
<Typography role={'body'} size={'large'}>
|
||||
Lorem ipsum dolor sit amet, consecrate
|
||||
adipiscing elit, sed do eiusmod tempor
|
||||
incididunt ut labore et dolore magna aliqua.
|
||||
|
@ -45,16 +51,20 @@ export default function Page() {
|
|||
Excepteur sint occaecat cupidatat non
|
||||
proident, sunt in culpa qui officia deserunt
|
||||
mollit anim id est laborum.
|
||||
</p>
|
||||
</Typography>
|
||||
</CardBody>
|
||||
</CardActionArea>
|
||||
<CardFooter>
|
||||
<div className={'flex flex-row gap-3'}>
|
||||
<Button icon={'add'}>Label 1</Button>
|
||||
<Button icon={'add'} iconPlace={'right'}>
|
||||
Label 2
|
||||
</Button>
|
||||
<SegmentedButtons>
|
||||
<IconButton
|
||||
icon={'add'}
|
||||
toggled={{
|
||||
selected: 'settings',
|
||||
unselected: 'add',
|
||||
}}
|
||||
variant={'filled'}
|
||||
/>
|
||||
<SegmentedButtons toggled={true}>
|
||||
<SegmentButton
|
||||
fillIcon={1}
|
||||
icon={'change_history'}
|
||||
|
@ -73,8 +83,13 @@ export default function Page() {
|
|||
</SegmentButton>
|
||||
</SegmentedButtons>
|
||||
<Checkbox />
|
||||
<Radio />
|
||||
<Slider />
|
||||
<Slider
|
||||
defaultValue={0}
|
||||
max={100}
|
||||
min={0}
|
||||
options={[0, 10, 20, 100]}
|
||||
/>
|
||||
<Slider defaultValue={0} max={100} min={0} />
|
||||
</div>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
|
|
@ -5,6 +5,7 @@ import { ButtonProps } from './button.types';
|
|||
import { bool, oneOf, string } from 'prop-types';
|
||||
import { ButtonLayout } from '../button-layout/button-layout';
|
||||
import { IconWrapper } from '../../icon/icon-wrapper';
|
||||
import { Typography } from '../../typography/typography';
|
||||
|
||||
/**
|
||||
* Button component
|
||||
|
@ -32,7 +33,13 @@ export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
|
|||
ref={ref}
|
||||
>
|
||||
<IconWrapper icon={icon} iconPlace={iconPlace}>
|
||||
<span className={'label-large'}>{props.children}</span>
|
||||
<Typography
|
||||
className={'label-large'}
|
||||
role={'label'}
|
||||
size={'large'}
|
||||
>
|
||||
{props.children}
|
||||
</Typography>
|
||||
</IconWrapper>
|
||||
</ButtonLayout>
|
||||
),
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import { forwardRef } from 'react';
|
||||
import { Icon } from '../../components';
|
||||
import { FABProps } from './fab.types';
|
||||
import { Icon } from '../../components';
|
||||
import React, { forwardRef } from 'react';
|
||||
import { bool, oneOf, string } from 'prop-types';
|
||||
import { Typography } from '../../typography/typography';
|
||||
import { ButtonLayout } from '../button-layout/button-layout';
|
||||
|
||||
/**
|
||||
|
@ -21,6 +22,7 @@ const sizes = {
|
|||
export const FAB = forwardRef<HTMLButtonElement, FABProps>(
|
||||
(
|
||||
{
|
||||
children,
|
||||
icon = 'edit',
|
||||
className = '',
|
||||
size = 'default',
|
||||
|
@ -43,7 +45,13 @@ export const FAB = forwardRef<HTMLButtonElement, FABProps>(
|
|||
{icon}
|
||||
</Icon>
|
||||
{size === 'extended' ? (
|
||||
<span className={'label-large'}>{props.children}</span>
|
||||
<Typography
|
||||
className={'label-large'}
|
||||
role={'label'}
|
||||
size={'large'}
|
||||
>
|
||||
{children}
|
||||
</Typography>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
import { string } from 'prop-types';
|
||||
import React, { forwardRef, useState } from 'react';
|
||||
import { IconWrapper } from '../../icon/icon-wrapper';
|
||||
import { Typography } from '../../typography/typography';
|
||||
import { SegmentedButton } from './segmented-buttons.types';
|
||||
import { ButtonLayout } from '../button-layout/button-layout';
|
||||
import { ButtonLayoutProps } from '../button-layout/button-layout.types';
|
||||
|
||||
export const SegmentButton = forwardRef<
|
||||
HTMLButtonElement,
|
||||
ButtonLayoutProps & SegmentedButton
|
||||
|
@ -19,6 +17,7 @@ export const SegmentButton = forwardRef<
|
|||
weight,
|
||||
svgSize,
|
||||
fillIcon,
|
||||
children,
|
||||
iconSize,
|
||||
opticalSize,
|
||||
toggled = false,
|
||||
|
@ -58,13 +57,22 @@ export const SegmentButton = forwardRef<
|
|||
type={type}
|
||||
weight={weight}
|
||||
>
|
||||
<span className={'label-large'}>{props.children}</span>
|
||||
<Typography
|
||||
className={'label-large'}
|
||||
role={'label'}
|
||||
size={'large'}
|
||||
>
|
||||
{children}
|
||||
</Typography>
|
||||
</IconWrapper>
|
||||
<span className={'m3 m3-button-segment-state-layer'} />
|
||||
</ButtonLayout>
|
||||
);
|
||||
},
|
||||
);
|
||||
import { ButtonLayout } from '../button-layout/button-layout';
|
||||
|
||||
import { ButtonLayoutProps } from '../button-layout/button-layout.types';
|
||||
|
||||
SegmentButton.propTypes = {
|
||||
children: string,
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { HTMLAttributes, ReactElement } from 'react';
|
||||
import { IconProps, IconWrapperProps } from '../../icon/icon.types';
|
||||
import { IconWrapperProps } from '../../icon/icon.types';
|
||||
|
||||
export type SegmentedButton = IconWrapperProps & {
|
||||
icon?: string;
|
||||
toggled?: boolean;
|
||||
centralRipple?: boolean;
|
||||
children?: string | ReactElement<IconProps>;
|
||||
};
|
||||
|
||||
export interface SegmentedButtons {
|
||||
|
|
|
@ -20,7 +20,4 @@ export type IconWrapperProps = IconPlacement &
|
|||
icon?: string;
|
||||
};
|
||||
|
||||
export type IconProps = SVGProps<SVGSVGElement> &
|
||||
GeneralIconProps & {
|
||||
children?: string | undefined;
|
||||
};
|
||||
export type IconProps = SVGProps<SVGSVGElement> & GeneralIconProps;
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
import { bool } from 'prop-types';
|
||||
import { CheckboxProps } from './checkbox.types';
|
||||
import { RippleEffect } from '../../ripple/ripple-effect';
|
||||
import useRippleEffect from '../../ripple/hooks/useRippleEffect';
|
||||
import { InputLayout } from '../input-layout/input-layout';
|
||||
import useRippleEffect from '../../ripple/hooks/useRippleEffect';
|
||||
import {
|
||||
forwardRef,
|
||||
useEffect,
|
||||
|
@ -51,7 +51,6 @@ export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
|
|||
className={'m3-checkbox-ripple-layer'}
|
||||
ref={ripplesRef}
|
||||
/>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -6,7 +6,3 @@ export interface InputLayoutProps
|
|||
typeInput?: string;
|
||||
type?: string;
|
||||
}
|
||||
|
||||
export interface LabelPlacement {
|
||||
labelPlacement?: 'left' | 'right';
|
||||
}
|
||||
|
|
|
@ -1,18 +1,60 @@
|
|||
import React, { forwardRef, HTMLAttributes } from 'react';
|
||||
import { InputLayout } from '../input-layout/input-layout';
|
||||
'use client';
|
||||
|
||||
export const Slider = forwardRef<
|
||||
HTMLInputElement,
|
||||
HTMLAttributes<HTMLInputElement>
|
||||
>((props, ref) => {
|
||||
return (
|
||||
<div className={'m3 m3-slider-container'}>
|
||||
<InputLayout
|
||||
className={props.className}
|
||||
ref={ref}
|
||||
type={'range'}
|
||||
typeInput={'slider'}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
import { InputLayout } from '../input-layout/input-layout';
|
||||
import React, {
|
||||
ChangeEvent,
|
||||
forwardRef,
|
||||
InputHTMLAttributes,
|
||||
useId,
|
||||
useLayoutEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
interface SliderProps extends InputHTMLAttributes<HTMLInputElement> {
|
||||
options?: number[];
|
||||
}
|
||||
|
||||
export const Slider = forwardRef<HTMLInputElement, SliderProps>(
|
||||
({ options, ...props }, ref) => {
|
||||
const sliderId = useId();
|
||||
const [isChrome, setIsChrome] = useState<boolean>(false);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
setIsChrome(navigator.userAgent.indexOf('AppleWebKit') != -1);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={'m3 m3-slider-container'}>
|
||||
<InputLayout
|
||||
{...props}
|
||||
className={props.className}
|
||||
list={sliderId}
|
||||
onChange={(event: ChangeEvent<HTMLInputElement>) => {
|
||||
props.onChange?.apply(this, props?.onChange?.prototype);
|
||||
|
||||
if (isChrome) {
|
||||
const fraction =
|
||||
(parseInt(event.target.value) /
|
||||
parseInt(event.target.max)) *
|
||||
100;
|
||||
event.target.style.background = `linear-gradient(\
|
||||
to right, var(--md-sys-color-primary) ${fraction}%, \
|
||||
var(--md-sys-color-surface-container-highest) ${fraction}%\
|
||||
)`;
|
||||
}
|
||||
}}
|
||||
ref={ref}
|
||||
type={'range'}
|
||||
typeInput={'slider'}
|
||||
/>
|
||||
{options && (
|
||||
<datalist id={sliderId}>
|
||||
{options.map((option, index) => (
|
||||
<option key={index} value={option} />
|
||||
))}
|
||||
</datalist>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -4,37 +4,41 @@ import { bool } from 'prop-types';
|
|||
import React, { forwardRef } from 'react';
|
||||
import { SwitchMainProps } from './switch.types';
|
||||
import { InputLayout } from '../input-layout/input-layout';
|
||||
import { LabelPlacement } from '../input-layout/input-layout.types';
|
||||
|
||||
/**
|
||||
* Switch component
|
||||
** description
|
||||
*/
|
||||
|
||||
export const Switch = forwardRef<
|
||||
HTMLInputElement,
|
||||
SwitchMainProps & LabelPlacement
|
||||
>(({ icon, selected = false, ...props }, ref) => (
|
||||
<div className={'m3 m3-switch'}>
|
||||
<InputLayout
|
||||
{...props}
|
||||
className={`m3 ${props.className ?? ''}`.trimEnd()}
|
||||
ref={ref}
|
||||
type={'checkbox'}
|
||||
/>
|
||||
<svg>
|
||||
<rect className={'m3 m3-switch-track'} />
|
||||
<circle className={'m3 m3-switch-handler'} />
|
||||
<circle className={'m3 m3-switch-handler-state-layer'} />
|
||||
<g>
|
||||
{icon && !selected && (
|
||||
<text className={'m3 m3-icon-unchecked'}>close</text>
|
||||
)}
|
||||
{icon && <text className={'m3 m3-icon-checked'}>check</text>}
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
));
|
||||
export const Switch = forwardRef<HTMLInputElement, SwitchMainProps>(
|
||||
({ icon, selected = false, ...props }, ref) => (
|
||||
<>
|
||||
<div className={'m3 m3-switch'}>
|
||||
<InputLayout
|
||||
{...props}
|
||||
className={`m3 ${props.className ?? ''}`.trimEnd()}
|
||||
ref={ref}
|
||||
type={'checkbox'}
|
||||
/>
|
||||
<svg>
|
||||
<rect className={'m3 m3-switch-track'} />
|
||||
<circle className={'m3 m3-switch-handler'} />
|
||||
<circle className={'m3 m3-switch-handler-state-layer'} />
|
||||
<g>
|
||||
{icon && !selected && (
|
||||
<text className={'m3 m3-icon-unchecked'}>
|
||||
close
|
||||
</text>
|
||||
)}
|
||||
{icon && (
|
||||
<text className={'m3 m3-icon-checked'}>check</text>
|
||||
)}
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
);
|
||||
|
||||
Switch.propTypes = {
|
||||
icon: bool,
|
||||
|
|
|
@ -1,76 +1,25 @@
|
|||
import { forwardRef, HTMLAttributes } from 'react';
|
||||
import { createElement, forwardRef } from 'react';
|
||||
import { getTypographyRole } from './utils/get-typography-role';
|
||||
import {
|
||||
TypographyProps,
|
||||
Typography as TypographyTargetRef,
|
||||
} from './typography.types';
|
||||
|
||||
export const Typography = {
|
||||
h1: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h1
|
||||
className={`m3 m3-typography display-hero ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h1>
|
||||
);
|
||||
},
|
||||
),
|
||||
h2: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h2
|
||||
className={`m3 m3-typography display-large ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h2>
|
||||
);
|
||||
},
|
||||
),
|
||||
h3: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h3
|
||||
className={`m3 m3-typography headline-medium ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h3>
|
||||
);
|
||||
},
|
||||
),
|
||||
h4: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h4
|
||||
className={`m3 m3-typography headline-small ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h4>
|
||||
);
|
||||
},
|
||||
),
|
||||
h5: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h5
|
||||
className={`m3 m3-typography title-medium ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h5>
|
||||
);
|
||||
},
|
||||
),
|
||||
h6: forwardRef<HTMLHeadingElement, HTMLAttributes<HTMLHeadingElement>>(
|
||||
(props, ref) => {
|
||||
return (
|
||||
<h6
|
||||
className={`m3 m3-typography title-small ${props.className}`}
|
||||
ref={ref}
|
||||
>
|
||||
{props.children}
|
||||
</h6>
|
||||
);
|
||||
},
|
||||
),
|
||||
};
|
||||
export const Typography = forwardRef<TypographyTargetRef, TypographyProps>(
|
||||
({ size, role, children, ...props }, ref) => {
|
||||
const typeElement = getTypographyRole(role, size);
|
||||
|
||||
const extraClasses =
|
||||
`m3 m3-typography ${size && role ? `${role}-${size}` : ''}`.trimEnd();
|
||||
|
||||
return createElement(
|
||||
typeElement,
|
||||
{
|
||||
...props,
|
||||
ref: ref,
|
||||
className: extraClasses,
|
||||
},
|
||||
children,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
import { HTMLAttributes } from 'react';
|
||||
|
||||
export type Typography =
|
||||
| HTMLLabelElement
|
||||
| HTMLHeadingElement
|
||||
| HTMLSpanElement
|
||||
| HTMLParagraphElement;
|
||||
|
||||
export type TypographySize = 'hero' | 'xl' | 'small' | 'medium' | 'large';
|
||||
|
||||
export type TypographyRole =
|
||||
| 'display'
|
||||
| 'headline'
|
||||
| 'title'
|
||||
| 'body'
|
||||
| 'label';
|
||||
|
||||
export interface TypographyProps extends HTMLAttributes<Typography> {
|
||||
size: TypographySize;
|
||||
role: TypographyRole;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { TypographyRole, TypographySize } from '../typography.types';
|
||||
|
||||
export function getTypographyRole(role: TypographyRole, size: TypographySize) {
|
||||
switch (role) {
|
||||
case 'display':
|
||||
return 'h1';
|
||||
case 'headline':
|
||||
switch (size) {
|
||||
case 'large' || 'hero' || 'xl':
|
||||
return 'h2';
|
||||
case 'medium':
|
||||
return 'h3';
|
||||
case 'small':
|
||||
return 'h4';
|
||||
}
|
||||
break;
|
||||
case 'title':
|
||||
switch (size) {
|
||||
case 'large' || 'hero' || 'xl':
|
||||
return 'h4';
|
||||
case 'medium':
|
||||
return 'h5';
|
||||
case 'small':
|
||||
return 'h6';
|
||||
}
|
||||
break;
|
||||
case 'body':
|
||||
return 'p';
|
||||
case 'label':
|
||||
return 'label';
|
||||
}
|
||||
}
|
|
@ -30,6 +30,9 @@ div.m3.m3-segmented-buttons
|
|||
& > svg > text
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
|
||||
& > span.m3.m3-ripple-domain > span.m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 12%, transparent)
|
||||
|
||||
&:disabled
|
||||
border: 1px solid color-mix(in srgb, var(--md-sys-color-outline) 12%, transparent)
|
||||
|
||||
|
@ -61,6 +64,3 @@ div.m3.m3-segmented-buttons
|
|||
& > span.m3.m3-button-segment-state-layer
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 12%, transparent)
|
||||
|
||||
&:active
|
||||
& > span.m3.m3-ripple-domain > span.m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-secondary-container) 12%, transparent)
|
||||
|
|
|
@ -12,17 +12,17 @@ div.m3.m3-card
|
|||
& > :is(div.m3-card-footer, header.m3-card-header, section.m3-card-body) > .m3-card-media:first-child,
|
||||
& > .m3-card-media:first-child,
|
||||
& > .m3-card-action-area:first-child > .m3-card-action-area-content > .m3-card-media:first-child
|
||||
padding: padding-calculating(false)
|
||||
border-radius: 12px !important
|
||||
padding: padding-calculating(false)
|
||||
|
||||
div.m3.m3-card > .m3-card-action-area:first-child > .m3-card-action-area-content > .m3-card-media:first-child
|
||||
padding: padding-calculating(false)
|
||||
border-radius: 12px !important
|
||||
padding: padding-calculating(false)
|
||||
|
||||
div.m3-card-footer, header.m3-card-header, section.m3-card-body, .m3-card-media.m3
|
||||
padding: padding-calculating(true)
|
||||
display: block
|
||||
box-sizing: border-box
|
||||
padding: padding-calculating(true)
|
||||
|
||||
.m3.m3-card-media
|
||||
&.m3-rounded
|
||||
|
@ -40,7 +40,7 @@ div.m3.m3-card-action-area
|
|||
contain: content
|
||||
position: relative
|
||||
border-radius: inherit
|
||||
transition: box-shadow .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
transition: background-color, box-shadow, .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
||||
& > div.m3.m3-card-action-area-content
|
||||
top: 0
|
||||
|
@ -52,7 +52,9 @@ div.m3.m3-card-action-area
|
|||
width: 100%
|
||||
height: 100%
|
||||
position: absolute
|
||||
transition: background-color .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
||||
& > .m3.m3-ripple-domain > .m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 12%, transparent)
|
||||
|
||||
&:hover
|
||||
& > span.m3.m3-card-state-layer
|
||||
|
@ -79,6 +81,3 @@ div.m3.m3-card-action-area
|
|||
&:not(&:has(span.m3.m3-ripple-domain))
|
||||
& > span.m3.m3-card-state-layer
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 12%, transparent)
|
||||
|
||||
& > span.m3.m3-ripple-domain > .m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 12%, transparent)
|
||||
|
|
|
@ -10,7 +10,7 @@ $weights: ("Thin": 100, "Light": 300, "Regular": 400, "Medium": 500, "Bold": 700
|
|||
|
||||
@each $name, $weight in $weights
|
||||
@font-face
|
||||
font-family: Roboto
|
||||
font-family: Roboto, sans-serif
|
||||
font-face-name: #{$name}
|
||||
font-weight: #{$weight}
|
||||
src: url("./font/Roboto-#{$name}.ttf")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
@ -5,6 +5,7 @@
|
|||
@import "ripple"
|
||||
@import "divider"
|
||||
@import "container"
|
||||
@import "typography"
|
||||
|
||||
@import "mixins/m3-mixins"
|
||||
|
||||
|
@ -19,9 +20,9 @@
|
|||
@import "input-styles/checkbox"
|
||||
@import "input-styles/text-field"
|
||||
|
||||
@import "./themes/tokens.css"
|
||||
@import "./themes/colors.module.css"
|
||||
@import "./themes/typography.module.css"
|
||||
@import "./themes/tokens"
|
||||
@import "./themes/colors.module"
|
||||
@import "./themes/typography.module"
|
||||
@import "./themes/theme.dark.css" (prefers-color-scheme: dark)
|
||||
@import "./themes/theme.light.css" (prefers-color-scheme: light)
|
||||
|
||||
|
@ -30,9 +31,6 @@ html
|
|||
color: var(--md-sys-color-on-surface)
|
||||
background-color: var(--md-sys-color-surface-container)
|
||||
|
||||
.m3
|
||||
user-select: none
|
||||
|
||||
.m3.m3-wrapper
|
||||
position: relative
|
||||
display: block
|
||||
|
|
|
@ -3,15 +3,16 @@ svg.m3.m3-svg-icon
|
|||
$types: ["Outlined", "Rounded", "Sharp"]
|
||||
|
||||
& > text
|
||||
alignment-baseline: central
|
||||
text-anchor: middle
|
||||
dominant-baseline: central
|
||||
alignment-baseline: central
|
||||
|
||||
@each $size in $sizes
|
||||
& > text.m3-size-#{$size}
|
||||
width: $size
|
||||
aspect-ratio: 1
|
||||
line-height: $size
|
||||
font-size: $size
|
||||
line-height: $size
|
||||
|
||||
@each $type in $types
|
||||
& > text.m3-#{$type}
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
div.m3.m3-checkbox-container
|
||||
@include m3-label-mixin
|
||||
width: 18px
|
||||
height: 18px
|
||||
@include m3-checkbox-container-mixin
|
||||
|
||||
& > span.m3.m3-checkbox-state-layer
|
||||
@include m3-state-layer-mixin
|
||||
|
||||
span.m3.m3-checkbox-ripple-layer
|
||||
z-index: 20
|
||||
width: 2.5rem
|
||||
height: 2.5rem
|
||||
contain: content
|
||||
border-radius: 50%
|
||||
position: absolute
|
||||
& > span.m3.m3-checkbox-ripple-layer
|
||||
z-index: 20
|
||||
width: 2.5rem
|
||||
height: 2.5rem
|
||||
contain: content
|
||||
border-radius: 50%
|
||||
position: absolute
|
||||
|
||||
input[type="checkbox"].m3.m3-checkbox
|
||||
margin: 0
|
||||
z-index: 10
|
||||
display: flex
|
||||
width: 1.125rem
|
||||
|
@ -28,6 +26,7 @@ input[type="checkbox"].m3.m3-checkbox
|
|||
transition: background-color .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
||||
& ~ span.m3-checkbox-state
|
||||
position: absolute
|
||||
color: var(--md-sys-color-on-surface-variant)
|
||||
transition: color .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
||||
|
@ -55,13 +54,13 @@ input[type="checkbox"].m3.m3-checkbox
|
|||
opacity: 38%
|
||||
|
||||
& ~ span.m3-checkbox-state
|
||||
pointer-events: none
|
||||
z-index: 10
|
||||
display: flex
|
||||
font-size: 24px
|
||||
font-weight: 700
|
||||
line-height: 24px
|
||||
align-items: center
|
||||
pointer-events: none
|
||||
justify-content: center
|
||||
font-family: Material-Symbols-Outlined-Regular, sans-serif
|
||||
font-variation-settings: 'FILL' 1, 'wght' 300, 'GRAD' 0, 'opsz' 24
|
||||
|
@ -83,6 +82,7 @@ input[type="checkbox"].m3.m3-checkbox
|
|||
|
||||
&:is(:user-invalid:is(:active, :indeterminate:active), .m3.m3-error:active) ~ span.m3.m3-checkbox-state-layer
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-error) 12%, transparent)
|
||||
|
||||
& ~ span.m3-ripple-domain > .m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-error) 20%, transparent)
|
||||
|
||||
|
@ -91,6 +91,7 @@ input[type="checkbox"].m3.m3-checkbox
|
|||
|
||||
&:is(:checked:active, :indeterminate:active) ~ span.m3.m3-checkbox-state-layer
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent)
|
||||
|
||||
& ~ span.m3-ripple-domain > .m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 20%, transparent)
|
||||
|
||||
|
@ -100,6 +101,7 @@ input[type="checkbox"].m3.m3-checkbox
|
|||
|
||||
&:active ~ span.m3.m3-checkbox-state-layer
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-on-surface) 12%, transparent)
|
||||
|
||||
& ~ span.m3-ripple-domain > .m3.ripple
|
||||
background-color: color-mix(in srgb, var(--md-sys-color-primary) 20%, transparent)
|
||||
|
||||
|
|
|
@ -5,12 +5,16 @@ div.m3.m3-radio-container
|
|||
display: inline-flex
|
||||
justify-content: center
|
||||
|
||||
& + label.m3.m3-radio-label
|
||||
margin-inline: 3px
|
||||
|
||||
& > span.m3-checkbox-ripple-layer, span.m3.m3-radio-state-layer
|
||||
z-index: 5
|
||||
width: 40px
|
||||
height: 40px
|
||||
aspect-ratio: 1
|
||||
|
||||
& > span.m3.m3-radio-state-layer
|
||||
width: 40px
|
||||
aspect-ratio: 1
|
||||
border-radius: 50%
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
|
|
|
@ -3,41 +3,51 @@ div.m3.m3-slider-container
|
|||
display: flex
|
||||
align-items: center
|
||||
|
||||
& > datalist
|
||||
display: none
|
||||
|
||||
|
||||
input[type="range"].m3.m3-slider
|
||||
margin: 0
|
||||
height: 4px
|
||||
appearance: none
|
||||
overflow: visible
|
||||
border-radius: 2px
|
||||
margin-inline: 10px
|
||||
background-color: var(--md-sys-color-surface-container-highest)
|
||||
margin-inline: 8px
|
||||
background: var(--md-sys-color-surface-container-highest)
|
||||
|
||||
&:-moz-any(&)
|
||||
height: 4px
|
||||
|
||||
&:-webkit-any(&)
|
||||
background: linear-gradient(to right, var(--md-sys-color-primary) 0%, var(--md-sys-color-surface-container-highest) 0%)
|
||||
|
||||
&::-moz-range-track
|
||||
height: 4px
|
||||
overflow: hidden
|
||||
border-radius: 2px
|
||||
|
||||
&::-moz-range-progress
|
||||
height: 4px
|
||||
overflow: hidden
|
||||
border-radius: 2px
|
||||
background-color: var(--md-sys-color-primary)
|
||||
|
||||
&::-moz-range-thumb
|
||||
@include input-range-thumb-mixin
|
||||
|
||||
border: none
|
||||
|
||||
&::-webkit-slider-container
|
||||
margin-inline: -8px
|
||||
appearance: none
|
||||
box-shadow: none
|
||||
border-radius: 2px
|
||||
min-block-size: 4px
|
||||
height: 4px
|
||||
|
||||
&::-webkit-slider-runnable-track
|
||||
height: 20px
|
||||
|
||||
&::-webkit-slider-thumb
|
||||
@include elevation-1(false)
|
||||
|
||||
&::after
|
||||
width: 40px
|
||||
aspect-ratio: 1
|
||||
background-color: transparent
|
||||
|
||||
&:hover
|
||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent)
|
||||
|
||||
&:is(:active, :focus-visible)
|
||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent)
|
||||
|
||||
width: 20px
|
||||
aspect-ratio: 1
|
||||
appearance: none
|
||||
overflow: visible
|
||||
border-radius: 50%
|
||||
box-sizing: border-box
|
||||
outline: 10px solid transparent
|
||||
background: var(--md-sys-color-primary)
|
||||
transition: .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
@include input-range-thumb-mixin
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
div.m3.m3-switch
|
||||
margin: 4px
|
||||
gap: 20px
|
||||
box-sizing: content-box
|
||||
margin: 4px
|
||||
height: 32px
|
||||
display: flex
|
||||
align-items: center
|
||||
justify-content: center
|
||||
width: 52px
|
||||
height: 32px
|
||||
justify-content: left
|
||||
box-sizing: content-box
|
||||
|
||||
& > svg
|
||||
overflow: visible
|
||||
transition: .2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||
width: 52px
|
||||
height: 32px
|
||||
overflow: visible
|
||||
transition: .2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||
|
||||
& > g
|
||||
transform: translate(11.5%, 81%)
|
||||
transition: .2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||
& > text
|
||||
font-family: Material-Symbols-Outlined-Regular
|
||||
font-size: 20px
|
||||
font-family: Material-Symbols-Outlined-Regular,serif
|
||||
|
||||
& > circle.m3.m3-switch-handler-state-layer, & > circle.m3.m3-switch-handler
|
||||
transition: .2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||
cy: 50%
|
||||
cx: 16px
|
||||
transition: .2s cubic-bezier(0.175, 0.885, 0.32, 1.275)
|
||||
|
||||
& > circle.m3.m3-switch-handler-state-layer
|
||||
r: 20px
|
||||
|
@ -42,13 +41,13 @@ div.m3.m3-switch
|
|||
height: 30px
|
||||
|
||||
& > input.m3
|
||||
cursor: pointer
|
||||
appearance: none
|
||||
opacity: 0 !important
|
||||
margin: 0
|
||||
width: 52px
|
||||
height: 32px
|
||||
cursor: pointer
|
||||
appearance: none
|
||||
position: absolute
|
||||
opacity: 0 !important
|
||||
|
||||
&:disabled
|
||||
cursor: not-allowed
|
||||
|
@ -93,8 +92,8 @@ div.m3.m3-switch
|
|||
r: 14px
|
||||
|
||||
&:not(:checked):disabled + svg > circle.m3.m3-switch-handler
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
fill-opacity: 38%
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
|
||||
&:hover:not(:disabled)
|
||||
&:checked + svg
|
||||
|
@ -102,25 +101,25 @@ div.m3.m3-switch
|
|||
fill: var(--md-sys-color-primary-container)
|
||||
|
||||
& > circle.m3.m3-switch-handler-state-layer
|
||||
fill: var(--md-sys-color-primary)
|
||||
fill-opacity: 8%
|
||||
fill: var(--md-sys-color-primary)
|
||||
|
||||
&:not(:checked) + svg
|
||||
& > circle.m3.m3-switch-handler
|
||||
fill: var(--md-sys-color-on-surface-variant)
|
||||
|
||||
& > circle.m3.m3-switch-handler-state-layer
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
fill-opacity: 8%
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
|
||||
&:active:not(:disabled)
|
||||
&:checked + svg > circle.m3.m3-switch-handler-state-layer
|
||||
fill: var(--md-sys-color-primary)
|
||||
fill-opacity: 12%
|
||||
fill: var(--md-sys-color-primary)
|
||||
|
||||
&:not(:checked) + svg > circle.m3.m3-switch-handler-state-layer
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
fill-opacity: 12%
|
||||
fill: var(--md-sys-color-on-surface)
|
||||
|
||||
&:is(:checked, :checked:disabled) + svg > rect.m3.m3-switch-track
|
||||
rx: 16px
|
||||
|
@ -137,8 +136,8 @@ div.m3.m3-switch
|
|||
fill: var(--md-sys-color-surface-container-highest)
|
||||
|
||||
&:checked + svg > rect.m3.m3-switch-track
|
||||
stroke: var(--md-sys-color-primary)
|
||||
fill: var(--md-sys-color-primary)
|
||||
stroke: var(--md-sys-color-primary)
|
||||
|
||||
&:disabled + svg
|
||||
& > g > text.m3
|
||||
|
@ -154,5 +153,5 @@ div.m3.m3-switch
|
|||
fill: color-mix(in srgb, var(--md-sys-color-on-surface) 38%, transparent)
|
||||
|
||||
& > rect.m3.m3-switch-track
|
||||
stroke: color-mix(in srgb, var(--md-sys-color-on-surface) 0%, transparent)
|
||||
fill: color-mix(in srgb, var(--md-sys-color-on-surface) 12%, transparent)
|
||||
stroke: color-mix(in srgb, var(--md-sys-color-on-surface) 0%, transparent)
|
|
@ -1,15 +1,17 @@
|
|||
@mixin m3-label-mixin
|
||||
@mixin m3-checkbox-container-mixin
|
||||
gap: 16px
|
||||
height: 40px
|
||||
display: flex
|
||||
aspect-ratio: 1
|
||||
position: relative
|
||||
align-items: center
|
||||
justify-content: center
|
||||
aspect-ratio: 1
|
||||
|
||||
@mixin m3-state-layer-mixin
|
||||
position: absolute
|
||||
width: 2.5rem
|
||||
aspect-ratio: inherit
|
||||
width: 40px
|
||||
aspect-ratio: 1
|
||||
border-radius: 50%
|
||||
position: absolute
|
||||
transition: background-color .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
||||
@mixin m3-fab-default($b-radius, $width, $height : $width, $padding : 0)
|
||||
|
@ -73,3 +75,25 @@
|
|||
right: 0
|
||||
position: absolute
|
||||
background: #00000000
|
||||
|
||||
@mixin input-range-thumb-mixin
|
||||
@include elevation-1(false)
|
||||
|
||||
&:hover
|
||||
|
||||
&:after
|
||||
content: '1'
|
||||
|
||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 8%, transparent)
|
||||
|
||||
&:is(:active, :focus-visible)
|
||||
outline: 10px solid color-mix(in srgb, var(--md-sys-color-primary) 12%, transparent)
|
||||
|
||||
width: 20px
|
||||
height: 20px
|
||||
appearance: none
|
||||
border-radius: 50%
|
||||
box-sizing: border-box
|
||||
outline: 10px solid transparent
|
||||
background: var(--md-sys-color-primary)
|
||||
transition: .2s cubic-bezier(0.2, 0, 0, 1)
|
||||
|
|
|
@ -14,10 +14,15 @@
|
|||
z-index: 20
|
||||
aspect-ratio: 1
|
||||
border-radius: 50%
|
||||
|
||||
animation-duration: .55s
|
||||
animation-iteration-count: 1
|
||||
animation-name: rippleAppearanceAnimation
|
||||
animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
|
||||
animation-duration: .55s
|
||||
transition: opacity, background, background-color, .55s cubic-bezier(0.4, 0, 0.2, 1)
|
||||
|
||||
transition-duration: .55s
|
||||
transition-property: opacity, background-color
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1)
|
||||
|
||||
&.visible
|
||||
opacity: 1 !important
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
:is(h1, h2, h3, h4, h5, h6, code, p, span, pre, label).m3.m3-typography {
|
||||
vertical-align: center;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=typography.css.map */
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"sourceRoot":"","sources":["typography.sass"],"names":[],"mappings":"AAAA;EACI","file":"typography.css"}
|
|
@ -0,0 +1,4 @@
|
|||
label
|
||||
white-space: nowrap
|
||||
display: inline-block
|
||||
vertical-align: middle
|
Loading…
Reference in New Issue