Merge branch 'release' of https://github.com/appsmithorg/appsmith into release
This commit is contained in:
commit
26f8606417
|
|
@ -1,14 +1,100 @@
|
|||
import { CommonComponentProps } from "./common";
|
||||
import React, { useState } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
type CheckboxProps = CommonComponentProps & {
|
||||
label: string;
|
||||
isChecked: boolean;
|
||||
onCheckChange: (isChecked: boolean) => void;
|
||||
isLoading: boolean;
|
||||
align: "left" | "right";
|
||||
cypressSelector?: string;
|
||||
onCheckChange?: (isChecked: boolean) => void;
|
||||
};
|
||||
|
||||
export default function Checkbox(props: CheckboxProps) {
|
||||
return null;
|
||||
}
|
||||
const Checkmark = styled.span<{
|
||||
disabled?: boolean;
|
||||
isChecked?: boolean;
|
||||
}>`
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
left: 0;
|
||||
width: ${props => props.theme.spaces[8]}px;
|
||||
height: ${props => props.theme.spaces[8]}px;
|
||||
background-color: ${props =>
|
||||
props.isChecked
|
||||
? props.disabled
|
||||
? props.theme.colors.blackShades[3]
|
||||
: props.theme.colors.info.main
|
||||
: "transparent"};
|
||||
border: 2px solid
|
||||
${props =>
|
||||
props.isChecked
|
||||
? props.disabled
|
||||
? props.theme.colors.blackShades[3]
|
||||
: props.theme.colors.info.main
|
||||
: props.theme.colors.blackShades[4]};
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 0px;
|
||||
left: 4px;
|
||||
width: 6px;
|
||||
height: 11px;
|
||||
border: solid
|
||||
${props =>
|
||||
props.disabled ? "#565656" : props.theme.colors.blackShades[9]};
|
||||
border-width: 0 2px 2px 0;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledCheckbox = styled.label<{
|
||||
disabled?: boolean;
|
||||
}>`
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
cursor: ${props => (props.disabled ? "not-allowed" : "pointer")};
|
||||
font-weight: ${props => props.theme.typography.p1.fontWeight};
|
||||
font-size: ${props => props.theme.typography.p1.fontSize}px;
|
||||
line-height: ${props => props.theme.typography.p1.lineHeight}px;
|
||||
letter-spacing: ${props => props.theme.typography.p1.letterSpacing}px;
|
||||
color: ${props => props.theme.colors.blackShades[7]};
|
||||
padding-left: ${props => props.theme.spaces[12] - 2}px;
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
height: 0;
|
||||
width: 0;
|
||||
}
|
||||
|
||||
input:checked ~ ${Checkmark}:after {
|
||||
display: block;
|
||||
}
|
||||
`;
|
||||
|
||||
const Checkbox = (props: CheckboxProps) => {
|
||||
const [checked, setChecked] = useState<boolean>(false);
|
||||
|
||||
const onChangeHandler = (checked: boolean) => {
|
||||
setChecked(checked);
|
||||
props.onCheckChange && props.onCheckChange(checked);
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledCheckbox disabled={props.disabled}>
|
||||
{props.label}
|
||||
<input
|
||||
type="checkbox"
|
||||
disabled={props.disabled}
|
||||
checked={checked}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
|
||||
onChangeHandler(e.target.checked)
|
||||
}
|
||||
/>
|
||||
<Checkmark disabled={props.disabled} isChecked={checked} />
|
||||
</StyledCheckbox>
|
||||
);
|
||||
};
|
||||
|
||||
export default Checkbox;
|
||||
|
|
|
|||
|
|
@ -1,12 +1,154 @@
|
|||
import { CommonComponentProps } from "./common";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
type RadioProps = CommonComponentProps & {
|
||||
align?: "horizontal" | "vertical" | "column" | "row";
|
||||
columns?: number;
|
||||
rows?: number;
|
||||
value?: string;
|
||||
type OptionProps = {
|
||||
label: string;
|
||||
value: string;
|
||||
disabled?: boolean;
|
||||
onSelect?: (value: string) => void;
|
||||
};
|
||||
|
||||
export default function Radio(props: RadioProps) {
|
||||
return null;
|
||||
type RadioProps = CommonComponentProps & {
|
||||
columns?: number;
|
||||
rows?: number;
|
||||
defaultValue: string;
|
||||
onSelect?: (value: string) => void;
|
||||
options: OptionProps[];
|
||||
};
|
||||
|
||||
const RadioGroup = styled.div<{
|
||||
rows?: number;
|
||||
}>`
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
${props =>
|
||||
props.rows && props.rows > 0
|
||||
? `
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
`
|
||||
: null};
|
||||
`;
|
||||
|
||||
const Radio = styled.label<{
|
||||
disabled?: boolean;
|
||||
columns?: number;
|
||||
rows?: number;
|
||||
}>`
|
||||
display: block;
|
||||
position: relative;
|
||||
padding-left: ${props => props.theme.spaces[12] - 2}px;
|
||||
cursor: ${props => (props.disabled ? "not-allowed" : "pointer")};
|
||||
font-size: ${props => props.theme.typography.p1.fontSize}px;
|
||||
font-weight: ${props => props.theme.typography.p1.fontWeight};
|
||||
line-height: ${props => props.theme.typography.p1.lineHeight}px;
|
||||
letter-spacing: ${props => props.theme.typography.p1.letterSpacing}px;
|
||||
color: ${props => props.theme.colors.blackShades[9]};
|
||||
${props =>
|
||||
props.rows && props.rows > 0
|
||||
? `flex-basis: calc(100% / ${props.rows})`
|
||||
: null};
|
||||
${props =>
|
||||
props.columns && props.columns > 0
|
||||
? `
|
||||
flex-basis: calc(100% / ${props.columns});
|
||||
margin-bottom: ${props.theme.spaces[11] + 1}px;
|
||||
`
|
||||
: null};
|
||||
|
||||
input {
|
||||
position: absolute;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.checkbox {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: ${props => props.theme.spaces[8]}px;
|
||||
height: ${props => props.theme.spaces[8]}px;
|
||||
background-color: transparent;
|
||||
border: ${props => props.theme.spaces[1] - 2}px solid
|
||||
${props => props.theme.colors.blackShades[4]};
|
||||
border-radius: 50%;
|
||||
margin-top: ${props => props.theme.spaces[0]}px;
|
||||
}
|
||||
|
||||
.checkbox:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
display: none;
|
||||
}
|
||||
|
||||
input:checked ~ .checkbox:after {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input:disabled ~ .checkbox:after {
|
||||
background-color: ${props => props.theme.colors.radio.disabled};
|
||||
}
|
||||
|
||||
.checkbox:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
width: ${props => props.theme.spaces[4]}px;
|
||||
height: ${props => props.theme.spaces[4]}px;
|
||||
${props =>
|
||||
props.disabled
|
||||
? `background-color: ${props.theme.colors.radio.disabled}`
|
||||
: `background-color: ${props.theme.colors.info.main};`};
|
||||
top: ${props => props.theme.spaces[1] - 2}px;
|
||||
left: ${props => props.theme.spaces[1] - 2}px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
`;
|
||||
|
||||
export default function RadioComponent(props: RadioProps) {
|
||||
const [selected, setSelected] = useState(props.defaultValue);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.rows && props.columns && props.rows > 0 && props.columns > 0) {
|
||||
console.error(
|
||||
"Please pass either rows prop or column prop but not both.",
|
||||
);
|
||||
}
|
||||
}, [props]);
|
||||
|
||||
useEffect(() => {
|
||||
setSelected(props.defaultValue);
|
||||
}, [props.defaultValue]);
|
||||
|
||||
const onChangeHandler = (value: string) => {
|
||||
setSelected(value);
|
||||
props.onSelect && props.onSelect(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<RadioGroup
|
||||
rows={props.rows}
|
||||
onChange={(e: any) => onChangeHandler(e.target.value)}
|
||||
>
|
||||
{props.options.map((option: OptionProps, index: number) => (
|
||||
<Radio
|
||||
key={index}
|
||||
columns={props.columns}
|
||||
rows={props.rows}
|
||||
disabled={props.disabled || option.disabled}
|
||||
>
|
||||
{option.label}
|
||||
<input
|
||||
type="radio"
|
||||
value={option.value}
|
||||
disabled={props.disabled || option.disabled}
|
||||
onChange={e => option.onSelect && option.onSelect(e.target.value)}
|
||||
checked={selected === option.value}
|
||||
name="radio"
|
||||
/>
|
||||
<span className="checkbox"></span>
|
||||
</Radio>
|
||||
))}
|
||||
</RadioGroup>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
59
app/client/src/components/ads/Tooltip.tsx
Normal file
59
app/client/src/components/ads/Tooltip.tsx
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import React from "react";
|
||||
import { CommonComponentProps } from "./common";
|
||||
import styled from "styled-components";
|
||||
import { Position, Tooltip, Classes } from "@blueprintjs/core";
|
||||
import { Classes as CsClasses } from "./common";
|
||||
|
||||
type Variant = "dark" | "light";
|
||||
|
||||
type TooltipProps = CommonComponentProps & {
|
||||
content: JSX.Element | string;
|
||||
position?: Position;
|
||||
children: JSX.Element;
|
||||
variant?: Variant;
|
||||
};
|
||||
|
||||
const TooltipWrapper = styled.div<{ variant?: Variant }>`
|
||||
.${Classes.TOOLTIP} .${Classes.POPOVER_CONTENT} {
|
||||
padding: 10px 12px;
|
||||
border-radius: 0px;
|
||||
background-color: ${props =>
|
||||
props.variant === "dark"
|
||||
? props.theme.colors.blackShades[0]
|
||||
: props.theme.colors.blackShades[8]};
|
||||
}
|
||||
div.${Classes.POPOVER_ARROW} {
|
||||
display: block;
|
||||
}
|
||||
.${Classes.TOOLTIP} {
|
||||
box-shadow: 0px 12px 20px rgba(0, 0, 0, 0.35);a
|
||||
}
|
||||
.${Classes.TOOLTIP} .${CsClasses.BP3_POPOVER_ARROW_BORDER},
|
||||
&&&& .${Classes.TOOLTIP} .${CsClasses.BP3_POPOVER_ARROW_FILL} {
|
||||
fill: ${props =>
|
||||
props.variant === "dark"
|
||||
? props.theme.colors.blackShades[0]
|
||||
: props.theme.colors.blackShades[8]};
|
||||
}
|
||||
`;
|
||||
|
||||
const TooltipComponent = (props: TooltipProps) => {
|
||||
return (
|
||||
<TooltipWrapper variant={props.variant}>
|
||||
<Tooltip
|
||||
content={props.content}
|
||||
position={props.position}
|
||||
usePortal={false}
|
||||
>
|
||||
{props.children}
|
||||
</Tooltip>
|
||||
</TooltipWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
TooltipComponent.defaultProps = {
|
||||
position: Position.TOP,
|
||||
variant: "dark",
|
||||
};
|
||||
|
||||
export default TooltipComponent;
|
||||
|
|
@ -15,6 +15,8 @@ export type ThemeProp = {
|
|||
export enum Classes {
|
||||
ICON = "cs-icon",
|
||||
TEXT = "cs-text",
|
||||
BP3_POPOVER_ARROW_BORDER = "bp3-popover-arrow-border",
|
||||
BP3_POPOVER_ARROW_FILL = "bp3-popover-arrow-fill",
|
||||
SPINNER = "cs-spinner",
|
||||
}
|
||||
|
||||
|
|
|
|||
22
app/client/src/components/stories/Checkbox.stories.tsx
Normal file
22
app/client/src/components/stories/Checkbox.stories.tsx
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import React from "react";
|
||||
import { withKnobs, boolean, text } from "@storybook/addon-knobs";
|
||||
import { withDesign } from "storybook-addon-designs";
|
||||
import { StoryWrapper } from "./Tabs.stories";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
import Checkbox from "components/ads/Checkbox";
|
||||
|
||||
export default {
|
||||
title: "Checkbox",
|
||||
component: Checkbox,
|
||||
decorators: [withKnobs, withDesign],
|
||||
};
|
||||
|
||||
export const CustomCheckbox = () => (
|
||||
<StoryWrapper>
|
||||
<Checkbox
|
||||
label={text("label", "Checked")}
|
||||
disabled={boolean("disabled", false)}
|
||||
onCheckChange={action("check-change")}
|
||||
/>
|
||||
</StoryWrapper>
|
||||
);
|
||||
56
app/client/src/components/stories/Radio.stories.tsx
Normal file
56
app/client/src/components/stories/Radio.stories.tsx
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import React from "react";
|
||||
import {
|
||||
withKnobs,
|
||||
select,
|
||||
boolean,
|
||||
text,
|
||||
number,
|
||||
} from "@storybook/addon-knobs";
|
||||
import { withDesign } from "storybook-addon-designs";
|
||||
import { StoryWrapper } from "./Tabs.stories";
|
||||
import RadioComponent from "components/ads/Radio";
|
||||
import { action } from "@storybook/addon-actions";
|
||||
|
||||
export default {
|
||||
title: "Radio",
|
||||
component: RadioComponent,
|
||||
decorators: [withKnobs, withDesign],
|
||||
};
|
||||
|
||||
export const Radio = () => (
|
||||
<StoryWrapper>
|
||||
<div style={{ height: "133px" }}>
|
||||
<RadioComponent
|
||||
defaultValue={select(
|
||||
"defaultValue",
|
||||
["React", "Angular", "Vue"],
|
||||
"React",
|
||||
)}
|
||||
columns={number("Column number", 2)}
|
||||
rows={number("Row number", 2)}
|
||||
disabled={boolean("Radio group disabled", false)}
|
||||
onSelect={action("selected-radio-option")}
|
||||
options={[
|
||||
{
|
||||
label: "React",
|
||||
value: "React",
|
||||
onSelect: action("first-radio-option"),
|
||||
disabled: boolean("Option-1-disabled", false),
|
||||
},
|
||||
{
|
||||
label: "Angular",
|
||||
value: "Angular",
|
||||
onSelect: action("second-radio-option"),
|
||||
disabled: boolean("Option-2-disabled", false),
|
||||
},
|
||||
{
|
||||
label: "Vue",
|
||||
value: "Vue",
|
||||
onSelect: action("third-radio-option"),
|
||||
disabled: boolean("Option-3-disabled", false),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</div>
|
||||
</StoryWrapper>
|
||||
);
|
||||
34
app/client/src/components/stories/Tooltip.stories.tsx
Normal file
34
app/client/src/components/stories/Tooltip.stories.tsx
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import React from "react";
|
||||
import { select, withKnobs } from "@storybook/addon-knobs";
|
||||
import { withDesign } from "storybook-addon-designs";
|
||||
import { Position } from "@blueprintjs/core";
|
||||
import TooltipComponent from "components/ads/Tooltip";
|
||||
import { StoryWrapper } from "components/ads/common";
|
||||
import Text, { TextType } from "components/ads/Text";
|
||||
import Button from "components/ads/Button";
|
||||
|
||||
export default {
|
||||
title: "Tooltip",
|
||||
component: TooltipComponent,
|
||||
decorators: [withKnobs, withDesign],
|
||||
};
|
||||
|
||||
export const MenuStory = () => (
|
||||
<StoryWrapper>
|
||||
<div style={{ paddingTop: "50px", paddingLeft: "50px", width: "200px" }}>
|
||||
<TooltipComponent
|
||||
position={select("Position", Object.values(Position), Position.RIGHT)}
|
||||
content={
|
||||
<Text type={TextType.P1} highlight>
|
||||
This is a tooltip
|
||||
</Text>
|
||||
}
|
||||
variant={select("variant", ["dark", "light"], "dark")}
|
||||
>
|
||||
<Text type={TextType.P1} highlight>
|
||||
Hover to show tooltip
|
||||
</Text>
|
||||
</TooltipComponent>
|
||||
</div>
|
||||
</StoryWrapper>
|
||||
);
|
||||
|
|
@ -572,6 +572,9 @@ export const theme: Theme = {
|
|||
darker: "#2B1A1D",
|
||||
darkest: "#462F32",
|
||||
},
|
||||
radio: {
|
||||
disabled: "#565656",
|
||||
},
|
||||
primaryOld: Colors.GREEN,
|
||||
primaryDarker: Colors.JUNGLE_GREEN,
|
||||
primaryDarkest: Colors.JUNGLE_GREEN_DARKER,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user