From 8f5cbba8b8cf422fac533b0bd1be27ecf1034dfa Mon Sep 17 00:00:00 2001 From: Navin Moorthy Date: Tue, 8 Dec 2020 18:48:28 +0530 Subject: [PATCH] =?UTF-8?q?docs(tailwind):=20=F0=9F=93=9D=20=20add=20tailw?= =?UTF-8?q?ind=20support=20&=20add=20examples=20(#186)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs(tailwind): 📝 add tailwind support for adding egs * test(aria): ✅ fix tests with role presentation https://dequeuniversity.com/rules/axe/4.1/presentation-role-conflict?application=axeAPI * docs(storybook): 📝 add global css for tailwind utilities support * chore: added datepicker tailwind examples * chore: scoped datepicker styles * chore: tailwind local styles * docs(storybook): 📝 fix tailwind scopify issue * chore: tailwind datepicker chevron fix Co-authored-by: Anurag --- .storybook/postcss.config.js | 12 +- .storybook/preview-body.html | 8 + .storybook/preview-head.html | 5 + package.json | 18 +- .../stories/DatePickerStyled.stories.tsx | 32 + src/datepicker/stories/Utils.component.tsx | 19 +- src/datepicker/stories/styled/Calendar.tsx | 119 + .../stories/styled/DatePicker.component.tsx | 56 + .../styled/RangeDatePicker.component.tsx | 69 + src/segment/Segment.ts | 6 +- src/segment/__tests__/Segment.test.tsx | 4 +- src/segment/stories/Segment.component.tsx | 1 + .../stories/SelectControlled.stories.tsx | 2 +- src/select/stories/SelectCustom.stories.tsx | 2 +- src/select/stories/SelectDynamic.stories.tsx | 2 +- src/select/stories/SelectFetch.stories.tsx | 2 +- src/select/stories/SelectMultiple.stories.tsx | 2 +- src/select/stories/SelectStyled.component.tsx | 118 + src/select/stories/SelectStyled.stories.tsx | 29 + src/select/stories/SelectWindows.stories.tsx | 2 +- tailwind.config.js | 11 + tailwind/index.css | 44 + yarn.lock | 2939 ++++++----------- 23 files changed, 1627 insertions(+), 1875 deletions(-) create mode 100644 .storybook/preview-body.html create mode 100644 .storybook/preview-head.html create mode 100644 src/datepicker/stories/DatePickerStyled.stories.tsx create mode 100644 src/datepicker/stories/styled/Calendar.tsx create mode 100644 src/datepicker/stories/styled/DatePicker.component.tsx create mode 100644 src/datepicker/stories/styled/RangeDatePicker.component.tsx create mode 100644 src/select/stories/SelectStyled.component.tsx create mode 100644 src/select/stories/SelectStyled.stories.tsx create mode 100644 tailwind.config.js create mode 100644 tailwind/index.css diff --git a/.storybook/postcss.config.js b/.storybook/postcss.config.js index 3f067e878..e2a537d54 100644 --- a/.storybook/postcss.config.js +++ b/.storybook/postcss.config.js @@ -18,6 +18,10 @@ function rewriteRootRule() { function addIdScope() { return root => { const filename = root.source.input.file; + + const isTailwind = path.basename(path.dirname(filename)) === "tailwind"; + if (isTailwind) return scopify("#tailwind")(root); + const basename = path.basename(filename, ".css"); const id = kebabCase(basename); return scopify(`#${id}`)(root); @@ -26,5 +30,11 @@ function addIdScope() { module.exports = { exec: true, - plugins: [rewriteRootRule(), addIdScope()], + plugins: [ + require("postcss-import"), + require("tailwindcss"), + require("autoprefixer"), + rewriteRootRule(), + addIdScope(), + ], }; diff --git a/.storybook/preview-body.html b/.storybook/preview-body.html new file mode 100644 index 000000000..fc1a22509 --- /dev/null +++ b/.storybook/preview-body.html @@ -0,0 +1,8 @@ + diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html new file mode 100644 index 000000000..21205a8eb --- /dev/null +++ b/.storybook/preview-head.html @@ -0,0 +1,5 @@ + + diff --git a/package.json b/package.json index e980e5e34..9a1228e1e 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "@testing-library/dom": "^7.28.1", "@testing-library/jest-dom": "^5.11.6", "@testing-library/react": "^11.2.2", - "@testing-library/react-hooks": "3.4.2", + "@testing-library/react-hooks": "3.6.0", "@testing-library/user-event": "12.5.0", "@textlint/markdown-to-ast": "^6.2.5", "@types/jest": "26.0.16", @@ -107,6 +107,7 @@ "@typescript-eslint/parser": "4.9.0", "all-contributors-cli": "^6.19.0", "ast-to-markdown": "^1.0.0", + "autoprefixer": "^9.8.6", "axios": "^0.21.0", "babel-eslint": "10.1.0", "babel-jest": "^26.6.3", @@ -117,8 +118,8 @@ "concurrently": "5.3.0", "conventional-github-releaser": "3.1.5", "cross-env": "7.0.3", - "eslint": "7.14.0", - "eslint-config-prettier": "6.15.0", + "eslint": "7.15.0", + "eslint-config-prettier": "7.0.0", "eslint-config-react-app": "6.0.0", "eslint-plugin-flowtype": "5.2.0", "eslint-plugin-import": "2.22.1", @@ -129,18 +130,20 @@ "gacp": "2.10.2", "glob": "^7.1.6", "glob-fs": "^0.1.7", - "husky": "4.3.0", + "husky": "4.3.5", "jest": "26.6.3", "jest-axe": "4.1.0", "jest-in-case": "1.0.2", "jest-matcher-utils": "26.6.2", - "lint-staged": "10.5.2", + "lint-staged": "10.5.3", "lodash": "4.17.20", "markdown-to-ast": "^6.0.3", "markdown-toc": "^1.2.0", "md-node-inject": "^1.0.1", "mockdate": "^3.0.2", "outdent": "^0.7.1", + "postcss": "^7.0.35", + "postcss-import": "^12.0.1", "postcss-scopify": "^0.1.9", "prettier": "2.2.1", "raw-loader": "^4.0.2", @@ -148,7 +151,7 @@ "react-dom": "17.0.1", "react-hook-form": "6.12.2", "react-spring": "8.0.27", - "react-test-renderer": "16.14.0", + "react-test-renderer": "17.0.1", "react-transition-group": "4.4.1", "react-virtual": "^2.3.2", "reakit": "1.3.1", @@ -158,12 +161,13 @@ "standard-version": "9.0.0", "storybook-addon-preview": "^2.1.0", "strip-comments": "^2.0.1", + "tailwindcss": "npm:@tailwindcss/postcss7-compat", "ts-jest": "26.4.4", "ts-morph": "^9.1.0", "ts-node": "^9.1.0", "tsd": "^0.14.0", "typescript": "4.1.2", - "webpack": "^5.9.0", + "webpack": "^5.10.0", "yaml": "^1.10.0" }, "peerDependencies": { diff --git a/src/datepicker/stories/DatePickerStyled.stories.tsx b/src/datepicker/stories/DatePickerStyled.stories.tsx new file mode 100644 index 000000000..d79c68402 --- /dev/null +++ b/src/datepicker/stories/DatePickerStyled.stories.tsx @@ -0,0 +1,32 @@ +import * as React from "react"; +import { Meta, Story } from "@storybook/react"; + +import "../../../tailwind/index.css"; +import { DatePicker } from "./styled/DatePicker.component"; +import { RangeDatePicker } from "./styled/RangeDatePicker.component"; + +export default { + component: DatePicker, + title: "DatePicker/Styled", + argTypes: { + value: { control: "date" }, + minValue: { control: "date" }, + maxValue: { control: "date" }, + defaultValue: { control: "date", defaultValue: new Date() }, + }, + decorators: [ + Story => { + document.body.id = "tailwind"; + return ; + }, + ], +} as Meta; + +const Base: Story = args => ; +const RangeBase: Story = args => ; + +export const Default = Base.bind({}); +Default.args = {}; + +export const Range = RangeBase.bind({}); +Default.args = {}; diff --git a/src/datepicker/stories/Utils.component.tsx b/src/datepicker/stories/Utils.component.tsx index 0f2e33ad5..f1654c385 100644 --- a/src/datepicker/stories/Utils.component.tsx +++ b/src/datepicker/stories/Utils.component.tsx @@ -10,6 +10,7 @@ export const CalendarIcon = () => ( export const DoubleChevronLeft = (props: any) => { return ( { ); @@ -29,26 +30,30 @@ export const DoubleChevronLeft = (props: any) => { export const ChevronLeft = (props: any) => { return ( ); }; export const ChevronRight = (props: any) => ( - + ); export const DoubleChevronRight = (props: any) => ( - + ); diff --git a/src/datepicker/stories/styled/Calendar.tsx b/src/datepicker/stories/styled/Calendar.tsx new file mode 100644 index 000000000..ee65cfd35 --- /dev/null +++ b/src/datepicker/stories/styled/Calendar.tsx @@ -0,0 +1,119 @@ +import * as React from "react"; +import { + CalendarCell, + CalendarGrid, + CalendarHeader, + CalendarButton, + CalendarWeekTitle, + CalendarCellButton, + CalendarStateReturn, + Calendar as CalendarWrapper, +} from "@renderlesskit/react"; + +import { + ChevronLeft, + ChevronRight, + DoubleChevronLeft, + DoubleChevronRight, +} from "../Utils.component"; + +export const Calendar: React.FC = state => { + return ( + +
+ + + + + + + + + + + + + +
+ + + + + {state.weekDays.map((day, dayIndex) => { + return ( + + {day.abbr.slice(0, 2)} + + ); + })} + + + + {state.daysInMonth.map((week, weekIndex) => ( + + {week.map((day, dayIndex) => ( + + + + ))} + + ))} + + +
+ ); +}; + +export const CalendarIcon = () => ( + +); diff --git a/src/datepicker/stories/styled/DatePicker.component.tsx b/src/datepicker/stories/styled/DatePicker.component.tsx new file mode 100644 index 000000000..dd8120290 --- /dev/null +++ b/src/datepicker/stories/styled/DatePicker.component.tsx @@ -0,0 +1,56 @@ +import * as React from "react"; + +import { + DatePickerSegment, + DatePickerContent, + DatePickerTrigger, + useDatePickerState, + DatePickerSegmentField, + DatePickerInitialState, + DatePicker as DatePickerWrapper, +} from "@renderlesskit/react"; +import { Calendar, CalendarIcon } from "./Calendar"; + +export const DatePicker: React.FC = props => { + const state = useDatePickerState({ + gutter: 0, + unstable_offset: [-19, 10], + formatOptions: { month: "2-digit", day: "2-digit", year: "numeric" }, + ...props, + }); + + return ( + <> + +
+ + {state.segments.map((segment, i) => ( + + ))} + + + + + +
+
+ + + + + ); +}; diff --git a/src/datepicker/stories/styled/RangeDatePicker.component.tsx b/src/datepicker/stories/styled/RangeDatePicker.component.tsx new file mode 100644 index 000000000..44b586018 --- /dev/null +++ b/src/datepicker/stories/styled/RangeDatePicker.component.tsx @@ -0,0 +1,69 @@ +import * as React from "react"; + +import { + DatePickerSegment, + DatePickerContent, + DatePickerTrigger, + DatePickerSegmentField, + DatePicker as DatePickerWrapper, + useDateRangePickerState, + DateRangePickerInitialState, +} from "@renderlesskit/react"; +import { Calendar, CalendarIcon } from "./Calendar"; + +export const RangeDatePicker: React.FC = props => { + const state = useDateRangePickerState({ + formatOptions: { month: "2-digit", day: "2-digit", year: "numeric" }, + ...props, + }); + + return ( + <> + +
+ + {state.startSegmentState.segments.map((segment, i) => ( + + ))} + +  -  + + {state.endSegmentState.segments.map((segment, i) => ( + + ))} + + + + +
+
+ + + + + ); +}; diff --git a/src/segment/Segment.ts b/src/segment/Segment.ts index 5ab8e9484..eede8574d 100644 --- a/src/segment/Segment.ts +++ b/src/segment/Segment.ts @@ -10,6 +10,7 @@ import { callAllHandlers } from "@chakra-ui/utils"; import { useDateFormatter } from "@react-aria/i18n"; import { createComponent, createHook } from "reakit-system"; +import { dataAttr } from "../utils"; import { SEGMENT_KEYS } from "./__keys"; import { DateSegment, SegmentStateReturn } from "./SegmentState"; import { useSpinButton, isNumeric, parseNumber } from "./helpers"; @@ -211,8 +212,7 @@ export const useSegment = createHook({ // A separator, e.g. punctuation case "literal": return { - role: "presentation", - "data-placeholder": false, + "data-placeholder": dataAttr(false), children: segment.text, ...htmlProps, }; @@ -222,7 +222,6 @@ export const useSegment = createHook({ case "timeZoneName": case "era": return { - role: "presentation", "data-placeholder": true, children: segment.text, ...htmlProps, @@ -234,7 +233,6 @@ export const useSegment = createHook({ id, "aria-label": segment.type, "aria-labelledby": `${id}`, - tabIndex: options.isDisabled ? undefined : 0, onKeyDown: callAllHandlers(htmlOnKeyDown, onKeyDown), onFocus: callAllHandlers(htmlOnFocus, onFocus), onMouseDown: callAllHandlers(htmlOnMouseDown, onMouseDown), diff --git a/src/segment/__tests__/Segment.test.tsx b/src/segment/__tests__/Segment.test.tsx index aa191d258..0ffb6fb82 100644 --- a/src/segment/__tests__/Segment.test.tsx +++ b/src/segment/__tests__/Segment.test.tsx @@ -3,13 +3,13 @@ import { cleanup } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { axe, render, press, screen } from "reakit-test-utils"; -import { repeat } from "../../utils/test-utils"; import { Segment, SegmentField, useSegmentState, SegmentInitialState, -} from ".."; +} from "../index"; +import { repeat } from "../../utils/test-utils"; afterEach(cleanup); diff --git a/src/segment/stories/Segment.component.tsx b/src/segment/stories/Segment.component.tsx index f94abaf1c..0276319c5 100644 --- a/src/segment/stories/Segment.component.tsx +++ b/src/segment/stories/Segment.component.tsx @@ -9,6 +9,7 @@ import { export const App: React.FC = props => { const state = useSegmentState(props); + console.log("%c state.segments", "color: #1d5673", state.segments); return (
diff --git a/src/select/stories/SelectControlled.stories.tsx b/src/select/stories/SelectControlled.stories.tsx index b56074860..7caea49d6 100644 --- a/src/select/stories/SelectControlled.stories.tsx +++ b/src/select/stories/SelectControlled.stories.tsx @@ -14,7 +14,7 @@ import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { component: SelectControlled, - title: "Select/SelectControlled", + title: "Select/Controlled", parameters: { preview: createPreviewTabs({ js: selectControlledTemplateJs, diff --git a/src/select/stories/SelectCustom.stories.tsx b/src/select/stories/SelectCustom.stories.tsx index a2adcf4a4..76c0e49d9 100644 --- a/src/select/stories/SelectCustom.stories.tsx +++ b/src/select/stories/SelectCustom.stories.tsx @@ -14,7 +14,7 @@ import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { component: SelectCustom, - title: "Select/SelectCustom", + title: "Select/Custom", parameters: { preview: createPreviewTabs({ js: selectCustomTemplateJs, diff --git a/src/select/stories/SelectDynamic.stories.tsx b/src/select/stories/SelectDynamic.stories.tsx index 27db6158c..988e76f14 100644 --- a/src/select/stories/SelectDynamic.stories.tsx +++ b/src/select/stories/SelectDynamic.stories.tsx @@ -14,7 +14,7 @@ import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { component: SelectDynamic, - title: "Select/SelectDynamic", + title: "Select/Dynamic", parameters: { preview: createPreviewTabs({ js: selectDynamicTemplateJs, diff --git a/src/select/stories/SelectFetch.stories.tsx b/src/select/stories/SelectFetch.stories.tsx index dca4304f7..f6324b827 100644 --- a/src/select/stories/SelectFetch.stories.tsx +++ b/src/select/stories/SelectFetch.stories.tsx @@ -12,7 +12,7 @@ import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { component: SelectFetch, - title: "Select/SelectFetch", + title: "Select/Fetch", parameters: { preview: createPreviewTabs({ js: selectFetchTemplateJs, diff --git a/src/select/stories/SelectMultiple.stories.tsx b/src/select/stories/SelectMultiple.stories.tsx index 7d8775a97..77a3052e1 100644 --- a/src/select/stories/SelectMultiple.stories.tsx +++ b/src/select/stories/SelectMultiple.stories.tsx @@ -14,7 +14,7 @@ import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; export default { component: SelectMultiple, - title: "Select/SelectMultiple", + title: "Select/Multiple", parameters: { preview: createPreviewTabs({ js: selectMultipleTemplateJs, diff --git a/src/select/stories/SelectStyled.component.tsx b/src/select/stories/SelectStyled.component.tsx new file mode 100644 index 000000000..8ba2c1e4e --- /dev/null +++ b/src/select/stories/SelectStyled.component.tsx @@ -0,0 +1,118 @@ +import * as React from "react"; + +import { + Select, + SelectOption, + SelectPopover, + useSelectState, + SelectInitialState, +} from "@renderlesskit/react"; + +const people = [ + "Wade Cooper", + "Arlene Mccoy", + "Devon Webb", + "Tom Cook", + "Tanya Fox", + "Hellen Schmidt", + "Caroline Schultz", + "Mason Heaney", + "Claudie Smitham", + "Emil Schaefer", +]; + +export const App: React.FC = () => { + const select = useSelectState({ gutter: 8 }); + + return ( +
+
+
+
+ Assigned to +
+
+ + + + + {people.length + ? people.map(person => ( + +
  • + + {person} + + {select.selectedValue === person && ( + + + + + + )} +
  • +
    + )) + : "No results found"} +
    +
    +
    +
    +
    + ); +}; diff --git a/src/select/stories/SelectStyled.stories.tsx b/src/select/stories/SelectStyled.stories.tsx new file mode 100644 index 000000000..46d8a58c0 --- /dev/null +++ b/src/select/stories/SelectStyled.stories.tsx @@ -0,0 +1,29 @@ +import * as React from "react"; +import { Meta, Story } from "@storybook/react"; + +import "../../../tailwind/index.css"; +import { App as Select } from "./SelectStyled.component"; +import { createPreviewTabs } from "../../../scripts/create-preview-tabs"; +import { selectStyledTemplate, selectStyledTemplateJs } from "./templates"; + +export default { + component: Select, + title: "Select/Styled", + parameters: { + preview: createPreviewTabs({ + js: selectStyledTemplateJs, + ts: selectStyledTemplate, + }), + }, + decorators: [ + Story => { + document.body.id = "tailwind"; + return ; + }, + ], +} as Meta; + +const Base: Story = args =>