Add Dynamic Poll Web Part with core functionality and styling

- Initialize Gulp build process with gulpfile.js
- Create package.json for project dependencies and scripts
- Add TypeScript declarations for SCSS modules
- Implement DynamicPollWebPart with property pane configuration
- Create PollDataService for SharePoint list interactions
- Develop core polling logic in PollCore.ts
- Define types for polls and answers in PollTypes.ts
- Create React components for DynamicPoll UI
- Add localization support for English and German
- Implement unit tests for core polling functionality
- Set up TypeScript and TSLint configurations
This commit is contained in:
Torsten Brendgen
2026-08-23 22:51:10 +02:00
commit ca41674188
30 changed files with 955 additions and 0 deletions
@@ -0,0 +1,70 @@
@import '~@microsoft/sp-office-ui-fabric-core/dist/sass/SPFabricCore.scss';
.poll {
background: "[theme: white, default: #ffffff]";
border: 1px solid "[theme: neutralLight, default: #edebe9]";
box-sizing: border-box;
color: "[theme: neutralPrimary, default: #323130]";
font-family: "Segoe UI", "Segoe UI Web (West European)", -apple-system, BlinkMacSystemFont, Roboto, "Helvetica Neue", sans-serif;
font-size: 14px;
padding: 20px;
width: 100%;
}
.question { font-size: 22px; font-weight: 600; line-height: 1.3; margin: 0 0 16px; }
.options { border: 0; margin: 0; padding: 0; }
.option {
align-items: center;
border-bottom: 1px solid "[theme: neutralLight, default: #edebe9]";
cursor: pointer;
display: flex;
gap: 10px;
min-height: 40px;
padding: 4px 8px;
}
.option:hover { background: "[theme: neutralLighter, default: #f3f2f1]"; }
.option input { height: 16px; margin: 0; width: 16px; }
.voteButton {
background: "[theme: themePrimary, default: #0078d4]";
border: 1px solid "[theme: themePrimary, default: #0078d4]";
color: "[theme: white, default: #ffffff]";
cursor: pointer;
font: inherit;
font-weight: 600;
margin-top: 16px;
min-height: 32px;
padding: 6px 20px;
}
.voteButton:hover { background: "[theme: themeDark, default: #005a9e]"; }
.voteButton:focus { outline: 2px solid "[theme: neutralPrimary, default: #323130]"; outline-offset: 2px; }
.voteButton:disabled { cursor: default; opacity: .6; }
.thanks { background: "[theme: themeLighterAlt, default: #eff6fc]"; margin-bottom: 16px; padding: 10px 12px; }
.error { color: "[theme: errorText, default: #a80000]"; margin-top: 10px; }
.results { margin-top: 20px; }
.resultsHeading { font-size: 18px; font-weight: 600; margin: 0 0 12px; }
.result { margin-bottom: 12px; }
.resultHeader { display: flex; gap: 12px; justify-content: space-between; margin-bottom: 4px; }
.track { background: "[theme: neutralLighter, default: #f3f2f1]"; height: 10px; overflow: hidden; width: 100%; }
.bar { background: "[theme: themePrimary, default: #0078d4]"; height: 100%; min-width: 0; transition: width 180ms ease; }
.bar1 { background: #498205; }
.bar2 { background: #8764b8; }
.bar3 { background: #ca5010; }
.bar4 { background: #038387; }
.bar0 { background: "[theme: themePrimary, default: #0078d4]"; }
.status,
.errorStatus {
border: 1px solid "[theme: neutralLight, default: #edebe9]";
color: "[theme: neutralPrimary, default: #323130]";
font-family: "Segoe UI", "Segoe UI Web (West European)", sans-serif;
padding: 16px;
}
.errorStatus { border-color: "[theme: errorText, default: #a80000]"; color: "[theme: errorText, default: #a80000]"; }
.visuallyHidden {
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
overflow: hidden;
position: absolute;
white-space: nowrap;
width: 1px;
}